Run consumer release commands through Go tools
This commit is contained in:
@@ -2,11 +2,13 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@@ -80,20 +82,13 @@ func TestMultiModuleLauncherUsesSelectedModuleAndProfile(t *testing.T) {
|
||||
set -eu
|
||||
printf 'cwd=%s args=%s\n' "$PWD" "$*" >> "$RELEASEKIT_TEST_GO_LOG"
|
||||
modfile=
|
||||
output=
|
||||
previous=
|
||||
for argument in "$@"; do
|
||||
case "$argument" in -modfile=*) modfile=${argument#-modfile=} ;; esac
|
||||
if [ "$previous" = -o ]; then output=$argument; fi
|
||||
previous=$argument
|
||||
done
|
||||
if [ -n "$modfile" ]; then cat "$modfile" >> "$RELEASEKIT_TEST_GO_LOG"; fi
|
||||
if [ "$1" = build ]; then
|
||||
cat > "$output" <<'TOOL'
|
||||
#!/bin/sh
|
||||
printf '<%s>\n' "$@" > "$RELEASEKIT_TEST_TOOL_ARGS"
|
||||
TOOL
|
||||
chmod +x "$output"
|
||||
if [ "$1" = tool ]; then
|
||||
shift 3
|
||||
printf '<%s>\n' "$@" > "$RELEASEKIT_TEST_TOOL_ARGS"
|
||||
fi
|
||||
`
|
||||
if err := os.WriteFile(filepath.Join(shimDir, "go"), []byte(shim), 0o700); err != nil {
|
||||
@@ -134,7 +129,7 @@ fi
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultiModuleLauncherBuildsToolFromSelectedDependency(t *testing.T) {
|
||||
func TestMultiModuleLauncherRunsToolFromSelectedDependency(t *testing.T) {
|
||||
example := filepath.Join(cliRepositoryRoot(t), "examples", "multi-module")
|
||||
repository := newCLIRepository(t)
|
||||
copyExampleTree(t, example, repository)
|
||||
@@ -161,27 +156,50 @@ func TestMultiModuleLauncherBuildsToolFromSelectedDependency(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
command := exec.Command(filepath.Join(repository, "release.sh"), "ckconfig", "v1.2.3")
|
||||
output, err := command.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("launcher error: %v output=%q", err, output)
|
||||
}
|
||||
for _, expected := range []string{
|
||||
"tool-version=v0.2.198 helper=tool-only dependency",
|
||||
`"publish"`, `"--repo"`, `"` + repository + `"`,
|
||||
`"--config"`, `"releasekit-ckconfig.json"`,
|
||||
`"--expected-module"`, `"integrations/ckconfig"`, `"v1.2.3"`,
|
||||
} {
|
||||
if !strings.Contains(string(output), expected) {
|
||||
t.Errorf("launcher output %q omits %q", output, expected)
|
||||
}
|
||||
}
|
||||
if strings.Contains(string(output), "tool-version=v0.2.197") {
|
||||
t.Fatalf("launcher built the root-selected ReleaseKit version: %s", output)
|
||||
}
|
||||
moduleAfter, err := os.ReadFile(filepath.Join(repository, "integrations", "ckconfig", "go.mod"))
|
||||
if err != nil || !bytes.Equal(moduleAfter, moduleBefore) {
|
||||
t.Fatalf("selected module go.mod changed: got %q want %q error=%v", moduleAfter, moduleBefore, err)
|
||||
for _, status := range []int{0, 1, 2, 3} {
|
||||
t.Run(strconv.Itoa(status), func(t *testing.T) {
|
||||
command := exec.Command(filepath.Join(repository, "release.sh"), "ckconfig", "v1.2.3")
|
||||
command.Env = setEnvironment(os.Environ(), "RELEASEKIT_TOOL_EXIT", strconv.Itoa(status))
|
||||
output, err := command.CombinedOutput()
|
||||
if status == 0 && err != nil {
|
||||
t.Fatalf("launcher error: %v output=%q", err, output)
|
||||
}
|
||||
if status != 0 {
|
||||
var exitError *exec.ExitError
|
||||
if !errors.As(err, &exitError) || exitError.ExitCode() != status {
|
||||
t.Fatalf("launcher error = %v, want exit %d; output=%q", err, status, output)
|
||||
}
|
||||
}
|
||||
for _, expected := range []string{
|
||||
"tool-version=v0.2.198 helper=tool-only dependency",
|
||||
`"publish"`, `"--repo"`, `"` + repository + `"`,
|
||||
`"--config"`, `"releasekit-ckconfig.json"`,
|
||||
`"--expected-module"`, `"integrations/ckconfig"`, `"v1.2.3"`,
|
||||
} {
|
||||
if !strings.Contains(string(output), expected) {
|
||||
t.Errorf("launcher output %q omits %q", output, expected)
|
||||
}
|
||||
}
|
||||
if strings.Contains(string(output), "tool-version=v0.2.197") {
|
||||
t.Fatalf("launcher ran the root-selected ReleaseKit version: %s", output)
|
||||
}
|
||||
moduleAfter, err := os.ReadFile(filepath.Join(repository, "integrations", "ckconfig", "go.mod"))
|
||||
if err != nil || !bytes.Equal(moduleAfter, moduleBefore) {
|
||||
t.Fatalf("selected module go.mod changed: got %q want %q error=%v", moduleAfter, moduleBefore, err)
|
||||
}
|
||||
if status := cliGitOutput(t, repository, "status", "--porcelain", "--untracked-files=all"); status != "" {
|
||||
t.Fatalf("launcher changed source: %q", status)
|
||||
}
|
||||
entries, err := os.ReadDir(filepath.Dir(repository))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, entry := range entries {
|
||||
if strings.HasPrefix(entry.Name(), ".releasekit-bootstrap.") {
|
||||
t.Fatalf("temporary bootstrap directory remains: %s", entry.Name())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -236,6 +236,26 @@ func TestWoodpeckerTagDeliveryUsesTaggedModuleVersion(t *testing.T) {
|
||||
assertToolOnlyChecksums(t, sumLog)
|
||||
})
|
||||
|
||||
t.Run("vendored tool dependency", func(t *testing.T) {
|
||||
goDir, goLog := installGoBootstrapShim(t)
|
||||
repository := newCLIRepository(t)
|
||||
const module = "go.maximumdirect.net/releasekit"
|
||||
writeRepositoryFile(t, repository, "go.mod", "module example.com/cli-candidate\n\ngo 1.25.0\n\nrequire "+module+" v0.2.197\n\ntool "+module+"/cmd/releasekit\n")
|
||||
env := templateEnvironment(repository, "", goDir, goLog)
|
||||
useSyntheticModuleProxy(t, env, "file://"+filepath.ToSlash(proxy))
|
||||
runWoodpeckerBlock(t, "go mod tidy\ngo mod vendor", repository, env)
|
||||
cliGitRun(t, repository, "add", "go.mod", "go.sum", "vendor")
|
||||
cliGitRun(t, repository, "commit", "-m", "vendor the selected release tool")
|
||||
env["CI_COMMIT_SHA"] = pushTaggedCLIRepository(t, repository)
|
||||
moduleBefore := readWoodpeckerFixtureFile(t, filepath.Join(repository, "go.mod"))
|
||||
sumBefore := readWoodpeckerFixtureFile(t, filepath.Join(repository, "go.sum"))
|
||||
output := runWoodpeckerBlock(t, command, repository, env)
|
||||
if !strings.Contains(output, "tool-version=v0.2.197 helper=tool-only dependency") {
|
||||
t.Fatalf("vendored tool was not selected: %q", output)
|
||||
}
|
||||
assertModuleBootstrap(t, repository, goLog, moduleBefore, sumBefore)
|
||||
})
|
||||
|
||||
t.Run("versioned replacement selects its declared source", func(t *testing.T) {
|
||||
goDir, goLog := installGoBootstrapShim(t)
|
||||
repository := newCLIRepository(t)
|
||||
@@ -400,7 +420,7 @@ func installGoBootstrapShim(t *testing.T) (string, string) {
|
||||
printf 'cwd=%s GOWORK=%s GOTOOLCHAIN=%s %s\n' "$PWD" "$GOWORK" "$GOTOOLCHAIN" "$*" >> "$RELEASEKIT_GO_LOG"
|
||||
"$RELEASEKIT_REAL_GO" "$@"
|
||||
status=$?
|
||||
if [ "$status" -eq 0 ] && [ "$1" = "build" ] && [ -n "${RELEASEKIT_SUM_LOG:-}" ]; then
|
||||
if [ "$status" -eq 0 ] && [ "$1" = "tool" ] && [ -n "${RELEASEKIT_SUM_LOG:-}" ]; then
|
||||
modfile=
|
||||
for argument in "$@"; do
|
||||
case "$argument" in -modfile=*) modfile=${argument#-modfile=} ;; esac
|
||||
@@ -433,20 +453,12 @@ case "$1" in
|
||||
list)
|
||||
printf '%s v0.2.0\n' "$RELEASEKIT_MODULE"
|
||||
;;
|
||||
build)
|
||||
output=
|
||||
previous=
|
||||
for argument in "$@"; do
|
||||
if [ "$previous" = "-o" ]; then output=$argument; break; fi
|
||||
previous=$argument
|
||||
done
|
||||
[ -n "$output" ] || { echo 'go build omitted output path' >&2; exit 90; }
|
||||
cat > "$output" <<'TOOL'
|
||||
#!/bin/sh
|
||||
printf '<%s>\n' "$@" > "$RELEASEKIT_TOOL_ARGS_LOG"
|
||||
exit "${RELEASEKIT_TOOL_EXIT:-0}"
|
||||
TOOL
|
||||
chmod +x "$output"
|
||||
mod)
|
||||
;;
|
||||
tool)
|
||||
shift 3
|
||||
printf '<%s>\n' "$@" > "$RELEASEKIT_TOOL_ARGS_LOG"
|
||||
exit "${RELEASEKIT_TOOL_EXIT:-0}"
|
||||
;;
|
||||
*)
|
||||
echo "unexpected Go command: $1" >&2
|
||||
@@ -532,7 +544,7 @@ func writeReleaseKitModuleProxy(t *testing.T) string {
|
||||
toolModule := "module " + module + "\n\ngo 1.25.0\n\nrequire " + toolDependency + " v1.0.0\n"
|
||||
for _, version := range []string{"v0.2.197", "v0.2.198"} {
|
||||
files := map[string]string{
|
||||
"cmd/releasekit/main.go": "package main\n\nimport (\"fmt\"; \"os\"; tooldep \"example.com/releasekit-helper\")\n\nfunc main() {\n\tfmt.Println(\"tool-version=" + version + " helper=\" + tooldep.Version)\n\tfmt.Printf(\"tool-args=%q\\n\", os.Args[1:])\n}\n",
|
||||
"cmd/releasekit/main.go": "package main\n\nimport (\"fmt\"; \"os\"; \"strconv\"; tooldep \"example.com/releasekit-helper\")\n\nfunc main() {\n\tfmt.Println(\"tool-version=" + version + " helper=\" + tooldep.Version)\n\tfmt.Printf(\"tool-args=%q\\n\", os.Args[1:])\n\tstatus, _ := strconv.Atoi(os.Getenv(\"RELEASEKIT_TOOL_EXIT\"))\n\tos.Exit(status)\n}\n",
|
||||
}
|
||||
writeModuleProxyVersion(t, proxyDir, module, version, toolModule, files)
|
||||
}
|
||||
@@ -633,16 +645,16 @@ func assertGoSelection(t *testing.T, repository, goLog string) {
|
||||
t.Helper()
|
||||
log := readWoodpeckerFixtureFile(t, goLog)
|
||||
list := "list -mod=mod -modfile="
|
||||
build := "build -mod=mod -modfile="
|
||||
tool := "tool -modfile="
|
||||
module := "go.maximumdirect.net/releasekit"
|
||||
if !strings.Contains(log, "GOWORK=off GOTOOLCHAIN=local") || !strings.Contains(log, list) || !strings.Contains(log, "-m "+module) {
|
||||
t.Fatalf("Go module selection command is missing required settings: %q", log)
|
||||
}
|
||||
if !strings.Contains(log, build) || !strings.Contains(log, module+"/cmd/releasekit") || strings.Contains(log, "@v0.2.0") {
|
||||
t.Fatalf("Go build did not use the selected module without a version suffix: %q", log)
|
||||
if !strings.Contains(log, tool) || !strings.Contains(log, " releasekit ci-deliver ") || strings.Contains(log, "@v0.2.0") {
|
||||
t.Fatalf("Go tool did not run the module-selected ReleaseKit: %q", log)
|
||||
}
|
||||
if strings.Index(log, list) > strings.Index(log, build) {
|
||||
t.Fatalf("Go build ran before module selection: %q", log)
|
||||
if strings.Index(log, list) > strings.Index(log, tool) {
|
||||
t.Fatalf("Go tool ran before module selection: %q", log)
|
||||
}
|
||||
var modfile string
|
||||
for _, field := range strings.Fields(log) {
|
||||
|
||||
Reference in New Issue
Block a user