Validate representative ReleaseKit consumers
This commit is contained in:
@@ -99,9 +99,28 @@ func TestCheckCommandBindsConfiguredChecksToCapturedCandidate(t *testing.T) {
|
||||
|
||||
func TestPublishCommandPublishesConfiguredCandidate(t *testing.T) {
|
||||
repository := newCLIRepository(t)
|
||||
writeRepositoryFile(t, repository, "docs/releases/v1.2.3.md", "# Example Product v1.2.3\n\n## Compatibility\n\nNo action required.\n")
|
||||
writeRepositoryFile(t, repository, "scripts/check-release-note.sh", `#!/bin/sh
|
||||
set -eu
|
||||
version=$RELEASEKIT_VERSION
|
||||
candidate=$RELEASEKIT_CANDIDATE
|
||||
test "$(git rev-parse HEAD)" = "$candidate"
|
||||
test "$(sed -n '1p' "docs/releases/$version.md")" = "# Example Product $version"
|
||||
grep -Fxq '## Compatibility' "docs/releases/$version.md"
|
||||
grep -Fxq 'No action required.' "docs/releases/$version.md"
|
||||
grep -Fxq 'module example.com/cli-candidate' go.mod
|
||||
printf '%s %s\n' "$version" "$candidate" >> "$RELEASEKIT_COMPATIBILITY_LOG"
|
||||
`)
|
||||
cliGitRun(t, repository, "add", "docs/releases/v1.2.3.md", "scripts/check-release-note.sh")
|
||||
cliGitRun(t, repository, "commit", "-m", "add compatibility note and check")
|
||||
checkLog := filepath.Join(t.TempDir(), "compatibility-check.log")
|
||||
settings := cli.Settings{
|
||||
Product: "Example Product",
|
||||
Remote: "origin",
|
||||
Checks: []cli.CheckCommand{{
|
||||
Args: []string{"sh", "scripts/check-release-note.sh"},
|
||||
Env: map[string]string{"RELEASEKIT_COMPATIBILITY_LOG": checkLog},
|
||||
}},
|
||||
}
|
||||
contents, err := json.Marshal(settings)
|
||||
if err != nil {
|
||||
@@ -133,6 +152,13 @@ func TestPublishCommandPublishesConfiguredCandidate(t *testing.T) {
|
||||
if got := cliGitOutput(t, remote, "rev-parse", "refs/tags/v1.2.3"); got != tagObject {
|
||||
t.Fatalf("remote tag object = %s, want %s", got, tagObject)
|
||||
}
|
||||
checkResult, err := os.ReadFile(checkLog)
|
||||
if err != nil {
|
||||
t.Fatalf("read product compatibility check result: %v", err)
|
||||
}
|
||||
if got, want := strings.Count(string(checkResult), "v1.2.3 "+commit), 1; got != want {
|
||||
t.Fatalf("product compatibility check ran %d times, want %d", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildCommandWritesValidatedReceiptForConfiguredArtifacts(t *testing.T) {
|
||||
|
||||
@@ -54,6 +54,51 @@ func TestDeliverManagedBuildUploadsArtifactsAndCleansTemporaryOutput(t *testing.
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeliverBinaryConsumerWithBuildinfoAndSelectedTargets(t *testing.T) {
|
||||
repository := newTaggedDeliveryConsumer(t)
|
||||
server, remote := newFacadeDeliveryServer(t, repository)
|
||||
defer server.Close()
|
||||
var progress strings.Builder
|
||||
|
||||
result, err := releasekit.Deliver(context.Background(), releasekit.DeliveryRequest{
|
||||
RepositoryDir: repository,
|
||||
Product: "Fixture",
|
||||
Version: "v1.2.3",
|
||||
Destination: facadeDeliveryDestination(server.URL),
|
||||
Build: &releasekit.BuildSpec{
|
||||
MainPackage: "./cmd/app",
|
||||
BinaryName: "fixture",
|
||||
Targets: []releasekit.Target{
|
||||
{OS: "linux", Arch: "amd64"},
|
||||
{OS: "linux", Arch: "arm64"},
|
||||
},
|
||||
},
|
||||
Output: &progress,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Deliver() error = %v; result = %#v", err, result)
|
||||
}
|
||||
if result.State != releasekit.DeliveryComplete || result.CandidateCommit != remote.commit {
|
||||
t.Fatalf("delivery result = %#v", result)
|
||||
}
|
||||
wantAssets := []string{
|
||||
"fixture-v1.2.3-linux-amd64",
|
||||
"fixture-v1.2.3-linux-arm64",
|
||||
"SHA256SUMS",
|
||||
}
|
||||
if len(result.Uploaded) != len(wantAssets) || len(remote.assets) != len(wantAssets) {
|
||||
t.Fatalf("uploaded = %#v; hosted assets = %v", result.Uploaded, mapKeys(remote.assets))
|
||||
}
|
||||
for _, name := range wantAssets {
|
||||
if _, ok := remote.assets[name]; !ok {
|
||||
t.Errorf("hosted assets omit %q: %v", name, mapKeys(remote.assets))
|
||||
}
|
||||
}
|
||||
if !strings.Contains(progress.String(), "checking fixture version output") {
|
||||
t.Fatalf("build progress = %q", progress.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeliverPrebuiltArtifactsRemainCallerOwned(t *testing.T) {
|
||||
repository := newTaggedDeliveryConsumer(t)
|
||||
outputDir := filepath.Join(t.TempDir(), "caller-owned-assets")
|
||||
|
||||
@@ -56,8 +56,7 @@ selected build targets; source-only delivery does not need application
|
||||
dependencies. This preparation may access the network and may update
|
||||
`go.sum`. The command takes CI values as arguments, so profile settings remain
|
||||
independent of Woodpecker environment variable names. See the
|
||||
[CI command contract](cli.md#prepare-a-tagged-ci-checkout-and-deliver-it) for
|
||||
the invocation and exit statuses.
|
||||
[CLI contract](cli.md) for the invocation and exit statuses.
|
||||
|
||||
ReleaseKit's source-only profile is
|
||||
[releasekit.json](../releasekit.json).
|
||||
|
||||
@@ -11,8 +11,8 @@ two Go facades and a command-line interface:
|
||||
- `buildinfo` is the small runtime facade. `Version` reports the injected
|
||||
application version, the main-module version when available, or `dev`.
|
||||
- `cmd/releasekit` is the executable interface. Its `version`, `check`,
|
||||
`publish`, `build`, and `deliver` commands adapt profiles and command output
|
||||
to the supported library operations.
|
||||
`publish`, `build`, `deliver`, and `ci-deliver` commands adapt profiles and
|
||||
command output to the supported library operations.
|
||||
|
||||
See the [CLI contract](../cli.md), [configuration reference](../config.md),
|
||||
[candidate check guide](../consumers/check.md),
|
||||
@@ -66,12 +66,12 @@ 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, standard suite, additional checks, and rechecks | `releasekit.Check`, `releasekit.Publish`, `internal/candidate`, `cmd/releasekit/internal/cli` | `TestCheckCapturesCandidateAndCallsAdditionalChecksOnce`, `TestPublishPushesOnlyTheCapturedAnnotatedTag`, `TestPublishFailedStandardSuiteSkipsAdditionalChecksAndTagCreation`, `TestPublishAdditionalCheckFailurePreservesCauseAndPreventsTagCreation`, `TestCheckCommandBindsConfiguredChecksToCapturedCandidate` |
|
||||
| Candidate capture, standard suite, additional checks, and rechecks | `releasekit.Check`, `releasekit.Publish`, `internal/candidate`, `cmd/releasekit/internal/cli` | `TestCheckCapturesCandidateAndCallsAdditionalChecksOnce`, `TestPublishPushesOnlyTheCapturedAnnotatedTag`, `TestPublishFailedStandardSuiteSkipsAdditionalChecksAndTagCreation`, `TestPublishAdditionalCheckFailurePreservesCauseAndPreventsTagCreation`, `TestCheckCommandBindsConfiguredChecksToCapturedCandidate`, `TestPublishCommandPublishesConfiguredCandidate` |
|
||||
| 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` |
|
||||
| Cross-builds, version smoke checks, empty target sets, and partial outputs | `releasekit.Build`, `internal/build`, `buildinfo` | `TestBuildCreatesSelectedTargetsAndInjectsVersion`, `TestBuildWithNoTargetsDoesNotInvokeCompiler`, `TestBuildReturnsPartialArtifactsAfterTargetFailure` |
|
||||
| Page-only and managed or prebuilt binary delivery | `releasekit.Deliver`, `internal/delivery`, `internal/gitea`, CLI | `TestDeliverPageOnlySkipsBuildAndHostedAssets`, `TestDeliverManagedBuildUploadsArtifactsAndCleansTemporaryOutput`, `TestDeliverPrebuiltArtifactsRemainCallerOwned`, `TestDeliverManagedBuildFailureCleansTemporaryOutputBeforeHostedWrites`, `TestDeliverManagedBuildCancellationCleansTemporaryOutput`, `TestDeliverBuildsTaggedArtifactsAndReusesAssets`, `TestDeliverRejectsTamperedAssetsAndStaleReceiptBeforeRemoteWrites` |
|
||||
| Page-only and managed or prebuilt binary delivery | `releasekit.Deliver`, `internal/delivery`, `internal/gitea`, CLI | `TestDeliverPageOnlySkipsBuildAndHostedAssets`, `TestDeliverManagedBuildUploadsArtifactsAndCleansTemporaryOutput`, `TestDeliverBinaryConsumerWithBuildinfoAndSelectedTargets`, `TestDeliverPrebuiltArtifactsRemainCallerOwned`, `TestDeliverManagedBuildFailureCleansTemporaryOutputBeforeHostedWrites`, `TestDeliverManagedBuildCancellationCleansTemporaryOutput`, `TestDeliverBuildsTaggedArtifactsAndReusesAssets`, `TestDeliverRejectsTamperedAssetsAndStaleReceiptBeforeRemoteWrites` |
|
||||
| Tagged checkout and build dependency preparation | `releasekit.PrepareTaggedCheckout`, `releasekit.PrepareBuildDependencies`, `internal/preparation`, `internal/git`, `internal/gotool` | `TestPrepareTaggedCheckoutFetchesExpectedCommitAndDetaches`, `TestPrepareTaggedCheckoutRejectsWrongCommitBeforeCheckout`, `TestPrepareTaggedCheckoutReportsLocalCheckoutConflict`, `TestPrepareTaggedCheckoutReportsConflictingLocalTag`, `TestPrepareBuildDependenciesPreservesPreparationEnvironment`, `TestPrepareBuildDependenciesPropagatesCommandFailure`, `TestPrepareBuildDependenciesPropagatesCancellation` |
|
||||
| Page, manifest, asset comparison, and additive retry outcomes | `internal/gitea` | `TestEnsureReleaseCreatesMissingPageFromCommittedNote`, `TestInspectAssetsDetectsSameNameAndSizeWithDifferentBytes`, `TestUploadMissingPartialFailureThenRerunOnlyMissingAssets` |
|
||||
| CLI profiles and prepared Woodpecker sequences | `cmd/releasekit`, `cmd/releasekit/internal/cli`, `examples/woodpecker/` | `TestLoadSettingsRejectsInvalidProfiles`, `TestWoodpeckerTagDeliveryTemplate`, `TestReleaseKitSourceDeliveryWorkflowFromTaggedCheckout` |
|
||||
@@ -86,5 +86,7 @@ The [Gitea integration guide](../integrations/gitea.md) owns the HTTP contract
|
||||
and hosted response handling. The [Woodpecker examples](../../examples/woodpecker/)
|
||||
are prepared integrations; their YAML is not active in this repository, and no
|
||||
live Woodpecker runner, configured secret, or hosted delivery has been used.
|
||||
Consumer migrations and measurement of removed consumer infrastructure remain
|
||||
future adoption work.
|
||||
A read-only PromptKit and Narratio migration review and projected deletion
|
||||
estimates are recorded in the [product roadmap](../roadmap/releasekit.md);
|
||||
actual consumer migrations and measurement of realized savings remain future
|
||||
adoption work.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# ReleaseKit audit implementation plan
|
||||
|
||||
Status: Stages 1–10 complete; Stage 11 next.
|
||||
Status: All implementation stages complete.
|
||||
Baseline: `e4be7fa` (2026-10-06). The [audit](audit.md) records the evidence,
|
||||
product goals, and selected direction. This document owns implementation order
|
||||
and completion criteria for that work.
|
||||
@@ -568,6 +568,27 @@ migration, and remaining deployment work. Every F1–F8 finding has an implement
|
||||
resolution and appropriately scoped evidence. Review and commit the final
|
||||
changes with a clean worktree.
|
||||
|
||||
**Completed:** The source-only consumer publication fixture runs one meaningful
|
||||
compatibility check against its committed note and module, then confirms the
|
||||
annotated tag on a local Git remote. A separate binary consumer fixture builds
|
||||
`buildinfo` binaries for selected Linux targets, checks native version output,
|
||||
and delivers both binaries plus `SHA256SUMS` to a local HTTP Gitea fixture.
|
||||
PromptKit and Narratio were reviewed read-only on 2026-10-06; the product
|
||||
roadmap records retained settings, runtime and policy/procedure adaptations,
|
||||
and projected deletion ranges. No sibling repositories were changed.
|
||||
|
||||
The final documentation review reconciled GoDoc, CLI/configuration references,
|
||||
consumer guidance, Woodpecker examples, the internal inventory, and product
|
||||
roadmap. The pre-release API migration is `Validate` to `AdditionalChecks` and
|
||||
`DeliveryRequest.Build` to `*BuildSpec`, with `Prebuilt` for retained artifacts;
|
||||
JSON `checks` remains the ordered additional-check setting. No new product
|
||||
decision was required. The completed stages address F1–F8; real source
|
||||
publication, an immutable tool pin, credentials, workflow activation, and live
|
||||
Gitea/Woodpecker verification remain deployment work.
|
||||
|
||||
The full offline suite and API boundary check pass with Go 1.25.0. Go formatting,
|
||||
documentation whitespace, and changed local-link checks pass.
|
||||
|
||||
## Open Questions
|
||||
|
||||
No unresolved product choice is required to implement these stages. The
|
||||
|
||||
@@ -204,6 +204,27 @@ Consumer policy and procedure changes should describe the deliberately adopted
|
||||
standard and its compatibility impact. Adoption should demonstrate reduced local
|
||||
infrastructure and one coherent release model.
|
||||
|
||||
## Representative migration review
|
||||
|
||||
Read-only reviews of the available PromptKit and Narratio checkouts were
|
||||
verified on 2026-10-06 at `4b8169d` and `8afb49c`; both worktrees were clean.
|
||||
These are migration assessments, not changes to either consumer.
|
||||
|
||||
| Consumer | Retain in its profile and product checks | Adaptation and procedure changes |
|
||||
| --- | --- | --- |
|
||||
| PromptKit, source-only | Product identity; its `Summary`, `Compatibility`, `Upgrade`, and `Changes` release-note sections; checks that exercise the three maintained Go examples and their product outputs. No runtime `buildinfo` import or binary targets are needed. | Its current release scripts total 209 lines. The projected deletion is about 120–160 lines of shared publication and generic validation machinery; retain the note-content rule and product-example checks as a configured additional check plus a small wiring test. PromptKit already pushes `main` before publication and creates annotated tags. Its release policy and procedure still need to add the hosted note page, delivery credentials, versioned CI invocation, and separate delivery status and recovery. |
|
||||
| Narratio, binary | Product/module identity, the `./cmd/narratio` main package, `narratio` executable name, Linux amd64, Linux arm64, and macOS arm64 targets, and the `narratio <version>` command. Keep the module-graph check (`go mod tidy -diff`) if it remains useful as a product-specific candidate check. | Its release, check, asset-builder, and helper scripts total 304 lines; two dedicated release test files total 741 lines. Projected deletions are about 220–280 shell lines and 450–650 repeated test lines, leaving a small consumer wiring test and any retained module/note checks. Replace the private linker-version variable with `buildinfo.Version()` while preserving the current command output. Its policy and procedure need to change lightweight tags to annotated tags, state that a successful tag push completes source publication, and move plugin-based page/assets delivery to the shared versioned CI command with content-aware retries and separately provisioned delivery credentials. |
|
||||
|
||||
The deletion figures are estimates from the reviewed files, not measured
|
||||
migration results or a promise that each line will disappear. Product checks,
|
||||
version output, target choices, and at least one ReleaseKit integration check
|
||||
remain with each consumer. The existing cross-project estimate of 1,000–1,250
|
||||
potentially removable lines remains directional until migrations are completed.
|
||||
The self-contained ReleaseKit fixtures exercise a meaningful source-only
|
||||
compatibility check through local Git publication, and a `buildinfo` binary
|
||||
consumer with selected targets through local HTTP delivery. These are separate
|
||||
publication and delivery operations.
|
||||
|
||||
## Remaining work
|
||||
|
||||
- Prepare and publish the first ReleaseKit source release under the
|
||||
|
||||
Reference in New Issue
Block a user