Add shared CI delivery command

This commit is contained in:
2026-10-06 19:26:54 +00:00
parent d970aac709
commit c6a5db8aeb
8 changed files with 338 additions and 26 deletions

View File

@@ -325,6 +325,145 @@ func TestDeliverBuildsTaggedArtifactsAndReusesAssets(t *testing.T) {
}
}
func TestCIDeliverLoadsTaggedProfileAndSkipsUnavailablePageOnlyDependencies(t *testing.T) {
repository := newCLIRepository(t)
writeRepositoryFile(t, repository, "go.mod", "module example.com/cli-candidate\n\ngo 1.25.0\n\nrequire example.com/unavailable/module v1.2.3\n")
cliGitRun(t, repository, "add", "go.mod")
cliGitRun(t, repository, "commit", "-m", "declare unavailable dependency")
state := &deliveryServerState{}
server := newDeliveryServer(t, state)
defer server.Close()
writeDeliveryProfileAt(t, repository, "profiles/ci-delivery.json", cli.Settings{
Product: "Example Product",
Delivery: &cli.DeliverySettings{BaseURL: server.URL, Owner: "owner", Repository: "example"},
})
expectedCommit := pushTaggedCLIRepository(t, repository)
state.commit = expectedCommit
writeDeliveryProfileAt(t, repository, "profiles/ci-delivery.json", cli.Settings{Product: "Later Branch Profile"})
t.Setenv("RELEASEKIT_GITEA_TOKEN", "fixture-token")
t.Setenv("GOPROXY", "off")
t.Setenv("GOSUMDB", "off")
var stdout, stderr bytes.Buffer
args := []string{"ci-deliver", "--repo", repository, "--config", "profiles/ci-delivery.json", "--commit", expectedCommit, "v1.2.3"}
if status := run(context.Background(), args, &stdout, &stderr); status != 0 {
t.Fatalf("run() status=%d stdout=%q stderr=%q", status, stdout.String(), stderr.String())
}
if state.releaseCreates != 1 || state.apiRequests == 0 {
t.Fatalf("page delivery did not reach the server: creates=%d requests=%d", state.releaseCreates, state.apiRequests)
}
if got := cliGitOutput(t, repository, "rev-parse", "HEAD"); got != expectedCommit {
t.Fatalf("prepared HEAD = %s, want %s", got, expectedCommit)
}
}
func TestCIDeliverRejectsWrongCommitBeforeGoOrHostedRequests(t *testing.T) {
repository := newCLIRepository(t)
writeRepositoryFile(t, repository, "go.mod", "module example.com/cli-candidate\n\ngo 1.25.0\n\nrequire example.com/unavailable/module v1.2.3\n")
cliGitRun(t, repository, "add", "go.mod")
cliGitRun(t, repository, "commit", "-m", "declare unavailable dependency")
state := &deliveryServerState{}
server := newDeliveryServer(t, state)
defer server.Close()
writeDeliveryProfile(t, repository, cli.Settings{
Product: "Example Product",
Build: &cli.BuildSettings{MainPackage: ".", BinaryName: "helper", Targets: []string{"linux/amd64"}},
Delivery: &cli.DeliverySettings{BaseURL: server.URL, Owner: "owner", Repository: "example"},
})
expectedCommit := pushTaggedCLIRepository(t, repository)
state.commit = expectedCommit
shimDir := t.TempDir()
markerPath := filepath.Join(shimDir, "go-invoked")
goShim := "#!/bin/sh\n: > \"$RELEASEKIT_GO_MARKER\"\nexit 99\n"
if err := os.WriteFile(filepath.Join(shimDir, "go"), []byte(goShim), 0o700); err != nil {
t.Fatal(err)
}
t.Setenv("RELEASEKIT_GO_MARKER", markerPath)
t.Setenv("PATH", shimDir+string(os.PathListSeparator)+os.Getenv("PATH"))
t.Setenv("RELEASEKIT_GITEA_TOKEN", "fixture-token")
var stdout, stderr bytes.Buffer
wrongCommit := strings.Repeat("0", 40)
args := []string{"ci-deliver", "--repo", repository, "--commit", wrongCommit, "v1.2.3"}
if status := run(context.Background(), args, &stdout, &stderr); status != 1 {
t.Fatalf("run() status=%d stdout=%q stderr=%q, want preparation failure", status, stdout.String(), stderr.String())
}
if !strings.Contains(stderr.String(), "resolves to commit") {
t.Fatalf("stderr=%q, want expected-commit mismatch", stderr.String())
}
if _, err := os.Stat(markerPath); !os.IsNotExist(err) {
t.Fatalf("Go was invoked before commit agreement: %v", err)
}
if state.apiRequests != 0 {
t.Fatalf("hosted API requests = %d, want 0", state.apiRequests)
}
}
func TestCIDeliverPreparesDependenciesAndBuildsConfiguredTargets(t *testing.T) {
repository := newDeliveryBuildRepository(t)
state := &deliveryServerState{}
server := newDeliveryServer(t, state)
defer server.Close()
writeDeliveryProfile(t, repository, cli.Settings{
Product: "Example Product",
Build: &cli.BuildSettings{MainPackage: ".", BinaryName: "helper", Targets: []string{fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)}},
Delivery: &cli.DeliverySettings{BaseURL: server.URL, Owner: "owner", Repository: "example"},
})
expectedCommit := pushTaggedCLIRepository(t, repository)
state.commit = expectedCommit
t.Setenv("RELEASEKIT_GITEA_TOKEN", "fixture-token")
var stdout, stderr bytes.Buffer
args := []string{"ci-deliver", "--repo", repository, "--commit", expectedCommit, "v1.2.3"}
if status := run(context.Background(), args, &stdout, &stderr); status != 0 {
t.Fatalf("run() status=%d stdout=%q stderr=%q", status, stdout.String(), stderr.String())
}
if state.releaseCreates != 1 || state.assetUploads != 2 {
t.Fatalf("delivery counts = creates:%d uploads:%d", state.releaseCreates, state.assetUploads)
}
if _, ok := state.assets["helper-v1.2.3-"+runtime.GOOS+"-"+runtime.GOARCH]; !ok {
t.Fatalf("binary not uploaded: %#v", state.assets)
}
}
func TestCIDeliverValidatesCredentialsBeforePreparingDependencies(t *testing.T) {
repository := newDeliveryBuildRepository(t)
state := &deliveryServerState{}
server := newDeliveryServer(t, state)
defer server.Close()
writeDeliveryProfile(t, repository, cli.Settings{
Product: "Example Product",
Build: &cli.BuildSettings{MainPackage: ".", BinaryName: "helper", Targets: []string{"linux/amd64"}},
Delivery: &cli.DeliverySettings{BaseURL: server.URL, Owner: "owner", Repository: "example"},
})
expectedCommit := pushTaggedCLIRepository(t, repository)
state.commit = expectedCommit
shimDir := t.TempDir()
markerPath := filepath.Join(shimDir, "go-invoked")
goShim := "#!/bin/sh\n: > \"$RELEASEKIT_GO_MARKER\"\nexit 99\n"
if err := os.WriteFile(filepath.Join(shimDir, "go"), []byte(goShim), 0o700); err != nil {
t.Fatal(err)
}
t.Setenv("RELEASEKIT_GO_MARKER", markerPath)
t.Setenv("PATH", shimDir+string(os.PathListSeparator)+os.Getenv("PATH"))
t.Setenv("RELEASEKIT_GITEA_TOKEN", "")
var stdout, stderr bytes.Buffer
args := []string{"ci-deliver", "--repo", repository, "--commit", expectedCommit, "v1.2.3"}
if status := run(context.Background(), args, &stdout, &stderr); status != 2 {
t.Fatalf("run() status=%d stdout=%q stderr=%q, want credential error", status, stdout.String(), stderr.String())
}
if !strings.Contains(stderr.String(), "non-empty token") {
t.Fatalf("stderr=%q, want missing-credential error", stderr.String())
}
if _, err := os.Stat(markerPath); !os.IsNotExist(err) {
t.Fatalf("Go was invoked before credential validation: %v", err)
}
if state.apiRequests != 0 {
t.Fatalf("hosted API requests = %d, want 0", state.apiRequests)
}
}
func TestDeliverRejectsInvalidTaggedSourceBeforeManagedBuild(t *testing.T) {
repository := newDeliveryBuildRepository(t)
state := &deliveryServerState{}
@@ -701,15 +840,23 @@ func writeDeliveryRelease(w http.ResponseWriter, serverURL string, state *delive
}
func writeDeliveryProfile(t *testing.T, repository string, settings cli.Settings) {
writeDeliveryProfileAt(t, repository, "releasekit.json", settings)
}
func writeDeliveryProfileAt(t *testing.T, repository, name string, settings cli.Settings) {
t.Helper()
contents, err := json.Marshal(settings)
if err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(repository, "releasekit.json"), contents, 0o600); err != nil {
path := filepath.Join(repository, filepath.FromSlash(name))
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
t.Fatal(err)
}
cliGitRun(t, repository, "add", "releasekit.json")
if err := os.WriteFile(path, contents, 0o600); err != nil {
t.Fatal(err)
}
cliGitRun(t, repository, "add", name)
cliGitRun(t, repository, "commit", "-m", "configure delivery")
}
@@ -779,6 +926,28 @@ func cliGitRun(t *testing.T, repository string, args ...string) {
}
}
func writeRepositoryFile(t *testing.T, repository, name, contents string) {
t.Helper()
path := filepath.Join(repository, filepath.FromSlash(name))
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(path, []byte(contents), 0o600); err != nil {
t.Fatal(err)
}
}
func pushTaggedCLIRepository(t *testing.T, repository string) string {
t.Helper()
cliGitRun(t, repository, "tag", "v1.2.3")
commit := cliGitOutput(t, repository, "rev-parse", "v1.2.3^{commit}")
remote := filepath.Join(t.TempDir(), "origin.git")
cliGitRun(t, repository, "init", "--bare", remote)
cliGitRun(t, repository, "remote", "add", "origin", remote)
cliGitRun(t, repository, "push", "origin", "refs/tags/v1.2.3")
return commit
}
func cliGitOutput(t *testing.T, repository string, args ...string) string {
t.Helper()
commandArgs := append([]string{"git"}, args...)