134 lines
6.4 KiB
Markdown
134 lines
6.4 KiB
Markdown
# CommandKit release procedure
|
|
|
|
## Scope and prerequisites
|
|
|
|
CommandKit publishes source-only Go module releases: an immutable annotated
|
|
version tag for one committed candidate and its matching checked-in release
|
|
note. This procedure does not publish a hosted release page, binaries,
|
|
checksums, or other delivery assets, and it requires no delivery credentials.
|
|
|
|
Use branch `main`, remote `origin`, and the expected effective push endpoint
|
|
`https://gitea.maximumdirect.net/eric/CommandKit.git`. The profile enforces that
|
|
endpoint during publication. The maintainer needs a local Go toolchain
|
|
compatible with the module's Go 1.25.5 minimum, Git with push access to `origin`,
|
|
and a POSIX shell.
|
|
|
|
This procedure follows the [release policy](policy/release.md); the release-note
|
|
footer follows the [OSS discoverability policy](policy/oss.md#discoverability).
|
|
|
|
ReleaseKit v0.2.0 owns candidate validation, publication guards, annotated tag
|
|
creation, tag publication, and outcome reporting. The repository profile selects
|
|
only its default candidate suite. The launcher bootstraps the module-selected
|
|
native executable into ignored `.releasekit/` storage and invokes its `publish`
|
|
command. The upstream [CLI reference](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/e030794969fb7787e647a90bbc4eb81bd0610f07/docs/cli.md),
|
|
[profile reference](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/e030794969fb7787e647a90bbc4eb81bd0610f07/docs/config.md),
|
|
and [publication guide](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/e030794969fb7787e647a90bbc4eb81bd0610f07/docs/consumers/publish.md)
|
|
own detailed command, profile, and status contracts.
|
|
|
|
## Prepare and publish a candidate
|
|
|
|
Choose a fresh, unused stable Semantic Version tag in the form
|
|
`vMAJOR.MINOR.PATCH`, with no leading zeroes. Before `v1.0.0`, a minor release
|
|
may change a documented contract if its note explains the impact and consumer
|
|
action; a patch release must not intentionally break contracts within its
|
|
minor line. Never reuse a version previously published through any release
|
|
channel. The first version is selected during release preparation, not embedded
|
|
in the tool or profile.
|
|
|
|
Start from `main` and prepare a note at `docs/releases/<version>.md`. Begin with
|
|
a heading containing `CommandKit` and the exact version. Include a useful
|
|
summary and any compatibility impact or upgrade instructions. End it with the
|
|
license and attribution links at that version's immutable source tag, replacing
|
|
`VERSION` with the selected tag:
|
|
|
|
```markdown
|
|
[COPYRIGHT](https://gitea.maximumdirect.net/eric/CommandKit/src/tag/VERSION/COPYRIGHT) |
|
|
[LICENSE](https://gitea.maximumdirect.net/eric/CommandKit/src/tag/VERSION/LICENSE) |
|
|
[ATTRIBUTION](https://gitea.maximumdirect.net/eric/CommandKit/src/tag/VERSION/docs/oss/attribution.md)
|
|
```
|
|
|
|
Review these paths in the candidate; the future tag URLs do not need to resolve
|
|
before publication.
|
|
|
|
Prepare dependencies separately from the offline candidate suite:
|
|
|
|
Run these commands in the same shell session so the version variable remains
|
|
set:
|
|
|
|
```sh
|
|
commandkit_version=vX.Y.Z
|
|
GOWORK=off GOTOOLCHAIN=local go mod download
|
|
```
|
|
|
|
If dependency preparation changes `go.mod` or `go.sum`, review and commit those
|
|
changes with the candidate. Commit the note and all candidate changes on `main`,
|
|
then publish that commit to `origin`:
|
|
|
|
```sh
|
|
git push origin HEAD:refs/heads/main
|
|
./scripts/release "$commandkit_version"
|
|
```
|
|
|
|
The launcher builds the ReleaseKit version selected by the module in readonly
|
|
mode. After preflight, `publish` runs the offline default Go suite once, checks
|
|
the candidate and remote guards, creates an annotated tag from the committed
|
|
note, and pushes only that tag object. The launcher does not push `main`; push
|
|
the candidate first. Do not require a separate `check` before `publish` or repeat
|
|
the same suite. Successful source publication does not wait for CI, module
|
|
availability, or consumer installation.
|
|
|
|
## Completion and statuses
|
|
|
|
Publication is complete when the intended annotated tag is successfully pushed
|
|
to the expected endpoint, or when an exact tag-object query confirms that push
|
|
after an error. Status 0 reports confirmed publication. Status 1 reports a
|
|
known failure or conflict; status 2 reports invalid input or profile; status 3
|
|
means the push outcome remains unresolved. See the upstream [CLI status
|
|
contract](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/e030794969fb7787e647a90bbc4eb81bd0610f07/docs/cli.md).
|
|
|
|
For a failed or ambiguous push, use the exact endpoint, version, and annotated
|
|
tag object reported by the invocation. Confirm that Git still resolves the
|
|
captured endpoint to itself before querying only that tag ref:
|
|
|
|
```sh
|
|
releasekit_endpoint='COPY THE CAPTURED ENDPOINT EXACTLY'
|
|
releasekit_version='vX.Y.Z'
|
|
releasekit_tag_object='COPY THE REPORTED TAG OBJECT ID'
|
|
releasekit_ref="refs/tags/$releasekit_version"
|
|
|
|
releasekit_resolved_endpoint=$(git ls-remote --get-url -- "$releasekit_endpoint") || {
|
|
printf '%s\n' 'publication state is unresolved: endpoint resolution failed' >&2
|
|
exit 1
|
|
}
|
|
if [ "$releasekit_resolved_endpoint" != "$releasekit_endpoint" ]; then
|
|
printf '%s\n' 'publication state is unresolved: endpoint resolution changed' >&2
|
|
exit 1
|
|
fi
|
|
releasekit_remote_tag=$(git ls-remote --refs -- "$releasekit_endpoint" "$releasekit_ref") || {
|
|
printf '%s\n' 'publication state is unresolved: remote query failed' >&2
|
|
exit 1
|
|
}
|
|
printf '%s\n' "$releasekit_remote_tag"
|
|
```
|
|
|
|
`--refs` returns the annotated tag object's ID, not its peeled commit. Compare
|
|
that ID with `releasekit_tag_object`: an exact match confirms publication; a
|
|
different object is a conflict; successful output with no matching ref proves
|
|
absence at the captured endpoint. A failed query or changed URL resolution is
|
|
unresolved, never evidence of absence. Do not query a different fetch URL or
|
|
follow a rewritten endpoint to infer the captured destination's state.
|
|
|
|
ReleaseKit retains a local tag after a failed push, so the tag blocks an ordinary
|
|
retry. After proving the tag absent at the captured endpoint,
|
|
confirm that it was never published or used by another release channel before
|
|
deliberately removing the unpublished local tag:
|
|
|
|
```sh
|
|
git tag -d "$releasekit_version"
|
|
```
|
|
|
|
Do not move, overwrite, recreate, or delete a published tag. If the exact tag
|
|
object is present remotely, keep it. Resolve conflicts with a fresh version;
|
|
corrections to published source require a new version. A transport failure
|
|
alone does not require a new version.
|