From e4cb311f7afa54520a1a67c1bcbdd8b1eb9dfa58 Mon Sep 17 00:00:00 2001 From: Nick Goodall Date: Tue, 13 Jan 2026 13:03:12 +0000 Subject: [PATCH] tidy up deployment output --- README.md | 16 +++++---- deploy.go | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 105 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b73e4fc..92d65a4 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,17 @@ A simple, rsync-based PocketBase deployment tool. -## init +## Commands -- start a new PocketBase project (optionally provide a service name via `pb init `) +### `init` -## dev +Start a new PocketBase project (optionally provide a service name via `pb init `) -- run a local dev server +### `dev` -## deploy +Run the local dev server. + +### `deploy` Deploys pocketbase to a remote server. This will: @@ -20,6 +22,6 @@ Deploys pocketbase to a remote server. This will: 4. Copy pb_public, pb_migrations and pb_hooks. 5. Start the service. -## logs +### logs -## secrets +### secrets diff --git a/deploy.go b/deploy.go index 591c741..16fa84d 100644 --- a/deploy.go +++ b/deploy.go @@ -1,15 +1,18 @@ package main import ( + "bufio" "bytes" "crypto/sha1" "errors" "fmt" + "io" "os" "os/exec" "path/filepath" "runtime" "strings" + "unicode" "github.com/pelletier/go-toml/v2" ) @@ -303,9 +306,26 @@ systemctl restart pb@%s func runSSHCommand(server, script string) error { cmd := exec.Command("ssh", append(sshArgs(server), "bash", "--noprofile", "--norc", "-c", script)...) - cmd.Stdout = os.Stdout + stdoutPipe, err := cmd.StdoutPipe() + if err != nil { + return err + } cmd.Stderr = os.Stderr - return cmd.Run() + if err := cmd.Start(); err != nil { + return err + } + + done := make(chan error, 1) + go func() { + done <- filterEnvStream(stdoutPipe, os.Stdout) + }() + + waitErr := cmd.Wait() + pipeErr := <-done + if waitErr != nil { + return waitErr + } + return pipeErr } func runSSHOutput(server, script string) (string, error) { @@ -316,7 +336,8 @@ func runSSHOutput(server, script string) (string, error) { if err := cmd.Run(); err != nil { return "", err } - return strings.TrimSpace(out.String()), nil + filtered := stripLeadingEnvLines(out.String()) + return strings.TrimSpace(filtered), nil } func syncLocalDirectories(server, remoteBase string, dirs []string) error { @@ -388,3 +409,75 @@ func closeSSHControlMaster(server string) { args = append(args, "-O", "exit", fmt.Sprintf("root@%s", server)) _ = exec.Command("ssh", args...).Run() } + +func filterEnvStream(r io.Reader, w io.Writer) error { + scanner := bufio.NewScanner(r) + scanner.Buffer(make([]byte, 0, 64*1024), 2*1024*1024) + skipping := true + for scanner.Scan() { + line := scanner.Text() + if skipping && isEnvLine(line) { + continue + } + if skipping { + skipping = false + } + if _, err := fmt.Fprintln(w, line); err != nil { + return err + } + } + if err := scanner.Err(); err != nil { + return err + } + return nil +} + +func stripLeadingEnvLines(input string) string { + scanner := bufio.NewScanner(strings.NewReader(input)) + scanner.Buffer(make([]byte, 0, 64*1024), 2*1024*1024) + skipping := true + var builder strings.Builder + addedLine := false + for scanner.Scan() { + line := scanner.Text() + if skipping && isEnvLine(line) { + continue + } + if skipping { + skipping = false + } + if addedLine { + builder.WriteByte('\n') + } + builder.WriteString(line) + addedLine = true + } + if err := scanner.Err(); err != nil { + return input + } + return builder.String() +} + +func isEnvLine(line string) bool { + trimmed := strings.TrimSpace(line) + if trimmed == "" { + return true + } + idx := strings.IndexRune(trimmed, '=') + if idx <= 0 { + return false + } + key := trimmed[:idx] + for i, r := range key { + if i == 0 { + if r != '_' && !unicode.IsLetter(r) { + return false + } + continue + } + if r != '_' && !unicode.IsLetter(r) && !unicode.IsDigit(r) { + return false + } + } + return true +}