package main import ( "encoding/json" "fmt" "os" "os/exec" "path/filepath" "runtime" "strings" "testing" ) func TestReleaseWrapperPreservesNativeExitStatuses(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("POSIX release entry point") } _, source, _, _ := runtime.Caller(0) root := filepath.Clean(filepath.Join(filepath.Dir(source), "../..")) originalPath := os.Getenv("PATH") realGit, err := exec.LookPath("git") if err != nil { t.Fatal(err) } controller, err := os.ReadFile(filepath.Join(root, "cmd/releasekit/main.go")) if err != nil { t.Fatal(err) } wrapper, err := os.ReadFile(filepath.Join(root, "scripts/release")) if err != nil { t.Fatal(err) } for _, mode := range []struct { name string status int version string }{{"success", 0, "v1.2.3"}, {"invalid", 2, "invalid"}, {"rejected", 1, "v1.2.3"}, {"unknown", 3, "v1.2.3"}} { t.Run(mode.name, func(t *testing.T) { repository := filepath.Join(t.TempDir(), "source") clone := exec.Command(realGit, "clone", "--local", "--no-hardlinks", root, repository) if output, err := clone.CombinedOutput(); err != nil { t.Fatalf("clone: %v %s", err, output) } cliGitRun(t, repository, "config", "user.name", "ReleaseKit Test") cliGitRun(t, repository, "config", "user.email", "fixture@example.test") cliGitRun(t, repository, "config", "commit.gpgsign", "false") if err := os.WriteFile(filepath.Join(repository, "scripts/release"), wrapper, 0755); err != nil { t.Fatal(err) } // Exercise the current controller, including changes awaiting this commit. if err := os.WriteFile(filepath.Join(repository, "cmd/releasekit/main.go"), controller, 0600); err != nil { t.Fatal(err) } if err := os.MkdirAll(filepath.Join(repository, "docs/releases"), 0700); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(repository, "docs/releases/v1.2.3.md"), []byte("# ReleaseKit v1.2.3\n"), 0600); err != nil { t.Fatal(err) } profile := map[string]any{"product": "ReleaseKit", "checks": []map[string]any{{"args": []string{"sh", "-c", "true"}}}} content, _ := json.Marshal(profile) if err := os.WriteFile(filepath.Join(repository, "releasekit.json"), content, 0600); err != nil { t.Fatal(err) } cliGitRun(t, repository, "add", "--all") cliGitRun(t, repository, "commit", "-m", "prepare wrapper fixture") remote := filepath.Join(t.TempDir(), "origin.git") cliGitRun(t, repository, "init", "--bare", remote) cliGitRun(t, repository, "remote", "set-url", "origin", remote) cliGitRun(t, repository, "push", "origin", "HEAD:refs/heads/main") fetch := filepath.Join(t.TempDir(), "fetch.git") cliGitRun(t, repository, "init", "--bare", fetch) cliGitRun(t, repository, "remote", "set-url", "origin", fetch) cliGitRun(t, repository, "remote", "set-url", "--push", "origin", remote) if mode.name == "rejected" { if err := os.WriteFile(filepath.Join(remote, "hooks/pre-receive"), []byte("#!/bin/sh\nexit 1\n"), 0755); err != nil { t.Fatal(err) } } if mode.name == "unknown" { bin := t.TempDir() marker := filepath.Join(bin, "push-started") shim := `#!/bin/sh for arg do if [ "$arg" = push ]; then "$RELEASEKIT_TEST_REAL_GIT" "$@" || exit 1 "$RELEASEKIT_TEST_REAL_GIT" remote set-url --push origin "$RELEASEKIT_TEST_MOVED_ENDPOINT" : > "$RELEASEKIT_TEST_PUSH_MARKER" exit 1 fi done if [ -f "$RELEASEKIT_TEST_PUSH_MARKER" ]; then for arg do if [ "$arg" = ls-remote ]; then exit 128; fi; done fi exec "$RELEASEKIT_TEST_REAL_GIT" "$@" ` if err := os.WriteFile(filepath.Join(bin, "git"), []byte(shim), 0755); err != nil { t.Fatal(err) } t.Setenv("PATH", bin+string(os.PathListSeparator)+os.Getenv("PATH")) t.Setenv("RELEASEKIT_TEST_REAL_GIT", realGit) t.Setenv("RELEASEKIT_TEST_PUSH_MARKER", marker) t.Setenv("RELEASEKIT_TEST_MOVED_ENDPOINT", fetch) } command := exec.Command("./scripts/release", mode.version) command.Dir = repository output, err := command.CombinedOutput() status := 0 if err != nil { exit, ok := err.(*exec.ExitError) if !ok { t.Fatal(err) } status = exit.ExitCode() } if status != mode.status { t.Fatalf("status=%d want=%d output=%s", status, mode.status, output) } if mode.name == "unknown" { if !strings.Contains(string(output), fmt.Sprintf("endpoint=%q", remote)) { t.Fatalf("captured endpoint missing: %s", output) } t.Setenv("PATH", originalPath) // Execute the runbook's guarded recovery commands verbatim. recovery := `test "$(git ls-remote --get-url -- "$releasekit_endpoint")" = "$releasekit_endpoint" && git ls-remote --refs -- "$releasekit_endpoint" "refs/tags/$releasekit_version"` query := exec.Command("sh", "-c", recovery) query.Dir = repository query.Env = append(os.Environ(), "releasekit_endpoint="+remote, "releasekit_version=v1.2.3") found, err := query.Output() if err != nil || len(found) == 0 { t.Fatalf("captured endpoint recovery failed: %q %v", found, err) } if !strings.Contains(string(found), cliGitOutput(t, repository, "rev-parse", "refs/tags/v1.2.3")) { t.Fatalf("wrong recovered tag: %s", found) } cliGitRun(t, repository, "config", "url."+fetch+".insteadOf", remote) blocked := exec.Command("sh", "-c", recovery) blocked.Dir = repository blocked.Env = query.Env if output, err := blocked.Output(); err == nil || len(output) != 0 { t.Fatalf("rewritten endpoint should block query: %q %v", output, err) } fetchQuery := exec.Command(realGit, "ls-remote", "--refs", "origin", "refs/tags/v1.2.3") fetchQuery.Dir = repository stale, err := fetchQuery.Output() if err != nil || len(stale) != 0 { t.Fatalf("fetch fixture unexpectedly found tag: %q %v", stale, err) } } }) } }