4.0 KiB
ReleaseKit release procedure
ReleaseKit's initial deliverable is source only. The authoritative repository
is origin at https://gitea.maximumdirect.net/eric/ReleaseKit.git, and the
release branch is main. A release completes when the intended annotated tag
is successfully pushed, or when one exact-object recovery query confirms that
the push succeeded. CI, hosted artifacts, and consumer installation are not
completion checks.
Prepare a candidate
Use a local Go 1.25 toolchain and a clean clone. Start on main, choose an
unused stable vMAJOR.MINOR.PATCH version, and add
docs/releases/<version>.md with a first heading containing ReleaseKit and
the exact version. Summarize the change and any compatibility or upgrade impact.
End the note with the three license links at the immutable source tag:
[COPYRIGHT](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/vX.Y.Z/COPYRIGHT) |
[LICENSE](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/vX.Y.Z/LICENSE) |
[ATTRIBUTION](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/vX.Y.Z/docs/oss/attribution.md)
Replace every vX.Y.Z with the selected version. These are links to the same
release note's immutable source tree and also work when the note is used as a
hosted release body.
Commit the note and all candidate changes on main, then publish that commit
to origin/main:
git push origin main
ReleaseKit checks that the worktree is clean, the candidate is on main, the
authoritative branch identifies that commit, and the version is unused locally
and on origin.
Prepare dependencies, then publish
Dependency preparation is separate from the offline candidate validation. Run it from the captured candidate source before the release command:
GOTOOLCHAIN=local go mod download
Then run the single publication command from the repository root:
./scripts/release vX.Y.Z
The committed releasekit.json selects the offline default test suite:
go test -mod=readonly -count=1 ./..., with toolchain and module network
access disabled for validation. The command validates once, checks the
authoritative remote state, creates a local annotated tag from the captured
candidate and checked-in note, rechecks the tag and remote guards, and pushes
only that tag object. It prints the published version, commit, and tag object
on success. Exit status 0 means publication is confirmed; status 1 means a
known failure or conflict; status 2 means invalid input or profile; status 3
means the push outcome remains unknown and requires resolution.
The CLI runs from the source tree being published, so this command also works for ReleaseKit's first release before any released ReleaseKit executable exists. It uses the local Go toolchain. Preparation must finish before the offline validation begins.
Resolve failures
A failed push triggers one exact authoritative tag query. An exact tag-object
match confirms publication even when Git reported an error. A proven absent tag
is not_published; a different object is a conflict; an unreadable query is
unknown. The command retains its local tag and reports the state, phase,
candidate commit, and tag object when available. Do not retry an unknown result
until you resolve the authoritative ref:
git ls-remote --refs origin "refs/tags/vX.Y.Z"
Compare the returned object ID with the tag object reported by the command.
An exact match confirms publication. If the ref is absent, the version was not
published; only then may you deliberately remove the unpublished local tag
with git tag -d vX.Y.Z before correcting the candidate or retrying. Do not
move, overwrite, or delete a tag that exists remotely. If a different object
uses the version, choose a new version after resolving the conflict.
If validation or a guard fails before the push, the local tag has not been
published. Correct and commit the candidate, publish main, and run the
command again. ReleaseKit does not publish executable artifacts or wait for
asynchronous delivery; any future deliverables require a separate policy and
procedure update.