Document source release procedure
This commit is contained in:
@@ -25,6 +25,7 @@ implemented component map.
|
||||
| LLM clients, prompts, schemas, profiles, or scheduling | [LLM Runtime](internal/llm.md) | It documents the transport boundary and PromptKit integration. |
|
||||
| Output, cache, resume, or debug artifacts | [Run State Internals](internal/state.md), [Operations](operations.md), and [Configuration](config.md) | These separate implementation details, operator behavior, and configuration contracts. |
|
||||
| External input formats, artifact schemas, or durable output files | [Integration Contracts](integrations/) | Integration documents define external and durable data contracts. |
|
||||
| Release preparation, tagging, publication, or verification | [Source Releases](release.md) and [Documentation Policy](policy/documentation.md) | The release procedure owns maintainer guards and immutable-tag recovery; the policy assigns release-note ownership. |
|
||||
| Proposed or unimplemented behavior | [Roadmap](roadmap/) | Future work belongs only in roadmap documentation until implemented. |
|
||||
|
||||
For an existing subsystem, also inspect its focused tests and the package-local
|
||||
|
||||
@@ -65,6 +65,8 @@ secret values.
|
||||
| CLI contract | `docs/cli.md` | Commands, arguments, flags, invocation semantics, and exit codes. | End-to-end operating procedures, configuration field definitions, runtime filesystem layout, module implementation details. |
|
||||
| Configuration contract | `docs/config.md` | Discovery and precedence, file schema, fields, defaults, environment overrides, validation rules, and user-selectable module or validator keys. | Complete example files, CLI syntax, runtime state lifecycle, module implementation details. |
|
||||
| Operations | `docs/operations.md` | Runtime workflows, physical filesystem and state layout, output, cache, and debug handling, resume, cleanup, permissions, recovery, and operational limits. | CLI flag syntax, configuration field definitions, logical output schemas, implementation mechanics. |
|
||||
| Source release procedure | `docs/release.md` | Maintainer release selection, candidate validation, tagging, publication guards, verification, and immutable-tag recovery. | Product installation summary, CLI version semantics, historical release summaries, CI implementation detail. |
|
||||
| Release-note history | `docs/releases/` | One checked-in historical summary for each source release made under the procedure. The note at the immutable tag is that release's record. | Current commands, behavior, contracts, and compatibility definitions. |
|
||||
| Public HTTP contract, if introduced | `docs/api.md` | Routes, authentication, media types, request and response schemas, status codes, pagination, caching, idempotency, rate limits, and HTTP retry semantics. | Client walkthroughs, upstream or downstream integration internals, implementation detail. |
|
||||
| Consumer guidance, if a public package or API is introduced | `docs/consumers/` | Task-oriented use of the public interface, minimal client examples, and consumer responsibilities. | HTTP wire semantics, external protocol contracts, internal implementation detail. |
|
||||
| External and durable integration contracts | `docs/integrations/` | External file formats and protocols, upstream and downstream contracts, logical output bundle paths and schemas, media types, and compatibility behavior. | Physical runtime placement and lifecycle, internal transformations, CLI syntax, configuration defaults. |
|
||||
@@ -95,6 +97,14 @@ runtime state and how to operate or recover the application. When a workflow
|
||||
crosses these topics, choose the document that owns the task and link to the
|
||||
other contracts.
|
||||
|
||||
### Releases
|
||||
|
||||
`docs/release.md` owns the source-release procedure. Release notes are
|
||||
historical summaries, not current-state contract owners: the checked-in note at
|
||||
an immutable tag records that release, while current canonical documentation
|
||||
must change with the behavior it describes. Do not use a release note to defer
|
||||
or replace current documentation updates.
|
||||
|
||||
### Contracts And Implementation
|
||||
|
||||
Integration and API documents define externally observable shapes and
|
||||
|
||||
158
docs/release.md
Normal file
158
docs/release.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# 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:
|
||||
|
||||
```markdown
|
||||
# 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:
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
```sh
|
||||
./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:
|
||||
|
||||
```sh
|
||||
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, the recorded and pushed commit, a matching note, and unused local and
|
||||
remote tags:
|
||||
|
||||
```sh
|
||||
git fetch origin main --tags
|
||||
|
||||
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:
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
```sh
|
||||
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.
|
||||
@@ -243,7 +243,7 @@ the pre-release confidence boundary.
|
||||
- The pipeline cannot publish binaries, releases, checksums, or other assets
|
||||
and requires no release secret.
|
||||
|
||||
## Stage 4: Establish The Canonical Release Procedure And Documentation Policy
|
||||
## Stage 4: Establish The Canonical Release Procedure And Documentation Policy ✅
|
||||
|
||||
### Goal
|
||||
|
||||
|
||||
Reference in New Issue
Block a user