diff --git a/README.md b/README.md index fcca627..4404009 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,26 @@ # push-to-dokku -Action to push to Dokku \ No newline at end of file +Action to push a remote repository to Dokku. + +## Usage + +``` +uses: https://lmika.dev/actions/push-to-dokku@v1.1 +with: + app: dokku-app-name + host: dokku-host + private-key: SSH key +``` + +Parameters are: + +- `host`: hostname of the Dokku instance to push the application to. +- `app`: the Dokku application name. +- `private-key`: the private SSH key +- `source-branch`: the code branch to push (default = `main`) +- `target-branch`: the Dokku branch to push to (default = same as source-branch) + +This action requires Go 1.22.4 or later. + +This action will write the private key to the .ssh instance and will push to the remote repository as the `dokku` +user. Both the source and target branch must be `main`. diff --git a/config.go b/config.go index 87c6d1f..def963b 100644 --- a/config.go +++ b/config.go @@ -3,15 +3,19 @@ package main import "os" type config struct { - HostName string - AppName string - PrivateKey string + HostName string + AppName string + PrivateKey string + LocalBranch string + RemoteBranch string } func readConfig() config { return config{ - HostName: os.Getenv("INPUT_HOST"), - AppName: os.Getenv("INPUT_APP"), - PrivateKey: os.Getenv("INPUT_PRIVATE-KEY"), + HostName: os.Getenv("INPUT_HOST"), + AppName: os.Getenv("INPUT_APP"), + PrivateKey: os.Getenv("INPUT_PRIVATE-KEY"), + LocalBranch: os.Getenv("INPUT_SOURCE-BRANCH"), + RemoteBranch: os.Getenv("INPUT_TARGET-BRANCH"), } } diff --git a/services.go b/services.go index 67aba79..c4548e3 100644 --- a/services.go +++ b/services.go @@ -12,10 +12,11 @@ import ( type Services struct { cfg config + keyFileName string } func NewServices(cfg config) *Services { - return &Services{cfg: cfg} + return &Services{cfg: cfg, keyFileName: "id_ecdsa"} } func (s *Services) AddPrivateKey() error { @@ -25,7 +26,8 @@ func (s *Services) AddPrivateKey() error { return err } - if err := writeFile(`${HOME}/.ssh/id_rsa`, s.cfg.PrivateKey, 0400); err != nil { + privateKey := strings.TrimSpace(s.cfg.PrivateKey) + "\n" + if err := writeFile(`${HOME}/.ssh/` + s.keyFileName, privateKey, 0400); err != nil { return err } @@ -39,9 +41,11 @@ func (s *Services) ConfigureSSH() error { if err := sshConfigTemplate.Execute(&bfr, struct { Cfg config Home string + KeyFileName string }{ Cfg: s.cfg, Home: os.Getenv("HOME"), + KeyFileName: s.keyFileName, }); err != nil { return err } @@ -67,7 +71,27 @@ func (s *Services) PushRepository() error { return err } - if err := runCmd("git", "push", "dokku", "main"); err != nil { + sourceBranch := s.cfg.LocalBranch + if sourceBranch == "" { + // Get the current ref + ref, err := runCmdExpectingOutput("git", "rev-parse", "HEAD") + if err != nil { + return err + } + + sourceBranch = strings.TrimSpace(ref) + } + remoteBranch := s.cfg.RemoteBranch + if remoteBranch == "" { + remoteBranch = "main" + } + + branchArg := sourceBranch + if sourceBranch != remoteBranch { + branchArg = fmt.Sprintf("%v:%v", sourceBranch, remoteBranch) + } + + if err := runCmd("git", "push", "dokku", branchArg); err != nil { return err } @@ -82,9 +106,20 @@ func runCmd(cmd ...string) error { return e.Run() } +func runCmdExpectingOutput(cmd ...string) (string, error) { + log.Printf(" .. [exec] %v", strings.Join(cmd, " ")) + e := exec.Command(cmd[0], cmd[1:]...) + e.Stderr = os.Stderr + res, err := e.Output() + if err != nil { + return "", err + } + return string(res), nil +} + func writeFile(path string, content string, mode os.FileMode) error { fullPath := os.ExpandEnv(path) - log.Printf(" .. [file] %v (%v bytes)", fullPath, len(content)) + log.Printf(" .. [file] %v (%v bytes)", fullPath, len(content)) return os.WriteFile(fullPath, []byte(content), mode) } @@ -97,6 +132,6 @@ Host * Host {{.Cfg.HostName}} HostName {{.Cfg.HostName}} User dokku - IdentityFile {{.Home}}/.ssh/id_rsa + IdentityFile {{.Home}}/.ssh/{{.KeyFileName}} `)) )