115 lines
5.3 KiB
Markdown
115 lines
5.3 KiB
Markdown
# ReleaseKit release procedure
|
|
|
|
ReleaseKit's deliverables are its source tag and a hosted Gitea page containing
|
|
the complete checked-in release note. The page is delivered asynchronously by
|
|
the prepared [Woodpecker workflow](../examples/woodpecker/releasekit-source-delivery.yml);
|
|
it is not a source-release completion check and carries no binary assets. 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 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:
|
|
|
|
```markdown
|
|
[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`:
|
|
|
|
```sh
|
|
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:
|
|
|
|
```sh
|
|
GOTOOLCHAIN=local go mod download
|
|
```
|
|
|
|
Then run the single publication command from the repository root:
|
|
|
|
```sh
|
|
./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:
|
|
|
|
```sh
|
|
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. The prepared Woodpecker workflow builds the CLI from the tagged
|
|
checkout and runs page-only delivery. To activate it after configuring the
|
|
destination and secret, copy it to `.woodpecker/releasekit-source-delivery.yml`
|
|
and add the Woodpecker repository secret `releasekit_gitea_token`. If page
|
|
delivery fails or is uncertain, inspect the hosted release and retry the same
|
|
immutable version from its tag:
|
|
|
|
```sh
|
|
git fetch origin "refs/tags/vX.Y.Z:refs/tags/vX.Y.Z"
|
|
git checkout --detach "vX.Y.Z"
|
|
mkdir -p .releasekit/bin
|
|
GOTOOLCHAIN=local GOPROXY=off GOSUMDB=off go build -o .releasekit/bin/releasekit ./cmd/releasekit
|
|
RELEASEKIT_GITEA_TOKEN="$GITEA_TOKEN" .releasekit/bin/releasekit deliver "vX.Y.Z"
|
|
```
|
|
|
|
The root ignore file excludes `.releasekit/`. Delivery uses the committed note
|
|
and does not build consumer binaries, create a checksum manifest, or require a
|
|
previously released ReleaseKit executable. Keep source publication and hosted
|
|
page delivery status separate; retry only after resolving an uncertain remote
|
|
write. The workflow secret is named `releasekit_gitea_token` and is mapped to
|
|
`RELEASEKIT_GITEA_TOKEN` only in the delivery step.
|