From 5e60fe3113c69f95c42fbbe32a8ca4b51f5b83c1 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Wed, 7 Oct 2026 02:49:47 +0000 Subject: [PATCH] Prepare the initial v0.1.0 release --- README.md | 3 + docs/consumers/delivery.md | 4 +- docs/policy/oss.md | 4 +- docs/policy/release.md | 17 +- docs/releases/v0.1.0.md | 64 +++ docs/roadmap/audit.md | 416 ------------------- docs/roadmap/implementation.md | 598 --------------------------- docs/roadmap/releasekit.md | 15 +- docs/roadmap/remediation.md | 164 -------- examples/woodpecker/tag-delivery.yml | 2 +- 10 files changed, 89 insertions(+), 1198 deletions(-) create mode 100644 docs/releases/v0.1.0.md delete mode 100644 docs/roadmap/audit.md delete mode 100644 docs/roadmap/implementation.md delete mode 100644 docs/roadmap/remediation.md diff --git a/README.md b/README.md index 69310ea..8f1d2d3 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,9 @@ delivery are documented. ReleaseKit does not declare binary deliverables. The [product roadmap](docs/roadmap/releasekit.md) records remaining adoption and deployment work. +See the [v0.1.0 release note](docs/releases/v0.1.0.md) for the initial baseline +and installation commands. + Run the offline Go test suite from the repository root with: ```sh diff --git a/docs/consumers/delivery.md b/docs/consumers/delivery.md index 8ef7d38..305cc8a 100644 --- a/docs/consumers/delivery.md +++ b/docs/consumers/delivery.md @@ -152,8 +152,8 @@ Use the maintained [tag-delivery workflow](../../examples/woodpecker/tag-deliver in the consumer repository's `.woodpecker/` directory. Set `GO_IMAGE` to an image with Go 1.25 or newer, Git, and a Go version compatible with the consumer module. Replace `RELEASEKIT_VERSION` with an immutable ReleaseKit revision or -published version. The example deliberately leaves this deployment pin as a -placeholder. Configure the Woodpecker repository secret +published version. The example selects the initial `v0.1.0` baseline; update +that pin when adopting a later release. Configure the Woodpecker repository secret `releasekit_gitea_token`; the template maps it to `RELEASEKIT_GITEA_TOKEN` only for the delivery step. The repository needs a `delivery` profile. Page-only and binary behavior both use this template; the profile's build target list selects diff --git a/docs/policy/oss.md b/docs/policy/oss.md index 3176be0..40a76cb 100644 --- a/docs/policy/oss.md +++ b/docs/policy/oss.md @@ -2,7 +2,7 @@ **Base Policy Version:** 1.8 -**Last Updated**: 2026-10-05 +**Last Updated**: 2026-10-07 **Upstream Source:** [oss.md](https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843/docs/policy/oss.md) @@ -53,7 +53,7 @@ provides texts to copy for applicable licenses and their companions. ## Project Licensing ReleaseKit's selected grant is LGPL version 3 or later, recorded in -[COPYRIGHT](../../COPYRIGHT). It applies to the library and a future release +[COPYRIGHT](../../COPYRIGHT). It applies to the library and release executable. Adapted policy documents, agent orientation, and the policy reading guide retain their CC-BY-SA-4.0 scope as identified there and in the [attribution document](../oss/attribution.md). diff --git a/docs/policy/release.md b/docs/policy/release.md index bd7da91..43169eb 100644 --- a/docs/policy/release.md +++ b/docs/policy/release.md @@ -2,7 +2,7 @@ **Base Policy Version:** 1.4 -**Last Updated**: 2026-10-05 +**Last Updated**: 2026-10-07 **Upstream Source:** [release.md](https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843/docs/policy/release.md) @@ -16,10 +16,10 @@ The repository-specific commands belong in `docs/release.md`. Historical release summaries belong in `docs/releases/`. The procedure must agree with the adopted policy and link to it rather than introduce additional release requirements. -This policy governs releases of ReleaseKit itself. Consumer release capabilities -are designed in the [product roadmap](../roadmap/releasekit.md) and acquire exact -public contracts when implemented. ReleaseKit's source publication command and -maintainer runbook are implemented; no ReleaseKit release has been published. +This policy governs releases of ReleaseKit itself. Go declarations and GoDoc +own supported consumer API contracts; the [product roadmap](../roadmap/releasekit.md) +records planned adoption and deployment work. The maintainer runbook describes +ReleaseKit's implemented source publication and hosted-page delivery procedure. ## Release Model And Completion @@ -121,10 +121,9 @@ publish builds, verify the required build targets. Select those targets for the project's actual support commitments; native testing on each platform and access to particular hardware are not default release prerequisites. -The default suite and its runnable command will be established with the Go -implementation. Documentation adoption checks validate this change; they do not -create permanent release gates. ReleaseKit's source-only deliverable adds no -binary target matrix. +The publication command runs the standard offline Go test suite, followed by +any additional product checks. The [maintainer runbook](../release.md) owns its +invocation. ReleaseKit's source-only deliverable adds no binary target matrix. Additional gates must address a concrete risk that the existing checks do not adequately cover. Do not automatically require linting, race testing, module diff --git a/docs/releases/v0.1.0.md b/docs/releases/v0.1.0.md new file mode 100644 index 0000000..5e2ea4c --- /dev/null +++ b/docs/releases/v0.1.0.md @@ -0,0 +1,64 @@ +# ReleaseKit v0.1.0 + +## Summary + +ReleaseKit's initial release provides an opinionated Go library and executable +for candidate validation, annotated source-tag publication, version injection, +selected-target builds, and Gitea release delivery. + +The root `releasekit` facade owns release orchestration. The separate `buildinfo` +facade supplies lightweight runtime version access. Both belong to one Go module +with a Go 1.25.0 minimum language version. + +## Capabilities + +- Run the standard offline Go test suite once, followed by optional + product-specific checks and selected-target build verification. +- Publish the exact annotated tag for a validated candidate already on + authoritative `main`, with bounded recovery after failed or ambiguous pushes. +- Cross-build selected Go targets with shared version injection, artifact names, + digests, and a native version smoke check. Source-only projects select no + binary targets. +- Deliver committed release notes and declared assets to Gitea, preserving + existing content and reporting partial, conflicting, and uncertain outcomes. +- Use one managed build-and-deliver operation or supply retained prebuilt + artifacts for retries and separate build/delivery environments. +- Prepare tagged CI checkouts and dependencies through the shared `ci-deliver` + command and maintained Woodpecker workflow. + +See the [CLI contract](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/docs/cli.md), +[configuration reference](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/docs/config.md), +[consumer delivery guide](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/docs/consumers/delivery.md), +and [runtime version guide](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/docs/consumers/runtime-version.md) +for supported behavior. + +## Adoption and compatibility + +Consumers can select this initial baseline with: + +```sh +go get gitea.maximumdirect.net/eric/ReleaseKit@v0.1.0 +go install gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit@v0.1.0 +``` + +Profiles declare product identity, additional checks, selected binaries and +targets, and a Gitea destination. Applications obtain their embedded version +through `buildinfo.Version()`. + +For consumers experimenting with earlier development revisions, rename the +`ReleaseRequest.Validate` callback to `AdditionalChecks` and remove repeated +standard-suite commands from profile `checks`. `DeliveryRequest.Build` now +accepts a `*BuildSpec` for managed builds; use `Prebuilt` for an existing +`BuildResult`. + +Compatibility follows the [release policy](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/docs/policy/release.md): before +v1.0.0, minor releases may change documented contracts with migration guidance; +patch releases preserve contracts within their minor line. + +ReleaseKit's deliverables are this immutable source tag and the hosted page +containing this complete note. Consumer migration and live Woodpecker deployment +remain adoption work tracked in the [product roadmap](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/docs/roadmap/releasekit.md). + +[COPYRIGHT](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/COPYRIGHT) | +[LICENSE](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/LICENSE) | +[ATTRIBUTION](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/docs/oss/attribution.md) diff --git a/docs/roadmap/audit.md b/docs/roadmap/audit.md deleted file mode 100644 index 413ec45..0000000 --- a/docs/roadmap/audit.md +++ /dev/null @@ -1,416 +0,0 @@ -# ReleaseKit pre-release audit - -Date: 2026-10-06. Reviewed source: `536a57916f6565ae8194c4563577dfcebd6cfb69`. -Status: historical review evidence and selected target direction for the -[implementation plan](implementation.md). -Audience: maintainers deciding the shared release standard before `v0.1.0`. - -## Assessment - -ReleaseKit's practical goals are to minimize application-owned release code, -duplication across the suite, and the time developers spend on release processes. -Shared conventions serve these goals by giving routine decisions one owner. -Applications supply product facts and product-specific checks; ReleaseKit owns -the procedure, sensible defaults, and recovery guidance. - -Evaluate recommendations by the application code they remove, the shared logic -they consolidate, and the recurring decisions they eliminate. Standardization, -configuration options, and diagnostic detail are useful when they reduce that -work. Keep routine release decisions inside ReleaseKit. - -The core direction is sound. Retain the publication/delivery separation, narrow -public facades, standard artifact naming, version injection, and content-aware -retries. Fix the reproduced validation and recovery defects in F1–F2 before -`v0.1.0`. Treat F3 as a focused improvement to internal build defaults. - -Build-environment reproducibility, hardware-specific configurability, and -extensive build inspection are outside the product's optimization goals. Use the -available compatible Go toolchain and shared baseline settings. Evaluate new -configuration and deployment machinery by the application code and developer -work they save. Different toolchains may produce different bytes; existing -published content remains protected by digest comparison. - -The implementation covers most mechanics in the [product roadmap](releasekit.md). -Representative adoption should demonstrate the -[architectural success criteria](../policy/architecture.md#success-criteria) -through deleted release code, fewer duplicated checks, and fewer routine decisions. -F4–F6 identify opportunities to centralize validation, delivery, and CI setup. - -The existing source transaction supports these goals. Annotated tags preserve -the checked-in note and provide an exact object for recovery. Requiring the -candidate on authoritative `main` keeps branch publication in preparation. -Separate delivery lets source publication finish independently of hosting. -Consumer migrations should adopt this common process and retain product identity, -target selection, compatibility decisions, and product-specific checks. - -## Scope and evidence - -Reviewed the development guide; agent, architecture, testing, documentation, and -release policies; facade ADR; roadmap; public declarations; CLI/configuration -and consumer guides; publication, build, delivery, Git and Gitea implementations; -and their relevant tests and workflow examples. The -[release policy](../policy/release.md) governs ReleaseKit's own releases. -The facade and integration contracts define consumer behavior. - -Also inspected the release scripts, module declarations, and available delivery -YAML in the six sibling projects named by the roadmap. This read-only sample -informed the assessment of adoption needs. -Existing extra checks should be retained according to their product-specific value. -For example, PromptKit has product-specific executable examples, whereas -Narratio currently requires Go 1.26 and several peers require Go 1.25.5. - -Validation on Linux/amd64 with Go 1.26.8: - -- `GOTOOLCHAIN=local GOPROXY=off GOSUMDB=off go test -mod=readonly -count=1 ./...` - passed on the reviewed checkout. -- `go run ./internal/apicheck` passed. -- Isolated probes against an archive of the reviewed commit reproduced F1–F3 - below. They used temporary consumer repositories and local bare Git remotes. - -The investigative probes ran in a disposable checkout. Their setup and outcomes -are recorded with each finding for future regressions. Validation covered local -fixtures on Go 1.26.8. Live Gitea/Woodpecker integration, published-module -installation, and minimum-Go-1.25 compatibility remain unverified. These results -belong to the original source review; this revision updates its recommendations. - -## Goal coverage - -| Goal | Assessment and evidence | -| --- | --- | -| One standard source-publication transaction | Substantially implemented in [Publish](../../internal/publish/publish.go): captured candidate, authoritative `main`, annotated tag, exact object/ref push, and bounded recovery. F2 is a correctness exception. | -| One validation of the intended candidate | Callback/default validation plus mutable-state rechecks are implemented in [candidate](../../internal/candidate/check.go). F1 can silently narrow the default suite; F4 concerns the selected customization model. | -| Consumer-selected binaries or source-only releases | [Build](../../internal/build/build.go) supports target pairs and empty sets. Source-only delivery creates no binary manifest. This is the right distinction. | -| Shared runtime version, build flags, naming, and smoke check | Implemented through [buildinfo](../../buildinfo/version.go), the builder, and external consumer build tests. F3 identifies an opportunity for predictable internal defaults. | -| Immutable hosted contents and recoverable partial delivery | [Delivery](../../internal/delivery/delivery.go) and [Gitea](../../internal/gitea/) compare notes and asset bytes, reject conflicts, and add missing assets. F7 identifies an outcome-reporting inconsistency. | -| Public contract ownership and small runtime dependency graph | Root and runtime facades follow [ADR 0001](../adr/0001-public-facade.md); compiled boundary checks pass. Keep these boundaries. | -| Thin application integration and less repeated infrastructure | Representative consumer adoption remains to be evaluated. F5–F6 identify remaining orchestration and setup duplication. | -| Ready deployment path | Prepared templates and local fixtures exist. Immutable deployment pins, credentials, activated workflows, and live verification remain explicitly open in the roadmap. | - -## Findings - -### F1 — High: ambient Go flags can turn candidate validation into a false pass - -**Evidence.** `runDefaultValidation` in -[internal/candidate/check.go](../../internal/candidate/check.go) controls module -network access, workspace discovery, and toolchain selection, but inherits -`GOFLAGS`. The default command supplies `-mod=readonly -count=1`; neither flag -cancels a test-name filter. Configured checks also inherit the environment through -[RunChecks](../../cmd/releasekit/internal/cli/config.go). ReleaseKit's own -[profile](../../releasekit.json) explicitly supplies the test command without -controlling `GOFLAGS`. - -**Reproduction.** Create a clean `main` fixture with a matching committed note -and one `TestFails` that calls `t.Fatal`. `Check` with no callback fails as -expected. Set `GOFLAGS=-run=^$` and invoke the same operation against the same -commit: it returns nil and reports `[no tests to run]`. -The [Go command documentation](https://pkg.go.dev/cmd/go#hdr-Environment_variables) -confirms that `GOFLAGS` supplies defaults to commands that recognize its flags. - -**Consequence.** A normal developer setting used for focused testing can cause a -release to pass after skipping the default suite. The reproduction uses an -unchanged committed candidate and an ordinary shell setting. - -**Recommendation.** Make the standard validation command own its effective Go -flags and host target, including values supplied through Go's persistent -configuration. Preserve caches and legitimate dependency preparation settings. -Share internal Go-environment handling where the semantics match. Preserve -the settings appropriate to native tests and static release builds separately. -Apply the same baseline to ReleaseKit's own profile. Retain a regression showing -that a failing test remains effective under an ambient filter. F4 and Design -Choice 1 describe how product-specific checks compose with this baseline. - -### F2 — High: automatic push recovery can query a different endpoint and report false absence - -**Evidence.** [reconcilePush](../../internal/publish/publish.go) calls -`Endpoint.QueryTag` using the captured URL and command-scoped remote. -[QueryTag](../../internal/git/tag.go) runs the query directly. -[Resolve/Recheck](../../internal/git/remote.go) call `verifyScopedURLs` before -publication. Git still applies current URL rewrite configuration to the captured -literal URL. The manual recovery instructions in -[the runbook](../release.md#resolve-failures) already require a URL-equality check. -The automatic path lacks the equivalent check. - -**Reproduction.** In a temporary publication fixture, wrap Git so the actual tag -push succeeds, then add a local `url..insteadOf` rule for -the captured endpoint and return exit 77 to simulate a lost acknowledgment. -`Publish` returns `state=not_published`, `phase=reconciliation`, and says the -authoritative tag is absent. Direct inspection of the original bare repository -shows the exact tag object returned in `PublicationResult` is present. - -**Consequence.** The result gives incorrect recovery advice after an ambiguous -push. It converts a query to the wrong endpoint into proof that the intended -endpoint lacks the published tag. This contradicts the existing recovery -contract for the authoritative endpoint. - -**Recommendation.** Within the existing bounded recovery context, verify that the -captured endpoint still resolves to itself before the one authoritative tag -query. If verification fails, preserve the push error and local tag and return -`unknown`. Keep recovery bound to the captured endpoint. Cover the -successful-publication/false-absence reproduction and ordinary recovery against -an unchanged endpoint. Preserve successful push as the completion point. - -### F3 — Internal improvement: ambient CPU settings change binary compatibility - -**Evidence.** `goEnvironment` in [internal/build/build.go](../../internal/build/build.go) -standardizes several Go settings and inherits architecture feature variables, -`GOEXPERIMENT`, and the persistent Go environment file. - -**Reproduction.** Build the same committed consumer and `v1.2.3` for -`linux/amd64` twice, once with `GOAMD64=v1` and once with `GOAMD64=v2`. -Both builds succeed with `SourceVerified=true` and the filename -`fixture-v1.2.3-linux-amd64`. Their SHA-256 digests differ, and `go version -m` -records the respective feature levels. Go documents these as different target -microarchitecture requirements in its -[environment reference](https://pkg.go.dev/cmd/go#hdr-Environment_variables). - -**Consequence.** A developer's ambient CPU setting can narrow a binary's hardware -compatibility. Different build inputs can also produce a digest conflict during -a delivery retry. Existing digest comparison correctly preserves published bytes. -The practical benefit of addressing this finding is predictable hardware -compatibility with fewer settings for application developers to manage. - -**Recommendation.** Use ordinary baseline CPU settings and shared build flags -internally, with the available compatible Go toolchain. Control incidental -settings that affect expected compatibility or validation. Keep the application -profile focused on its package, binary name, and targets. Exact toolchain -pinning and detailed build metadata remain optional operational choices. -When a retry requires the original bytes, preserve and reuse those artifacts. -Design Choice 2 compares local toolchain use with a centrally maintained build -environment for consumers that benefit from shared setup. - -### F4 — Design priority: adding a custom check replaces the entire standard suite - -**Evidence.** [CLI routing](../../cmd/releasekit/main.go) installs a validation -callback whenever `checks` is nonempty. [Validate](../../internal/candidate/check.go) -then skips its default test command. This agrees with the -[configuration contract](../config.md), and the Go API deliberately permits a -replacement `Validate` callback. - -**Consequence.** Adding one product-specific example check requires the consumer -to remember and reproduce the standard test command, environment, and ordering. -The profile becomes a small release program that repeats shared policy. Migrating -to built-in tests requires removing their invocation from existing custom scripts -to preserve one suite run. - -**Recommendation.** Run the shared offline suite once, followed by optional -product-specific checks. Move redundant suite invocations out of consumer scripts. -Retain checks for actual product behavior, such as PromptKit's examples. Add -alternative test-invocation settings when a concrete consumer requirement -justifies them. This choice changes the current customization contract; Design -Choice 1 records the replacement-callback alternative. - -### F5 — Design priority: the CLI owns reusable tagged-build delivery orchestration - -**Evidence.** [runDelivery](../../cmd/releasekit/main.go) chooses a temporary -output directory, invokes the public builder, converts receipts, and then calls -`Deliver`. The [public delivery request](../../delivery.go) accepts an already -produced `BuildResult`. A Go consumer wanting the normal build-and-deliver -operation must reproduce orchestration already implemented by the CLI. The -default CLI path also builds and runs the native smoke executable -before `Deliver` verifies that HEAD matches the selected local tag. - -**Consequence.** Temporary storage, build sequencing, tagged-source preflight, -and cleanup have more than one potential owner. An invalid tagged checkout can -consume a complete cross-build before it is rejected. The CLI owns domain coordination -alongside its parsing, presentation, and exit-status responsibilities. - -**Recommendation.** Put the ordinary verify-tagged-source, build-selected-targets, -and deliver sequence behind the orchestration facade. Verify the local tagged -source before expensive compilation, then retain the necessary checks before -remote effects. Let the CLI adapt JSON, credentials, and output to that operation. -Use the same build declaration for candidate validation and delivery. Support -caller-provided builds for concrete needs such as retrying with retained -artifacts, as discussed in Design Choice 3. Keep separate building useful for -local development. The ordinary consumer workflow should complete delivery in -one invocation; advanced artifact handoffs can use private coordination data -when needed. - -### F6 — Adoption priority: shared deployment still depends on copied mechanics - -**Evidence.** The original source-only and binary templates repeated -fetch/checkout guards, local exclusions, cache setup, and tool installation; -they are now consolidated in the maintained -[tag-delivery template](../../examples/woodpecker/tag-delivery.yml). The binary -template added an explicit build/receipt/deliver sequence even though the CLI -already supports combined delivery. ReleaseKit's -[own workflow](../../examples/woodpecker/releasekit-source-delivery.yml) has a -separate first-release bootstrap. Consumer pins remain placeholders as documented. - -**Consequence.** Copied CI mechanics require maintenance in each consumer and -can drift. A shared installation and update convention would simplify local -publication and CI delivery. - -**Recommendation.** Provide one maintained integration entry point and one -default delivery sequence for source-only and binary profiles. Consumers select -the ReleaseKit version, supply product settings, and provision credentials. -Centralize installation and update instructions. Use versioned source -installation for the shared CI command. Evaluate a maintained image by the -additional setup and maintenance effort it saves. -Keep dependency preparation separate from offline validation/builds. A split -build/delivery flow remains useful for an actual credential boundary or artifact -handoff. See Design Choice 4 for packaging alternatives. - -The original `TestWoodpeckerDeliveryCommandSequences` and the ReleaseKit -workflow test reconstructed workflow commands, so YAML drift could leave the -tests green. The maintained tag template and ReleaseKit's bootstrap workflow -are now exercised from their command blocks by local Git/HTTP fixtures. The Go -bootstrap shim verifies template arguments while mapping the pinned module -invocation to the test executable; it does not verify published-module -availability. Real installation and live Woodpecker execution remain -deployment work. - -### F7 — Medium: delivery asset classifications overlap inconsistently - -**Evidence.** In [UploadMissing](../../internal/gitea/upload.go), a failed -reconciliation list adds an asset to `Uncertain` while leaving it in `Pending`. -The `AssetMissing` reconciliation branch does the same for an unresolved write; -the default/unverifiable branch removes it from `Pending`. A reconciled conflict -can also remain pending. The existing -`TestUploadMissingReportsUnknownWhenReconciliationReadFails` in -[upload_test.go](../../internal/gitea/upload_test.go) explicitly expects the -same asset in both pending and uncertain collections. - -**Consequence.** Overlapping categories require special handling by consumers. -The CLI can present one file as both pending and uncertain, while a -slightly different failure reports it only as uncertain. The overall unknown -state remains conservative. Consistent categories would simplify recovery -reporting and automation. - -**Recommendation.** Prefer mutually exclusive current-outcome categories: -confirmed matching, uploaded, known pending, conflicting, and uncertain. Move an -asset out of pending when its outcome becomes uncertain or conflicting, and -clarify the facade GoDoc. Design Choice 5 records the alternative superset -interpretation. - -### F8 — Maintainability: artifact rules have several implementation owners - -**Evidence.** Filename construction occurs in `artifactFilename` in -[the builder](../../internal/build/build.go), `receiptArtifactFilename` in -[CLI receipt handling](../../cmd/releasekit/internal/cli/receipt.go), and -`declaredBuildAssets` in [delivery](../../internal/delivery/assets.go). -Target normalization and filename-component validation are also repeated across -these boundaries. CLI receipt handling carries substantial domain validation -alongside JSON serialization. Build invocation uses its own `exec.CommandContext` -path while default validation uses [process.Run](../../internal/process/process.go), -with independently constructed Go environments. - -**Consequence.** A change to target identity, naming, or build settings can leave -the builder, receipt reader, and delivery validator disagreeing. F1 and F3 show -why divergent Go-environment ownership matters beyond cosmetic duplication. - -**Recommendation.** Give internal build/artifact rules one owner and reuse them -from receipt and delivery adapters. Share Go invocation/environment construction -where the semantics match. Keep the explicit facade conversions required -by the ADR. Focus refactoring on the small internal helpers that own these rules. - -## Target state - -Retain the existing source transaction: committed stable-version note, clean -`main`, candidate already on authoritative `main`, one validation, selected-target -build verification, exact annotated-tag publication, and bounded recovery. -Source publication finishes independently of hosted delivery. Keep additive, -content-checked delivery and lightweight runtime version access. - -Make ordinary integration a versioned tool invocation plus a small product -profile and credential provisioning. The profile supplies product identity, -selected binaries and targets, delivery destination, and product-specific checks. -ReleaseKit owns the standard suite, routine build settings, delivery sequence, -and recovery reporting. Product developers choose versions and write -compatibility notes. Evaluate each proposed setting by the work it saves them. - -The [implementation plan](implementation.md) owns the stages, API changes, -regression coverage, and completion criteria needed to reach this target. -Representative adoption should demonstrate fewer scripts, duplicated tests, -setup steps, and recurring release decisions. - -Feature expansion should follow demonstrated consumer needs and measurable -reductions in application maintenance or developer effort. - -## Design Choices - -The implementation plan selects the recommended directions below for the -upcoming sprint. Alternatives record the tradeoffs for future consumer needs. -These choices describe the target behavior; current contracts change as their -implementation lands. - -### 1. Should product checks supplement or replace standard validation? - -**Selected direction:** Run the shared offline Go suite once, followed by optional -product-specific checks. ReleaseKit owns the command and its routine environment -settings. Migrate repeated suite invocations out of application scripts. Add -alternative invocation settings when an actual consumer requirement establishes -their value. An application adding an example check should declare that check -and receive the standard suite automatically. This gives developers one ordinary -validation path to understand. - -**Viable alternative:** Keep a replacement callback or complete validation -command for products with unusual test layouts. This is a simple composition -boundary and can accommodate existing product test infrastructure. It assigns -more release responsibility to the application, so its value depends on the -specific consumer need. - -### 2. How should ReleaseKit choose build settings? - -**Selected direction:** Use the available compatible Go toolchain, ordinary -baseline CPU settings, and shared build flags. Handle incidental settings internally -so developers can rely on the selected target's expected compatibility. Keep -application configuration small. Toolchain-dependent byte differences are -acceptable; digest checks preserve existing published content, and retained -artifacts support retries requiring the same bytes. ReleaseKit can own baseline -settings internally while applications declare their packages and targets. - -**Viable alternative:** A shared CI image can supply a centrally selected Go -version and build environment when this makes installation and support easier. -Maintainers own image updates; applications use the shared integration. This is -useful where a common environment reduces operational work. Its value should be -measured against image maintenance and the suite's differing Go requirements. -Explicit hardware variants can be added for a demonstrated product need. - -### 3. Should the library own build-and-deliver, or accept only completed builds? - -**Selected direction:** Provide one facade operation for tagged-source verification, -selected-target builds, temporary storage, checksums, uploads, and cleanup. -Use it from the CLI so both interfaces share the procedure. Retain separate -building for local development and support prebuilt delivery where a concrete -handoff or retry requirement justifies it. Routine delivery should require one -invocation, with ReleaseKit managing the artifact lifecycle. This minimizes -consumer orchestration code. - -**Viable alternative:** Keep separate build and delivery primitives with a -maintained composition helper. This suits consumers that require credential -isolation between stages or need to retain artifacts for later delivery. Those -consumers accept responsibility for the artifact lifecycle in exchange for the -operational separation they need. - -### 4. How should the shared executable and CI integration be distributed? - -**Selected direction:** Choose the simplest maintained entry point for installation, -updates, and delivery. Use versioned source installation and a shared CI delivery -command. The command prepares the tagged checkout, reads its product profile, -prepares dependencies for selected binaries, and invokes ordinary facade delivery. -Centralize reusable setup and provide one clear upgrade procedure. Applications -select a ReleaseKit version and supply product settings and credentials; shared -integration owns routine setup. -Assess packaging by the consumer code and recurring developer work it removes. - -**Viable alternative:** Publish a maintained CI image containing ReleaseKit and -a compatible Go/Git environment when it substantially reduces setup. The image -provides a ready-to-run integration and centralizes environment maintenance. -It also creates an image publication and update responsibility, which should be -reflected in the release procedure. Either packaging choice should give -applications a small configuration and a routine invocation. - -### 5. How should delivery results support simple recovery? - -**Selected direction:** Use exclusive outcome categories: matching, uploaded, known -pending, conflicting, and uncertain. Present ordinary callers with completion or -a clear failure and recovery instruction. Keep asset details available for -diagnostics. Derive recovery guidance centrally so each application can present -the result directly. Consistent categories simplify implementation and -interpretation. - -**Viable alternative:** Pending includes every unfinished declaration, with -conflicting/uncertain as diagnostic subsets. This can simplify a progress UI -when defined explicitly and applied in every branch. Consumers must then -subtract blocked subsets before deriving retry work. Apply the chosen -meaning consistently across all outcomes. diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md deleted file mode 100644 index d2fda19..0000000 --- a/docs/roadmap/implementation.md +++ /dev/null @@ -1,598 +0,0 @@ -# ReleaseKit audit implementation plan - -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. - -## How to execute this plan - -Implement one numbered stage per prompt, in order. Each stage includes its -production change, relevant tests, and current-contract documentation. Leave the -repository compiling and its checks passing at each stage boundary. Record -completed stages here with a concise validation result; report the commit -identifier in the stage completion response. Read -[development guidance](../development.md) and its applicable policies at the -start of each stage. - -Use the [agent policy](../policy/agents.md), [architecture -policy](../policy/architecture.md), [testing policy](../policy/testing.md), and -[documentation policy](../policy/documentation.md). Discover current symbols -through the codebase graph, then inspect their callers and tests before editing. -The paths below locate the baseline; internal names may evolve during the work. -Use ordinary functions and existing internal packages where their ownership -fits. Public named types remain facade-owned with explicit internal conversions. - -For each stage, run focused behavioral tests for its changed responsibilities. -Then run the existing repository checks from the root: - -```sh -GOTOOLCHAIN=local GOPROXY=off GOSUMDB=off go test -mod=readonly -count=1 ./... -GOTOOLCHAIN=local GOPROXY=off GOSUMDB=off go run ./internal/apicheck -``` - -Prepare dependencies before these offline checks when needed. Review changed -GoDoc, examples, local documentation links and fragments, and `git diff --check`. -Reuse successful checks for unchanged content. Commit each completed stage -under the agent policy. These implementation checks serve the development -workflow. - -## Decisions for this sprint - -These choices resolve the audit's design alternatives for implementation: - -- Candidate validation runs the standard offline Go suite once, then optional - product checks, then selected-target build verification. Rename the Go - callback to `AdditionalChecks`; JSON retains `checks` with additive semantics. -- ReleaseKit uses the available compatible Go toolchain, internal baseline CPU - settings, and shared build flags. It controls incidental flags and persistent - Go settings while preserving operational configuration such as caches. -- `Deliver` accepts a build declaration and owns temporary build output, - checksums, uploads, and cleanup. An explicit prebuilt path retains original - artifacts for retries and supports separated build/delivery environments. -- Delivery asset categories are disjoint observations: matching, uploaded, - known pending, conflicting, and uncertain. Existing overall delivery states - and content-preservation rules remain authoritative. -- A versioned source-installed command is the initial shared CI entry point. - Add `ci-deliver` for explicit CI checkout and dependency preparation followed - by the same facade delivery operation. Ordinary `deliver` remains suitable - for an already prepared checkout. CI images remain an operational option. -- Shared artifact rules and Go execution settings have small internal owners. - Application profiles continue to declare product facts and additional checks. - -The callback and delivery request changes are deliberate pre-release API -changes. Update all in-repository callers and their canonical documentation in -the corresponding stage. The initial release note should describe the final -interfaces and migration impact when that release is prepared. - -The sprint preserves the existing source transaction, successful-tag-push -completion point, bounded recovery, content-aware retries, standalone `Build`, -and lightweight `buildinfo`. Build observations and private receipts retain -their existing source-eligibility meaning. Toolchain-dependent byte differences -remain acceptable. Build identity remains an observation of the checked source -and produced files under the existing contracts. Live deployment and sibling -repository migrations remain separate adoption work in the -[product roadmap](releasekit.md). - -## Stage 1 — Keep ambiguous-push recovery on the captured endpoint - -**Covers:** F2. **Primary owners:** `internal/git/tag.go`, -`internal/git/remote.go`, `internal/publish/publish.go` and their tests. - -1. Before `Endpoint.QueryTag` performs its remote read, reuse - `verifyScopedURLs` with the captured endpoint and command-scoped configuration. - Verify that the captured URL still resolves to itself. Use the existing - reconciliation context and timeout for both verification and the remote read. -2. Treat verification failure as unreadable authoritative state. Preserve error - identity through wrapping so `reconcilePush` reports `unknown`, retains the - local tag, and preserves the original push failure for diagnosis. -3. Keep the captured endpoint as recovery's authority. The local resolution - check precedes the existing single remote tag query. Preserve exact tag-object - and peeled-commit comparison and successful push as the completion point. -4. Update relevant recovery GoDoc and internal guidance to explain the - automatic URL-resolution check. Keep the manual recovery runbook consistent. - -**Completion evidence:** Extend the existing local Git publication fixtures with -F2's lost-acknowledgment reproduction: actually publish the tag, install a URL -rewrite to an empty bare repository, then report a push error. Recovery must -return unknown and preserve the tag/error; direct inspection of the original -remote must find the intended object. Existing unchanged-endpoint success, -absence, conflict, and unreadable-recovery tests continue to pass. Test the -behavior through publication; avoid a second copy of the full recovery matrix. - -**Completed:** Recovery now verifies the captured URL before its one tag query. -The rewrite reproduction returns unknown, preserves the local tag and both -errors, and confirms the object on the original remote. Focused publication -tests, the full offline suite, API boundary checks, and documentation whitespace -checks pass. - -## Stage 2 — Own effective Go settings for validation and builds - -**Covers:** F1, F3, Go-environment portion of F8. **Primary owners:** -`internal/candidate/check.go`, `internal/build/build.go`, `internal/process/`, -and a small new `internal/gotool` package. - -1. Put effective Go-environment construction and common invocation behavior in - `internal/gotool`. Reuse the existing subprocess boundary for context, - working directory, output, and error handling. Support native validation and - static target builds as distinct modes of the same implementation. -2. Account for both the process environment and values from Go's persistent - environment file. Resolve effective Go configuration with the installed Go - command under local toolchain selection and a controlled `GOFLAGS`. Ensure - configuration discovery itself tolerates the ambient settings being replaced; - an experiment override used only for discovery must not become the build - default. Carry effective operational settings into child environments, then - use `GOENV=off` - there so removed settings cannot reappear from the persistent file. Retain - ordinary process variables and effective cache, module-cache, temporary, - tool-location, and native C-tool settings. Keep informational `go env` output - separate from configuration when constructing child environments. -3. Own `GOFLAGS`, `GOWORK`, `GOTOOLCHAIN`, module-network settings, target - selection, experiment selection, and architecture-feature settings. Standard - validation uses `go test -mod=readonly -count=1 ./...`, host OS/architecture, - `GOWORK=off`, `GOTOOLCHAIN=local`, `GOPROXY=off`, `GONOPROXY=none`, and - `GOSUMDB=off`. Resolve the Go host target independently of ambient cross-build - settings. Native tests retain native Go cgo behavior and explicit native - C-tool configuration; release builds retain `CGO_ENABLED=0`. -4. Clear ambient experiments and architecture tuning for the child so the - selected Go toolchain supplies ordinary baseline defaults. Handle the Go - feature variables for supported toolchains, including `GOAMD64`, `GOARM`, - `GOARM64`, `GO386`, `GOMIPS`, `GOMIPS64`, `GOPPC64`, `GORISCV64`, and `GOWASM`. - Clearing must take effect for persisted values as well. Retain the existing - release flags, linker injection, target selection, and native version smoke - check. Keep these settings internal; the profile needs no new tuning fields. -5. Route default validation, build toolchain/host queries, target compilation, - and native smoke-build compilation through the shared owner. Preserve useful - compiler diagnostics and cancellation. Custom product commands retain their - explicitly selected arguments and environment overlays. -6. Update the build and check consumer guides and relevant GoDoc with the - supported behavior: shared baseline settings and the available compatible - toolchain. Exact internal environment construction belongs in internal docs. - -**Completion evidence:** A genuinely failing fixture test still fails with -`GOFLAGS=-run=^$` supplied through either the process or a temporary Go env file. -An ambient cross-target setting still results in host-native validation. Extend -existing build fixtures to demonstrate that ambient/persisted `GOAMD64=v2` and -experiment settings do not alter the selected baseline build settings. Inspect -build metadata where useful; identical binary bytes are unnecessary evidence. -Use a temporary configured cache to demonstrate that persistent cache choices -survive. Preserve existing version injection, empty-target, cancellation, and -partial-build behavior. Fixtures use temporary Go configuration and never edit -the developer's persistent settings. - -**Completed:** Shared Go configuration now drives default validation, -toolchain/host queries, target builds, and the native smoke build. Failing -validation fixtures prove process and persistent `GOFLAGS` cannot suppress a -real test and that cross-target settings still run tests on the host. Build -metadata confirms ambient and persistent tuning are cleared, and a temporary -persistent cache is used. Focused tests, the full offline suite, API boundary -checks, and documentation whitespace checks pass. - -## Stage 3 — Make product checks additive - -**Covers:** F4 and ReleaseKit's own F1 exposure. **Primary owners:** `check.go`, -`publish.go`, `internal/candidate/`, CLI profile mapping and fixtures. - -1. Rename `ReleaseRequest.Validate` to - `AdditionalChecks func(context.Context, Candidate) error` and update the - corresponding internal request and facade conversions. The callback keeps - the existing candidate-value ownership and error-wrapping behavior. -2. Make `candidate.Validate` always run the shared offline suite first. On - success, invoke `AdditionalChecks` once when supplied. Run selected-target - build verification after these checks through the existing orchestration. - A failure or cancellation ends the sequence and preserves its cause. -3. Retain `checks` in JSON as ordered additional commands. Map the CLI's - `RunChecks` callback to `AdditionalChecks`. Keep the existing argument-vector - and per-command environment semantics. -4. Remove repeated standard-suite commands from `releasekit.json` and example - profiles. Preserve additional checks that address actual product behavior. - Update in-repository callback callers and fixtures to provide small valid Go - modules with an effective default suite. A callback fixture must exercise - its intended callback behavior after that suite succeeds. -5. Update facade GoDoc, `docs/config.md`, `docs/cli.md`, check/publish consumer - guides, examples, and affected internal documentation. Explain migration: - rename the callback and remove standard-suite invocations from custom checks. - -**Completion evidence:** Through the public facade, prove that a failed standard -suite prevents the additional callback and publication, that an additional -failure prevents publication while preserving error identity, and that a -successful publication runs the standard suite and additional checks once for -its captured candidate. Reuse existing mutation/recheck tests with the new -callback. One CLI profile test covers ordered extra commands. Keep callback -unit coverage and end-to-end suite-count coverage at distinct boundaries. - -**Completed:** `AdditionalChecks` now runs after the standard offline suite in -the public check and publish flows; selected builds remain after both. The CLI -keeps ordered JSON `checks` as additional commands, and the bundled profiles no -longer repeat the standard suite. Facade tests prove suite failure stops checks -and publication, additional-check errors retain identity, and successful -publication runs both once for its captured candidate. CLI coverage verifies -ordered checks. The full offline suite, API boundary check, and documentation -whitespace checks pass. - -## Stage 4 — Consolidate artifact identity and declaration rules - -**Covers:** artifact portion of F8. **Primary owners:** `internal/build/`, -`internal/delivery/assets.go`, `cmd/releasekit/internal/cli/receipt.go`. - -1. Add a small internal artifact-contract owner for target normalization, - filename-component validation, artifact names, and the expected declaration - for a build. Choose `internal/artifact` for these shared pure rules. -2. Move the existing rules from builder, receipt, and delivery into that owner. - Preserve accepted inputs, target order/deduplication, filenames, manifest - naming, and validation meaning. Keep build execution in `internal/build`, - hosted-content checks in delivery/Gitea, and receipt JSON/path handling in - the CLI adapter. -3. Use ordinary conversions at facade and receipt boundaries. Preserve - facade-owned public types and the current private receipt format. Consolidate - repeated declaration comparisons while retaining boundary-specific checks - for repository, commit, version, file location, and actual file contents. -4. Update the internal package inventory. Keep exact public build/result - contracts in GoDoc and private receipt lifecycle in its existing owner. - -**Completion evidence:** Existing build-to-receipt-to-delivery tests retain -behavior for normalized targets, filenames, altered files, mismatched identity, -and manifests. Add only missing coverage for disagreement between these -boundaries. The API/dependency checker confirms that the shared internal owner -has not leaked through exported signatures or runtime dependencies. - -**Completed:** `internal/artifact` now owns target normalization, filename -components, binary declarations, and checksum-manifest naming. The builder, -receipt adapter, and delivery validation share those rules while retaining -their build, receipt-path/file, and hosted-content responsibilities. Existing -coverage plus a mismatched delivery declaration check preserve cross-boundary -behavior. Focused tests, the full offline suite, API boundary checks, and -documentation whitespace checks pass. - -## Stage 5 — Make delivery outcomes disjoint and actionable - -**Covers:** F7. **Primary owners:** `internal/gitea/upload.go`, delivery result -GoDoc, CLI delivery reporting, and their tests. - -1. Define the five collections as current observations for each reported asset. - `Matching` means existing matching content; `Uploaded` means confirmed upload - during this invocation; `Pending` means known missing work; `Conflicting` - means a detected conflict; `Uncertain` means unresolved state. Each asset - appears in at most one collection in a returned result. -2. In every upload/reconciliation branch, remove an asset from `Pending` when - moving it to matching, uploaded, conflicting, or uncertain. In particular, - fix failed reconciliation reads, conflicts, and unresolved writes. Later - known-missing assets can remain pending when an earlier upload stops work. -3. Preserve the existing overall delivery states and their handling of remote - writes. Early failures can return incomplete asset information. Category - exclusivity establishes no claim that every declaration has been observed. -4. Keep concise state-based recovery guidance in one CLI formatter: correct - local/preflight failures before retrying; retry partial delivery after fixing - its cause; resolve uncertain remote state before retrying; investigate - conflicting content and use a new version when source or published contents - require correction. Mention retained original artifacts when a rebuild would - conflict. Go callers use the documented overall state and asset categories. -5. Update delivery GoDoc, `docs/cli.md`, the delivery consumer guide and Gitea - integration documentation. Keep diagnostics available alongside the summary. - -**Completion evidence:** Update the existing reconciliation-read-failure test -that currently expects overlap. Extend existing upload tests to cover conflict, -missing-after-ambiguous-upload, matching-after-lost-acknowledgment, and later -pending assets. Assert category exclusivity and meaningful overall state at the -upload boundary. CLI tests verify recovery meaning and exit classification -without freezing full diagnostic wording. - -**Completed:** Delivery asset categories now contain disjoint current -observations, with later known-missing assets retained when an earlier upload -stops work. CLI failures include state-based recovery guidance, while GoDoc and -the delivery and Gitea guides describe category meaning and incomplete early -observations. Upload and CLI tests cover reconciliation outcomes, recovery -classification, and category exclusivity. The full offline suite, API boundary -check, and documentation whitespace checks pass. - -## Stage 6 — Give the facade ownership of build-and-deliver - -**Covers:** F5. **Primary owners:** `delivery.go`, `internal/delivery/`, -`internal/build/`, and existing temporary-directory helpers. - -1. Change `DeliveryRequest.Build` to `*BuildSpec`. Add - `Prebuilt *BuildResult` and `Output io.Writer`. `Build` requests managed builds; - `Prebuilt` supplies an existing result. Supplying both is an invalid request - because the operation needs one artifact source. With neither, or with an - empty selected target set, ordinary delivery is page-only. Preserve the - existing handling of empty prebuilt results. -2. Implement the reusable orchestration inside `internal/delivery`; the public - facade performs conversions. Verify version, product, local tag/HEAD - agreement, checkout cleanliness, and the committed release note before - compilation. Preserve historical lightweight-tag and detached-HEAD support. -3. For nonempty `Build`, create temporary output outside the worktree using the - existing helper, invoke the shared builder, and feed its result into the - existing asset validation/delivery path. Defer cleanup for success, failure, - and cancellation. Return diagnostic progress through `Output`; managed - temporary paths have no caller-owned lifetime. -4. Before hosted writes, retain the tagged-source eligibility check and the - build-result, file-digest, and manifest checks. A checkout change during the - build must fail eligibility. Use the same captured tag commit to read the - note and validate the build. Reuse the existing builders and delivery client. -5. `Prebuilt` retains caller-owned files and existing source/identity/content - checks. Its build result declares its targets as today. The CLI continues - comparing receipts with the selected profile. This path supports original - bytes across retries; callers own retention and cleanup. -6. Keep pre-remote build/preflight failures `DeliveryNotAttempted`. Preserve - candidate identity when known, wrapped error causes, cancellation, and the - current mapping of hosted failures and partial progress. -7. Update all Go callers for the request shape. As an intermediate step, map - the CLI's current already-built result to `Prebuilt`; Stage 7 removes that - duplicate orchestration. Update delivery GoDoc and the consumer guide with - the normal `Build` path and the explicit `Prebuilt` lifecycle. - -**Completion evidence:** Add facade-level tests using a real small Go consumer -and a local HTTP server for managed binary delivery and page-only delivery. -Prove invalid tagged source fails before Go compilation or hosted writes, -build failure prevents hosted writes, and managed temporary output is cleaned -on success and failure. Extend existing mutation/cancellation coverage where -needed. Preserve prebuilt retry, digest conflict, note conflict, and source -eligibility coverage. Confirm the two facades' dependency boundaries. - -**Completed:** `Deliver` now owns optional managed builds, page-only requests, -and explicit prebuilt artifact delivery behind the public facade. Managed output -uses temporary storage outside the checkout and is cleaned after success, -failure, and cancellation; source and note checks precede compilation, and -eligibility is rechecked before hosted writes. Prebuilt files remain -caller-owned. Consumer and internal package guides describe these paths. -Facade-level consumer and HTTP tests cover managed upload, page-only delivery, -preflight and build failures, checkout mutation, cleanup, cancellation, and -prebuilt ownership. The full offline suite, API boundary check, and -documentation whitespace checks pass. - -## Stage 7 — Route ordinary CLI delivery through the facade - -**Covers:** the CLI portion of F5. **Primary owners:** -`cmd/releasekit/main.go`, CLI receipt adapters, CLI tests and documentation. - -1. Change ordinary `runDelivery` to pass the configured `BuildSpec` and output - writer directly to `Deliver`. Remove its temporary-directory and standalone - build coordination. Keep profile parsing, credential lookup, presentation, - and exit-code selection in the CLI. -2. Retain `build --output` and `deliver --assets`. The latter loads and verifies - the private receipt, compares it with the selected profile, and supplies - `Prebuilt`. Keep stale-receipt invalidation and standalone build behavior. -3. Share the final CLI-to-facade delivery adapter so the CI entry point in Stage - 9 can use it after preparation. Keep ordinary `deliver` free of dependency - downloading and checkout mutation. -4. Update CLI/configuration guidance and examples to make one `deliver` - invocation the normal path. Describe split build/delivery for retained bytes - and credential separation. Preserve exit statuses 0, 1, 2, and 3. - -**Completion evidence:** CLI tests cover source-only and binary profiles, -preflight failure before compilation, token/profile errors, and the explicit -receipt path. Reuse Stage 6 for domain failure coverage. Confirm the maintained -ordinary command exercises the facade-owned lifecycle and reports F7's results. - -**Completed:** Ordinary `deliver` now passes configured builds and progress -output directly to the public facade; the CLI retains profile, credential, -receipt, presentation, and exit-status handling. `--assets` still validates -the private receipt and supplies caller-owned artifacts. CLI tests cover -page-only and binary profiles, preflight rejection before build progress, -retained prebuilt artifacts, retry observations, and temporary-output cleanup. -The binary workflow and consumer guidance use one `deliver` invocation by -default and explain the separate `build`/`--assets` path. The full offline suite, -API boundary check, and documentation whitespace checks pass. - -## Stage 8 — Add reusable CI preparation operations - -**Covers:** preparation ownership in F6. **Primary owners:** a new root -`preparation.go`, `internal/git/`, `internal/gotool/`, and a small internal -preparation coordinator. - -1. Add facade-owned `TaggedCheckoutRequest` with `RepositoryDir`, `Version`, - `Remote`, and `ExpectedCommit` strings, and - `PrepareTaggedCheckout(context.Context, TaggedCheckoutRequest) error`. - An empty remote selects `origin`. This is an explicit preparation operation - for disposable CI checkouts; ordinary delivery keeps its current behavior. -2. Validate the version and required expected commit before mutation. Fetch - the selected tag from the selected remote with an explicit tag refspec, - verify that its peeled commit equals the expected CI commit, detach checkout - at that commit, and verify HEAD agreement. Use the existing Git subprocess - boundary and preserve Git errors. Use ordinary checkout/fetch behavior; - conflicting local changes or tags are reported for the operator to resolve. -3. Add `PrepareBuildDependencies(context.Context, string) error`, taking the - repository directory. Internally run `go mod download` with the available - compatible local Go toolchain and workspace discovery disabled. Preparation - uses the caller's dependency-access settings, including proxy/private-module - configuration and caches. This operation is explicitly network-capable. - Keep offline test/build environments from Stage 2 distinct from preparation. -4. Keep both operations behind the root facade with internal implementations. - These two additions serve the concrete shared CI workflow and Go consumers - with the same preparation needs. Keep their API small: CI-provider variables, - JSON profile loading, credentials, and output formatting stay in adapters. -5. Add GoDoc and a short preparation section to the delivery consumer guide; - update the internal package inventory. State filesystem/network effects and - cancellation behavior. Preparation does not publish a tag or hosted content. - -**Completion evidence:** Local Git fixtures verify expected-commit agreement, -wrong-tag rejection before checkout, detached checkout, and ordinary local -conflict behavior. A subprocess-boundary test verifies dependency preparation -uses the repository and preparation environment and propagates failure and -cancellation. Keep default tests offline with a local module cache or a small -Go-command fixture; no live module server is needed. - -**Completed:** The root facade now exposes `PrepareTaggedCheckout` and -`PrepareBuildDependencies`. Checkout preparation fetches an explicit tag -refspec, compares the peeled commit with the expected full object ID, and -detaches only after a match; tests cover default and selected remotes, wrong -commits, conflicting local edits and tags, and input rejection before fetch. -Dependency preparation runs `go mod download` with workspace discovery off and -the local Go toolchain, preserving caller proxy, private-module, and cache -settings; subprocess fixtures verify repository selection, failure details, -and cancellation without network access. GoDoc, the delivery consumer guide, -and the internal inventory describe effects and ownership. The full offline -suite, API boundary check, and documentation whitespace checks pass. - -## Stage 9 — Add the shared CI delivery command - -**Covers:** the shared command portion of F6. -**Primary owners:** CLI parsing/routing, CLI command tests, `docs/cli.md`, -and `docs/config.md`. - -1. Add: - - ```text - releasekit ci-deliver [--repo DIR] [--config FILE] [--remote NAME] --commit OID VERSION - ``` - - Options precede the version, consistent with existing commands. Repository - and profile defaults match `deliver`; remote defaults to `origin`. The - explicit command authorizes preparation of the selected CI checkout. -2. Call `PrepareTaggedCheckout`, then load the profile from that checked-out - source, then validate the selected delivery configuration and credentials. - When the profile selects binaries, call `PrepareBuildDependencies`. Finish - through Stage 7's ordinary delivery adapter and `Deliver`. Page-only profiles - skip application dependency preparation and binary work. Read custom profile - paths under the existing CLI path rules. -3. Keep the provider adapter declarative: Woodpecker supplies `CI_WORKSPACE`, - `CI_COMMIT_SHA`, and `CI_COMMIT_TAG` as command arguments. The library and - ordinary CLI operations remain independent of Woodpecker environment names. - Preparation failures return 1; argument/profile/credential errors return 2; - final delivery uses the existing success/failure/unknown status mapping. -4. Update command usage, `docs/cli.md`, and configuration guidance for the new - entry point, its preparation effects, profile-loading order, and exit codes. - Keep ordinary `deliver` documented as operating on prepared source. - -**Completion evidence:** Exercise the command with local Git/HTTP fixtures for -source-only and binary delivery. Prove the profile is read after checkout, -a wrong CI commit fails before application builds or hosted writes, and a -source-only module with unavailable dependencies still reaches page delivery. -Reuse facade tests for the individual preparation and delivery operations. - -**Completed:** `ci-deliver` now prepares the tagged checkout against the -provider-supplied commit, loads the profile from that checkout, validates its -delivery settings and credential, downloads dependencies only for selected -binary targets, and finishes through the existing delivery facade. Local -Git/HTTP fixtures cover source-only and binary delivery, relative custom profile -loading, commit mismatch before Go or hosted requests, and unavailable -source-only dependencies. CLI and configuration guidance describe preparation, -provider arguments, effects, and exit statuses. The full offline suite, API -boundary check, and documentation whitespace checks pass. - -## Stage 10 — Consolidate and exercise maintained CI templates - -**Covers:** installation, workflow duplication, and artifact-testing in F6. -**Primary owners:** `examples/woodpecker/`, CLI workflow tests, installation -instructions, and the product roadmap. - -1. Select versioned source execution as the default bootstrap: - `go run gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit@PIN ci-deliver ...`. - `PIN` is an immutable ReleaseKit revision or published version. Applications - choose a compatible Go/Git image and provision the delivery token. The shared - command owns checkout checks, conditional dependency preparation, and delivery. - The normal Go caches suffice; optional CI cache mounts remain deployment - configuration. Document `go install ...@PIN` for a locally retained executable - and one upgrade procedure based on changing the selected version. -2. Consolidate source-only and binary Woodpecker templates into one maintained - `examples/woodpecker/tag-delivery.yml`, with the product profile selecting - page-only or binary behavior. Remove the two superseded templates and repair - their links. Retain the distinct first-release bootstrap in - `releasekit-source-delivery.yml`, since ReleaseKit's own first source release - must build its tool from the tagged source. Simplify it around the shared - command where this preserves that bootstrap. -3. Replace tests that reconstruct the workflow commands with checks tied to the - maintained artifact. Use a small extractor for the template's one command - block and execute it with controlled CI variables, local Git/HTTP fixtures, - and a Go bootstrap shim that maps the pinned remote tool invocation to the - CLI built from the test checkout. Validate the module/command/version - arguments in the shim. Apply the template's matrix substitutions and - Woodpecker dollar escaping before shell execution. Keep the template subset - simple enough for a small test helper; a general YAML runner is unnecessary. -4. Document bootstrap requirements, token provision, compatible Go selection, - optional caches, dependency preparation, and the version upgrade procedure. - Align `releasekit.md`'s remaining adoption work with source installation; - identify live deployment and the real immutable pin as remaining work. - -**Completion evidence:** Execute the actual maintained command block for both -source-only and binary fixture delivery. A repeated invocation preserves -matching remote content. The bootstrap shim proves template wiring, not -published-module availability. Record that distinction and retain real -installation/live Woodpecker verification as deployment work. - -**Completed:** Source-only and binary consumer delivery now share one -profile-driven `tag-delivery.yml` using versioned `go run ... ci-deliver`; the -duplicated templates were removed. ReleaseKit's separate first-source workflow -still builds its CLI from tagged source and then uses `ci-deliver`. CLI workflow -tests extract and execute the maintained command blocks with matrix -substitution, Woodpecker dollar escaping, local Git/HTTP fixtures, and a Go -bootstrap shim. Both profiles deliver successfully twice, preserving matching -pages and binary assets. The shim validates command wiring but does not prove -published-module availability. Consumer and maintainer guidance now covers -bootstrap requirements, credentials, Go compatibility, caches, dependency -preparation, and pin upgrades. Real pins and live integration remain deployment -work. The full offline suite, API boundary check, and documentation whitespace -checks pass. - -## Stage 11 — Validate representative adoption and close the sprint - -**Covers:** audit-wide acceptance and adoption evidence. **Primary owners:** -existing external-consumer fixtures, consumer guidance, this plan, and the -remaining-work section of `releasekit.md`. - -1. Exercise a source-only consumer with one meaningful extra check and a binary - consumer using `buildinfo`, selected targets, and Gitea delivery. Reuse and - extend the fixtures from prior stages. Verify publication through local Git - remotes and delivery through local HTTP fixtures as separate operations. -2. Review available sibling projects named by the product roadmap read-only. - Use PromptKit and Narratio as the source-only and binary representatives. - Record a concise migration assessment: retained product settings/checks, - release code and repeated tests that can be deleted, runtime-version - adaptation, and required policy - or procedure changes. Label projected deletions as estimates. If a sibling - checkout is unavailable, use the audit evidence and label its verification - date. Keep implementation tests self-contained in ReleaseKit. -3. Assess the final user workflow against the audit: standard tests once, - additional checks declared once, one ordinary delivery invocation, one - versioned CI entry point, clear recovery, and shared artifact/build rules. - Address implementation gaps within their existing stage scope before closing - the sprint. Record any new product decision as such. -4. Reconcile GoDoc, CLI/configuration references, consumer guides, maintained - examples, internal inventory, and the product roadmap with implemented - behavior. Keep the audit's original evidence historical. Record completion - here and link to the remaining adoption/deployment work. -5. Run the standard offline suite and API checks on the final implementation. - Run them with the minimum supported Go 1.25 toolchain when available in the - implementation environment; otherwise record that verification limitation - explicitly. Minimum-version verification is evidence about the existing - module requirement, rather than a new permanent release matrix. -6. Leave source publication, real installation verification, credentials, - workflow activation, live service checks, and changes in sibling repositories - for their deployment/adoption tasks. Follow the maintainer release procedure - when a release is separately requested. Keep ReleaseKit's own deliverables - source-only under the current release policy. - -**Completion evidence:** A concise final record identifies the passing checks, -representative workflows, projected adoption savings, implemented API/profile -migration, and remaining deployment work. Every F1–F8 finding has an implemented -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 -selected approaches and rationale are recorded in the audit's design choices. -Real deployment pins, credentials, service availability, and per-application -migration scheduling are inputs to subsequent deployment/adoption work. They -are separate from the implementation acceptance criteria above. diff --git a/docs/roadmap/releasekit.md b/docs/roadmap/releasekit.md index 832321c..a39eeef 100644 --- a/docs/roadmap/releasekit.md +++ b/docs/roadmap/releasekit.md @@ -1,7 +1,7 @@ # ReleaseKit: shared release process Status: Initial implementation, policy adoption, and architecture remediation -are complete. Consumer adoption, publication, and live integration work remain. +are complete. Consumer adoption and live CI integration work remain. This roadmap records the shared release-process opportunity identified in PromptKit, ConfigKit, Audita, Notarius, Narratio, and Scriptorium on 2026-09-29, @@ -227,20 +227,23 @@ publication and delivery operations. ## Remaining work -- Prepare and publish the first ReleaseKit source release under the - [maintainer procedure](../release.md), then deliver its hosted note page. +- Use the [v0.1.0 baseline](../releases/v0.1.0.md) for initial consumer integration + under the [maintainer procedure](../release.md). - Choose the broader consumer integration test plan and migration sequence. Evaluate API clarity, product-specific checks, and the infrastructure removed from each consuming repository. -- Replace the maintained example's ReleaseKit version placeholder with a real - immutable revision or published version. Provision delivery credentials and - activate consumer Woodpecker workflows as part of deployment. +- Provision delivery credentials and activate consumer Woodpecker workflows + using the maintained example's `v0.1.0` pin or a later selected immutable + version as part of deployment. - Verify live Gitea delivery and Woodpecker execution. Existing verification uses local Git and HTTP fixtures; no live deployment has been verified. - Keep ReleaseKit executable binary distribution deferred until deliverables are deliberately selected. Selecting binaries would require delivery declarations, target checks, automation responsibilities, and corresponding release policy and procedure updates. +- Evaluate a maintained ReleaseKit CI image or specialized validation/build + settings when a demonstrated consumer need justifies their maintenance cost + under [ADR 0002](../adr/0002-routine-releases.md). ## Reviewed implementations diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md deleted file mode 100644 index 766c096..0000000 --- a/docs/roadmap/remediation.md +++ /dev/null @@ -1,164 +0,0 @@ -# ReleaseKit audit follow-up review - -Date: 2026-10-06. -Reviewed source: `55333b0`. -Status: Complete. R1 and R2 are resolved. - -## Scope and assessment - -Reviewed the changes since `536a579` against the [audit](audit.md), completed -[implementation plan](implementation.md), [architecture policy](../policy/architecture.md), -and [routine-release decision](../adr/0002-routine-releases.md). The worktree -was clean at the start of the review. - -The selected architecture is substantially implemented. One Go module exposes -the root orchestration facade and lightweight `buildinfo` runtime facade. -Internal packages own candidate validation, Git publication and recovery, -Go environments, artifact declarations, managed delivery builds, Gitea effects, -and explicit CI preparation. The CLI adapts profiles, credentials, output, and -exit statuses. Standard validation precedes additive product checks; ordinary -delivery uses one facade-owned build-and-deliver operation. The maintained -consumer workflow invokes the shared versioned CI command. - -The audit's F1–F8 changes are present, with behavioral tests for their selected -contracts. R1 below identifies a new defect in the shared Go-environment owner; -R2 identifies increased test cost and coupling introduced by additive validation. -The review found no additional public-type ownership or dependency-direction -gap. The deliberate additive-check, baseline-build, managed-delivery, and CI -preparation decisions remain appropriate. The findings call for implementation -repairs within those decisions. - -## R1 — Medium: Go discovery treats successful diagnostics as invalid configuration - -Status: Resolved. -Category: Correctness and an accidental environment prerequisite. -Introduced by: `0809312`. - -**Evidence:** [Go configuration discovery](../../internal/gotool/gotool.go) -routes both stdout and stderr into the same buffer in `discover` (lines -189–205). `New` parses that combined output as JSON (lines 59–81). A successful -`go env -json` invocation with a warning therefore becomes a decoding failure. -This affects candidate validation and nonempty builds through their shared owner. - -**Reproduction:** Create a clean `main` repository with a Go 1.25 module, a -passing test, a matching committed note, and a source-only product profile. -Set `GOPATH` to the installed Go toolchain's `GOROOT`. On Go 1.26.8, -`go test -mod=readonly -count=1 ./...` succeeds with a warning on stderr. -`releasekit check --repo DIR v1.2.3` fails before running that suite: - -```text -prepare Go toolchain: decode Go host settings: invalid character 'w' looking for beginning of value -``` - -The warning-producing configuration is discouraged by Go, but the Go command -accepts it. ReleaseKit's selected environment contract preserves effective -operational settings; it establishes no requirement that successful discovery -produce an empty diagnostic stream. The same decoding failure follows from any -successful discovery command that emits stderr alongside valid stdout JSON. - -**Required remediation:** Capture configuration stdout and diagnostics -separately. Parse stdout as JSON and retain stderr for command-failure reporting -or ordinary diagnostics. Preserve subprocess error identity, cancellation, -effective operational settings, and the selected validation/build environments. - -**Focused verification:** A controlled Go-command fixture returns valid JSON on -stdout, a diagnostic on stderr, and exit 0; discovery succeeds and preserves -the settings. A failing command retains useful stderr and its cause. Existing -ambient/persistent flag, host-target, cache, and architecture-tuning regressions -continue to pass. These checks add no warning-free configuration requirement. - -**Resolution (2026-10-07):** Discovery captures stdout and stderr separately, -parses configuration from stdout, and preserves diagnostic output and subprocess -causes on failure. A subprocess fixture proves successful JSON discovery accepts -stderr diagnostics and preserves host/cache settings; another verifies failure -diagnostics and exit-error identity. The success regression failed before the -fix. Go-environment, candidate-validation, and build regression checks pass. - -## R2 — Medium: Wrapper regression testing repeats the project suite inside itself - -Status: Resolved. -Category: Test maintainability and development cost. -Introduced by: `3e9b5c1`. - -**Evidence:** [The wrapper regression](../../cmd/releasekit/release_wrapper_test.go) -clones the complete repository for each exit-status scenario, overlays a -hand-maintained list of production and test files (lines 32–45), and invokes -the source publication wrapper. The success, rejected-push, and unknown-push -scenarios each run the project's default suite inside the parent suite. -An inherited `RELEASEKIT_SKIP_WRAPPER_TEST` flag prevents recursive execution -of this one test, while the other publication, delivery, build, and workflow -tests run again in each clone. - -During this review, process inspection confirmed the nested native publisher, -`go test ./...`, and cloned test binaries. The uncached offline suite passed; -the root package took 40.751 seconds and the CLI package took 115.533 seconds -on this host. These timings are observations, not proposed test-duration limits. - -The extra executions provide little distinct evidence about wrapper exit-code -preservation. The file overlay also couples the fixture to unrelated package -changes and supplies only selected uncommitted files, so development checks can -exercise a mixture of the current worktree and committed source. - -**Required remediation:** Keep the real source-bootstrap wrapper and local Git -exit-status scenarios, while giving their candidate validation a small, -self-contained test fixture. Assemble the tool source consistently from the -version being tested. Replace the manually maintained production/test overlay -and suite-recursion skip mechanism with a fixture that exercises wrapper -behavior without rerunning ReleaseKit's complete test suite. Retain the actual -publication and recovery behavior already protected by this regression. - -**Focused verification:** The real wrapper still preserves success 0, known -failure 1, invalid input 2, and uncertain publication 3. The candidate fixture -runs its standard suite, and captured-endpoint recovery still finds the -intended object with separate fetch and push repositories. The outer default -suite supplies the project's broader behavioral evidence once. Use test scope -and command observations for verification rather than a wall-clock gate. - -**Resolution (2026-10-07):** Wrapper fixtures capture the current nonignored -source, including tracked and untracked worktree changes, through one inventory. -They exclude the project's test files and add one small candidate test with an -external validation log. The manually maintained overlay and recursion skip -flag are removed. The real source-bootstrap wrapper preserves statuses 0, 1, -2, and 3; the validation log confirms one suite execution for each valid -candidate and none for invalid input. Captured-endpoint recovery and URL-rewrite -guards still pass with separate fetch and push repositories. - -The focused wrapper regression passes in 7.964 seconds on this host. The final -uncached offline suite passes, with the CLI package taking 22.842 seconds. -These measurements record the observed reduction in duplicated work and add -no duration requirement. - -## Completion verification - -Both fixes are implemented with focused regression evidence. The complete -offline suite and compiled API/dependency checker pass with Go 1.26.8 on -Linux/amd64 using the commands below. Documentation link and whitespace checks -pass. Each remediation unit is committed separately with a plain English -message. Production changes are confined to Go configuration discovery; the -wrapper change preserves the existing publication and recovery contracts. - -## Validation and remaining scope - -The following checks passed on the reviewed source and after remediation with -Go 1.26.8 on Linux/amd64: - -```sh -GOWORK=off GOPROXY=off GONOPROXY=none GOSUMDB=off GOTOOLCHAIN=local \ - go test -mod=readonly -count=1 ./... -GOWORK=off GOPROXY=off GOTOOLCHAIN=local go run ./internal/apicheck -``` - -The R1 reproduction used a temporary committed consumer repository and a native -CLI built from the reviewed source. Publication and delivery suite checks used -local Git and HTTP fixtures. No consuming repository was changed, release was -published, deployment was activated, or live hosted delivery was performed. -This review did not rerun minimum-Go-1.25 validation; the completed implementation -plan records that earlier verification. Real installation, consumer migration, -credentials, and live CI/Gitea verification remain adoption/deployment work in -the [product roadmap](releasekit.md). - -R1's implicit warning-free discovery prerequisite is the additional restriction -identified by this review. The review found no further strengthened guarantee -requiring remediation. Preserve existing published-content immutability and the -ordinary source-eligibility observations; the findings require no reproducible -build promise, stronger concurrency guarantee, or additional release gate. diff --git a/examples/woodpecker/tag-delivery.yml b/examples/woodpecker/tag-delivery.yml index 69e051f..e0aa067 100644 --- a/examples/woodpecker/tag-delivery.yml +++ b/examples/woodpecker/tag-delivery.yml @@ -1,7 +1,7 @@ matrix: include: - GO_IMAGE: golang:1.25.0-bookworm - RELEASEKIT_VERSION: REPLACE_WITH_IMMUTABLE_VERSION + RELEASEKIT_VERSION: v0.1.0 when: - event: tag