Compile packages for selected targets

This commit is contained in:
2026-10-07 22:27:31 +00:00
parent 1c41f7a0d1
commit cabc56b134
20 changed files with 406 additions and 40 deletions

View File

@@ -130,8 +130,9 @@ type ValidationSettings struct {
// GoValidationSettings selects checks performed by the Go toolchain.
type GoValidationSettings struct {
Race bool `json:"race,omitempty"`
FullVet bool `json:"full_vet,omitempty"`
Race bool `json:"race,omitempty"`
FullVet bool `json:"full_vet,omitempty"`
CompileTargets []string `json:"compile_targets,omitempty"`
}
// DeliverySettings selects the hosted Gitea release destination.
@@ -219,6 +220,17 @@ func LoadSettings(repoDir, configPath string) (Settings, error) {
}
}
}
if settings.Validation != nil {
for i, target := range settings.Validation.Go.CompileTargets {
if strings.Count(target, "/") != 1 {
return Settings{}, fmt.Errorf("profile %q: validation.go.compile_targets[%d] must be GOOS/GOARCH", configPath, i)
}
goos, goarch, _ := strings.Cut(target, "/")
if strings.TrimSpace(goos) == "" || strings.TrimSpace(goarch) == "" {
return Settings{}, fmt.Errorf("profile %q: validation.go.compile_targets[%d] must be GOOS/GOARCH", configPath, i)
}
}
}
return settings, nil
}

View File

@@ -144,7 +144,7 @@ func TestLoadSettingsDefaultsRemoteAndConfigPath(t *testing.T) {
func TestLoadSettingsReadsGoValidation(t *testing.T) {
repoDir := t.TempDir()
profilePath := filepath.Join(repoDir, "releasekit.json")
if err := os.WriteFile(profilePath, []byte(`{"product":"Example","validation":{"go":{"race":true,"full_vet":true}}}`), 0o600); err != nil {
if err := os.WriteFile(profilePath, []byte(`{"product":"Example","validation":{"go":{"race":true,"full_vet":true,"compile_targets":["linux/amd64","linux/arm64","darwin/arm64"]}}}`), 0o600); err != nil {
t.Fatal(err)
}
@@ -155,6 +155,9 @@ func TestLoadSettingsReadsGoValidation(t *testing.T) {
if settings.Validation == nil || !settings.Validation.Go.Race || !settings.Validation.Go.FullVet {
t.Fatalf("validation settings = %#v, want Go race and full vet enabled", settings.Validation)
}
if got, want := strings.Join(settings.Validation.Go.CompileTargets, ","), "linux/amd64,linux/arm64,darwin/arm64"; got != want {
t.Fatalf("compile targets = %q, want %q", got, want)
}
}
func TestExampleProfileLoads(t *testing.T) {
@@ -207,6 +210,10 @@ func TestLoadSettingsRejectsInvalidProfiles(t *testing.T) {
{name: "unknown top-level field", content: `{"product":"Example","future":{}}`, want: "unknown field"},
{name: "build package required", content: `{"product":"Example","build":{"binary_name":"example","targets":["linux/amd64"]}}`, want: "build.main_package is required"},
{name: "build target format", content: `{"product":"Example","build":{"main_package":".","binary_name":"example","targets":["linux"]}}`, want: "must be GOOS/GOARCH"},
{name: "compile target format", content: `{"product":"Example","validation":{"go":{"compile_targets":["linux"]}}}`, want: "validation.go.compile_targets[0] must be GOOS/GOARCH"},
{name: "compile target missing architecture", content: `{"product":"Example","validation":{"go":{"compile_targets":["linux/"]}}}`, want: "validation.go.compile_targets[0] must be GOOS/GOARCH"},
{name: "compile target missing operating system", content: `{"product":"Example","validation":{"go":{"compile_targets":["/amd64"]}}}`, want: "validation.go.compile_targets[0] must be GOOS/GOARCH"},
{name: "compile target repeated separator", content: `{"product":"Example","validation":{"go":{"compile_targets":["linux/amd64/arm64"]}}}`, want: "validation.go.compile_targets[0] must be GOOS/GOARCH"},
{name: "unsafe binary name", content: `{"product":"Example","build":{"main_package":".","binary_name":"../example","targets":["linux/amd64"]}}`, want: "filename component"},
{name: "unknown command field", content: `{"product":"Example","checks":[{"args":["true"],"shell":true}]}`, want: "unknown field"},
{name: "command is required", content: `{"product":"Example","checks":[{"args":[]}]}`, want: "must include a command"},

View File

@@ -159,12 +159,18 @@ func validationSpec(settings *cli.ValidationSettings) releasekit.ValidationSpec
if settings == nil {
return releasekit.ValidationSpec{}
}
return releasekit.ValidationSpec{
result := releasekit.ValidationSpec{
Go: releasekit.GoValidationSpec{
Race: settings.Go.Race,
FullVet: settings.Go.FullVet,
Race: settings.Go.Race,
FullVet: settings.Go.FullVet,
CompileTargets: make([]releasekit.Target, len(settings.Go.CompileTargets)),
},
}
for index, target := range settings.Go.CompileTargets {
goos, goarch, _ := strings.Cut(target, "/")
result.Go.CompileTargets[index] = releasekit.Target{OS: goos, Arch: goarch}
}
return result
}
func candidateFailureText(err error) string {

View File

@@ -116,12 +116,21 @@ func TestCandidateRequestMapsGoValidation(t *testing.T) {
request := candidateRequest(cli.Invocation{Repository: "repository", Version: "v1.2.3"}, cli.Settings{
Product: "Example Product",
Validation: &cli.ValidationSettings{
Go: cli.GoValidationSettings{Race: true, FullVet: true},
Go: cli.GoValidationSettings{Race: true, FullVet: true, CompileTargets: []string{"linux/amd64", "darwin/arm64"}},
},
}, nil)
if !request.Validation.Go.Race || !request.Validation.Go.FullVet {
t.Fatalf("candidate request validation = %#v, want Go race and full vet enabled", request.Validation)
}
wantTargets := []releasekit.Target{{OS: "linux", Arch: "amd64"}, {OS: "darwin", Arch: "arm64"}}
if len(request.Validation.Go.CompileTargets) != len(wantTargets) {
t.Fatalf("candidate request compile targets = %#v, want %#v", request.Validation.Go.CompileTargets, wantTargets)
}
for index := range wantTargets {
if request.Validation.Go.CompileTargets[index] != wantTargets[index] {
t.Fatalf("candidate request compile targets = %#v, want %#v", request.Validation.Go.CompileTargets, wantTargets)
}
}
}
func TestCandidateCommandsPresentValidationDiagnosticsOnce(t *testing.T) {
@@ -434,7 +443,11 @@ func TestDeliverPageOnlyCreatesAndReusesRelease(t *testing.T) {
state := &deliveryServerState{}
server := newDeliveryServer(t, state)
defer server.Close()
settings := cli.Settings{Product: "Example Product", Delivery: &cli.DeliverySettings{BaseURL: server.URL, Owner: "owner", Repository: "example"}}
settings := cli.Settings{
Product: "Example Product",
Validation: &cli.ValidationSettings{Go: cli.GoValidationSettings{CompileTargets: []string{"linux/amd64"}}},
Delivery: &cli.DeliverySettings{BaseURL: server.URL, Owner: "owner", Repository: "example"},
}
writeDeliveryProfile(t, repository, settings)
state.commit = cliGitOutput(t, repository, "rev-parse", "HEAD")
cliGitRun(t, repository, "tag", "v1.2.3") // Historical lightweight tags are valid delivery inputs.