133 lines
4.7 KiB
Go
133 lines
4.7 KiB
Go
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), "../.."))
|
|
realGit, err := exec.LookPath("git")
|
|
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)
|
|
}
|
|
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)
|
|
}
|
|
query := exec.Command(realGit, "ls-remote", "--refs", "--", remote, "refs/tags/v1.2.3")
|
|
query.Dir = repository
|
|
found, err := query.Output()
|
|
if err != nil || len(found) == 0 {
|
|
t.Fatalf("captured endpoint lost published tag: %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)
|
|
}
|
|
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)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|