Align repository policies with shared standards
This commit is contained in:
173
docs/release.md
173
docs/release.md
@@ -1,71 +1,97 @@
|
||||
# Releasing Narratio
|
||||
|
||||
This document is the maintainer procedure for creating a Narratio source and
|
||||
binary release. The synchronous release boundary is a successful push of one
|
||||
new tag to `origin`; Woodpecker and Gitea publication happen later and do not
|
||||
change that result.
|
||||
This is the maintainer runbook for the [Release Policy](policy/release.md).
|
||||
Its [explicit exceptions](policy/release.md#policy-exceptions) preserve the
|
||||
successful tag push as the automated responsibility boundary. Binary publication
|
||||
is asynchronous; later consumer-facing inspection is optional.
|
||||
|
||||
## Prerequisites and publication scope
|
||||
|
||||
Use a checkout on `main` with Git authentication permitting fetches and pushes
|
||||
to `origin`, the authoritative Git remote. Install Git, a POSIX shell, standard
|
||||
Unix build tools, and the Go toolchain below. Make required modules available
|
||||
before offline validation. No model/provider credentials are needed. Gitea
|
||||
publication credentials belong to CI's secret store, not the local command.
|
||||
|
||||
Synchronous guards inspect local tags and `origin`, not every configured remote
|
||||
or Gitea release entry. Do not select a version known to have been published in
|
||||
any channel, even if these guards cannot see it.
|
||||
|
||||
## Go prerequisite
|
||||
|
||||
Release preparation requires the maintained Go 1.26 baseline. Tag CI currently
|
||||
uses the explicitly pinned `golang:1.26.7` image for candidate validation and
|
||||
asset construction; that asynchronous work does not change the tag-push
|
||||
completion boundary.
|
||||
uses the explicitly pinned `golang:1.26.7` image for validation and asset builds.
|
||||
That asynchronous work does not change the tag-push completion boundary.
|
||||
|
||||
## Choose a version and write its note
|
||||
|
||||
Narratio is past `v1.0.0`. Use an unused stable tag in the exact form
|
||||
`vMAJOR.MINOR.PATCH`:
|
||||
Select an unused stable version under the
|
||||
[versioning rules](policy/release.md#versioning-and-compatibility). Narratio is
|
||||
past v1.0.0; intentional CLI/configuration breaks require a major release.
|
||||
|
||||
- increment `MINOR` for backward-compatible features;
|
||||
- increment `PATCH` for backward-compatible fixes; and
|
||||
- reserve a new `MAJOR` for an intentional breaking documented contract.
|
||||
Create `docs/releases/vMAJOR.MINOR.PATCH.md` using the
|
||||
[required note structure](policy/release.md#release-documentation).
|
||||
Describe CLI, configuration, artifact, integration, and operating-contract
|
||||
changes, and the required operator action. Link to current canonical
|
||||
documentation for exact behavior.
|
||||
|
||||
Before preparing the candidate, create
|
||||
`docs/releases/vMAJOR.MINOR.PATCH.md` with this structure:
|
||||
## Prepare and record the candidate
|
||||
|
||||
```markdown
|
||||
# Narratio vMAJOR.MINOR.PATCH
|
||||
Before committing, perform these manual reviews in addition to automated checks:
|
||||
|
||||
This release ...
|
||||
- Confirm compatibility/version selection and update affected canonical
|
||||
documentation and maintained examples.
|
||||
- Remove completed roadmap documents covering work included in this release;
|
||||
retain pending work. Their history remains in Git. Do not delete historical
|
||||
release notes.
|
||||
- Review the diff, staged changes, and untracked files for credentials, private
|
||||
data, generated output, unintended files, and unrelated changes.
|
||||
- Review changed documentation links and behavior-bearing commands. Automated
|
||||
link checks supplement rather than replace review.
|
||||
|
||||
## Summary
|
||||
Commit the note and candidate changes, then push that commit to `main` through
|
||||
the ordinary development workflow. Record the exact candidate:
|
||||
|
||||
## Compatibility
|
||||
|
||||
## Upgrade
|
||||
|
||||
## Changes
|
||||
```sh
|
||||
git rev-parse HEAD
|
||||
```
|
||||
|
||||
The compatibility section identifies relevant CLI, configuration, artifact,
|
||||
integration, or operating-contract changes. The upgrade section states the
|
||||
required operator action, or explicitly says that no special action is
|
||||
required. Release notes are immutable historical summaries; link to the
|
||||
current canonical documentation for detailed behavior.
|
||||
|
||||
Commit the note and all candidate changes, then use the ordinary development
|
||||
workflow to push that commit to `main`. Do not create a release tag before the
|
||||
candidate is committed and `origin/main` contains the exact same commit.
|
||||
Do not create a tag until `origin/main` points to that same commit. If the
|
||||
candidate changes, repeat the reviews and validation.
|
||||
|
||||
## Validate the candidate
|
||||
|
||||
Run the shared checker from any directory:
|
||||
From the repository root, run:
|
||||
|
||||
```sh
|
||||
scripts/check-release-candidate.sh vMAJOR.MINOR.PATCH
|
||||
```
|
||||
|
||||
The script also works when invoked by its absolute path from another directory.
|
||||
It validates the version and matching note, module hygiene, formatting,
|
||||
whitespace, uncached tests, race tests, static checks, documentation, examples,
|
||||
and three official cross-build assets. It uses `GOWORK=off`, does not contact
|
||||
application services, CI, or Gitea, and does not create tags or modify tracked
|
||||
source. Fix any failure on `main`, commit it, push it normally, and rerun the
|
||||
checker.
|
||||
and three cross-build assets. It uses `GOWORK=off`, does not contact application
|
||||
services, CI, or Gitea, and does not create tags or modify tracked source.
|
||||
Fix failures on `main`, commit, push normally, and rerun validation.
|
||||
|
||||
The checker builds Linux assets for `amd64` and `arm64` and a macOS asset for
|
||||
`arm64`. The macOS cross-build proves compilation; it is not native macOS
|
||||
runtime evidence.
|
||||
The macOS cross-build proves compilation, not native runtime behavior.
|
||||
|
||||
## Declared deliverables and automation
|
||||
|
||||
The source release is the exact version tag at the validated commit.
|
||||
The tag-triggered `.woodpecker/release.yml` validates the tagged source,
|
||||
runs `scripts/build-release-assets.sh`, and publishes these Gitea assets:
|
||||
|
||||
- `narratio-vMAJOR.MINOR.PATCH-linux-amd64`
|
||||
- `narratio-vMAJOR.MINOR.PATCH-linux-arm64`
|
||||
- `narratio-vMAJOR.MINOR.PATCH-darwin-arm64` (best effort)
|
||||
- `SHA256SUMS`
|
||||
|
||||
The builder embeds the version, disables ambient Go workspaces, and checks a
|
||||
host binary's `version` output. The release publisher uses the matching
|
||||
checked-in note and generates SHA-256 checksums. Existing files are skipped and
|
||||
overwrite is disabled. No image or package-registry deliverable is declared.
|
||||
CI does not choose versions, modify source candidates, or move tags.
|
||||
|
||||
## Publish the tag
|
||||
|
||||
@@ -78,27 +104,64 @@ scripts/release.sh vMAJOR.MINOR.PATCH
|
||||
The command fetches and checks `origin/main`, re-runs candidate validation,
|
||||
then fetches and checks again before creating an explicitly unsigned lightweight
|
||||
tag for the originally recorded commit. It refuses dirty, divergent, changed,
|
||||
or already-tagged candidates. It pushes only:
|
||||
or already-tagged candidates. It verifies the local tag target and pushes only:
|
||||
|
||||
```text
|
||||
refs/tags/vMAJOR.MINOR.PATCH:refs/tags/vMAJOR.MINOR.PATCH
|
||||
```
|
||||
|
||||
It never commits changes, pushes `main`, force-pushes, moves a tag, or pushes
|
||||
all tags. A successful push of that exact ref completes the release command;
|
||||
the command prints the tag and commit, then returns without waiting for CI,
|
||||
querying Gitea, downloading assets, or checking checksums.
|
||||
It never commits changes, pushes `main`, force-pushes, moves tags, or pushes all
|
||||
tags. Successful publication of that ref completes the command; it prints the
|
||||
tag and commit and returns without waiting for CI, querying Gitea, downloading
|
||||
assets, or checking checksums.
|
||||
|
||||
If a failure occurs before the tag is created, correct the candidate on `main`
|
||||
and repeat validation. If the push fails after local tag creation, the local tag
|
||||
is intentionally retained for inspection and the command must not be retried
|
||||
blindly. Once the upstream tag has been pushed, it is immutable. Correct any
|
||||
defect or failed asynchronous publication with a new patch version, a new
|
||||
release note, and the complete procedure again.
|
||||
## Failure handling
|
||||
|
||||
Before tag creation, correct the candidate on `main` and repeat validation.
|
||||
If a push fails after local tag creation, the local tag is retained for inspection.
|
||||
Do not retry blindly or assume the remote received nothing: a connection failure
|
||||
can leave publication uncertain. Inspect the exact remote ref before taking any
|
||||
local-tag cleanup action. This is recovery from a failed command, not a
|
||||
post-success publication gate.
|
||||
|
||||
After publication, follow the
|
||||
[immutability and correction rules](policy/release.md#immutability-and-correction).
|
||||
Correct defects or failed asynchronous publication with a new semantically
|
||||
appropriate version, matching note, and the complete procedure. Never replace
|
||||
existing tagged assets in place.
|
||||
|
||||
## Optional asynchronous inspection
|
||||
|
||||
After a successful tag push, a human may later inspect the tag-triggered
|
||||
Woodpecker run and the corresponding Gitea release for binaries and checksums.
|
||||
This is optional follow-up only. Automated releasers must not wait for, poll,
|
||||
or treat CI/Gitea completion as a condition of the successful tag push.
|
||||
A human may later inspect the tag-triggered Woodpecker job and Gitea release.
|
||||
This is optional follow-up, never part of the automated releaser's completion
|
||||
criteria. Do not wait for or poll CI/Gitea from the release command.
|
||||
|
||||
For optional source verification, substitute the released version below and
|
||||
compare the remote target to the recorded candidate hash:
|
||||
|
||||
```sh
|
||||
git ls-remote --tags origin refs/tags/vMAJOR.MINOR.PATCH
|
||||
git rev-parse 'refs/tags/vMAJOR.MINOR.PATCH^{commit}'
|
||||
```
|
||||
|
||||
Download the three named binaries and `SHA256SUMS` from the matching Gitea release
|
||||
into an empty inspection directory. In that directory, verify on Linux:
|
||||
|
||||
```sh
|
||||
sha256sum --check SHA256SUMS
|
||||
```
|
||||
|
||||
On macOS, use `shasum -a 256 --check SHA256SUMS`. After successful verification,
|
||||
make the matching host binary executable and run its version command, for example
|
||||
on Linux amd64 (replace the version in both commands):
|
||||
|
||||
```sh
|
||||
chmod +x ./narratio-vMAJOR.MINOR.PATCH-linux-amd64
|
||||
./narratio-vMAJOR.MINOR.PATCH-linux-amd64 version
|
||||
```
|
||||
|
||||
Expected output is `narratio vMAJOR.MINOR.PATCH`. Use only the matching architecture
|
||||
on other supported hosts. Checksums establish consistency with the downloaded
|
||||
checksum file, not a new signature or independent authenticity guarantee.
|
||||
Missing assets are an asynchronous publication problem, not grounds to move or
|
||||
reuse the successfully published source tag.
|
||||
|
||||
Reference in New Issue
Block a user