319 lines
18 KiB
Markdown
319 lines
18 KiB
Markdown
# Release tooling simplification
|
|
|
|
Status: implementation roadmap; no implementation has started. Local page-only
|
|
Gitea delivery and protection of the supplied token path are selected for
|
|
implementation. The recommendations in Open Decisions remain unselected.
|
|
Current release behavior stays with its canonical owners until implementation
|
|
updates them.
|
|
|
|
## Purpose and authority
|
|
|
|
Reduce CommandKit's release infrastructure to declarative module profiles,
|
|
a small launcher, and focused tests of CommandKit-owned wiring. Delegate
|
|
reusable candidate validation and publication mechanics to ReleaseKit while
|
|
retaining CommandKit's domain-specific checks in their existing owners. Add
|
|
hosted Gitea release pages as a separate local delivery operation after source
|
|
publication.
|
|
|
|
The [agent policy](../policy/agents.md),
|
|
[release policy](../policy/release.md#candidate-validation), and
|
|
[testing policy](../policy/testing.md#upstream-integration-testing-ownership)
|
|
govern implementation. The [release procedure](../release.md) continues to own
|
|
the current workflow until implementation updates it.
|
|
|
|
## Current baseline
|
|
|
|
Baseline: CommandKit commit `a74fcb20041cbccde93f9b9a1e3b24cb8dd131e7`.
|
|
|
|
- The root [module](../../go.mod) selects
|
|
`go.maximumdirect.net/releasekit v0.8.0` as a Go tool. The release toolchain
|
|
remains Go 1.26.8, and the consumer minimum remains Go 1.26.0.
|
|
- [Core](../../releasekit.json),
|
|
[ckconfig](../../integrations/ckconfig/releasekit.json), and
|
|
[ckprompt](../../integrations/ckprompt/releasekit.json) have separate profiles.
|
|
They select their physical module directories, the current SSH endpoint, and
|
|
an explicit repository-root shared-file list. They enable no optional file
|
|
checks or additional product checks, and configure no hosted delivery.
|
|
- The 49-line [launcher](../../scripts/release) maps the three selectors, changes
|
|
to the repository root, builds the root-selected tool into ignored
|
|
`.releasekit/bin/` storage for the host, and delegates publication to ReleaseKit.
|
|
- [Launcher tests](../../scripts/release_test.go) occupy 506 lines, including
|
|
custom command recording, fake build/publisher processes, and tests of the
|
|
assertion helpers themselves.
|
|
- The 399-line [publication exercise](../../scripts/release_integration_test.go)
|
|
creates disposable Git repositories, release notes, and suite markers. It
|
|
checks tag structure, exact remote objects, suite counts, nested tag prefixes,
|
|
and endpoint rejection in addition to exercising CommandKit's launcher.
|
|
- CommandKit's API, CLI, integration, and maintained consumer behavior is tested
|
|
in the owning package suites. There is no separate CommandKit-specific
|
|
candidate-validation implementation to replace or preserve.
|
|
|
|
After the baseline review, the maintainer supplied the local credential file
|
|
`.releasekit/gitea-token`. Its contents were not read. The file was confirmed
|
|
ignored, untracked, and mode `0600`; authentication was not tested. The existing
|
|
directory ignore rule now serves credential storage as well as executable
|
|
storage and remains needed after executable-storage removal.
|
|
|
|
During review, a temporary core profile enabled all four proposed file checks
|
|
below. ReleaseKit's local `check` accepted the committed core candidate with
|
|
Go 1.26.8. This was diagnostic evidence only: no profiles changed, no publication
|
|
occurred, and equivalent integration-module checks remain outstanding.
|
|
|
|
## Targeted end state
|
|
|
|
### Ownership
|
|
|
|
CommandKit retains module selectors, product identities, profile locations,
|
|
the authoritative endpoint selection, release order, release-note meaning,
|
|
compatibility decisions, and attribution accuracy. Its existing public API,
|
|
CLI, integration-adaptation, and consumer-example tests remain local and run
|
|
through the owning module's suite. No parallel release-only domain suite is
|
|
needed unless a concrete CommandKit requirement is otherwise unprotected.
|
|
|
|
ReleaseKit supplies the standard offline candidate suite, selected generic file
|
|
checks, candidate/note and publication guards, tag creation and publication,
|
|
hosted delivery, outcome reporting, and recovery. CommandKit's launcher delegates
|
|
those operations. Existing source-release completion and immutability rules
|
|
continue to apply. Hosted pages are the added delivery channel; binary
|
|
deliverables and platform support commitments remain unchanged.
|
|
|
|
### Profiles
|
|
|
|
Subject to OD-1, select these existing ReleaseKit options in each profile:
|
|
|
|
| Selection | Intended protection |
|
|
| --- | --- |
|
|
| `validation.go_format: true` | Detect unformatted committed Go source. |
|
|
| `validation.markdown: {}` | Detect broken local Markdown destinations and supported heading fragments. |
|
|
| `validation.module_distribution.workspace_files: true` | Detect committed development workspace files in selected inputs. |
|
|
| `validation.module_distribution.local_replacements: true` | Detect filesystem replacements in selected committed module declarations. |
|
|
|
|
Separately from OD-1, select
|
|
`validation.forbidden_files: [".releasekit/gitea-token"]` in all three profiles.
|
|
This delegates protection of the supplied credential path to ReleaseKit's
|
|
existing check. The path is repository-relative and the check applies across
|
|
the captured repository even for an integration release. It does not read token
|
|
contents, scan other paths, or inspect Git history.
|
|
|
|
Retain the explicit shared-file lists and use ReleaseKit's existing input scope.
|
|
The root profile does not run every nested module's suite. File checks inspect
|
|
committed inputs and do not replace formatting worktree changes or reviewing
|
|
documentation meaning, attribution, and external links. Markdown keeps its
|
|
default treatment of outside-checkout destinations; no stricter boundary mode
|
|
is proposed.
|
|
|
|
The pinned [ReleaseKit configuration reference](https://forge.maximumdirect.net/base-layer/releasekit/src/commit/23203f235cc414c4ffe0fd3941030eb0c9f9943f/docs/config.md)
|
|
owns exact scope and behavior, including nested-module boundaries and vendored
|
|
inputs. Do not expand an option's scope into a general repository prohibition.
|
|
Race testing, full vet, compilation matrices, size limits, and additional
|
|
forbidden-file paths are not selected by this roadmap. They can be considered
|
|
separately for demonstrated needs.
|
|
|
|
### Launcher and recovery
|
|
|
|
Subject to OD-2, use the root module's registered `go tool releasekit` through
|
|
`exec`, keeping the current selector interface and publication argument mapping.
|
|
Retain host normalization, workspace-off execution, the local toolchain, and
|
|
read-only module metadata. Preserve other effective Go settings rather than
|
|
silently replacing them while arranging read-only selection. Go 1.26.8's
|
|
`go tool` does not accept `-mod=readonly` directly; use its supported Go settings
|
|
mechanism and verify the intended behavior.
|
|
|
|
Remove explicit executable storage when the launcher no longer creates it.
|
|
Retain `/.releasekit/` in `.gitignore` for the credential file, and update its
|
|
comment to describe that purpose. Update recovery instructions to use the
|
|
registered tool or the entry point printed for the saved attempt. Preserve
|
|
ReleaseKit's distinction between publication outcome and record-storage errors.
|
|
|
|
Share module selection and host-safe tool invocation between publication,
|
|
delivery, and recovery where applicable. Delivery selects the same module
|
|
profile as publication; recovery uses its recorded attempt rather than inferring
|
|
identity from a current profile. Keep the existing publication interface and
|
|
provide an explicit delivery invocation without automatically chaining the two
|
|
operations. Choose a small wrapper arrangement during implementation rather
|
|
than adding a coordination framework or duplicating selector tables.
|
|
|
|
A pending upstream request concerns host-safe consumer launcher examples and
|
|
regression coverage. It is not a dependency of this work: v0.8.0 already supports
|
|
registered tools. Keep host normalization locally because the reviewed
|
|
`go tool` invocation inherited foreign `GOOS`/`GOARCH` values and failed to run.
|
|
Do not switch tool-version selection from the root module to each integration
|
|
merely to match the upstream multi-module example.
|
|
|
|
### Hosted Gitea release pages
|
|
|
|
Configure this delivery selection in each module profile:
|
|
|
|
| Field | Selected value |
|
|
| --- | --- |
|
|
| `delivery.forge` | `gitea` |
|
|
| `delivery.base_url` | `https://forge.maximumdirect.net` |
|
|
| `delivery.owner` | `base-layer` |
|
|
| `delivery.repository` | `commandkit` |
|
|
| `delivery.token_file` | `.releasekit/gitea-token` |
|
|
|
|
Preserve the profiles' distinct product identities and physical module
|
|
directories. All pages belong to the same Gitea repository and are keyed by
|
|
the complete tag: `vX.Y.Z` for core, `integrations/ckconfig/vX.Y.Z` for ckconfig,
|
|
and `integrations/ckprompt/vX.Y.Z` for ckprompt. Pass the selected profile and
|
|
semantic version to `deliver`; ReleaseKit derives the complete module tag.
|
|
|
|
With no build targets, delivery is page-only. ReleaseKit uses the complete
|
|
checked-in module release note, including its licensing footer, as the hosted
|
|
body. No binary assets, receipts, or checksum manifests are added. Use current
|
|
forge URLs and the full module tag for future notes' immutable source and
|
|
licensing links. Existing published tags and notes remain unchanged.
|
|
|
|
After source publication succeeds, explicitly invoke delivery from a clean
|
|
checkout whose `HEAD` identifies that published tag's commit. For later retries,
|
|
use the original tagged source and its recorded module files. Report the source
|
|
publication outcome and hosted-delivery outcome separately, including the hosted
|
|
URL on success. A delivery failure leaves the source release complete; repair
|
|
delivery without republishing or moving its tag.
|
|
|
|
Delivery performs its own read-only credential preflight, without rerunning
|
|
candidate validation or publishing a tag. Hosted-service availability and the
|
|
Gitea token do not become source-publication gates. A nonblank
|
|
`RELEASEKIT_GITEA_TOKEN` environment value takes precedence over the configured
|
|
file. The file path resolves from the repository root for all three modules.
|
|
|
|
ReleaseKit accepts matching hosted content and reports conflicting content
|
|
without overwriting it. Resolve uncertain hosted writes before retrying the
|
|
same immutable version. The pinned
|
|
[delivery guide](https://forge.maximumdirect.net/base-layer/releasekit/src/commit/23203f235cc414c4ffe0fd3941030eb0c9f9943f/docs/consumers/delivery.md)
|
|
owns exact delivery behavior and recovery. Start with tags containing the new
|
|
delivery configuration; historical page backfilling remains a separate decision.
|
|
This local workflow needs no CI delivery job or additional secret distribution.
|
|
|
|
### Focused local tests
|
|
|
|
Replace the release-test scaffolding with a small controlled Go-command boundary
|
|
that invokes the actual launcher. Cover:
|
|
|
|
- Selector-to-profile/module routing for core, ckconfig, and ckprompt, including
|
|
consistency with the checked-in profiles' intended module and product.
|
|
- Invalid argument handling before tool invocation.
|
|
- Invocation from another directory and paths containing spaces.
|
|
- Host normalization and workspace/toolchain/read-only settings.
|
|
- Publication and delivery argument, output-stream, and child exit-status
|
|
forwarding, with the selected module profile reaching the delivery operation.
|
|
- Profile wiring for the shared Gitea destination, token path, and its selected
|
|
committed-path protection; assertions do not read the credential file.
|
|
|
|
Exercise module routing separately from exit statuses rather than multiplying
|
|
every combination. Assert behavior and meaningful selections, not helper
|
|
implementation details or exact usage prose.
|
|
|
|
Remove the disposable publication exercise and its Git fixtures, synthetic
|
|
notes, markers, tag inspection, and environment-isolation helpers when no longer
|
|
used. Remove assertion-helper self-tests and the custom build-call log/parser
|
|
with their obsolete consumers. Trust upstream publication and delivery coverage;
|
|
do not move a duplicate suite into a different local package or export a new
|
|
test-helper API. There is no line-count target for the replacement tests.
|
|
|
|
## Work from baseline to target
|
|
|
|
### 1. Configure validation and hosted delivery
|
|
|
|
- [ ] Resolve OD-1 and record the chosen scope here.
|
|
- [ ] Update the three profiles for the selected options while preserving their
|
|
module identities, endpoint, and shared-file selections.
|
|
- [ ] Add the agreed delivery destination and forbidden token path to each
|
|
profile. Preserve the ignored token file and the directory ignore rule.
|
|
- [ ] Run the selected checks against each module's committed candidate inputs.
|
|
Review findings against existing contracts; fix relevant defects without
|
|
introducing broad exclusions or unrelated remediation by default.
|
|
- [ ] Update the release policy's delivery scope and the release procedure's
|
|
selected-check and hosted-delivery descriptions with the profile changes.
|
|
|
|
### 2. Simplify the launcher and its tests
|
|
|
|
- [ ] Resolve OD-2 and implement the selected invocation path.
|
|
- [ ] Add or adapt focused wiring tests before deleting the coverage they replace.
|
|
- [ ] Remove `scripts/release_integration_test.go`, assertion-helper self-tests,
|
|
and unused build/publisher scaffolding after reviewing their coverage ownership.
|
|
- [ ] If registered-tool execution is selected, remove executable-storage setup
|
|
while retaining `/.releasekit/` for credentials and updating its comment.
|
|
Do not delete user-local files as part of the refactor.
|
|
- [ ] Expose explicit module-aware delivery using shared invocation plumbing.
|
|
Keep publication and delivery independently invocable and retryable.
|
|
- [ ] Update recovery commands, delivery prerequisites and retry instructions,
|
|
and token environment/file precedence. Remove obsolete opt-in publication
|
|
exercise instructions from the release and development guides with the
|
|
corresponding behavior change.
|
|
|
|
### 3. Validate and finish
|
|
|
|
- [ ] Validate with Go 1.26.8 and prepared dependencies. Exercise the real
|
|
registered tool's host execution and read-only behavior once where the local
|
|
wiring tests use a controlled process; use nonpublishing operations.
|
|
- [ ] Run the owning module suites and selected ReleaseKit checks against the
|
|
final candidates. ReleaseKit `check` already runs the selected module's suite;
|
|
avoid repeating the same successful suite solely for another checklist item.
|
|
- [ ] Distinguish workspace behavior evidence from each module's independent
|
|
dependency graph. For disposable committed-candidate checks, use matching
|
|
notes and existing module metadata; do not invent future dependency versions
|
|
or checksums to make validation pass.
|
|
- [ ] Review the documentation, local links, and final diff. Confirm that
|
|
domain-specific package tests remain and that removed helpers have no users.
|
|
Check future-note guidance for module-specific full tags and immutable forge
|
|
links; do not rewrite published notes to adopt the new workflow.
|
|
- [ ] Verify delivery profile routing and operation forwarding with controlled
|
|
processes. Rely on upstream tests for Gitea authentication, HTTP writes, and
|
|
content reconciliation rather than adding a duplicate local delivery engine
|
|
suite. No real token or hosted writes are needed for these migration checks.
|
|
- [ ] Record validation results and completed work here. Retire the completed
|
|
roadmap through the usual documentation lifecycle when appropriate.
|
|
|
|
These are migration tasks, not additional permanent release gates. Verification
|
|
needs no production tag push or hosted delivery. Ordinary releases continue to
|
|
use one publication command, with no required preliminary `check` run, followed
|
|
by a separate hosted-delivery operation. Confirmed source publication remains
|
|
the source-release completion point; hosted-delivery failure is reported and
|
|
handled separately.
|
|
|
|
## Open Decisions
|
|
|
|
### OD-1: Which optional checks become release gates?
|
|
|
|
**Recommendation:** Select all four options in the profiles table. Formatting
|
|
and local link checks automate existing contributor review work. The two module
|
|
distribution checks address accidental inclusion of development-only metadata
|
|
that a successful local test run can overlook. Reusing upstream mechanisms keeps
|
|
this protection declarative and avoids maintaining local checker code.
|
|
|
|
This is a deliberate addition to release-time validation, not merely deletion
|
|
of duplicate code. The observed core pass does not establish every module's
|
|
compatibility with the selected input scope. Resolve integration findings and
|
|
the applicability of vendored or fixture inputs before treating the selection
|
|
as adopted. Record the chosen release scope in the release procedure.
|
|
The specific forbidden token path and page-only delivery are already selected
|
|
for implementation and are not part of this open decision.
|
|
|
|
**Viable alternative:** Select formatting and Markdown now and defer the module
|
|
distribution checks. This automates familiar review work with less change to
|
|
accepted release contents, and preserves flexibility for legitimate committed
|
|
module fixtures. It leaves accidental workspace files or filesystem replacements
|
|
to ordinary review. Choose this alternative if the broader distribution checks
|
|
would reject justified inputs or their added protection does not warrant the
|
|
restriction. Do not compensate by writing equivalent local validators.
|
|
|
|
### OD-2: Registered tool or persistent native executable?
|
|
|
|
**Recommendation:** Use host-normalized `go tool releasekit`. The tool is already
|
|
registered in the root module, the Go cache supplies the executable, and the
|
|
launcher can forward its exit status without managing `.releasekit/bin/`.
|
|
This also removes executable-storage test machinery and documentation, while
|
|
the directory ignore rule remains for the token. Preserve read-only metadata
|
|
selection and test the effective environment before replacing the current
|
|
bootstrap.
|
|
|
|
**Viable alternative:** Retain the current native build and persistent executable
|
|
while simplifying profiles and tests. It is already proven to handle inherited
|
|
cross-build targets, accepts an explicit build-time read-only flag, and provides
|
|
a durable recovery entry point independent of a later Go-driver invocation.
|
|
It retains storage, bootstrap, and recovery-documentation maintenance, so it
|
|
removes less local infrastructure. Prefer it only if verification identifies a
|
|
meaningful recovery or tool-resolution need that the registered-tool path does
|
|
not meet; the pending upstream example change alone is not such a blocker.
|