Align release policy and operational documentation
This commit is contained in:
@@ -64,7 +64,8 @@ git show cb5b435:docs/roadmap/remediation.md
|
||||
```
|
||||
|
||||
Release-candidate, publication, and verification work follows the operational
|
||||
[release procedure](release.md).
|
||||
[release procedure](release.md). Its single publication command validates the
|
||||
committed candidate and publishes only the intended refs.
|
||||
|
||||
The completed string-and-integer schema-version implementation and remediation
|
||||
records are preserved in Git history at `244104f`. The
|
||||
@@ -116,9 +117,9 @@ Use focused checks while iterating, with validation proportionate to the change
|
||||
under the testing policy. Documentation-only work normally needs the local-link
|
||||
check below and whitespace review; behavior-bearing examples and commands also
|
||||
need execution. Use `go test -race ./...` for ownership or concurrency changes.
|
||||
The [release checker](release.md#4-publish-the-committed-candidate) performs one
|
||||
minimum-toolchain offline race-suite run, one full vet pass, and Linux
|
||||
cross-builds using readonly module mode.
|
||||
The [publication command](release.md#4-publish-the-committed-candidate) invokes
|
||||
the release checker once. It performs one minimum-toolchain offline race-suite
|
||||
run, one full vet pass, and Linux cross-builds using readonly module mode.
|
||||
It already covers examples, links, and package boundaries; do not additionally
|
||||
run the everyday checker just to repeat those checks. CI never gates a release.
|
||||
|
||||
@@ -139,7 +140,8 @@ code changes. Use the component overview to find the corresponding implementatio
|
||||
| Secrets, bootstrap, redaction, explanation | [References](../internal/engine/secret_reference_test.go), [bootstrap](../internal/engine/secrets_test.go), [rendering](../internal/engine/render_test.go), [explanation](../internal/engine/explain_test.go) | `go test ./internal/engine -run 'Secret\|Bootstrap\|Effective\|Explain\|Explanation\|History\|Sensitivity'` |
|
||||
| Consumer examples and migration fixtures | [Consumer tests](../examples/consumers/consumers_test.go), [API examples](../example_test.go) | `go test ./examples/consumers` and `go test . -run '^Example'` |
|
||||
| Documentation links and dependency isolation | [Link checks](../documentation_test.go), [import boundary](../import_boundary_test.go), [public boundary](../public_boundary_test.go) | `go test . -run 'TestLocalDocumentationLinks\|TestDependencyImportBoundary\|TestPublicFacadeBoundary'` |
|
||||
| Check-command behavior | [Shell regression](../release_check_test.go) | `go test . -run '^TestCheckScripts'` |
|
||||
| Development and release checker behavior | [Shell regression](../release_check_test.go) | `go test . -run 'TestCheckScripts\|TestDevelopmentCheck'` |
|
||||
| Guarded release publication and recovery | [Publication regression](../release_publish_test.go) | `go test . -run '^TestReleasePublication'` |
|
||||
|
||||
## Fuzz validation
|
||||
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
|
||||
**Upstream Source:** [Standard Repository Policies](https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843/docs/policy/release.md)
|
||||
|
||||
ConfigKit's [release procedure](../release.md) uses one publication command
|
||||
with the selected local checker and explicit main-then-tag pushes.
|
||||
|
||||
## Purpose
|
||||
|
||||
This policy defines a proportionate workflow for validating and publishing an
|
||||
@@ -19,28 +16,21 @@ The repository-specific commands belong in `docs/release.md`. Historical release
|
||||
summaries belong in `docs/releases/`. The procedure must agree with the adopted
|
||||
policy and link to it rather than introduce additional release requirements.
|
||||
|
||||
## ConfigKit applicability
|
||||
## ConfigKit Applicability
|
||||
|
||||
ConfigKit adopts a source-only Go module release model. The source tag and
|
||||
version-matched release note are the declared deliverables. Standalone binaries,
|
||||
container images, and separate binary/package-registry publication are not
|
||||
required. This does not waive source compilation, dependency maintenance, testing, or
|
||||
local target-build validation. Post-publication consumer retrieval is optional,
|
||||
as described under Release Model.
|
||||
ConfigKit publishes a source-only Go module. Its declared deliverables are the
|
||||
immutable annotated source tag and version-matched checked-in release note.
|
||||
Standalone binaries, container images, hosted release objects, and separate
|
||||
registry publication are not required. Additional channels require a deliberate
|
||||
update to the policy and procedure.
|
||||
|
||||
The release procedure must define the module path, authoritative remote,
|
||||
supported Go versions and operating-system/architecture targets, prerequisite
|
||||
dependency acquisition, and the exact verification commands once established.
|
||||
The default tests themselves remain deterministic and offline. Additional
|
||||
publication channels require documented deliverables and verification before use.
|
||||
|
||||
The Go API, documented YAML/resolution semantics, and structured diagnostic
|
||||
contracts all participate in compatibility review. A signature-preserving change
|
||||
The Go API, documented YAML and resolution semantics, and structured diagnostic
|
||||
contracts participate in compatibility review. A signature-preserving change
|
||||
can still break consumers. Human diagnostic wording is stable only where a
|
||||
contract expressly promises it. Minimum Go version and platform support changes
|
||||
also require an explicit compatibility assessment.
|
||||
contract expressly promises it. Minimum Go version and platform support
|
||||
changes also require an explicit compatibility assessment.
|
||||
|
||||
### Platform support
|
||||
### Platform Support
|
||||
|
||||
Linux is the release-validated platform. macOS has best-effort support: keeping
|
||||
it working remains desirable, but neither native macOS validation nor Darwin
|
||||
@@ -49,50 +39,59 @@ does not by itself block a release. Voluntary checks and fixes are welcome; ther
|
||||
is no guarantee that each release has been validated on macOS.
|
||||
|
||||
The [release procedure](../release.md#release-identity-and-support) owns target
|
||||
architectures and required Linux checks. This support change applies to upcoming
|
||||
releases; historical release notes and their validation records remain unchanged.
|
||||
The v0.3.0 release note must explain the change in Compatibility, with version
|
||||
selection following this policy's existing compatibility rules.
|
||||
architectures and required Linux checks. Historical release notes and their
|
||||
validation records remain unchanged.
|
||||
|
||||
## Release Model
|
||||
## Release Model And Completion
|
||||
|
||||
A source release identifies one exact committed source revision through an
|
||||
immutable version tag and a version-matched, checked-in release note. ConfigKit's
|
||||
primary release branch is `main`; its tags are annotated. The
|
||||
[release procedure](../release.md) names the authoritative publication remote.
|
||||
immutable version tag and a version-matched, checked-in release note. The
|
||||
primary release branch is `main` unless the adopted policy specifies otherwise.
|
||||
The procedure must name the authoritative publication remote.
|
||||
|
||||
A successful push of the intended tag, with its source commit available on the
|
||||
authoritative primary branch, completes the release. ConfigKit publishes the
|
||||
committed candidate to `main` before pushing only the intended tag.
|
||||
authoritative primary branch, completes the release. The source commit may be
|
||||
pushed before the tag or published together with it through an atomic push.
|
||||
The procedure must choose and document the supported approach.
|
||||
|
||||
ConfigKit uses sequential explicit pushes: first the captured candidate to
|
||||
authoritative `main`, then the annotated tag. Its
|
||||
[release procedure](../release.md) names `origin` and checks that its fetch and
|
||||
push destinations resolve to the authoritative URL.
|
||||
|
||||
Release commands must finish at successful publication. They must not wait for
|
||||
or poll CI, require successful CI status, inspect downloadable artifacts, or
|
||||
check consumer installation or Go module availability as completion gates.
|
||||
Optional remote tag read-back and fresh consumer retrieval do not delay release
|
||||
completion.
|
||||
|
||||
A failed or ambiguous push requires resolving the authoritative remote state
|
||||
before declaring success or retrying; successful pushes do not require a
|
||||
separate remote read-back gate.
|
||||
|
||||
ConfigKit publishes source only. If additional deliverables are deliberately
|
||||
adopted, they must be traceable to the tagged source, identify the same version,
|
||||
and have documented publication responsibilities and verification.
|
||||
Remote tag read-back and fresh consumer retrieval are optional and non-gating
|
||||
after successful publication. A failed push receives one bounded check of the
|
||||
authoritative ref; do not poll or blindly retry.
|
||||
|
||||
Release automation may validate or publish a release only when its exact
|
||||
responsibility is documented. Automation must not silently change the source
|
||||
candidate, move a published tag, replace a published deliverable, or repair a
|
||||
release in place.
|
||||
Repositories may publish source only. Additional binaries, images, packages,
|
||||
checksums, or other declared deliverables may be published asynchronously from
|
||||
the tagged source. The procedure must identify those deliverables and the
|
||||
responsibility of their automation. Published deliverables must be traceable
|
||||
to that source and identify the same version.
|
||||
|
||||
ConfigKit currently declares no additional deliverables. Its source-tag push
|
||||
is the completion point.
|
||||
|
||||
## Versioning And Compatibility
|
||||
|
||||
Stable releases use Semantic Versioning in the form `vMAJOR.MINOR.PATCH`, with
|
||||
no leading zeroes. The selected version must be unused locally and on the
|
||||
authoritative remote. A version known to have been published elsewhere must
|
||||
not be reused.
|
||||
no leading zeroes. Prereleases require an explicit adopted policy defining
|
||||
their format and use.
|
||||
|
||||
Unless an adopted policy explicitly supports and defines prereleases,
|
||||
prerelease versions are not permitted.
|
||||
ConfigKit does not support prereleases.
|
||||
|
||||
The selected version must be unused locally and on the authoritative remote.
|
||||
Do not require queries to every configured remote or publication service.
|
||||
A version known to have already been published must not be reused, even if the
|
||||
normal guards do not inspect that channel. Adding a distribution channel
|
||||
requires a deliberate update to the policy and procedure where needed.
|
||||
|
||||
For releases at or after `v1.0.0`:
|
||||
|
||||
@@ -105,89 +104,123 @@ configuration, data, integration, or compatibility contract when the release
|
||||
note explains the impact and required consumer action. A patch release must
|
||||
not intentionally break those contracts within its minor line.
|
||||
|
||||
A repository with additional compatibility promises must define them in its
|
||||
adopted policy or canonical contract documentation. A release note may explain
|
||||
a compatibility change, but it must not redefine the current compatibility
|
||||
contract.
|
||||
Additional compatibility promises and deliberate exceptions belong in the
|
||||
adopted policy or canonical contract documentation. Release notes explain
|
||||
changes; they do not redefine current compatibility contracts.
|
||||
|
||||
## Release Documentation
|
||||
## Release Documentation And Preparation
|
||||
|
||||
Every release made under this policy must include
|
||||
`docs/releases/<version>.md` in the tagged source tree. The filename must use
|
||||
the complete version tag, and the document must begin with a title containing
|
||||
the product name and that exact version.
|
||||
Every new release must include `docs/releases/<version>.md` in the tagged
|
||||
source tree. Use the complete version tag as the filename and begin with a
|
||||
title containing the product name and that exact version.
|
||||
|
||||
ConfigKit requires the first line `# ConfigKit <version>`.
|
||||
|
||||
Include a short summary and any relevant compatibility impact or upgrade
|
||||
instructions. Choose sections suited to the release and keep the note
|
||||
proportionate to the change. The annotated tag's message is the checked-in note.
|
||||
proportionate to the change.
|
||||
|
||||
Release notes are immutable historical summaries. They should link to current
|
||||
canonical documentation for exact behavior. Every affected canonical document
|
||||
must be updated in the same candidate; a release note must not substitute for
|
||||
current documentation or defer required documentation changes.
|
||||
Keep exact current contracts in their canonical documents and update affected
|
||||
documentation with the behavior change. Link to those documents from the note
|
||||
where useful. If annotated tags are used, derive their summary from the
|
||||
checked-in note.
|
||||
|
||||
Each new release note must end with the release navigation defined by the
|
||||
[OSS policy](oss.md#discoverability). Preserve those links on a hosted download
|
||||
page if one is used. The release procedure owns URL construction and channel
|
||||
treatment. This is ordinary preparation, not a new network check or approval
|
||||
gate; historical release notes are unchanged.
|
||||
ConfigKit uses the complete checked-in note as the annotated tag message.
|
||||
|
||||
## Candidate Preparation And Validation
|
||||
Include the release footer defined by the [OSS policy](oss.md#discoverability)
|
||||
in each new release document. The release procedure defines the concrete URLs
|
||||
and publication mechanics. Prepare these links with the release note; they do
|
||||
not add a network check or approval gate. If a hosted download page is used in
|
||||
a future channel, preserve the footer there.
|
||||
|
||||
The publication command validates the final committed candidate once with
|
||||
ConfigKit's local release checker, using one maintained patch of the minimum
|
||||
supported Go line on Linux. The checker runs one full offline race suite, one
|
||||
full vet pass, and CGO-disabled Linux amd64/arm64 builds. The race suite
|
||||
protects library behavior, ownership,
|
||||
and concurrent use; it includes examples, documentation links, consumer fixtures,
|
||||
and package boundaries without separate runs. Full vet checks more than the
|
||||
subset normally run by tests, so test-time vet is disabled. The two cross-builds
|
||||
cover supported configurations that native race compilation does not. A second
|
||||
toolchain is optional and non-gating.
|
||||
Handle version selection, release-note content, and retirement of completed
|
||||
roadmaps during preparation. Preserve planned and deferred work and repair
|
||||
affected links when retiring roadmaps. Reuse ordinary change review for
|
||||
unintended files, credentials, and private data. Scope release-content review
|
||||
to the tagged source.
|
||||
|
||||
All Go checks use readonly module mode and an offline dependency cache.
|
||||
Formatting and whitespace remain ordinary development checks. Review module
|
||||
tidiness when dependencies change, rather than auditing it on every release.
|
||||
## Candidate Validation
|
||||
|
||||
Commit the release note and associated changes before release validation. The
|
||||
publication command captures the exact candidate and rechecks it after the
|
||||
validator. A changed candidate requires a fresh invocation and validation.
|
||||
Do not publish uncommitted or unvalidated content. Local check failures still
|
||||
block publication. Skipped test cases are reported, not separate human sign-off
|
||||
requirements.
|
||||
Provide one publication command that validates the final committed candidate,
|
||||
checks publication state, and publishes the intended refs. A validation-only
|
||||
mode or command may be provided for diagnosis, but must not be a required step
|
||||
before publication repeats the same checks.
|
||||
|
||||
Compatibility review, release-note accuracy, removal of completed roadmaps, and
|
||||
review for unintended files, credentials, private data, and unrelated changes
|
||||
are ordinary preparation. The executing agent may perform them without routine
|
||||
human approval or separate manual evidence records. Ask the maintainer only for
|
||||
genuine unresolved decisions or missing authority. A clean existing checkout is
|
||||
sufficient; a dedicated clone is optional. Dependency and toolchain update
|
||||
research belongs to maintenance or relevant changes, not every release.
|
||||
ConfigKit uses `./scripts/release.sh vMAJOR.MINOR.PATCH`. The separate
|
||||
`scripts/release-check.sh` remains an optional diagnostic command; the
|
||||
publication command invokes it once and does not use a persistent candidate
|
||||
record.
|
||||
|
||||
Run the complete deterministic, offline default test suite once for the final
|
||||
candidate, following the [testing policy](testing.md). For repositories that
|
||||
publish builds, verify the required build targets. Select those targets for
|
||||
the application's actual support commitments; native testing on each platform
|
||||
and access to particular hardware are not default release prerequisites.
|
||||
|
||||
ConfigKit's one maintained Go 1.25 baseline runs the full suite with the race
|
||||
detector and test-time vet disabled. This protects library behavior, ownership,
|
||||
and concurrent use; the suite already includes examples, consumer fixtures,
|
||||
documentation links, and package boundaries. One full vet pass adds static
|
||||
checks beyond the test-time subset. CGO-disabled Linux amd64 and arm64 builds
|
||||
cover supported configurations distinct from native race compilation. macOS
|
||||
and newer-toolchain checks are optional.
|
||||
|
||||
Additional gates must address a concrete risk that the existing checks do not
|
||||
adequately cover. Do not automatically require linting, race testing, module
|
||||
hygiene audits, documentation audits, credential scans, example validation, or
|
||||
expanded platform matrices solely because they are possible. Retain such
|
||||
checks when their distinct protection justifies their cost. A one-time migration
|
||||
check must not silently become a permanent release requirement.
|
||||
|
||||
The selected Go commands use readonly module mode with `GOPROXY=off`; acquire
|
||||
the baseline toolchain and dependencies before validation. Formatting and
|
||||
whitespace remain ordinary development checks in `scripts/check.sh`.
|
||||
Review module tidiness when dependencies change, not as a release gate.
|
||||
|
||||
Release tests must not require real credentials, mutable application services,
|
||||
paid APIs, provider probes, or inference calls. The procedure may describe dependency
|
||||
preparation separately from offline validation.
|
||||
|
||||
Avoid duplicate validation across release phases. Successful checks for the
|
||||
same final candidate need not be repeated solely to satisfy another phase;
|
||||
any reuse must clearly apply to that exact candidate. Persistent validation
|
||||
caches are not required. If the candidate changes, validate the new candidate.
|
||||
Cheap publication-state checks may be repeated immediately before pushing
|
||||
because local or remote state may have changed during validation.
|
||||
|
||||
Automate mechanical guards. Human review gates are strongly disfavored: add one
|
||||
only through an explicit project-specific policy decision explaining the
|
||||
concrete risk and why ordinary change review or automation is insufficient.
|
||||
Do not add routine confirmations for checks the command can perform itself.
|
||||
|
||||
Compatibility review, release-note accuracy, completed-roadmap retirement, and
|
||||
review for unintended files or credentials remain ordinary preparation. The
|
||||
executing agent may perform them without routine human approval or separate
|
||||
manual evidence records. Publication itself requires authorization.
|
||||
|
||||
## Publication Guards
|
||||
|
||||
Publication requires authorization before invoking the command. The command
|
||||
must verify all of the following:
|
||||
Automate the checks needed to publish the intended source under a fresh version:
|
||||
|
||||
- the stable version has the required format and is unused locally and on the
|
||||
- the version has the adopted format and is unused locally and on the
|
||||
authoritative remote;
|
||||
- the current branch is `main`, and the worktree and index are clean;
|
||||
- the committed source and matching release note identify the exact validated
|
||||
candidate;
|
||||
- the authoritative remote main can advance to that candidate without
|
||||
discarding history;
|
||||
- the local automated gates succeeded for that commit; and
|
||||
- the annotated tag identifies that candidate and only the intended refs are
|
||||
- the worktree and index are clean on the primary release branch;
|
||||
- the source being published is the exact candidate that passed validation,
|
||||
including its matching release note;
|
||||
- the remote primary branch can be advanced to that candidate without
|
||||
discarding remote history, and is published before the tag; and
|
||||
- the tag identifies the validated candidate and only the intended refs are
|
||||
published.
|
||||
|
||||
Push the exact candidate to authoritative main, then create and verify the
|
||||
annotated tag before pushing only its ref. Do not use `git push --tags` or
|
||||
implicit follow-tags publication. A failed or ambiguous push receives one
|
||||
authoritative-state check before success, rejection, or unknown status is
|
||||
reported.
|
||||
ConfigKit also checks that `origin` has exactly the authoritative fetch and
|
||||
push destination, including configured push URLs. The command checks the
|
||||
candidate and unused version again after validation, and checks local state
|
||||
before creating the tag. Ignored local files do not block publication.
|
||||
|
||||
The repository-specific procedure must make these guards executable or give
|
||||
copyable commands for performing them.
|
||||
Fetch the authoritative branch and tag state as needed for these checks.
|
||||
Do not force branch or tag updates to bypass a failed guard. Publish explicit
|
||||
refs rather than all local tags. Do not require CI success, publication-service
|
||||
availability checks, or a separate manual confirmation for each guard.
|
||||
|
||||
## Immutability And Correction
|
||||
|
||||
@@ -201,33 +234,33 @@ rerun the publication command. If a push fails or its outcome is ambiguous,
|
||||
inspect the authoritative remote before retrying. Remove an unpublished local
|
||||
tag only after confirming it was never published or used by a release channel.
|
||||
An unavailable remote leaves publication status unknown; do not overwrite a tag
|
||||
to resolve uncertainty. A transient transport failure alone does not require
|
||||
a new version.
|
||||
to resolve uncertainty.
|
||||
|
||||
If publication or post-publication verification reveals a defect, leave the
|
||||
published release intact. Correct the defect on the primary branch, choose a
|
||||
new patch version or other semantically appropriate new version, write a new
|
||||
matching release note, and perform the complete release procedure again.
|
||||
Transient network, authentication, CI, or consumer-availability failures do not
|
||||
by themselves require a new version.
|
||||
|
||||
A distribution channel's supported yank, deprecation, or advisory mechanism
|
||||
may warn consumers away from a defective release, but it must not replace that
|
||||
release's contents or reuse its version.
|
||||
A defect requiring changes to published source or contents requires a corrected
|
||||
commit, a new semantically appropriate version, a matching release note, and
|
||||
the release procedure again. Leave the original release intact. A channel's
|
||||
yank, deprecation, or advisory mechanism may warn consumers away from a defective
|
||||
release without replacing its contents or reusing its version.
|
||||
|
||||
## Repository Release Procedure
|
||||
|
||||
Maintain `docs/release.md` as the executable maintainer runbook. It identifies
|
||||
prerequisites, version and note preparation, the single publication command,
|
||||
declared deliverables and build targets, successful-tag-push completion, and
|
||||
partial or unknown-state recovery. Keep optional diagnostics and consumer
|
||||
verification clearly optional. The procedure must agree with this policy.
|
||||
Maintain `docs/release.md` as a short, executable maintainer runbook. It must
|
||||
identify prerequisites, the primary branch and authoritative remote, version
|
||||
and note preparation, one publication command with local checks and guards,
|
||||
source-only deliverables, the successful-tag-push completion point, and
|
||||
partial or unknown-state recovery.
|
||||
|
||||
Use copyable commands where practical. Keep optional diagnostics and consumer
|
||||
verification clearly optional. The procedure must not turn preparation work,
|
||||
ordinary change review, or post-publication investigation into additional
|
||||
release gates.
|
||||
|
||||
## Policy Exceptions
|
||||
|
||||
Any exception to this policy must be explicitly documented in this section,
|
||||
including the repository constraint requiring it, its rationale, scope, and
|
||||
compensating controls. Customizing release mechanics must not silently weaken
|
||||
the policy's integrity, validation, documentation, verification, or immutability
|
||||
requirements.
|
||||
The following historical exceptions do not change the current release workflow.
|
||||
|
||||
For v0.1.1 only, the maintainer approved renaming the reserved `_configkit` key to
|
||||
`configkit` as an error-correcting point release because there are no current
|
||||
|
||||
@@ -124,12 +124,21 @@ success. Otherwise it reports branch-only, conflicting, or unknown state and
|
||||
retains any local tag.
|
||||
|
||||
Inspect exact refs before any retry. Set `release_version` to the attempted
|
||||
version and compare main with the candidate printed or recorded from the run:
|
||||
version and compare main with the candidate from the command's report:
|
||||
|
||||
```sh
|
||||
release_version=v0.5.0
|
||||
authoritative=https://gitea.maximumdirect.net/eric/ConfigKit.git
|
||||
git ls-remote --refs --exit-code "$authoritative" refs/heads/main
|
||||
if remote_main=$(git ls-remote --refs --exit-code "$authoritative" refs/heads/main); then
|
||||
printf 'remote main: %s\n' "$remote_main"
|
||||
else
|
||||
result=$?
|
||||
if [ "$result" -eq 2 ]; then
|
||||
printf 'authoritative main confirmed absent\n' >&2
|
||||
else
|
||||
printf 'remote main state unknown; inspect before retrying\n' >&2
|
||||
fi
|
||||
fi
|
||||
ref="refs/tags/$release_version"
|
||||
if remote_tag=$(git ls-remote --refs --exit-code "$authoritative" "$ref"); then
|
||||
printf 'remote tag: %s\n' "$remote_tag"
|
||||
@@ -141,7 +150,11 @@ else
|
||||
printf 'remote tag state unknown; do not reuse the version\n' >&2
|
||||
fi
|
||||
fi
|
||||
git rev-parse --verify "refs/tags/$release_version"
|
||||
if local_tag=$(git rev-parse --verify "refs/tags/$release_version" 2>/dev/null); then
|
||||
printf 'local tag object: %s\n' "$local_tag"
|
||||
else
|
||||
printf 'no local tag object\n'
|
||||
fi
|
||||
```
|
||||
|
||||
A query failure is not proof that the tag is absent. Compare the remote tag
|
||||
@@ -168,5 +181,17 @@ version into a new module without a local `replace` directive. These checks
|
||||
are optional and non-gating. Do not poll CI or wait for module propagation.
|
||||
Private-host credentials must already be configured. For direct-origin
|
||||
verification, use a temporary consumer module and check the exact module path
|
||||
and version reported by `go list -m`. Report optional verification separately
|
||||
from publication success.
|
||||
and version reported by `go list -m`:
|
||||
|
||||
```sh
|
||||
consumer_dir=$(mktemp -d)
|
||||
(
|
||||
cd "$consumer_dir"
|
||||
go mod init example.invalid/configkit-release-check
|
||||
GOPRIVATE=gitea.maximumdirect.net GOPROXY=direct go get "gitea.maximumdirect.net/eric/ConfigKit@$release_version"
|
||||
go list -m -f '{{.Path}} {{.Version}}' gitea.maximumdirect.net/eric/ConfigKit
|
||||
)
|
||||
```
|
||||
|
||||
The output should show the exact module path and selected version. Report this
|
||||
optional check separately from publication success.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Release Workflow Implementation Plan
|
||||
|
||||
Status: ready for implementation; no stages completed by this planning pass.
|
||||
Status: implemented on 2026-09-28. All stages are complete.
|
||||
|
||||
Implement the [release roadmap](release.md) in the numbered order below. Each
|
||||
stage is a bounded work unit for a gpt-5.6-terra coding agent; finish its tests
|
||||
@@ -177,6 +177,12 @@ no longer require a manually recorded candidate before single-command publicatio
|
||||
|
||||
## Stage 3 — Complete documentation alignment and integrated validation
|
||||
|
||||
**Completed 2026-09-28.** Reconciled the adopted release policy with its pinned
|
||||
upstream source and ConfigKit decisions; aligned the runbook, development guide,
|
||||
and roadmap records with the implemented command. Bash syntax, focused release
|
||||
tests, local documentation links, whitespace review, and the final real baseline
|
||||
release checker passed on Linux. No publication or push was performed.
|
||||
|
||||
Reconcile `docs/policy/release.md` with the pinned upstream release policy. Adopt
|
||||
shared paragraphs verbatim except for substantive local decisions. Remove the
|
||||
temporary deferral, all-remotes freshness rule, and stale prospective v0.3.0 note
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Standard Policy Documentation Alignment
|
||||
|
||||
Status: implemented on 2026-09-28. The [implementation record](implementation.md)
|
||||
contains the completed stages and validation evidence.
|
||||
Status: implemented on 2026-09-28. The completed implementation record and
|
||||
validation evidence are preserved at `faf5ff8:docs/roadmap/implementation.md`.
|
||||
|
||||
ConfigKit's seven [adopted policies](../policy/meta.md) now identify the pinned
|
||||
Standard Repository Policies revision
|
||||
@@ -11,10 +11,9 @@ applicable policies. [COPYRIGHT](../../COPYRIGHT) and the
|
||||
[attribution notices](../oss/attribution.md) identify the separately licensed
|
||||
adapted policy and orientation material.
|
||||
|
||||
The [release policy](../policy/release.md) retains ConfigKit's existing
|
||||
operational requirements. The [maintainer runbook](../release.md) remains their
|
||||
command owner. The separate [release-workflow roadmap](release.md) owns future
|
||||
publication automation and gate review; this policy alignment did not implement
|
||||
that workflow.
|
||||
The [release policy](../policy/release.md) and
|
||||
[maintainer runbook](../release.md) own current release requirements and
|
||||
operations. The separate [release-workflow roadmap](release.md) records the
|
||||
subsequent publication-automation work.
|
||||
|
||||
These completed records remain until normal release preparation retires them.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Single-Command Release Workflow and Gate Review
|
||||
|
||||
Status: accepted target; execution order and acceptance checks are defined in the
|
||||
[implementation plan](implementation.md).
|
||||
Status: implemented on 2026-09-28. The
|
||||
[implementation plan](implementation.md) records the completed work and checks.
|
||||
|
||||
## Intent and baseline
|
||||
|
||||
@@ -15,14 +15,15 @@ The upstream reference is release policy v1.4 at
|
||||
`d84a38ebab26f048cafbe59a2246700c35d29843`:
|
||||
[standard release policy](https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843/docs/policy/release.md).
|
||||
|
||||
Today, `scripts/release-check.sh` performs local validation; the runbook separately
|
||||
At the planning baseline, `scripts/release-check.sh` performed local validation; the runbook separately
|
||||
records a candidate commit and executes shell blocks for guards, branch push,
|
||||
annotated tagging, and tag push. The checker runs module hygiene, formatting and
|
||||
whitespace checks, one race-enabled suite, vet, and Linux amd64/arm64 cross-builds
|
||||
using a maintained Go 1.25 patch. Publication completes on successful tag push.
|
||||
|
||||
These remain the current requirements until deliberately revised. This roadmap
|
||||
does not itself waive existing gates.
|
||||
The implementation plan records the subsequent gate selection and publication
|
||||
command. Current requirements belong to the
|
||||
[release policy](../policy/release.md) and [runbook](../release.md).
|
||||
|
||||
## Target release contract
|
||||
|
||||
@@ -40,7 +41,7 @@ authorization, not the standing local-commit policy.
|
||||
The command validates the exact candidate once. An optional validation-only mode
|
||||
may support diagnosis but is not a prerequisite followed by duplicate validation.
|
||||
Do not require both everyday and release checkers. An implementation need not
|
||||
introduce a persistent validation cache merely to replace today's manual record.
|
||||
introduce a persistent validation cache merely to replace the former manual record.
|
||||
|
||||
Mechanical guards ensure a clean worktree/index on the primary branch, an unused
|
||||
valid version locally and on the authoritative remote, a matching release note,
|
||||
@@ -54,12 +55,11 @@ consumer installation, or optional verification. Do not add a successful-push
|
||||
remote read-back gate. If future artifact channels are adopted, delivery status
|
||||
must remain separate; this task introduces none.
|
||||
|
||||
## Gate review target
|
||||
## Selected gate rationale
|
||||
|
||||
Keep the full deterministic offline suite as the core check. The selected gates
|
||||
below provide distinct protection without repeating validation. Their rationale
|
||||
belongs in the adopted release policy, with commands in the runbook and tooling
|
||||
once implemented.
|
||||
belongs in the adopted release policy, with commands in the runbook and tooling.
|
||||
|
||||
| Check | Selected end state and rationale |
|
||||
| --- | --- |
|
||||
|
||||
@@ -12,13 +12,13 @@ fail() {
|
||||
}
|
||||
|
||||
check_candidate() {
|
||||
local current status
|
||||
current=$(git branch --show-current) || fail "cannot read the current branch"
|
||||
[[ "$current" == main ]] || fail "release requires the main branch"
|
||||
status=$(git status --porcelain=v1 --untracked-files=all) || fail "cannot inspect the worktree"
|
||||
[[ -z "$status" ]] || fail "release requires a clean index and worktree"
|
||||
current=$(git rev-parse --verify HEAD) || fail "cannot identify the candidate"
|
||||
[[ "$current" == "$candidate" ]] || fail "candidate changed; commit and validate it again"
|
||||
local context=$1 current status
|
||||
current=$(git branch --show-current) || fail "$context: cannot read the current branch"
|
||||
[[ "$current" == main ]] || fail "$context: release requires the main branch"
|
||||
status=$(git status --porcelain=v1 --untracked-files=all) || fail "$context: cannot inspect the worktree"
|
||||
[[ -z "$status" ]] || fail "$context: release requires a clean index and worktree"
|
||||
current=$(git rev-parse --verify HEAD) || fail "$context: cannot identify the candidate"
|
||||
[[ "$current" == "$candidate" ]] || fail "$context: candidate changed; commit and validate it again"
|
||||
}
|
||||
|
||||
check_unused_version() {
|
||||
@@ -59,7 +59,7 @@ push_urls=$(git remote get-url --push --all origin 2>/dev/null) || fail "origin
|
||||
fail "origin must have exactly the authoritative fetch and push destination"
|
||||
|
||||
candidate=$(git rev-parse --verify HEAD) || fail "cannot identify the candidate"
|
||||
check_candidate
|
||||
check_candidate "before validation"
|
||||
check_unused_version
|
||||
|
||||
note_path="docs/releases/$version.md"
|
||||
@@ -85,7 +85,7 @@ git merge-base --is-ancestor "$fetched_main" "$candidate" ||
|
||||
fail "candidate cannot advance authoritative main without discarding history"
|
||||
|
||||
./scripts/release-check.sh || fail "release validation failed; no refs were published"
|
||||
check_candidate
|
||||
check_candidate "after validation"
|
||||
check_unused_version
|
||||
|
||||
if git push --no-follow-tags "$remote_url" "$candidate:refs/heads/main"; then
|
||||
@@ -93,37 +93,37 @@ if git push --no-follow-tags "$remote_url" "$candidate:refs/heads/main"; then
|
||||
else
|
||||
if observed_main=$(read_remote_ref refs/heads/main); then
|
||||
[[ "$observed_main" == "$candidate" ]] ||
|
||||
fail "main push did not publish; authoritative main differs from the candidate"
|
||||
fail "main push did not publish candidate $candidate; authoritative main differs"
|
||||
else
|
||||
result=$?
|
||||
((result == 2)) && fail "main push failed; authoritative main is absent"
|
||||
fail "main push outcome is unknown; inspect authoritative main before retrying"
|
||||
((result == 2)) && fail "main push failed for $candidate; authoritative main is absent"
|
||||
fail "main push outcome is unknown for $candidate; inspect authoritative main before retrying"
|
||||
fi
|
||||
fi
|
||||
|
||||
check_candidate
|
||||
check_candidate "main at $candidate; tag not yet published"
|
||||
git tag -a -F "$note_file" --cleanup=verbatim "$version" "$candidate" ||
|
||||
fail "could not create the local annotated tag"
|
||||
fail "main is at $candidate; could not create local tag $version"
|
||||
tag_target=$(git rev-parse --verify "refs/tags/$version^{}") ||
|
||||
fail "cannot verify the local tag target"
|
||||
[[ "$tag_target" == "$candidate" ]] || fail "local tag does not identify the candidate"
|
||||
fail "main is at $candidate; cannot verify local tag $version"
|
||||
[[ "$tag_target" == "$candidate" ]] || fail "main is at $candidate; local tag $version targets another commit"
|
||||
tag_type=$(git cat-file -t "refs/tags/$version") ||
|
||||
fail "cannot inspect the local tag"
|
||||
[[ "$tag_type" == tag ]] || fail "release tag must be annotated"
|
||||
fail "main is at $candidate; cannot inspect local tag $version"
|
||||
[[ "$tag_type" == tag ]] || fail "main is at $candidate; local tag $version is not annotated"
|
||||
tag_oid=$(git rev-parse --verify "refs/tags/$version") ||
|
||||
fail "cannot identify the annotated tag"
|
||||
fail "main is at $candidate; cannot identify local tag $version"
|
||||
|
||||
if git push --no-follow-tags "$remote_url" "refs/tags/$version:refs/tags/$version"; then
|
||||
:
|
||||
else
|
||||
if observed_tag=$(read_remote_ref "refs/tags/$version"); then
|
||||
[[ "$observed_tag" == "$tag_oid" ]] ||
|
||||
fail "authoritative tag conflicts with the local tag; never replace it"
|
||||
fail "authoritative tag $version conflicts with the local tag at $candidate; never replace it"
|
||||
else
|
||||
result=$?
|
||||
((result == 2)) &&
|
||||
fail "tag push failed; main is published, but the local tag is unpublished"
|
||||
fail "tag push outcome is unknown; retain the local tag and inspect authoritative state"
|
||||
fail "tag push failed; main is at $candidate, but local tag $version is unpublished"
|
||||
fail "tag $version push outcome is unknown for $candidate; retain the local tag and inspect authoritative state"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user