Enable race testing in validation

This commit is contained in:
2026-10-07 22:10:34 +00:00
parent 89981abbe5
commit 30fe4fe206
20 changed files with 510 additions and 61 deletions

View File

@@ -23,10 +23,10 @@ go run ./cmd/releasekit check [--repo DIR] [--config FILE] VERSION
`VERSION` must use stable `vMAJOR.MINOR.PATCH` syntax. Options must precede the
version. The repository defaults to the current directory, and the profile
defaults to `<repository>/releasekit.json`. A successful command prints the
captured local commit and version. It checks the committed release note, local
Git state, runs the standard offline Go test suite, and then runs any configured
additional checks in profile order. It does not inspect remote availability or
publish a tag.
captured local commit and version. It checks the committed release note and
local Git state, runs the standard offline Go test suite (with `-race` when
`validation.go.race` is true), and then runs any configured additional checks
in profile order. It does not inspect remote availability or publish a tag.
`check` writes errors and diagnostics to standard error. It returns status 0
after local validation, 1 after a candidate validation failure, and 2 for usage,
@@ -40,10 +40,11 @@ Publish a source tag:
go run ./cmd/releasekit publish [--repo DIR] [--config FILE] VERSION
```
`publish` reads the same product, remote, and additional-check settings as
`check`. It checks the authoritative remote and validates the candidate: the
standard offline Go test suite runs first, followed by configured checks in
profile order. It then creates an annotated local tag and pushes only its exact
`publish` reads the same product, remote, validation, and additional-check
settings as `check`. It checks the authoritative remote and validates the
candidate: the single standard offline Go test suite runs first, with `-race`
when `validation.go.race` is true, followed by configured checks in profile
order. It then creates an annotated local tag and pushes only its exact
tag object. It prints the confirmed version, candidate commit, and tag object
on success. Validation
progress and failed publication state, including the captured publication

View File

@@ -11,6 +11,7 @@ The current profile fields are:
| `product` | Yes | Product name used by release operations. |
| `remote` | No | Selected Git remote; defaults to `origin`. |
| `checks` | No | Ordered additional child commands, each with an argument vector and optional environment map. |
| `validation` | No | Optional shared checks selected by ReleaseKit. |
| `build` | No | Optional main package, binary name, and selected `GOOS/GOARCH` target strings. |
| `delivery` | No | Optional Gitea `base_url`, `owner`, `repository`, and `token_env` settings for tagged-source delivery. |
@@ -25,6 +26,17 @@ Unknown fields are rejected so a setting cannot be silently ignored. The
target requires the package and binary name; each target is written as one
`GOOS/GOARCH` pair. An omitted or empty target list means no binary work.
The optional `validation` object selects shared checks implemented by ReleaseKit.
`validation.go.race` enables the race detector for the single standard Go test
suite. When omitted or false, the ordinary native suite runs. For example:
```json
{
"product": "Example",
"validation": {"go": {"race": true}}
}
```
The `delivery` object contains `base_url`, `owner`, `repository`, and optional
`token_env`. Its values are required when running `deliver`, but credentials are
not required for `check`, `publish`, or `build`. `token_env` names the
@@ -32,10 +44,11 @@ environment variable containing the Gitea token; it defaults to
`RELEASEKIT_GITEA_TOKEN`. The CLI reads this variable only for `deliver` and
passes its value explicitly to the library operation.
The `check` and `publish` commands always run
`go test -mod=readonly -count=1 ./...` with Go module and toolchain network
access disabled. They then run each configured `checks` command once, in order,
as an additional product check. Selected-target builds run after both. Do not
The `check` and `publish` commands run one
`go test -mod=readonly -count=1 ./...` suite with Go module and toolchain network
access disabled, adding `-race` when `validation.go.race` is true. They then run
each configured `checks` command once, in order, as an additional product
check. Selected-target builds run after the suite and product checks. Do not
repeat the standard suite in `checks`; doing so runs it twice. The `build`
command uses the selected build settings and writes binaries to `dist` unless
`--output` selects another path.

View File

@@ -8,6 +8,9 @@ result, err := releasekit.Check(ctx, releasekit.ReleaseRequest{
RepositoryDir: "/work/project",
Product: "Example",
Version: "v1.2.3",
Validation: releasekit.ValidationSpec{
Go: releasekit.GoValidationSpec{Race: true},
},
AdditionalChecks: func(ctx context.Context, candidate releasekit.Candidate) error {
return runProjectChecks(ctx, candidate.RepositoryDir)
},
@@ -24,14 +27,17 @@ version must be stable `vMAJOR.MINOR.PATCH`. The committed
product name and exact version as complete title elements. No local tag with
that version may already exist.
ReleaseKit always runs `go test -mod=readonly -count=1 ./...` with the available
compatible local Go toolchain, then calls `AdditionalChecks` once when supplied.
It does not download a different toolchain automatically. The standard suite
uses the Go host target, disables workspace and module network access, and
ignores ambient `GOFLAGS`, experiment, and CPU feature overrides. Effective
cache and native cgo/C-tool settings are preserved, including values from Go's
persistent environment file. The check revalidates the branch, commit, and
cleanliness after validation.
ReleaseKit runs one `go test -mod=readonly -count=1 ./...` suite with the
available compatible local Go toolchain, then calls `AdditionalChecks` once
when supplied. Set `Validation.Go.Race` to run that suite with `-race`; the zero
value keeps the ordinary native suite. ReleaseKit does not download a different
toolchain automatically. If the race prerequisite is unavailable, the `go-test`
check fails rather than being skipped. The suite uses the Go host target,
disables workspace and module network access, and ignores ambient `GOFLAGS`,
experiment, and CPU feature overrides. Effective cache and native cgo/C-tool
settings are preserved, including values from Go's persistent environment
file. The check revalidates the branch, commit, and cleanliness after
validation.
A successful check is evidence about the local candidate only. It does not
check whether a remote branch or tag is available and does not create a tag.

View File

@@ -8,6 +8,9 @@ result, err := releasekit.Publish(ctx, releasekit.ReleaseRequest{
RepositoryDir: "/work/project",
Product: "Example",
Version: "v1.2.3",
Validation: releasekit.ValidationSpec{
Go: releasekit.GoValidationSpec{Race: true},
},
AdditionalChecks: func(ctx context.Context, candidate releasekit.Candidate) error {
return runProjectChecks(ctx, candidate.RepositoryDir)
},
@@ -20,12 +23,15 @@ fmt.Println(result.Version, result.CandidateCommit, result.TagObject)
Publication captures a clean candidate on `main`, validates its committed
release note, and checks the selected remote before running candidate checks.
It always runs `go test -mod=readonly -count=1 ./...` with the available
compatible local Go toolchain. It then calls `AdditionalChecks` once when
supplied. The standard suite cannot be replaced; move product-specific behavior
into `AdditionalChecks` and remove repeated standard-suite commands from custom
checks. A failed suite or additional check prevents tag creation, and wrapped
errors preserve their causes.
It runs one `go test -mod=readonly -count=1 ./...` suite with the available
compatible local Go toolchain. Set `Validation.Go.Race` to run that suite with
`-race`; its zero value keeps the ordinary native suite. It then calls
`AdditionalChecks` once when supplied. The standard suite cannot be replaced;
move product-specific behavior into `AdditionalChecks` and remove repeated
standard-suite commands from custom checks. A failed suite or additional check
prevents tag creation, and wrapped errors preserve their causes.
If race prerequisites are unavailable, the selected suite fails as `go-test`
instead of silently running without the race detector.
If `Build` selects targets, ReleaseKit verifies them after the standard suite
and additional checks, before creating the tag. The operation then rechecks the

View File

@@ -46,7 +46,7 @@ these implemented packages:
| `internal/tempdir` | Disposable system temporary storage outside source worktrees. |
| `internal/process` | Cancellable child-process execution with per-command environment overlays and removals. |
| `internal/preparation` | Coordination for expected-commit tag checkout and Go module dependency preparation. |
| `internal/validation` | Shared default Go validation, structured check failures, and lazy committed-file access for captured candidates; `internal/candidate` retains capture, callback sequencing, and local-state rechecks. |
| `internal/validation` | Shared Go validation with optional race selection, structured check failures, and lazy committed-file access for captured candidates; `internal/candidate` retains capture, callback sequencing, and local-state rechecks. |
| `internal/publish` | Publication guards, one validation run, annotated tag creation, push, and recovery state. |
| `internal/runtimeinfo` | Private version lookup used by the runtime facade. |
| `internal/versioncontract` | Shared stable-version rules and linker-symbol identity. |
@@ -78,7 +78,7 @@ not a separate release matrix:
| Capability | Implementation owner | Existing evidence |
| --- | --- | --- |
| Runtime version lookup and injected application version | `buildinfo`, `internal/runtimeinfo`, `internal/versioncontract`, `internal/build` | `TestVersionInConsumerExecutable`, `TestVersion` |
| Candidate capture, shared validation, public diagnostics, additional checks, and rechecks | `releasekit.Check`, `releasekit.Publish`, `internal/candidate`, `internal/validation`, `cmd/releasekit/internal/cli` | `TestCheckCapturesCandidateAndCallsAdditionalChecksOnce`, `TestCheckReturnsPublicValidationError`, `TestPublishPushesOnlyTheCapturedAnnotatedTag`, `TestPublishFailedStandardSuiteSkipsAdditionalChecksAndTagCreation`, `TestPublishAdditionalCheckFailurePreservesCauseAndPreventsTagCreation`, `TestCheckCommandBindsConfiguredChecksToCapturedCandidate`, `TestPublishCommandPublishesConfiguredCandidate`, `TestCandidateCommandsPresentValidationDiagnosticsOnce` |
| Candidate capture, shared validation, public diagnostics, additional checks, and rechecks | `releasekit.Check`, `releasekit.Publish`, `internal/candidate`, `internal/validation`, `cmd/releasekit/internal/cli` | `TestRunUsesOneSuiteWithSelectedRaceSetting`, `TestRunReportsRacePrerequisiteFailureWithoutFallback`, `TestRunExecutesRaceEnabledSuiteOnHost`, `TestCandidateRequestMapsRaceValidation`, `TestLoadSettingsReadsRaceValidation`, `TestCheckUsesSelectedRaceSuiteBeforeAdditionalChecks`, `TestCheckCapturesCandidateAndCallsAdditionalChecksOnce`, `TestCheckReturnsPublicValidationError`, `TestPublishPushesOnlyTheCapturedAnnotatedTag`, `TestPublishFailedStandardSuiteSkipsAdditionalChecksAndTagCreation`, `TestPublishAdditionalCheckFailurePreservesCauseAndPreventsTagCreation`, `TestCheckCommandBindsConfiguredChecksToCapturedCandidate`, `TestPublishCommandPublishesConfiguredCandidate`, `TestCandidateCommandsPresentValidationDiagnosticsOnce` |
| Shared Go settings for validation and builds | `internal/gotool`, `internal/process`, `internal/candidate`, `internal/build` | `TestDefaultValidationDoesNotInheritGOFLAGSRunFilter`, `TestNativeAndStaticCommandsUseOwnedBaseline`, `TestPersistentSettingsPreserveCachesAndNativeCTools`, `TestBuildIgnoresAmbientAndPersistentArchitectureTuning` |
| Authoritative endpoint and exact annotated tag publication | `releasekit.Publish`, `internal/publish`, `internal/git` | `TestPublishPushesOnlyTheCapturedAnnotatedTag`, `TestResolveUsesPushURLAndQueriesWithoutMutation` |
| Publication partial and uncertain recovery | `internal/publish`, `internal/git` | `TestPublishRejectedPushKeepsLocalTagAndReportsNotPublished`, `TestPublishLostAcknowledgmentConfirmsExactRemoteObject`, `TestPublishLostAcknowledgmentWithChangedEndpointRemainsUnknown`, `TestPublishUnavailableReconciliationRemainsUnknownAndPreservesPushError` |

View File

@@ -8,10 +8,11 @@ post-validation build callback and local-state recheck. `internal/publish`
adds its endpoint guards, tag creation, push, and recovery around that same
candidate path.
The current executor runs the default offline Go suite. Its request carries the
captured repository directory and commit, output writer, and internal
settings. `Request.ReadCandidateTree` lets a selected file check request
candidate contents; the default Go-only path does not enumerate the tree.
The executor runs one offline Go suite, optionally with the race detector when
selected. Its request carries the captured repository directory and commit,
output writer, and internal settings. `Request.ReadCandidateTree` lets a
selected file check request candidate contents; the Go-only path does not
enumerate the tree.
`CandidateTree` gets metadata and bytes from Git objects, reads blob bytes
lazily, and resolves destinations without consulting the worktree or
neighboring files.

View File

@@ -226,6 +226,11 @@ imports only lightweight `buildinfo`. Stages 12–14 implement this agreed appro
## Stage 1: Introduce the specification with race selection
**Completion:** Complete. `ReleaseRequest.Validation.Go.Race` and profile
`validation.go.race` select `-race` for the single native Go suite. Both
candidate operations share the selection, and race failures retain the `go-test`
identity without falling back to an ordinary suite.
**Outcome:** The first public/profile selection changes the one existing suite.
1. Add `ReleaseRequest.Validation`, `ValidationSpec.Go`, and

View File

@@ -1,7 +1,7 @@
# Validation API and profile model
Status: Shared validation foundation implemented; optional v0.2.0 capabilities
and their public/profile settings remain future work.
Status: Shared validation foundation and Go race selection implemented;
remaining v0.2.0 capabilities and their settings are future work.
This roadmap describes the shared model that enables the optional validation
capabilities in the [v0.2.0 roadmap](v0.2.0.md). It owns their common API,
@@ -18,9 +18,9 @@ Selected executable builds follow validation. The CLI maps profile `checks`
commands to the additional-check callback.
This provides a common procedure and a product-specific extension point. The
request and profile currently have no structured selection for shared optional
validation. Race testing, full vet, package compilation, formatting, Markdown,
module-distribution, and file-size checks need a coherent home as they are added.
request and profile now have a structured selection for race testing; full vet,
package compilation, formatting, Markdown, module-distribution, and file-size
checks will use the same model as their capabilities are added.
The model should let consumers declare their choices once while ReleaseKit owns
execution and coordination. This follows [ADR 0002](../adr/0002-routine-releases.md):
@@ -124,11 +124,10 @@ failure-stopping behavior of the candidate workflow.
## Implementation
The [implementation plan](implementation.md) records the completed foundation:
shared execution, internal diagnostics, captured candidate-tree inspection and
destination resolution, facade diagnostics, and consistent CLI presentation.
The public `ReleaseRequest.Validation` field and profile `validation` object are
not yet available; each setting will be introduced with its first working
The [implementation plan](implementation.md) records the completed foundation
and current rollout. The facade exposes `ReleaseRequest.Validation.Go.Race`, and
profiles accept `validation.go.race`; both select `-race` for the one base Go
suite. Each remaining setting will be introduced with its first working
capability. Individual checkers, module-selected CI tooling, and the publication
endpoint expectation remain future work in the [v0.2.0 roadmap](v0.2.0.md).