Files
promptkit/docs/release.md

9.4 KiB

Release Procedure

This runbook implements the release policy. Promptkit publishes source-only Go module tags from main to origin. A successful push of the selected annotated tag, after its source commit is available on main, completes the release. Do not wait for CI or Go module availability. After source publication, deliver the hosted Gitea release page as described below. Report source publication and hosted delivery separately.

Prepare The Candidate

Required tools are Git, Go with race-detector support, POSIX shell, and Python 3. Work from the repository root with push access to origin.

Use the latest Go installation available locally for the release tool, the candidate validation, and the maintained examples. Make it the active go command and record its version:

export GOTOOLCHAIN=local
go version

For a minor release, advance Promptkit's consumer minimum to the initial stable release of that Go series before committing the candidate:

release_go_version=$(go env GOVERSION)
release_go_series=${release_go_version#go}
release_go_series=${release_go_series%.*}
go mod edit "-go=${release_go_series}.0"

For example, Go 1.27.1 normally results in go 1.27.0. Keep a higher patch minimum if a dependency or identified correctness fix requires it. For a patch release, leave the consumer minimum unchanged; using a newer validation toolchain does not itself raise that minimum. If the candidate needs a higher minimum, prepare a minor release instead. See the consumer-minimum policy.

Prepare module caches before validation; this may update go.sum and belongs before the candidate commit:

GOTOOLCHAIN=local go mod download

Choose an unused stable version and create docs/releases/<version>.md with a title containing Promptkit and that exact version, a short summary, and any relevant compatibility impact or upgrade instructions. No fixed section headings are required. Describe a raised Go minimum and its compatibility impact under the versioning policy. End each new note with the licensing footer below, using the selected version:

[COPYRIGHT](https://forge.maximumdirect.net/base-layer/promptkit/src/tag/vX.Y.Z/COPYRIGHT) | [LICENSE](https://forge.maximumdirect.net/base-layer/promptkit/src/tag/vX.Y.Z/LICENSE) | [ATTRIBUTION](https://forge.maximumdirect.net/base-layer/promptkit/src/tag/vX.Y.Z/docs/oss/attribution.md)

Check the footer paths against the candidate; the future tag need not resolve remotely during preparation. Follow the OSS policy for these links. Hosted delivery reuses this complete note without a separate summary. Promptkit publishes no binaries, attachments, or checksum manifests.

For hosted delivery, supply a Gitea API token with access to publish releases through RELEASEKIT_GITEA_TOKEN or the ignored local file .releasekit/gitea-token, with owner-only permissions for the file. A nonblank environment value takes precedence. ReleaseKit trims surrounding whitespace from file contents. Keep the token out of commits and shared logs. The profile rejects that exact token path if committed; it does not scan other files or Git history. Source publication uses Git authentication and neither reads nor requires the delivery token.

Retire completed roadmaps while preserving deferred work and repairing incoming links. Review the intended changes through the ordinary development workflow, commit the candidate on main, and push main to origin before publication. Preparation may update module metadata; the release bootstrap and validation preserve the committed candidate.

Validate And Publish

For an optional local diagnostic of a committed candidate, run:

./scripts/releasekit.sh check vMAJOR.MINOR.PATCH

This is not a required step before publication. The upstream candidate-check contract describes its requirements.

Run the single publication command with the chosen version:

./scripts/release.sh vMAJOR.MINOR.PATCH

The familiar wrapper delegates to the native ReleaseKit executable selected in go.mod. The committed profile selects the race-enabled Go suite, full vet, committed Go formatting, local Markdown links, workspace and filesystem replacement inspection, and semantic checks for the three maintained offline consumer examples. It also checks that the configured local token path is not committed. ReleaseKit verifies the committed candidate and publication state, then publishes only the selected tag. Its checks run once for this candidate; do not repeat them as a separate sign-off.

The native command returns status 0 for confirmed publication, 1 for a known validation or publication failure, 2 for invalid input or profile, and 3 when the push outcome remains unknown. Successful publication needs no remote read-back, CI wait, or installation check. Provider probes and inference calls are not part of validation.

Deliver The Hosted Release

After source publication succeeds, keep a clean checkout at the published tag's commit and run:

./scripts/releasekit.sh deliver vMAJOR.MINOR.PATCH

The profile selects Gitea at https://forge.maximumdirect.net, owner base-layer, repository promptkit. With no build targets, ReleaseKit creates or accepts a stable, non-draft release page containing the complete committed note and licensing footer. There is no binary build, attachment upload, or candidate revalidation. Delivery does not publish another tag or wait for CI.

ReleaseKit performs its authenticated, read-only repository preflight during delivery; no separate preflight is required before source publication. Missing credentials or an unavailable hosted service leave the source release complete.

Delivery returns status 0 for completion, 1 for an operational failure, conflict, or partial delivery, 2 for invalid configuration or credential/access errors, and 3 for an unresolved hosted write. Report the hosted URL on success and retain the diagnostic and delivery state on failure. See the upstream delivery guide for the full result contract.

For a later retry, use a clean checkout of the original tag with its recorded module files and make the token available locally. For example, in a separate checkout with the tag available:

git switch --detach vMAJOR.MINOR.PATCH
./scripts/releasekit.sh deliver vMAJOR.MINOR.PATCH

The launcher builds the tool selected by that checkout. Matching hosted content is accepted; conflicting content is not overwritten. Resolve an unknown hosted write before retrying. Retry delivery with the same immutable version rather than rerunning publish or moving a tag. Corrections to published source or content require a new appropriate version. These steps apply to tags containing this delivery configuration; older releases retain their original workflows.

Failure Recovery

This section covers source publication. Hosted-delivery recovery is described above; its failure does not undo source publication.

For status 1, use the diagnostic to distinguish a validation failure from a known publication conflict. Correct and commit candidate defects, push main, and rerun publication with an unused version when appropriate. Status 2 means the invocation or profile must be corrected.

If local tag creation or verification fails, inspect the reported local ref: it may remain even when ReleaseKit could not establish its object ID. Apply the authoritative-state checks below before removing a retained tag.

For status 3, do not retry or remove the local tag until the remote outcome is resolved. ReleaseKit reports the attempted version, tag object, and recovery state, including the captured publication endpoint when available. Use that endpoint—not merely the current origin URL—to query the exact tag; follow the upstream failure-recovery procedure.

CLI diagnostics mask HTTP(S) credentials. If the displayed endpoint is redacted, use the actual endpoint captured for that attempt, with authentication supplied locally; do not copy the redacted display as a transport URL or expose credentials in shared logs.

releasekit_endpoint='COPY_CAPTURED_ENDPOINT'
releasekit_version='vX.Y.Z'
test "$(git ls-remote --get-url -- "$releasekit_endpoint")" = "$releasekit_endpoint" &&
  git ls-remote --refs -- "$releasekit_endpoint" "refs/tags/$releasekit_version"

Compare the returned object ID with the reported tag object. An exact match confirms publication. A missing ref confirms absence only when the endpoint identity check and query both succeed. If either check fails, the outcome remains unknown; correct the transport configuration and resolve it before retrying. Only after authoritative absence is confirmed may an unpublished local tag be removed before correcting the candidate or retrying. Never move, overwrite, or delete a published tag.

Policy Changes

Update the policy and this procedure together when changing release governance. Consumers own their dependency-availability and release checks; their readiness does not delay completion of a Promptkit release.