Prepare the v1.6.0 release
This commit is contained in:
@@ -1,471 +0,0 @@
|
||||
# Release Procedure Upgrade Implementation Plan
|
||||
|
||||
## Purpose And Status
|
||||
|
||||
This document is the executable implementation plan for
|
||||
[`release-procedure.md`](release-procedure.md). The feature roadmap owns the
|
||||
accepted user intent, policy choices, required outcome, and responsibility
|
||||
boundary. This plan translates that target into bounded implementation stages
|
||||
suitable for one `gpt-5.6-terra` coding prompt apiece.
|
||||
|
||||
All five stages were completed in numeric order. This document is retained as
|
||||
implementation history; current release behavior is owned by the checked-in
|
||||
scripts and canonical release documentation. This plan superseded the completed
|
||||
pipeline-configuration implementation plan that previously occupied this path;
|
||||
that feature's implemented behavior is now owned by current canonical
|
||||
documentation and code.
|
||||
|
||||
## Settled Implementation Decisions
|
||||
|
||||
The following decisions are final for this implementation:
|
||||
|
||||
- The synchronous release boundary is a successful push of the exact selected
|
||||
tag ref to `origin`. Neither `scripts/release.sh` nor any instruction that
|
||||
defines successful release completion may poll Woodpecker, query build
|
||||
status, wait for a Gitea release, download assets, or verify asynchronous
|
||||
publication.
|
||||
- The supported command surfaces are exactly:
|
||||
`scripts/build-release-assets.sh VERSION OUTPUT_DIR`,
|
||||
`scripts/check-release-candidate.sh VERSION`, and
|
||||
`scripts/release.sh VERSION`.
|
||||
- All scripts are POSIX `sh`, use `set -eu`, derive the repository root from
|
||||
their own checked-in location, and use narrowly named variables. They do not
|
||||
rely on the caller's current directory and do not repurpose `HOME`,
|
||||
`CODEX_HOME`, or common system-option variables.
|
||||
- A private source-only `scripts/release-lib.sh` owns the stable semantic
|
||||
version parser and shared fatal-error/reporting helpers. It has no behavior
|
||||
merely from being sourced. Public scripts source it relative to their own
|
||||
location so version syntax and error conventions do not drift.
|
||||
- Stable versions match exactly
|
||||
`v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)`. Prerelease and build
|
||||
suffixes are rejected.
|
||||
- `scripts/build-release-assets.sh` accepts exactly two arguments. Its output
|
||||
path must be absolute, must not be `/` or the repository root, must not be a
|
||||
symlink or non-directory, and must either not exist or be an empty directory.
|
||||
The script creates the directory when absent, writes only its six named
|
||||
assets and any narrowly scoped temporary smoke binary, and never recursively
|
||||
clears a caller-supplied path.
|
||||
- Official targets are CGO-disabled Linux, Darwin, and Windows builds for both
|
||||
`amd64` and `arm64`. Filenames are
|
||||
`narratio-VERSION-GOOS-GOARCH`, with `.exe` only on Windows. Builds use
|
||||
`-trimpath`, `-s -w`, and
|
||||
`-X gitea.maximumdirect.net/eric/narratio/internal/buildinfo.Version=VERSION`.
|
||||
- The asset builder verifies `narratio version` on the current host. When the
|
||||
host is one of the six official targets it executes that official asset;
|
||||
otherwise it builds a separate temporary host smoke binary, executes it,
|
||||
and removes only that file. Expected output is exactly
|
||||
`narratio VERSION`.
|
||||
- `scripts/check-release-candidate.sh` is read-only with respect to tracked
|
||||
source and Git refs. It accepts exactly one version, validates the matching
|
||||
note, performs repository and Go-module hygiene checks, runs every required
|
||||
test/static/build/documentation/example check uncached where applicable,
|
||||
verifies formatting and whitespace, and calls the shared asset builder in a
|
||||
directory created with `mktemp -d`. Every Go command it owns runs with
|
||||
`GOWORK=off`.
|
||||
- The candidate checker deliberately does not require `main`, a clean checkout,
|
||||
synchronized remote refs, or an unused tag. This allows it to validate a
|
||||
candidate before commit and to run in tag CI's detached checkout. Those
|
||||
mutable publication guards belong only to `scripts/release.sh`.
|
||||
- `scripts/release.sh` accepts exactly one version, operates only against the
|
||||
remote named `origin` and branch named `main`, and never accepts bypass,
|
||||
force, alternate-remote, skip-check, or CI-wait flags.
|
||||
- The publication script uses a two-phase guard. It checks cheap local and
|
||||
upstream conditions before the potentially long candidate checker, then
|
||||
fetches and rechecks the clean checkout, exact `HEAD == origin/main`, and
|
||||
local/remote tag absence immediately before creating the tag. This prevents
|
||||
a long validation run from publishing after the candidate or upstream tip
|
||||
changed.
|
||||
- Release tags remain explicitly unsigned lightweight tags. The script uses
|
||||
`git -c tag.gpgSign=false tag VERSION COMMIT`, verifies that the ref type is
|
||||
`commit` and resolves to the recorded commit, and pushes only
|
||||
`refs/tags/VERSION:refs/tags/VERSION`. It never pushes `main` or uses
|
||||
`git push --tags`.
|
||||
- A failed push leaves the unpublished local tag intact for inspection. The
|
||||
script never silently deletes or retries it. A successful push prints the
|
||||
version and exact commit, returns zero immediately, and performs no later
|
||||
network or CI action.
|
||||
- Release-script behavioral tests use real temporary Git repositories and a
|
||||
local bare `origin`, with a fixture-local stub candidate checker where a
|
||||
full repository validation would add no confidence. They never touch the
|
||||
developer's actual refs or any network service.
|
||||
- Tag CI uses `golang:1.25.5` and
|
||||
`woodpeckerci/plugin-release:0.3.1`. Its steps are named
|
||||
`validate-release`, `build-release-assets`, and `publish-release` in that
|
||||
dependency order.
|
||||
- The release plugin explicitly sets title
|
||||
`Narratio ${CI_COMMIT_TAG}`, note
|
||||
`docs/releases/${CI_COMMIT_TAG}.md`, flattened SHA-256 checksums,
|
||||
`file-exists: skip`, `overwrite: false`, and `prerelease: false`. Skipping an
|
||||
existing remote release preserves idempotence and immutability; repairing a
|
||||
failed published tag remains a new-patch-release operation.
|
||||
- Release documentation describes optional later inspection but never makes
|
||||
CI success, Gitea release creation, checksum download, or host asset execution
|
||||
a required step after a successful tag push.
|
||||
- This feature does not create the next release note, tag a version, push
|
||||
`main`, or publish a release. Those actions occur only after this
|
||||
implementation sprint is complete and a separate release candidate is
|
||||
selected.
|
||||
|
||||
## Instructions For Every Stage
|
||||
|
||||
Before changing files in each stage:
|
||||
|
||||
1. Read `docs/development.md`, all documents under `docs/policy/`, this plan,
|
||||
and the relevant portions of
|
||||
[`release-procedure.md`](release-procedure.md).
|
||||
2. Inspect the current scripts, Woodpecker workflows, release notes,
|
||||
`internal/buildinfo`, `internal/app/version.go`, and focused repository
|
||||
checks relevant to the stage. Prefer the codebase knowledge graph for Go
|
||||
discovery and use text search for shell, YAML, and Markdown.
|
||||
3. Confirm the worktree state and preserve unrelated changes.
|
||||
4. Re-read the responsibility boundary before editing any publication command:
|
||||
successful upstream tag push ends the synchronous release process.
|
||||
|
||||
During every stage:
|
||||
|
||||
- Keep public shell interfaces and file ownership exactly as settled above.
|
||||
- Use the Go standard library and ordinary POSIX tools already available in the
|
||||
builder images; do not add a shell framework, Go dependency, release SaaS,
|
||||
or package-manager tool.
|
||||
- Keep tests deterministic, offline, and free of real credentials and remote
|
||||
infrastructure. Use `t.TempDir()` and local bare Git repositories for
|
||||
publication behavior.
|
||||
- Test consequential behavior at the narrowest stable boundary. Avoid tests
|
||||
that merely snapshot complete script text or duplicate every shell branch.
|
||||
- Make failures identify the responsible script, invalid value, or failed
|
||||
command without printing environment dumps or secret values.
|
||||
- Do not document future behavior outside `docs/roadmap/` until the stage that
|
||||
makes that behavior usable. Update canonical current-behavior documentation
|
||||
in the same stage that completes the release procedure.
|
||||
- Format changed Go files, run `sh -n` on changed shell files, use focused
|
||||
tests while iterating, and finish each stage with `git diff --check` plus the
|
||||
stage's exit criteria.
|
||||
- Do not create, delete, move, or push a real Narratio tag while implementing
|
||||
or testing this feature.
|
||||
|
||||
## Stage 1 — Shared Release Library And Asset Builder
|
||||
|
||||
**Status: Completed**
|
||||
|
||||
### Goal
|
||||
|
||||
Create the single safe implementation of version validation and official
|
||||
release-asset construction without changing Git refs, CI, or current release
|
||||
documentation.
|
||||
|
||||
### Required Work
|
||||
|
||||
1. Create `scripts/release-lib.sh` as a source-only POSIX library. Give its
|
||||
functions a Narratio-specific prefix. At minimum it must provide:
|
||||
- a fatal-error helper that prefixes errors with the calling release tool;
|
||||
- exact stable-semver validation; and
|
||||
- a helper for locating the repository root from a public script's absolute
|
||||
or relative path without depending on the caller's working directory.
|
||||
Keep the library private to the scripts; it is not a supported user-facing
|
||||
API.
|
||||
2. Create executable `scripts/build-release-assets.sh` with the exact
|
||||
`VERSION OUTPUT_DIR` interface and output-directory contract in the settled
|
||||
decisions. Reject missing/extra arguments, malformed versions, relative or
|
||||
dangerously broad output paths, symlink/non-directory output, and a
|
||||
nonempty output directory before building anything.
|
||||
3. Build the six official binaries in deterministic target order. Use the
|
||||
current command package and build-info linker symbol; do not duplicate or
|
||||
change application version semantics.
|
||||
4. Verify exact host version output as settled above. Ensure a failed build or
|
||||
version mismatch is fatal and leaves no false success message. Temporary
|
||||
smoke output must be inside the validated staging directory and removed
|
||||
narrowly.
|
||||
5. Add focused tests under a new `internal/releasecheck` test package. Protect
|
||||
the meaningful asset-builder risks without making the default Go suite
|
||||
compile all six targets repeatedly:
|
||||
- argument and semver rejection;
|
||||
- refusal of unsafe, symlink, non-directory, and nonempty destinations;
|
||||
- creation only beneath an accepted empty destination; and
|
||||
- exact naming/version behavior through one controlled host build or a
|
||||
command shim, whichever is simpler and remains behavior-focused.
|
||||
The operational six-target build is exercised directly in the stage exit
|
||||
criteria and later by candidate validation.
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- `sh -n scripts/release-lib.sh scripts/build-release-assets.sh` succeeds.
|
||||
- Focused `internal/releasecheck` tests pass.
|
||||
- Running the asset builder with a synthetic stable version and a fresh
|
||||
temporary output directory produces exactly six official assets and the
|
||||
host version check succeeds.
|
||||
- Invalid and unsafe output examples fail before creating release assets.
|
||||
- `go test ./...`, `go vet ./...`, `go build ./...`, and
|
||||
`git diff --check` succeed.
|
||||
|
||||
## Stage 2 — Central Release-Candidate Checker
|
||||
|
||||
**Status: Completed**
|
||||
|
||||
### Goal
|
||||
|
||||
Create one read-only source-candidate validator that maintainers and tag CI can
|
||||
run identically, eliminating drift between documented preparation and tagged
|
||||
source validation.
|
||||
|
||||
### Required Work
|
||||
|
||||
1. Create executable `scripts/check-release-candidate.sh` with the exact
|
||||
one-version interface. Source `release-lib.sh`, resolve and enter the
|
||||
repository root, and validate the version before using it in a path.
|
||||
2. Require `docs/releases/VERSION.md` to be nonempty, begin with the exact
|
||||
`# Narratio VERSION` heading, and contain exact
|
||||
`## Summary`, `## Compatibility`, `## Upgrade`, and `## Changes` headings.
|
||||
Do not parse prose or impose historical-note requirements on other tags.
|
||||
3. Enforce repository/module hygiene:
|
||||
- exact Narratio module declaration;
|
||||
- no tracked `go.work` or `go.work.sum`;
|
||||
- no `vendor` directory;
|
||||
- no single-line or block `replace` declaration in `go.mod`;
|
||||
- `GOWORK=off go mod tidy -diff` leaves module files unchanged;
|
||||
- all tracked `*.go` files are `gofmt` clean; and
|
||||
- both working-tree and cached whitespace checks pass.
|
||||
4. Run the complete Narratio candidate checks with `GOWORK=off`:
|
||||
- `go test -count=1 ./...`;
|
||||
- `go test -race -count=1 ./...`;
|
||||
- `go vet ./...`;
|
||||
- `go build ./...`;
|
||||
- `go test -count=1 ./internal/doccheck`; and
|
||||
- `go test -count=1 ./internal/config -run '^TestExamplesLoadAndValidate$'`.
|
||||
5. Create one temporary directory with `mktemp -d`, install a trap that removes
|
||||
only that verified directory, and invoke `build-release-assets.sh` with the
|
||||
selected version. The candidate checker owns no independent target matrix,
|
||||
filenames, linker flags, or version smoke logic.
|
||||
6. Extend `internal/releasecheck` with lean behavioral coverage for the
|
||||
candidate checker's guards. Use isolated fixture repositories and command
|
||||
shims where needed so default tests do not recursively run the complete
|
||||
Narratio suite. Cover malformed version/note, wrong module identity,
|
||||
disallowed workspace/vendor/replace state, propagation of a failing owned
|
||||
validation command, and evidence that owned Go commands receive
|
||||
`GOWORK=off`.
|
||||
7. Ensure the checker itself does not inspect the active branch, fetch a
|
||||
remote, require a clean status, check tag availability, mutate refs, or
|
||||
contact Woodpecker/Gitea. Those are deliberately outside this script's
|
||||
contract.
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- `sh -n scripts/release-lib.sh scripts/build-release-assets.sh scripts/check-release-candidate.sh`
|
||||
succeeds.
|
||||
- Focused `internal/releasecheck` tests pass, including failure propagation.
|
||||
- A disposable fixture with a compliant synthetic release note exercises the
|
||||
candidate checker successfully; malformed fixtures fail with actionable
|
||||
script-owned errors.
|
||||
- The repository-wide test, race, vet, build, documentation, example,
|
||||
formatting, module-tidiness, and whitespace checks all pass independently.
|
||||
- No Git ref, tracked file, or external service is mutated by the checker.
|
||||
|
||||
## Stage 3 — Guarded Tag Publication Command
|
||||
|
||||
**Status: Completed**
|
||||
|
||||
### Goal
|
||||
|
||||
Provide one safe, non-interactive command that publishes exactly one guarded
|
||||
lightweight tag and stops immediately when the upstream Git push succeeds.
|
||||
|
||||
### Required Work
|
||||
|
||||
1. Create executable `scripts/release.sh` with the exact one-version interface.
|
||||
Source the shared library and reject invalid arguments before running Git
|
||||
operations.
|
||||
2. Implement the first cheap guard phase:
|
||||
- require branch `main`;
|
||||
- require an empty `git status --porcelain` result;
|
||||
- fetch `origin main --tags`;
|
||||
- record `HEAD^{commit}` as the immutable candidate for this attempt;
|
||||
- require it to equal `origin/main^{commit}`;
|
||||
- require the matching note to exist in that candidate; and
|
||||
- reject an existing local or exact upstream tag.
|
||||
3. Invoke `scripts/check-release-candidate.sh VERSION` without suppressing its
|
||||
output or weakening any check.
|
||||
4. Implement the second guard phase immediately after validation:
|
||||
- refetch `origin main --tags`;
|
||||
- require the checkout still to be clean and on `main`;
|
||||
- require `HEAD` and `origin/main` still to equal the originally recorded
|
||||
candidate commit; and
|
||||
- recheck exact local and upstream tag absence.
|
||||
Do not silently select a newer commit or restart validation.
|
||||
5. Create the explicitly unsigned lightweight tag against the recorded commit,
|
||||
verify its object type and resolved commit, show a concise local summary,
|
||||
and push only its fully qualified tag ref to `origin`.
|
||||
6. On push success, print one concise completion message containing the tag and
|
||||
commit and exit zero immediately. There must be no commands after the push
|
||||
that query CI, Gitea, a release API, assets, or checksums. Do not sleep or
|
||||
retry waiting for asynchronous state.
|
||||
7. On failure before tag creation, leave refs unchanged. On failure after local
|
||||
tag creation, retain the local tag and return a clear instruction that it is
|
||||
unpublished and requires inspection. Never automatically delete, move,
|
||||
force-push, or reuse a tag.
|
||||
8. Add behavioral tests in `internal/releasecheck` using temporary working
|
||||
repositories and local bare `origin` repositories. Put a successful stub
|
||||
candidate checker at the fixture's expected checked-in path so tests isolate
|
||||
tag policy rather than rerun compilation. Cover at least:
|
||||
- wrong branch and dirty checkout rejection;
|
||||
- local `HEAD` not equal to `origin/main`;
|
||||
- candidate-checker failure;
|
||||
- existing local and upstream tag rejection;
|
||||
- upstream `main` changing between the two guard phases;
|
||||
- successful creation of a lightweight remote tag pointing to the exact
|
||||
candidate commit;
|
||||
- push failure retaining the local tag; and
|
||||
- absence of any pushed branch or unrelated tag.
|
||||
Tests must never use the real repository's `origin` or network.
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- All release scripts pass `sh -n`.
|
||||
- Focused publication tests pass and prove the exact remote-tag outcome and
|
||||
failure behavior.
|
||||
- A success-path test demonstrates that the release command returns as soon as
|
||||
the local bare-remote tag push succeeds; it performs no CI/Gitea follow-up.
|
||||
- `go test ./...`, `go test -race ./...`, `go vet ./...`, `go build ./...`, and
|
||||
`git diff --check` succeed.
|
||||
- No real Narratio tag or remote ref is created or changed.
|
||||
|
||||
## Stage 4 — Asynchronous Woodpecker Release Integration
|
||||
|
||||
**Status: Completed**
|
||||
|
||||
### Goal
|
||||
|
||||
Make tag CI consume the shared candidate and asset contracts while preserving
|
||||
strict validation-before-publication ordering and complete independence from
|
||||
the synchronous tag command.
|
||||
|
||||
### Required Work
|
||||
|
||||
1. Rewrite `.woodpecker/release.yml` around three explicit steps:
|
||||
- `validate-release` in `golang:1.25.5`, invoking
|
||||
`./scripts/check-release-candidate.sh "$CI_COMMIT_TAG"`;
|
||||
- `build-release-assets` in `golang:1.25.5`, depending on
|
||||
`validate-release`, requiring a fresh absent/empty absolute `$PWD/dist`,
|
||||
and invoking the shared asset builder; and
|
||||
- `publish-release`, depending on `build-release-assets` and using
|
||||
`woodpeckerci/plugin-release:0.3.1`.
|
||||
Remove the redundant inline target matrix, validation command list, and
|
||||
separate cross-build step from the release workflow.
|
||||
2. Configure publication exactly as settled: the existing release-token
|
||||
secret, `dist/narratio-*` files, explicit title and tagged note, flattened
|
||||
`SHA256SUMS`, `file-exists: skip`, no overwrite, and no prerelease.
|
||||
3. Preserve the tag-only event trigger. Do not add a pipeline callback, status
|
||||
endpoint, wait command, or any coupling from `scripts/release.sh` to this
|
||||
workflow.
|
||||
4. Update `internal/doccheck/doccheck_test.go` so the dependency assertion names
|
||||
`validate-release` and still proves transitively that publication cannot run
|
||||
after failed validation. Extend its minimal YAML model only as needed to
|
||||
protect consequential release invariants:
|
||||
- the validator calls the shared checker;
|
||||
- asset publication depends on validated shared construction;
|
||||
- the release plugin image is pinned;
|
||||
- title and note use the selected tag; and
|
||||
- overwrite/prerelease remain disabled.
|
||||
Avoid snapshotting the whole workflow or duplicating every plugin setting.
|
||||
5. Confirm `.woodpecker/verify.yml` and `.woodpecker/shuffle.yml` remain normal
|
||||
push/PR and scheduled validation. Do not make either wait for or invoke a
|
||||
release operation.
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- The Woodpecker YAML parses and the focused `internal/doccheck` workflow
|
||||
dependency/invariant tests pass.
|
||||
- The release workflow has one target matrix owner and one candidate-check
|
||||
owner, both under `scripts/`.
|
||||
- `publish-release` has a dependency path to `validate-release`; no failure in
|
||||
validation or asset building can publish.
|
||||
- Static inspection confirms `scripts/release.sh` has no reference to
|
||||
Woodpecker, Gitea release status, or CI polling.
|
||||
- `go test ./...`, `go test -race ./...`, `go vet ./...`, `go build ./...`,
|
||||
documentation/example checks, and `git diff --check` succeed.
|
||||
|
||||
## Stage 5 — Canonical Release Documentation And Final Audit
|
||||
|
||||
**Status: Completed**
|
||||
|
||||
### Goal
|
||||
|
||||
Document the now-implemented maintainer workflow in one canonical location,
|
||||
make it discoverable, and perform a complete offline acceptance audit without
|
||||
creating or publishing a real release.
|
||||
|
||||
### Required Work
|
||||
|
||||
1. Create `docs/release.md` as the canonical current-behavior procedure. It
|
||||
must include:
|
||||
- stable SemVer selection for a post-`v1.0.0` project;
|
||||
- the exact future release-note structure;
|
||||
- candidate preparation and ordinary `main` push expectations;
|
||||
- direct use of `scripts/check-release-candidate.sh`;
|
||||
- direct use and complete safety contract of `scripts/release.sh`;
|
||||
- lightweight-tag immutability and correction through a new patch version;
|
||||
- the explicit statement that successful upstream tag push completes the
|
||||
release command; and
|
||||
- a clearly optional asynchronous inspection section, separated from the
|
||||
release steps and stating that a human may inspect CI/Gitea later but an
|
||||
automated releaser must not wait for it.
|
||||
Do not embed a second implementation of script guards as a long shell block;
|
||||
the scripts own volatile mechanics and the document owns the maintainer
|
||||
workflow and policy.
|
||||
2. Update `docs/development.md` with a task-guide row pointing release work to
|
||||
`docs/release.md`. Keep its validation summary concise and link to the
|
||||
release procedure/checker rather than duplicating the candidate command
|
||||
list.
|
||||
3. Update `docs/policy/documentation.md` to assign canonical ownership for the
|
||||
maintainer release procedure and version-matched historical notes. Preserve
|
||||
the rule that release notes link to, rather than replace, current contract
|
||||
documentation.
|
||||
4. Update `docs/releases/README.md` to explain forward-looking note structure,
|
||||
retain its existing `v1.5.0` entry, and identify the Gitea release collection
|
||||
as the binary/checksum source when asynchronous publication succeeds. Do
|
||||
not backfill or rewrite historical notes.
|
||||
5. Review other current documentation for claims that release completion waits
|
||||
on CI. Remove or link any conflicting duplication. Do not add release
|
||||
mechanics to operations, CLI, architecture, or integration documents unless
|
||||
they already own a directly affected current contract.
|
||||
6. Mark `docs/roadmap/release-procedure.md` implemented only after scripts,
|
||||
tests, CI, and canonical documentation match its target. Keep implementation
|
||||
status in roadmap documents; current-behavior claims belong in
|
||||
`docs/release.md` and the policy/developer routing documents.
|
||||
7. Perform a final behavior and safety audit:
|
||||
- inspect all scripts for unsafe path deletion, unresolved variables,
|
||||
accidental secret output, broad ref pushes, force options, and commands
|
||||
after the successful tag push;
|
||||
- run all release-script behavioral tests against temporary local remotes;
|
||||
- run the asset builder directly with a synthetic stable version and a
|
||||
fresh temporary output directory, then verify the six filenames and host
|
||||
version output;
|
||||
- validate candidate-checker success in its isolated fixture and every
|
||||
important failure class without creating a real note or tag;
|
||||
- confirm the release workflow reads the note from the tagged tree and
|
||||
cannot publish before validation; and
|
||||
- confirm no test or documentation instruction requires live CI, Gitea,
|
||||
credentials, or paid/external adapters.
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- All local Markdown links and Woodpecker dependency checks pass.
|
||||
- `sh -n scripts/release-lib.sh scripts/build-release-assets.sh scripts/check-release-candidate.sh scripts/release.sh`
|
||||
succeeds.
|
||||
- Release-script tests and the direct six-target asset build pass without
|
||||
touching real refs or external services.
|
||||
- The full repository validation set from `docs/development.md` passes:
|
||||
- `go test ./...`;
|
||||
- `go test -race ./...`;
|
||||
- `go vet ./...`;
|
||||
- `go build ./...`;
|
||||
- `go test ./internal/doccheck`; and
|
||||
- `go test ./internal/config -run '^TestExamplesLoadAndValidate$'`.
|
||||
- `go mod tidy -diff`, tracked-file `gofmt` inspection,
|
||||
`git diff --check`, and `git diff --cached --check` succeed.
|
||||
- The repository contains no synthetic release note, local test tag, build
|
||||
asset, credential, temporary repository, or other generated test residue.
|
||||
- No real release is tagged or pushed during this implementation plan.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None. The feature roadmap and settled decisions above are sufficient to
|
||||
implement the release procedure without additional product or policy choices.
|
||||
Reference in New Issue
Block a user