feat: auto-update app-dono-cliente when a new image is pushed to :latest

Adds a StepRunUpdater step that starts app-dono-updater after the app
container comes up: a poll loop (docker pull, compare image IDs,
recreate on change) baked into the official docker:cli image via
`sh -c`, reusing the same docker run argv as the initial container
start so the two can't drift.

Not built on Watchtower: containrrr/watchtower was archived upstream
in Dec 2025 with no maintained successor recommended for production
use, so this avoids taking on that dependency.
This commit is contained in:
2026-08-26 12:30:44 -03:00
parent ef126eaf61
commit a05b98fdf5
8 changed files with 244 additions and 18 deletions
+41
View File
@@ -0,0 +1,41 @@
package tui
import (
"os/exec"
"reflect"
"strings"
"testing"
)
// TestShellQuoteArgsRoundTrip guards the updater's poll-script generation: cv fields
// (e.g. cert_dir_path) are operator-entered and get embedded into a shell script run
// inside the updater container. If shellQuote/shellQuoteArgs mis-escapes a value, that's
// a command-injection bug, not just a cosmetic one. This feeds tricky values through a
// real `sh` and checks they come back out exactly as they went in.
func TestShellQuoteArgsRoundTrip(t *testing.T) {
if _, err := exec.LookPath("sh"); err != nil {
t.Skip("sh not available")
}
cases := [][]string{
{"simple"},
{"has space"},
{"it's got a quote"},
{"$(echo injected)"},
{"a;b|c&d"},
{"back`tick`"},
{"multi", "arg space", "o'clock", "$HOME", "'"},
}
for _, args := range cases {
script := "printf '%s\\n' " + shellQuoteArgs(args)
out, err := exec.Command("sh", "-c", script).Output()
if err != nil {
t.Fatalf("sh failed for %v: %v", args, err)
}
got := strings.Split(strings.TrimRight(string(out), "\n"), "\n")
if !reflect.DeepEqual(got, args) {
t.Errorf("round trip mismatch for %v: got %v", args, got)
}
}
}