142 lines
6.6 KiB
Markdown
142 lines
6.6 KiB
Markdown
# Release Procedure
|
|
|
|
The [release policy](policy/release.md) owns versioning, compatibility,
|
|
publication completion, and immutability. This runbook supplies Scriptorium's
|
|
commands; release notes under `docs/releases/` are historical summaries. The
|
|
[OSS policy](policy/oss.md#discoverability) owns license and attribution
|
|
discoverability requirements.
|
|
|
|
## Prepare The Candidate
|
|
|
|
Use a POSIX shell, Git with a configured tagger identity and access to
|
|
`origin`, and a Go toolchain compatible with `go.mod`. The native host must
|
|
support Go's race detector and have its required C compiler. If Git is
|
|
configured to sign tags, its signing tool and key must be available. Run from the
|
|
repository root. Provision the toolchain and module cache before offline
|
|
validation; when dependencies are not cached:
|
|
|
|
```sh
|
|
GOWORK=off go mod download
|
|
```
|
|
|
|
Choose an unused stable version under the release policy. Commit its note as
|
|
`docs/releases/<version>.md`, beginning with a title such as
|
|
`# Scriptorium v0.14.0` (an example, not an instruction to select that version).
|
|
Include a concise summary and relevant compatibility impact or upgrade action.
|
|
End the note with the following footer, replacing `<version>` in all three absolute
|
|
URLs with the selected version tag (for example, `v0.14.0`):
|
|
|
|
```markdown
|
|
[COPYRIGHT](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/<version>/COPYRIGHT) | [LICENSE](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/<version>/LICENSE) | [ATTRIBUTION](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/<version>/docs/oss/attribution.md)
|
|
```
|
|
|
|
Check that all three URLs name files in the candidate tree at that tag. The tag may
|
|
not resolve online until publication. The checked-in note is copied unchanged
|
|
into the hosted release body by the existing workflow, so do not maintain a
|
|
second footer there.
|
|
Update affected canonical documentation with the change, and retire completed
|
|
roadmap material when appropriate while preserving deferred work and links.
|
|
|
|
Finish and commit the intended candidate on `main`, then publish that branch:
|
|
|
|
```sh
|
|
git -c push.followTags=false push origin refs/heads/main:refs/heads/main
|
|
```
|
|
|
|
The publication command inspects the configured push endpoint of `origin`,
|
|
not a potentially stale remote-tracking ref. If a separate push URL is
|
|
configured, it is authoritative for both checks and publication. Configure one
|
|
publication URL; multiple push endpoints cannot be validated as one remote.
|
|
|
|
## Publish
|
|
|
|
Invoke the single [publication command](../scripts/release.sh), substituting
|
|
the selected version:
|
|
|
|
```sh
|
|
sh scripts/release.sh v0.14.0
|
|
```
|
|
|
|
The command validates a clean worktree and index on `main`, an unused local and
|
|
remote version, exact agreement with authoritative remote `main`, and a
|
|
checked-in note whose first-level title contains Scriptorium and the exact
|
|
version. Ignored local files do not make the candidate dirty.
|
|
|
|
The source-boundary guards reject committed workspaces, vendor trees, and
|
|
module replacements.
|
|
|
|
It then runs the complete suite once with the race detector and builds Linux
|
|
amd64 and arm64 binaries using `CGO_ENABLED=0`, `-trimpath`, and
|
|
`-ldflags '-s -w'`. The native test run uses the host platform and enables cgo.
|
|
Validation disables workspaces, uses read-only module mode, and disables module
|
|
and toolchain downloads. Missing dependencies must be provisioned separately;
|
|
fix the environment and rerun the command. No persistent validation cache is
|
|
maintained by the release tool.
|
|
|
|
The command rechecks candidate and publication state, creates an annotated tag
|
|
from the committed note, and pushes only that tag's exact object to its explicit
|
|
ref. It does not push branches, follow other tags, force updates, or wait for
|
|
CI. Temporary notes and validation builds are removed on exit. The successful
|
|
summary identifies the source commit and tag object and reports binary
|
|
delivery separately as asynchronous and unverified.
|
|
|
|
## Asynchronous Binary Delivery
|
|
|
|
The tag-triggered [hosted workflow](../.woodpecker/release.yml) builds and
|
|
publishes:
|
|
|
|
- `scriptorium-<version>-linux-amd64`;
|
|
- `scriptorium-<version>-linux-arm64`; and
|
|
- `SHA256SUMS`.
|
|
|
|
The matching checked-in note supplies the hosted release body. The workflow
|
|
owns image selection, packaging, checksum generation, and upload configuration.
|
|
Its upload step skips existing files and does not overwrite the release.
|
|
Source-publication success does not attest to workflow success or asset
|
|
availability.
|
|
|
|
Workflow inspection, downloads, checksum verification, and a compatible-host
|
|
smoke test are optional delivery diagnostics. They must not delay or redefine
|
|
source-release completion. No polling or consumer-installation check is part
|
|
of the publication command.
|
|
|
|
## Failure Recovery
|
|
|
|
Before tag creation, correct and commit a failed candidate, publish `main`,
|
|
and invoke the publication command again. A changed candidate must pass its
|
|
own validation.
|
|
|
|
After an unsuccessful push, the command queries the authoritative endpoint.
|
|
If it confirms the exact tag object and candidate, it reports source success.
|
|
Otherwise it exits unsuccessfully and preserves the local tag. It never retries
|
|
a push or deletes a tag automatically. If the endpoint is unavailable, the
|
|
publication status is unknown, not evidence that nothing was published.
|
|
|
|
For manual diagnosis, select the affected version and compare the local tag
|
|
object and peeled commit with the authoritative remote:
|
|
|
|
```sh
|
|
release_version=v0.14.0
|
|
release_remote=$(git remote get-url --push origin)
|
|
git rev-parse "refs/tags/$release_version" "refs/tags/$release_version^{commit}"
|
|
git ls-remote "$release_remote" refs/heads/main \
|
|
"refs/tags/$release_version" "refs/tags/$release_version^{}"
|
|
```
|
|
|
|
Do not retry while the outcome remains unknown. If the tag exists remotely,
|
|
do not move, recreate, or delete it. If the tag was never published or used by
|
|
any release channel, an explicitly authorized local cleanup may delete only
|
|
that unpublished tag; then rerun the command to validate and publish the
|
|
candidate. The command intentionally rejects an existing local tag rather than
|
|
assuming that a previous process validated it.
|
|
|
|
For transient delivery failures, inspect what has already been uploaded before
|
|
retrying the same immutable tag. The upload step's skip behavior alone does not
|
|
prove checksum consistency. Add missing assets only if they match the tagged
|
|
source and any already-published manifest, without replacing existing contents.
|
|
Compare rebuilt bytes with published checksums when recovering a partial
|
|
upload; do not assume toolchain changes reproduce identical binaries. If safe
|
|
completion is impossible, or published source, notes, packaging, or artifact
|
|
contents need correction, leave the original release intact and publish a new
|
|
version from a corrected commit.
|