releaseflow_promote_shell_test.go
Rama main · réplica de lectura del repositorio original.
package main
import (
"errors"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
// dockerStub stands in for `docker buildx imagetools`. DOCKER_STUB_MODE picks
// what the registry appears to say:
//
// ok - both tags resolve to the same digest (a successful promote)
// mismatch - the floating tag resolves elsewhere (the move did not land)
// fail - inspect cannot read the registry at all (auth, outage, typo)
//
// `create` always succeeds: the question under test is whether the VERIFY step
// believes it.
const dockerStub = `#!/bin/sh
echo "$*" >> "$DOCKER_STUB_LOG"
case "$3" in
create) exit 0 ;;
esac
case "$DOCKER_STUB_MODE" in
ok) echo '"sha256:aaaa"'; exit 0 ;;
mismatch)
case "$*" in
*latest*) echo '"sha256:bbbb"'; exit 0 ;;
*) echo '"sha256:aaaa"'; exit 0 ;;
esac ;;
fail) echo "error: failed to read registry" >&2; exit 1 ;;
esac
echo "docker stub: unknown mode" >&2
exit 99
`
// runStepUnderRunnerShell runs a workflow step the way the RUNNER does: GitHub's
// default for `run:` on Linux is `bash -e {0}` - NO pipefail. The older harness
// added pipefail, which is stricter than production and would have made a
// pipeline whose failure is swallowed by its last command look safe.
func runStepUnderRunnerShell(t *testing.T, script, dockerMode, tag string) (int, string, []string) {
t.Helper()
dir := t.TempDir()
scriptPath := filepath.Join(dir, "step.sh")
if err := os.WriteFile(scriptPath, []byte(script), 0o644); err != nil {
t.Fatal(err)
}
stubDir := filepath.Join(dir, "bin")
if err := os.Mkdir(stubDir, 0o755); err != nil {
t.Fatal(err)
}
logPath := filepath.Join(dir, "docker.log")
if err := os.WriteFile(filepath.Join(stubDir, "docker"), []byte(dockerStub), 0o755); err != nil {
t.Fatal(err)
}
cmd := exec.Command("bash", "--noprofile", "--norc", "-e", scriptPath)
cmd.Env = append(os.Environ(),
"PATH="+stubDir+string(os.PathListSeparator)+os.Getenv("PATH"),
"GITHUB_REF_NAME="+tag,
"GORELEASER_CURRENT_TAG="+tag,
"DOCKER_STUB_MODE="+dockerMode,
"DOCKER_STUB_LOG="+logPath,
)
out, err := cmd.CombinedOutput()
code := 0
if err != nil {
var ee *exec.ExitError
if !errors.As(err, &ee) {
t.Fatalf("running step: %v\n%s", err, out)
}
code = ee.ExitCode()
}
var calls []string
if b, rerr := os.ReadFile(logPath); rerr == nil {
for _, l := range strings.Split(strings.TrimSpace(string(b)), "\n") {
if l != "" {
calls = append(calls, l)
}
}
}
return code, string(out), calls
}
// A verification step that cannot fail is worse than none, because it gets
// quoted as evidence. Reading the two digests with a bare pipeline made both
// reads return the empty string when the registry was unreadable - and two
// empty strings compare equal, so the step announced a verified promotion it
// had not checked. `set -e` does not save it: the pipeline's status is `tr`'s.
func TestPromoteFailsWhenTheRegistryCannotBeRead(t *testing.T) {
script := extractRunBlock(t, mustReadRepoFile(t, releaseWorkflowPath), "Promote the floating tags (stable only)")
code, out, _ := runStepUnderRunnerShell(t, script, "fail", "v0.62.0")
if code == 0 {
t.Fatalf("the promote step reported success while it could not read a single digest:\n%s", out)
}
}
// The check must still catch the thing it exists for: a floating tag that did
// not actually move to the attested digest.
func TestPromoteFailsWhenTheTagDidNotMove(t *testing.T) {
script := extractRunBlock(t, mustReadRepoFile(t, releaseWorkflowPath), "Promote the floating tags (stable only)")
code, out, _ := runStepUnderRunnerShell(t, script, "mismatch", "v0.62.0")
if code == 0 {
t.Fatalf("a floating tag pointing somewhere else was accepted:\n%s", out)
}
if !strings.Contains(out, "did not move") {
t.Errorf("the failure does not say what went wrong:\n%s", out)
}
}
// And the happy path must promote BOTH tags and verify BOTH.
func TestPromoteMovesBothTagsAndVerifiesThem(t *testing.T) {
script := extractRunBlock(t, mustReadRepoFile(t, releaseWorkflowPath), "Promote the floating tags (stable only)")
code, out, calls := runStepUnderRunnerShell(t, script, "ok", "v0.62.0")
if code != 0 {
t.Fatalf("a clean promote exited %d:\n%s", code, out)
}
var created, inspected int
for _, c := range calls {
if strings.Contains(c, "create") {
created++
}
if strings.Contains(c, "inspect") {
inspected++
}
}
if created != 2 {
t.Errorf("moved %d tags, want 2 (latest and latest-iperf)", created)
}
if inspected != 4 {
t.Errorf("made %d digest reads, want 4 (both tags, both sides of the comparison)", inspected)
}
}