Map CLI profiles to selected modules
This commit is contained in:
@@ -51,6 +51,13 @@ func TestUnknownCommand(t *testing.T) {
|
||||
func TestCheckCommandBindsConfiguredChecksToCapturedCandidate(t *testing.T) {
|
||||
raceSelected := racePrerequisitesAvailable()
|
||||
repository := newCLIRepository(t)
|
||||
moduleDir := filepath.Join(repository, "integrations", "ckconfig")
|
||||
writeRepositoryFile(t, repository, "integrations/ckconfig/go.mod", "module example.com/ckconfig\n\ngo 1.25.0\n")
|
||||
writeRepositoryFile(t, repository, "integrations/ckconfig/docs/releases/v1.2.3.md", "# Example Product v1.2.3\n\nNested release note.\n")
|
||||
writeRepositoryFile(t, repository, "integrations/ckconfig/fixture_test.go", "package ckconfig\nimport \"testing\"\nfunc TestFixture(t *testing.T) {}\n")
|
||||
writeRepositoryFile(t, repository, "integrations/ckconfig/race_fixture_test.go", "//go:build race\n\npackage ckconfig\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestRaceBuildSelection(t *testing.T) {\n\tmarker := os.Getenv(\"RELEASEKIT_RACE_MARKER\")\n\tif marker == \"\" { return }\n\tif err := os.WriteFile(marker, []byte(\"race enabled\"), 0o600); err != nil { t.Fatal(err) }\n}\n")
|
||||
cliGitRun(t, repository, "add", "integrations/ckconfig")
|
||||
cliGitRun(t, repository, "commit", "-m", "add nested module candidate")
|
||||
profilePath := filepath.Join(t.TempDir(), "profile with spaces.json")
|
||||
orderPath := filepath.Join(t.TempDir(), "check-order")
|
||||
t.Setenv("RELEASEKIT_CHECK_ORDER_FILE", orderPath)
|
||||
@@ -70,9 +77,10 @@ func TestCheckCommandBindsConfiguredChecksToCapturedCandidate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
settings := cli.Settings{
|
||||
Product: "Example Product",
|
||||
Remote: "origin",
|
||||
Checks: []cli.CheckCommand{check("first"), check("second")},
|
||||
Product: "Example Product",
|
||||
ModuleDir: "integrations/ckconfig",
|
||||
Remote: "origin",
|
||||
Checks: []cli.CheckCommand{check("first"), check("second")},
|
||||
}
|
||||
if raceSelected {
|
||||
settings.Validation = &cli.ValidationSettings{Go: cli.GoValidationSettings{Race: true}}
|
||||
@@ -102,7 +110,10 @@ func TestCheckCommandBindsConfiguredChecksToCapturedCandidate(t *testing.T) {
|
||||
if got, want := strings.Count(stderr.String(), "v1.2.3|"+commit), 2; got != want {
|
||||
t.Fatalf("configured checks received captured candidate %d times, want %d; stderr=%q", got, want, stderr.String())
|
||||
}
|
||||
if want := fmt.Sprintf("local candidate v1.2.3 at %s is valid\n", commit); stdout.String() != want {
|
||||
if !strings.Contains(stderr.String(), fmt.Sprintf("%s|%s|%s|example.com/ckconfig|integrations/ckconfig/v1.2.3", moduleDir, repository, moduleDir)) {
|
||||
t.Fatalf("configured checks did not receive the selected module directory and identity: %q", stderr.String())
|
||||
}
|
||||
if want := fmt.Sprintf("local candidate module example.com/ckconfig version v1.2.3 tag integrations/ckconfig/v1.2.3 at %s is valid\n", commit); stdout.String() != want {
|
||||
t.Fatalf("stdout = %q, want %q", stdout.String(), want)
|
||||
}
|
||||
if raceSelected {
|
||||
@@ -154,6 +165,40 @@ func TestCandidateRequestMapsGoValidation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCandidateRequestPreservesModuleAndSharedFileSelection(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
shared []string
|
||||
wantNil bool
|
||||
wantValues []string
|
||||
}{
|
||||
{name: "nil", wantNil: true},
|
||||
{name: "empty", shared: []string{}},
|
||||
{name: "selected", shared: []string{"README.md", "docs/policy.md"}, wantValues: []string{"README.md", "docs/policy.md"}},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
request := candidateRequest(cli.Invocation{Repository: "repository", Version: "v1.2.3"}, cli.Settings{
|
||||
ModuleDir: "integrations/ckconfig",
|
||||
Validation: &cli.ValidationSettings{SharedFiles: test.shared},
|
||||
}, nil)
|
||||
if request.ModuleDir != "integrations/ckconfig" {
|
||||
t.Fatalf("module selection = %q", request.ModuleDir)
|
||||
}
|
||||
if (request.Validation.SharedFiles == nil) != test.wantNil {
|
||||
t.Fatalf("mapped shared_files = %#v, want nil=%t", request.Validation.SharedFiles, test.wantNil)
|
||||
}
|
||||
if len(request.Validation.SharedFiles) != len(test.wantValues) {
|
||||
t.Fatalf("mapped shared_files = %#v, want %#v", request.Validation.SharedFiles, test.wantValues)
|
||||
}
|
||||
for i, path := range test.wantValues {
|
||||
if request.Validation.SharedFiles[i] != path {
|
||||
t.Fatalf("mapped shared_files = %#v, want %#v", request.Validation.SharedFiles, test.wantValues)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidationSpecPreservesMarkdownObjectSelection(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
@@ -172,6 +217,33 @@ func TestValidationSpecPreservesMarkdownObjectSelection(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublishExpectedModuleRejectsMismatchBeforeProductCommands(t *testing.T) {
|
||||
repository := newCLIRepository(t)
|
||||
writeRepositoryFile(t, repository, "integrations/ckconfig/go.mod", "module example.com/ckconfig\n\ngo 1.25.0\n")
|
||||
marker := filepath.Join(t.TempDir(), "product-command-ran")
|
||||
profile, err := json.Marshal(cli.Settings{
|
||||
Product: "Example Product",
|
||||
Checks: []cli.CheckCommand{{Args: []string{"sh", "-c", "touch " + marker}}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
writeRepositoryFile(t, repository, "releasekit.json", string(profile))
|
||||
cliGitRun(t, repository, "add", "releasekit.json", "integrations/ckconfig/go.mod")
|
||||
cliGitRun(t, repository, "commit", "-m", "configure root release profile")
|
||||
var stdout, stderr bytes.Buffer
|
||||
status := run(context.Background(), []string{"publish", "--repo", repository, "--expected-module", "integrations/ckconfig", "v1.2.3"}, &stdout, &stderr)
|
||||
if status != 2 || !strings.Contains(stderr.String(), "profile module selection") {
|
||||
t.Fatalf("publish status=%d stdout=%q stderr=%q, want module-selection error", status, stdout.String(), stderr.String())
|
||||
}
|
||||
if _, err := os.Stat(marker); !os.IsNotExist(err) {
|
||||
t.Fatalf("product command ran despite module mismatch: stat error=%v", err)
|
||||
}
|
||||
if err := exec.Command("git", "-C", repository, "show-ref", "--verify", "refs/tags/v1.2.3").Run(); err == nil {
|
||||
t.Fatal("module mismatch created a release tag")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCandidateCommandsRunMarkdownProfile(t *testing.T) {
|
||||
repository := newCLIRepository(t)
|
||||
profile, err := json.Marshal(cli.Settings{
|
||||
@@ -328,10 +400,10 @@ printf '%s %s\n' "$version" "$candidate" >> "$RELEASEKIT_COMPATIBILITY_LOG"
|
||||
}
|
||||
commit := cliGitOutput(t, repository, "rev-parse", "HEAD")
|
||||
tagObject := cliGitOutput(t, repository, "rev-parse", "refs/tags/v1.2.3")
|
||||
if want := fmt.Sprintf("published v1.2.3 at %s (tag object %s)\n", commit, tagObject); stdout.String() != want {
|
||||
if want := fmt.Sprintf("published v1.2.3 as v1.2.3 at %s (tag object %s)\n", commit, tagObject); stdout.String() != want {
|
||||
t.Fatalf("stdout = %q, want %q", stdout.String(), want)
|
||||
}
|
||||
if !bytes.Contains(stderr.Bytes(), []byte("validating and publishing v1.2.3")) || !bytes.Contains(stderr.Bytes(), []byte("example.com/cli-candidate")) {
|
||||
if !bytes.Contains(stderr.Bytes(), []byte("validating and publishing module . version v1.2.3")) || !bytes.Contains(stderr.Bytes(), []byte("example.com/cli-candidate")) {
|
||||
t.Fatalf("stderr does not show publication progress and validation: %q", stderr.String())
|
||||
}
|
||||
if got := cliGitOutput(t, remote, "rev-parse", "refs/tags/v1.2.3"); got != tagObject {
|
||||
@@ -351,6 +423,47 @@ printf '%s %s\n' "$version" "$candidate" >> "$RELEASEKIT_COMPATIBILITY_LOG"
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildCommandUsesProfileModuleSelection(t *testing.T) {
|
||||
repository := newCLIRepository(t)
|
||||
writeRepositoryFile(t, repository, "integrations/ckconfig/go.mod", "module example.com/ckconfig\n\ngo 1.25.0\n")
|
||||
profile, err := json.Marshal(cli.Settings{
|
||||
Product: "Example Product",
|
||||
ModuleDir: "integrations/ckconfig",
|
||||
Build: &cli.BuildSettings{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
writeRepositoryFile(t, repository, "releasekit.json", string(profile))
|
||||
var stdout, stderr bytes.Buffer
|
||||
status := run(context.Background(), []string{"build", "--repo", repository, "v1.2.3"}, &stdout, &stderr)
|
||||
if status != 0 {
|
||||
t.Fatalf("build status=%d stdout=%q stderr=%q", status, stdout.String(), stderr.String())
|
||||
}
|
||||
if !strings.Contains(stdout.String(), "no build targets selected for module example.com/ckconfig version v1.2.3 tag integrations/ckconfig/v1.2.3") {
|
||||
t.Fatalf("build did not use profile module selection: %q", stdout.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfileSharedFilesRequireCommittedFilesWithoutEnablingChecks(t *testing.T) {
|
||||
repository := newCLIRepository(t)
|
||||
profile, err := json.Marshal(cli.Settings{
|
||||
Product: "Example Product",
|
||||
Validation: &cli.ValidationSettings{SharedFiles: []string{"docs/shared.md"}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
writeRepositoryFile(t, repository, "releasekit.json", string(profile))
|
||||
cliGitRun(t, repository, "add", "releasekit.json")
|
||||
cliGitRun(t, repository, "commit", "-m", "configure an explicit shared file")
|
||||
var stdout, stderr bytes.Buffer
|
||||
status := run(context.Background(), []string{"check", "--repo", repository, "v1.2.3"}, &stdout, &stderr)
|
||||
if status != 1 || !strings.Contains(stderr.String(), "shared-files") || !strings.Contains(stderr.String(), "docs/shared.md") {
|
||||
t.Fatalf("check status=%d stdout=%q stderr=%q, want missing shared-files failure", status, stdout.String(), stderr.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildCommandWritesValidatedReceiptForConfiguredArtifacts(t *testing.T) {
|
||||
repository := newCLIBuildRepository(t, `package main
|
||||
|
||||
@@ -440,7 +553,12 @@ func TestCandidateCheckHelper(t *testing.T) {
|
||||
os.Exit(9)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "%s|%s", os.Getenv("RELEASEKIT_VERSION"), os.Getenv("RELEASEKIT_CANDIDATE"))
|
||||
workdir, err := os.Getwd()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(9)
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "%s|%s|%s|%s|%s|%s|%s", os.Getenv("RELEASEKIT_VERSION"), os.Getenv("RELEASEKIT_CANDIDATE"), workdir, os.Getenv("RELEASEKIT_REPOSITORY_DIR"), os.Getenv("RELEASEKIT_MODULE_DIR"), os.Getenv("RELEASEKIT_MODULE_PATH"), os.Getenv("RELEASEKIT_TAG"))
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
@@ -760,7 +878,7 @@ func TestDeliverFailureReportsRecoveryForPartialConflictAndUnknownStates(t *test
|
||||
{
|
||||
name: "partial",
|
||||
status: 1,
|
||||
recovery: []string{"recovery: fix the reported cause", "retry this version"},
|
||||
recovery: []string{"recovery: fix the reported cause", "retry module example.com/cli-candidate version v1.2.3 tag v1.2.3"},
|
||||
assetObservation: "pending helper-v1.2.3-linux-amd64",
|
||||
},
|
||||
{
|
||||
@@ -773,7 +891,7 @@ func TestDeliverFailureReportsRecoveryForPartialConflictAndUnknownStates(t *test
|
||||
{
|
||||
name: "unknown",
|
||||
status: 3,
|
||||
recovery: []string{"resolve the remote state before retrying"},
|
||||
recovery: []string{"recovery: resolve the remote state for module example.com/cli-candidate version v1.2.3 tag v1.2.3"},
|
||||
assetObservation: "uncertain helper-v1.2.3-linux-amd64",
|
||||
missingObservation: "pending SHA256SUMS",
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user