6.1 KiB
Source Releases
This procedure is for maintainers publishing Notarius source releases. A
release is an immutable lightweight vMAJOR.MINOR.PATCH tag on main together
with its checked-in docs/releases/<tag>.md note. Tag CI validates that source
candidate after publication; it does not publish or repair a release.
Notarius publishes no binaries, archives, checksums, signatures, containers,
package-manager entries, or Gitea release objects. Windows is not supported.
Do not create retrospective notes for the pre-procedure v0.1.0, v0.2.0, or
v0.3.0 tags.
Select And Describe The Release
Choose an unused stable semantic version in the form vMAJOR.MINOR.PATCH.
Prereleases are not supported. Before v1.0.0, a minor release may change a
documented CLI, configuration, durable artifact, integration, or operating
contract when its note explains the impact and required operator action. A
patch release must not intentionally break those documented contracts within
its minor line.
Create the version-matched note as part of the candidate. Every new note uses this structure, with concise, truthful content in each section:
# Notarius vMAJOR.MINOR.PATCH
This release ...
## Summary
## Compatibility
## Upgrade
## Changes
The note is a historical summary. Link to current canonical documentation for exact behavior, and update that documentation in the candidate rather than using the note as a substitute.
Prepare The Candidate
Set the selected release version and disable Go workspace use for every candidate command:
RELEASE_VERSION=vMAJOR.MINOR.PATCH
export RELEASE_VERSION GOWORK=off
Run the shared source-candidate checks from the repository. They cover module hygiene, tests, race tests, vet, builds, formatting, whitespace, maintained configuration validation, and the Linux and Darwin command-build matrix:
./scripts/check-release-source.sh "$RELEASE_VERSION"
Before committing, manually follow every changed local Markdown link and
review the candidate for unintended files, generated output, credentials, or
other unrelated changes. Commit the release note and all affected current
documentation, then run the shared checker against that exact candidate. Push
the candidate commit to main only after it succeeds. Record the exact commit
only after that push:
RELEASE_COMMIT=$(git rev-parse 'HEAD^{commit}')
export RELEASE_COMMIT
For private-module installation, configure standard GOPRIVATE matching this
module and ordinary Git authentication for the hosting service before running
the verification below. The exact authentication mechanism belongs to the
maintainer environment; never record credentials or environment dumps in a
release note, command history, or repository file.
Guard And Publish The Tag
Fetch current remote references, then run this guard without editing the
candidate. It requires main, a clean worktree and index, disabled workspace
use, a stable release version, the recorded and pushed commit, a matching note,
and unused local and remote tags:
git fetch origin main --tags
if ! printf '%s\n' "$RELEASE_VERSION" |
grep -E -x 'v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)' >/dev/null
then
printf '%s\n' "invalid release version: $RELEASE_VERSION" >&2
exit 1
fi
test "$GOWORK" = off
test "$(git branch --show-current)" = main
test -z "$(git status --porcelain)"
test "$RELEASE_COMMIT" = "$(git rev-parse 'HEAD^{commit}')"
test "$RELEASE_COMMIT" = "$(git rev-parse 'origin/main^{commit}')"
test -s "docs/releases/$RELEASE_VERSION.md"
grep -F -x "# Notarius $RELEASE_VERSION" "docs/releases/$RELEASE_VERSION.md"
for heading in '## Summary' '## Compatibility' '## Upgrade' '## Changes'; do
grep -F -x "$heading" "docs/releases/$RELEASE_VERSION.md"
done
if git rev-parse -q --verify "refs/tags/$RELEASE_VERSION" >/dev/null; then
printf '%s\n' "local tag already exists: $RELEASE_VERSION" >&2
exit 1
fi
if git ls-remote --exit-code --tags origin "refs/tags/$RELEASE_VERSION" >/dev/null 2>&1; then
printf '%s\n' "remote tag already exists: $RELEASE_VERSION" >&2
exit 1
fi
Create an explicitly lightweight tag against the guarded commit, verify its target, and push only that tag ref:
git -c tag.gpgSign=false tag "$RELEASE_VERSION" "$RELEASE_COMMIT"
test "$(git cat-file -t "$RELEASE_VERSION")" = commit
test "$(git rev-parse "$RELEASE_VERSION^{commit}")" = "$RELEASE_COMMIT"
git push origin "refs/tags/$RELEASE_VERSION:refs/tags/$RELEASE_VERSION"
Never use git push --tags, move a published tag, or delete a published tag.
Verify The Published Release
Confirm that the remote tag still points at the guarded commit and that the note is available from the tagged tree:
REMOTE_TAG_COMMIT=$(git ls-remote origin "refs/tags/$RELEASE_VERSION" | awk '{print $1}')
test "$REMOTE_TAG_COMMIT" = "$RELEASE_COMMIT"
git show "$RELEASE_VERSION:docs/releases/$RELEASE_VERSION.md" >/dev/null
Verify a fresh source installation and its diagnostic version. The temporary directory confines the installed command to this check:
release_verification_dir=$(mktemp -d)
trap 'rm -rf "$release_verification_dir"' 0 HUP INT TERM
mkdir -p "$release_verification_dir/bin"
GOWORK=off GOBIN="$release_verification_dir/bin" go install \
"gitea.maximumdirect.net/eric/notarius/cmd/notarius@$RELEASE_VERSION"
test "$("$release_verification_dir/bin/notarius" --version)" = "notarius $RELEASE_VERSION"
An exact fresh checkout and GOWORK=off go build ./cmd/notarius is an
equivalent source verification when local installation policy requires it.
notarius --version is diagnostic only; downstream compatibility remains
defined by the published receipt and artifact contracts.
Failure And Correction Policy
If candidate validation fails before publication, fix the candidate on main,
rerun the shared checker, and repeat the guards. An unpublished local tag may
be deleted after inspection.
If the remote tag or tag CI reveals a defect, leave the published tag intact.
Fix the defect on main, choose a new patch version, write a new matching
note, and repeat this procedure. Do not weaken tag immutability or add release
assets as a workaround.