Retire completed roadmaps and retain pending adoption work
This commit is contained in:
@@ -1,67 +0,0 @@
|
||||
# Feature request from ConfigKit: adaptable release validation
|
||||
|
||||
Status: Requested by a prospective downstream consumer; not yet adopted by
|
||||
ReleaseKit.
|
||||
|
||||
ConfigKit would like to adopt ReleaseKit's common source-release process and
|
||||
retire most of its repository-owned release scripts and publication tests. It is
|
||||
a source-only Go library. ConfigKit can follow ReleaseKit's existing convention
|
||||
of publishing the candidate to `main` before running the tag-publication
|
||||
command; it does not need binary artifacts or a different source-publication
|
||||
sequence.
|
||||
|
||||
## Select one base Go test invocation
|
||||
|
||||
ReleaseKit's [candidate check](../consumers/check.md) currently runs its
|
||||
standard `go test` suite before any configured additional checks. ConfigKit's
|
||||
selected release validation includes a race-enabled run of its full test
|
||||
suite, with a separate full vet pass. Expressing the race run as an additional
|
||||
check would run the suite twice and retain avoidable consumer-specific release
|
||||
wiring.
|
||||
|
||||
Please provide a small public API and profile capability for a consumer to
|
||||
select its **one base Go test invocation** for candidate validation. The
|
||||
selection should replace the default invocation, rather than add a second test
|
||||
run. Without a selection, ReleaseKit's current default remains useful. Both
|
||||
`Check` and `Publish`, including their CLI forms, should use the selected
|
||||
invocation consistently while ReleaseKit continues to own candidate capture,
|
||||
validation order, result reporting, and publication. ConfigKit needs to select
|
||||
a full-suite race run with test-time vet omitted because it selects a separate
|
||||
full vet pass. ReleaseKit can choose the simplest public expression of that
|
||||
choice; ConfigKit is not asking for a general-purpose release pipeline or
|
||||
consumer-owned orchestration.
|
||||
|
||||
## Evaluate shared release checks
|
||||
|
||||
ConfigKit also uses a separate full `go vet` pass and compile checks for Linux
|
||||
amd64 and arm64. Please assess whether these checks are useful enough across
|
||||
ReleaseKit consumers to offer directly through its public API and profile,
|
||||
either as defaults or as selected options where product support differs.
|
||||
|
||||
In particular, a source-only library needs to verify that its packages compile
|
||||
for selected targets without declaring executable artifacts or adding delivery
|
||||
work. ReleaseKit could make that distinction available to consumers. The goal
|
||||
is to keep these checks, when selected, within the same candidate validation
|
||||
and publication flow without repeating work already done by the base test.
|
||||
Whether race, vet, or cross-target compilation should be common defaults is a
|
||||
ReleaseKit product decision; ConfigKit asks for an assessment, not a universal
|
||||
new release gate.
|
||||
|
||||
## Optional publication endpoint expectation
|
||||
|
||||
ConfigKit currently identifies one expected authoritative Git destination. An
|
||||
optional expected-endpoint setting in ReleaseKit's public API and profile could
|
||||
let a consumer verify that the selected remote resolves to its declared
|
||||
destination before publication. Please consider whether this is broadly useful
|
||||
and simpler than retaining a small consumer-owned preflight check. Existing
|
||||
ReleaseKit remote selection and endpoint handling should remain the common
|
||||
publication model.
|
||||
|
||||
## Adoption outcome
|
||||
|
||||
A useful outcome would let ConfigKit declare its product identity, selected
|
||||
validation, and any expected publication destination, then rely on ReleaseKit's
|
||||
standard candidate check and tag-publication command. ConfigKit would retain
|
||||
its compatibility decisions and release notes while removing duplicated release
|
||||
mechanics. Source publication would still complete at the confirmed tag push;
|
||||
CI and hosted delivery would remain separate from that completion point.
|
||||
@@ -1,182 +0,0 @@
|
||||
# Feature Request From PromptKit: Shared Release Validation
|
||||
|
||||
Status: Requested by a prospective downstream consumer; not yet adopted by
|
||||
ReleaseKit.
|
||||
|
||||
Date: 2026-10-07.
|
||||
|
||||
This request derives from PromptKit's
|
||||
[ReleaseKit adoption assessment](https://gitea.maximumdirect.net/eric/promptkit/src/commit/7310ef34a44dae7288db7b281e2a6b7f2c56c4e9/docs/roadmap/releasekit.md),
|
||||
which reviewed ReleaseKit `v0.1.0`. It describes downstream needs and leaves
|
||||
public API design, shared defaults, and implementation choices to ReleaseKit.
|
||||
|
||||
## Consumer Context And Goal
|
||||
|
||||
PromptKit is a source-only Go library with concurrent LLM execution and
|
||||
backend-capacity management. It would like to adopt ReleaseKit's common
|
||||
source-publication process and reduce its own release infrastructure to
|
||||
product settings and a few substantive project checks. Its existing release
|
||||
scripts contain 209 lines, most of which implement validation rather than
|
||||
publication.
|
||||
|
||||
PromptKit accepts changes to its release process in exchange for a common
|
||||
standard and lower maintenance. The opportunity is to share useful validation
|
||||
capabilities, rather than preserve every existing shell command or local rule.
|
||||
Its consumer-example assertions and compatibility decisions remain meaningful
|
||||
project responsibilities.
|
||||
|
||||
The four primary requests below concern reusable validation. Two additional
|
||||
candidates are included for evaluation if their wider value justifies shared
|
||||
support. PromptKit's choices about race testing, full vet, and credential
|
||||
scanning remain under review; these requests describe useful capabilities
|
||||
without making their acceptance a prerequisite for adoption.
|
||||
|
||||
## Primary Requests
|
||||
|
||||
### 1. Shared Go Formatting Validation
|
||||
|
||||
Please make Go formatting validation available through ReleaseKit's public
|
||||
validation API and release profile, so the shared candidate workflow can
|
||||
report tracked Go source that needs formatting.
|
||||
|
||||
PromptKit currently owns a shell check that identifies its tracked Go files
|
||||
and verifies their formatting. The operation is common to Go repositories;
|
||||
maintaining that mechanism independently adds little project-specific value.
|
||||
A useful shared capability would inspect source, report the affected files,
|
||||
and leave formatting changes to ordinary development.
|
||||
|
||||
The benefit is consistent validation and diagnostics with less local script
|
||||
maintenance. PromptKit can follow ReleaseKit's selected formatting convention
|
||||
without requiring preservation of its current enumeration or command loop.
|
||||
|
||||
### 2. Shared Offline Markdown-Link Validation
|
||||
|
||||
Please make validation of local Markdown links available through the public
|
||||
validation API and release profile. PromptKit needs checks for local file
|
||||
destinations and heading fragments, with enough diagnostic context to locate
|
||||
and correct a broken link.
|
||||
|
||||
Documentation is part of PromptKit's consumer interface. Broken navigation
|
||||
between its guides, formats, policies, and examples makes otherwise correct
|
||||
documentation harder to use. Its current local Markdown checker is the
|
||||
largest generic block in its release-validation script.
|
||||
|
||||
Shared support would remove a locally maintained parser and standardize the
|
||||
supported Markdown behavior across consumers. ReleaseKit can establish the
|
||||
supported link and heading conventions; PromptKit does not require its exact
|
||||
current parsing or anchor rules. Repository-specific choices about links to
|
||||
material outside the checkout should remain distinguishable from generally
|
||||
useful local-link validation.
|
||||
|
||||
The desired operation is offline and reports problems without changing
|
||||
documentation. External website availability is a separate concern and adds
|
||||
no value to this request.
|
||||
|
||||
### 3. Race Detection Within One Standard Test Run
|
||||
|
||||
Please provide a supported public API and profile choice for race-enabled
|
||||
execution of the standard full Go suite during candidate validation.
|
||||
|
||||
PromptKit's concurrent execution and capacity management make race detection
|
||||
useful: ordinary successful tests can miss unsafe shared-state access. Its
|
||||
current release validation runs the full suite with the race detector.
|
||||
ReleaseKit's current
|
||||
[candidate workflow](../consumers/check.md) always runs the ordinary suite;
|
||||
expressing a race run as an additional check would execute the complete suite
|
||||
twice.
|
||||
|
||||
The desired capability selects race-enabled execution for that one suite
|
||||
run, while ReleaseKit continues to own the candidate workflow. The selection
|
||||
should work consistently through the public API and CLI/profile forms of
|
||||
candidate checking and publication. A consumer can select the ordinary suite
|
||||
when that is sufficient.
|
||||
|
||||
This overlaps with ConfigKit's
|
||||
[base-test invocation request](feature-request-configkit.md#select-one-base-go-test-invocation).
|
||||
PromptKit would benefit from the same shared capability; it does not need a
|
||||
separate PromptKit-specific test mechanism. ReleaseKit can decide the smallest
|
||||
appropriate public expression of the choice and whether race testing belongs
|
||||
among its common defaults.
|
||||
|
||||
### 4. Shared Full Go Vet Validation
|
||||
|
||||
Please consider exposing full Go vet analysis as part of ReleaseKit's public
|
||||
validation API and release profile, coordinated with the standard suite.
|
||||
|
||||
PromptKit currently runs full vet separately. Ordinary Go test execution
|
||||
includes only a subset of vet analyses, so replacing the current procedure
|
||||
with the standard test run does not provide equivalent static analysis. The
|
||||
additional analyses can detect defects that are not exercised by tests.
|
||||
|
||||
PromptKit can temporarily retain a configured full-vet command. A shared
|
||||
capability would let consumers express that validation choice directly and
|
||||
let ReleaseKit coordinate the analysis with testing to avoid unnecessary
|
||||
overlap. The desired outcome is full selected analysis and one complete
|
||||
suite execution; PromptKit leaves the means of achieving that outcome to
|
||||
ReleaseKit.
|
||||
|
||||
This also overlaps with ConfigKit's
|
||||
[shared-check request](feature-request-configkit.md#evaluate-shared-release-checks).
|
||||
Full vet may be useful as a common default or as an explicit selection.
|
||||
PromptKit is asking for a shared capability, not prescribing additional gates
|
||||
for every ReleaseKit consumer.
|
||||
|
||||
## Additional Candidates For Evaluation
|
||||
|
||||
### 5. Optional Go Module Distribution Checks
|
||||
|
||||
PromptKit's architecture keeps committed workspace files and local filesystem
|
||||
module replacements out of its released source. These rules help a shared
|
||||
library remain independent of neighboring checkouts. Disabling workspace
|
||||
discovery during validation controls the test environment but does not check
|
||||
the files being distributed.
|
||||
|
||||
If other consumers have the same need, optional public validation capabilities
|
||||
could check for committed workspace files and local filesystem replacements.
|
||||
Consumers should be able to select the distribution rules relevant to them;
|
||||
a versioned module replacement is different from a local filesystem
|
||||
dependency, and Go applications may deliberately distribute workspace files.
|
||||
|
||||
The potential benefit is reusable inspection and consistent diagnostics
|
||||
without each library owning its own checks. PromptKit can also keep a small
|
||||
local check if that is simpler than introducing shared support. This is a
|
||||
lower-priority candidate, not a request for universal bans on workspaces,
|
||||
replacement directives, or vendoring.
|
||||
|
||||
### 6. Optional Recognizable-Credential Checks
|
||||
|
||||
PromptKit's assessment recommends retiring its mandatory credential-pattern
|
||||
scan, while retaining ordinary credential-aware change review. A viable
|
||||
alternative is to keep a lightweight automated signal for recognizable
|
||||
accidentally committed credential formats.
|
||||
|
||||
If ReleaseKit finds broader consumer value in that alternative, please
|
||||
consider an optional public validation capability for such checks. A useful
|
||||
offering would make its detection scope clear and account for the possibility
|
||||
of matching synthetic examples or fixtures. It would complement ordinary
|
||||
review rather than imply comprehensive detection.
|
||||
|
||||
Shared support could centralize maintenance of the selected detection behavior
|
||||
and remove another local script fragment. PromptKit is not requesting a
|
||||
general security-scanning subsystem, preservation of its current regex, or
|
||||
a mandatory credential gate. This candidate warrants adoption only if its
|
||||
additional protection justifies its maintenance and false-positive costs.
|
||||
|
||||
## Desired Adoption Outcome
|
||||
|
||||
The strongest opportunities are shared formatting and Markdown validation,
|
||||
followed by useful race/vet choices within a single candidate-validation flow.
|
||||
The module-distribution and credential candidates merit separate evaluation
|
||||
because their policies and benefits vary between consumers.
|
||||
|
||||
For accepted capabilities, availability through both the public Go API and
|
||||
the maintained CLI/profile would let PromptKit select them without creating
|
||||
its own release executable. PromptKit can retain its consumer-example
|
||||
assertions as additional checks and use ReleaseKit's supported conventions
|
||||
for shared validation and diagnostics.
|
||||
|
||||
PromptKit would continue to prepare its release note and publish its candidate
|
||||
to authoritative `main` before invoking source publication. Confirmed tag
|
||||
publication completes the source release; CI and hosted delivery remain
|
||||
separate. Those responsibilities already fit ReleaseKit's common workflow
|
||||
and do not require new features for this request.
|
||||
@@ -1,656 +0,0 @@
|
||||
# ReleaseKit v0.2.0 implementation plan
|
||||
|
||||
Status: Complete. Stages 1–15 are implemented and locally verified.
|
||||
|
||||
This plan replaces the completed foundation sequence. It implements the target
|
||||
state in [v0.2.0.md](v0.2.0.md), using the shared design in [model.md](model.md),
|
||||
[ADR 0003](../adr/0003-declarative-validation.md), and
|
||||
[ADR 0004](../adr/0004-module-selected-tooling.md). A Luna coding agent should
|
||||
execute one numbered stage per prompt, in order.
|
||||
|
||||
## Current baseline and completion scope
|
||||
|
||||
At baseline commit `3974a46`, the foundation and all six
|
||||
[remediation findings](remediation.md) were complete. `Check` and `Publish`
|
||||
shared candidate-request conversion and validation.
|
||||
`internal/validation` runs the default offline suite and owns diagnostics and
|
||||
candidate-tree access. Committed-file readers are offline; destination resolution
|
||||
handles symlinks, parent traversal, cancellation, and absolute in-checkout paths.
|
||||
The root error types and CLI presentation preserve findings and cause context.
|
||||
`buildinfo` retains its independent runtime dependency graph.
|
||||
|
||||
The stages in this plan complete the remaining v0.2.0 validation selections,
|
||||
module-selected CI bootstrap, and Audita migration. Audita's migration is
|
||||
recorded in commit `17421bc`. The final local audit covers the full Go suite,
|
||||
compiled API/dependency boundaries, maintained examples, documentation, and
|
||||
dependency notices. Architecture review, hosted deployment, release tagging,
|
||||
and decisions about further testing follow this implementation.
|
||||
|
||||
| Release-roadmap item | Implementation stages |
|
||||
| --- | --- |
|
||||
| 1. Shared validation API/profile model | 1–3, 5–11, 15 |
|
||||
| 2. Module-selected CI tool and Audita migration | 12–14 |
|
||||
| 3. One suite with race selection | 1 |
|
||||
| 4. Separate full vet | 2 |
|
||||
| 5. Package compilation | 3 |
|
||||
| 6. Expected publication endpoint | 4 |
|
||||
| 7. Go formatting | 5 |
|
||||
| 8. Markdown links and optional boundary | 9–11 |
|
||||
| 9. Independent distribution rules | 6–7 |
|
||||
| 10. Individual file size | 8 |
|
||||
|
||||
## Instructions for every stage
|
||||
|
||||
- Start with [development.md](../development.md) and applicable policies. Locate
|
||||
current symbols with the codebase graph and inspect the worktree. The named
|
||||
paths below describe the current baseline.
|
||||
- Introduce each public and profile setting with its working capability, as
|
||||
agreed. Update its GoDoc, configuration reference, consumer guidance, and
|
||||
relevant CLI/internal documentation in that same stage.
|
||||
- Use ordinary internal structs/functions and explicit facade conversions.
|
||||
Keep product assertions in `AdditionalChecks` and profile `checks`.
|
||||
- Select tests for the stage's actual risks under the
|
||||
[testing policy](../policy/testing.md). Use local Git repositories, Go
|
||||
packages, controlled command doubles, and HTTP fixtures. Default tests remain
|
||||
offline and independent of real credentials or sibling checkouts.
|
||||
- Verification lists describe required evidence, including existing tests.
|
||||
Give each behavior a test owner: parser/checker tests cover syntax and rules;
|
||||
candidate-tree and Git tests cover file access and resolution; conversion
|
||||
tests cover each API/profile selection; shared orchestration tests cover
|
||||
ordering, failure stopping, cancellation, and callback execution. Use
|
||||
representative integration cases to verify these boundaries work together.
|
||||
Add coverage where the change introduces a risk or leaves an evidence gap.
|
||||
- Prepare newly selected development dependencies before offline validation.
|
||||
Apply the [OSS policy](../policy/oss.md) when adding dependencies or adapting
|
||||
third-party material, including any required attribution and license texts.
|
||||
- Verify the focused outcome, stage its relevant changes, review the diff, and
|
||||
create a nonempty commit with a short plain English message. Preserve unrelated
|
||||
work, report the stage's outcome and verification, and stop until the next
|
||||
stage is requested. These stages require local work and automated checks;
|
||||
consumer changes in Stage 14 are committed in that repository.
|
||||
|
||||
## Design carried through the stages
|
||||
|
||||
### Public and profile declarations
|
||||
|
||||
The completed specification is facade-owned:
|
||||
|
||||
```go
|
||||
type ValidationSpec struct {
|
||||
Go GoValidationSpec
|
||||
GoFormat bool
|
||||
Markdown *MarkdownValidationSpec
|
||||
ModuleDistribution ModuleDistributionValidationSpec
|
||||
FileSize *FileSizeValidationSpec
|
||||
}
|
||||
|
||||
type GoValidationSpec struct {
|
||||
Race bool
|
||||
FullVet bool
|
||||
CompileTargets []Target
|
||||
}
|
||||
|
||||
type MarkdownValidationSpec struct {
|
||||
EnforceCheckoutBoundary bool
|
||||
}
|
||||
|
||||
type ModuleDistributionValidationSpec struct {
|
||||
WorkspaceFiles bool
|
||||
LocalReplacements bool
|
||||
}
|
||||
|
||||
type FileSizeValidationSpec struct {
|
||||
LimitBytes *int64
|
||||
Exclusions []string
|
||||
}
|
||||
```
|
||||
|
||||
Add `Validation ValidationSpec` and `ExpectedPushURL string` to `ReleaseRequest`.
|
||||
`Target` is the existing root-facade operating-system/architecture pair. Each
|
||||
stage adds only the fields it makes operational. The CLI owns corresponding
|
||||
JSON structs and converts them in `cmd/releasekit`; internal production packages
|
||||
use their own contracts.
|
||||
|
||||
| Go selection | Profile selection | Omitted/zero behavior |
|
||||
| --- | --- | --- |
|
||||
| `Go.Race` | `validation.go.race` | Ordinary native test suite |
|
||||
| `Go.FullVet` | `validation.go.full_vet` | Existing test-time vet |
|
||||
| `Go.CompileTargets` | `validation.go.compile_targets` | No package-compilation pass |
|
||||
| `GoFormat` | `validation.go_format` | No formatting check |
|
||||
| `Markdown` | `validation.markdown` | Nil/omitted/null disables the check; `{}` enables it |
|
||||
| `Markdown.EnforceCheckoutBoundary` | `validation.markdown.enforce_checkout_boundary` | Outside-checkout links reported as out of scope |
|
||||
| `ModuleDistribution.WorkspaceFiles` | `validation.module_distribution.workspace_files` | Rule disabled |
|
||||
| `ModuleDistribution.LocalReplacements` | `validation.module_distribution.local_replacements` | Rule disabled |
|
||||
| `FileSize` | `validation.file_size` | Nil/omitted/null disables the check; `{}` enables it |
|
||||
| `FileSize.LimitBytes` | `validation.file_size.limit_bytes` | Nil/omitted/null selects 1,000,000 bytes when enabled |
|
||||
| `FileSize.Exclusions` | `validation.file_size.exclusions` | No exclusions |
|
||||
| `ExpectedPushURL` | `expected_push_url` | Empty/omitted disables the publication expectation |
|
||||
|
||||
Profile compilation targets use `GOOS/GOARCH` strings. Require a complete pair
|
||||
because a partial target would otherwise silently select different compilation.
|
||||
Use the existing Go target/environment mechanisms; let the selected Go toolchain
|
||||
report unsupported targets. An artifact naming constraint does not determine
|
||||
package-compilation compatibility.
|
||||
|
||||
Byte limits are integer counts; zero is an explicit zero-byte limit, and negative
|
||||
counts are invalid. Exclusions are literal repository-relative file or directory
|
||||
paths; directory selections include committed descendants. Match path boundaries
|
||||
so excluding `assets` leaves `assets-other` selected. Ordinary relative path
|
||||
normalization is sufficient. An unmatched exclusion has no effect. Metacharacters
|
||||
remain literal Git path characters.
|
||||
|
||||
### Execution and ownership
|
||||
|
||||
The shared procedure is one native test suite, selected full vet, selected
|
||||
package-compilation targets, and selected file checks, followed by product
|
||||
checks and existing artifact builds/rechecks. File-check ordering is an internal
|
||||
procedure: formatting, workspace files, local replacements, file size, then
|
||||
Markdown. Stop after a failed check. A checker may return multiple findings;
|
||||
this plan does not require collecting failures from every selected check.
|
||||
|
||||
Resolve the Go environment once per validation operation and reuse it. Native
|
||||
race/vet work preserves the existing effective cgo/C-tool configuration. Static
|
||||
package compilation uses `CGO_ENABLED=0`. The existing offline module/toolchain
|
||||
controls remain owned by `internal/gotool`.
|
||||
|
||||
Pass settings through the root `candidateRequest`, `internal/candidate.Request`,
|
||||
`internal/publish.Request`, and `validation.Request`. Both operations and their
|
||||
CLI forms use the same decisions. Keep expected URL comparison in publication
|
||||
preflight. Existing capture/rechecks, endpoint guards, recovery, publication
|
||||
completion, and delivery outcomes retain their meaning.
|
||||
|
||||
Reuse the existing internal failures and facade conversion. Add stable identities
|
||||
`go-vet`, `package-compile`, `go-format`, `workspace-files`, `local-replacements`,
|
||||
`file-size`, and `markdown-links` as implemented. Supply paths, locations,
|
||||
targets, directives, and measurements as applicable. Preserve causes and
|
||||
cancellation through `errors.Is`/`errors.As`. CLI failures use existing exit
|
||||
classifications and complete contextual presentation.
|
||||
|
||||
File checks share one candidate inventory per validation operation and load blobs
|
||||
as needed. Inventory includes tracked vendor files and nested modules. Regular
|
||||
source blobs feed formatting and Markdown parsing. Workspace-file detection
|
||||
includes named symlink blobs; module parsing follows committed symlinks to
|
||||
candidate-contained regular declarations. Unavailable selected input produces
|
||||
an inspection error. File size measures regular and symlink blobs. Gitlinks have
|
||||
no parent-tree blob size, and their contents remain outside the inspected tree.
|
||||
|
||||
### Dependencies and Markdown convention
|
||||
|
||||
Use standard `go/format` for Go formatting. Its convention follows the Go
|
||||
standard library used to build ReleaseKit. Use `golang.org/x/mod/modfile` at
|
||||
`golang.org/x/mod v0.40.0` for complete module-declaration parsing. Use
|
||||
`github.com/yuin/goldmark/v2 v2.1.6` internally for Markdown AST parsing and source
|
||||
positions. Both selected module manifests support the existing Go 1.25 baseline;
|
||||
implementation should record their exact source revisions and notices under the
|
||||
OSS policy. References: [modfile](https://pkg.go.dev/golang.org/x/mod/modfile)
|
||||
and [Goldmark](https://github.com/yuin/goldmark/tree/v2.1.6).
|
||||
|
||||
PromptKit's current script supplies the starting heading/link examples. Preserve
|
||||
its basic anchor transformation: lowercase heading text, retain Unicode letters
|
||||
and numbers, underscore, hyphen, and spaces, then replace spaces with hyphens.
|
||||
Use visible heading text from the Markdown AST, including inline code text and
|
||||
excluding HTML tags/formatting delimiters. Support ATX and Setext headings. For
|
||||
repeated headings, append increasing numeric suffixes starting at `-1`, selecting
|
||||
an unused identifier when a generated suffix collides with another heading.
|
||||
Document these refinements to the starting script's behavior.
|
||||
|
||||
Recognize inline links, images, and full/collapsed/shortcut reference links through
|
||||
the parser. Code blocks and inline code supply examples rather than link nodes.
|
||||
Raw HTML destinations remain outside this Markdown-link capability. Undefined
|
||||
references rendered as ordinary text by the parser are not a new Markdown lint
|
||||
rule. Decode Markdown escapes/entities through the parser and percent escapes
|
||||
once when resolving URI path/fragment components. Compare decoded fragments in
|
||||
lowercase to preserve PromptKit's starting convention. Ignore URI query
|
||||
components for file existence. Empty paths target the source document; an empty
|
||||
fragment selects its top. Schemed and protocol-relative URIs receive no availability
|
||||
request. Fragment checking applies to regular Markdown destinations; other
|
||||
existing files/directories receive existence checking.
|
||||
|
||||
Use committed destination resolution and cached parsed documents/anchors.
|
||||
Missing destinations, unresolved cycles, and missing supported anchors fail the
|
||||
selected Markdown check. Actual outside-checkout destinations are reported as
|
||||
out of scope by default and fail with boundary enforcement. Submodule-content
|
||||
observations remain reported as out of scope under either setting: the boundary
|
||||
option concerns checkout escape and does not establish a submodule prohibition.
|
||||
Write nonfailure observations to the supplied output writer; a nil writer
|
||||
selects ordinary quiet library use. Diagnostics identify the source use site,
|
||||
location, and destination. Document source columns as one-based byte columns.
|
||||
|
||||
### CI tool bootstrap
|
||||
|
||||
Build using temporary copies of the released application's `go.mod` and `go.sum`,
|
||||
with Go's alternate `-modfile` and normal module preparation in those copies.
|
||||
Confirm that ReleaseKit is already selected before building its command. This
|
||||
preserves the application's version declaration and require/replace semantics
|
||||
while allowing missing tool-only indirect requirements/checksums to be prepared
|
||||
without dirtying immutable tagged source. It supports consumers whose application
|
||||
imports only lightweight `buildinfo`. Stages 12–14 implement this agreed approach.
|
||||
|
||||
## Stage 1: Introduce the specification with race selection
|
||||
|
||||
**Completion:** Complete. `ReleaseRequest.Validation.Go.Race` and profile
|
||||
`validation.go.race` select `-race` for the single native Go suite. Both
|
||||
candidate operations share the selection, and race failures retain the `go-test`
|
||||
identity without falling back to an ordinary suite.
|
||||
|
||||
**Outcome:** The first public/profile selection changes the one existing suite.
|
||||
|
||||
1. Add `ReleaseRequest.Validation`, `ValidationSpec.Go`, and
|
||||
`GoValidationSpec.Race`, plus equivalent CLI-owned JSON settings. Add explicit
|
||||
conversions through both candidate and publication request paths.
|
||||
2. Build the base invocation in `internal/validation`: preserve
|
||||
`go test -mod=readonly -count=1 ./...`, adding `-race` when selected. Reuse
|
||||
the native Go environment and report tool/prerequisite failures as `go-test`.
|
||||
3. Preserve additional-check and build ordering. Update exact API/profile
|
||||
references and add a minimal consumer example for the selection.
|
||||
|
||||
**Verification:** Default and selected invocations, exactly one suite, API/profile
|
||||
selection equivalence, both operations, unavailable race prerequisites with no
|
||||
silent fallback, preserved causes/cancellation, and failure before product
|
||||
checks/builds/tag creation. Use a small real race-enabled fixture on supported
|
||||
hosts and a controlled Go command for portable prerequisite-failure coverage.
|
||||
|
||||
## Stage 2: Coordinate a separate full vet pass
|
||||
|
||||
**Completion:** Complete. `ReleaseRequest.Validation.Go.FullVet` and profile
|
||||
`validation.go.full_vet` disable test-time vet for the one native test suite and
|
||||
run native `go vet -mod=readonly ./...` afterward. Vet failures retain the
|
||||
`go-vet` identity, and the selection is shared by the API and profile paths.
|
||||
|
||||
**Outcome:** Full vet replaces test-time vet overlap through one declaration.
|
||||
|
||||
1. Add `Go.FullVet` and `validation.go.full_vet` through the same conversion path.
|
||||
2. When enabled, add `-vet=off` to the one test invocation and run native
|
||||
`go vet -mod=readonly ./...` afterward using the same tool/environment.
|
||||
3. Attribute vet failures to `go-vet` and update canonical usage guidance.
|
||||
|
||||
**Verification:** Ordinary, race-only, vet-only, and combined selections; one
|
||||
suite; vet after successful tests; suppression of test-time vet only when
|
||||
selected; failure/cancellation stopping; default behavior and API/profile parity.
|
||||
Protect the selected command relationship without freezing incidental flag order.
|
||||
|
||||
## Stage 3: Compile packages for selected targets
|
||||
|
||||
**Completion:** Complete. `Go.CompileTargets` and profile
|
||||
`validation.go.compile_targets` select static package compilation after tests
|
||||
and vet. Failures use `package-compile` and include the selected target;
|
||||
artifact building remains separate.
|
||||
|
||||
**Outcome:** Source compatibility checks work independently of artifacts.
|
||||
|
||||
1. Add `Go.CompileTargets` and string-array profile targets. Convert to internal
|
||||
Go targets and validate complete pairs consistently for API and profile use.
|
||||
2. After test/vet, run `go build -mod=readonly -o <os.DevNull> ./...` in static
|
||||
mode for each selected target. The Go build null-output mode suppresses
|
||||
executable output, including a module with a single main package.
|
||||
3. Report failures as `package-compile`, including the selected target. Keep
|
||||
output names, linker version injection, smoke tests, receipts, and manifests
|
||||
in artifact building. Document compilation versus target execution.
|
||||
|
||||
**Verification:** Linux amd64/arm64, a supported additional Go pair, source-only
|
||||
library, single-main and multiple-main modules (including repeated executable
|
||||
basenames), target failure, unchanged candidate files, `CGO_ENABLED=0`, preserved
|
||||
ordering, and page-only delivery with compilation selected but no build targets.
|
||||
Reuse the existing Go environment tests for controls already protected there.
|
||||
|
||||
## Stage 4: Compare the optional expected push URL
|
||||
|
||||
**Completion:** Complete. `ReleaseRequest.ExpectedPushURL` and profile
|
||||
`expected_push_url` require an exact match with Git's resolved effective push
|
||||
URL before validation. Mismatches return `ErrUnexpectedPushURL` with expected
|
||||
and resolved values; `Check` ignores the publication-only expectation.
|
||||
|
||||
**Outcome:** Publication rejects a different effective destination before validation.
|
||||
|
||||
1. Add `ExpectedPushURL` and `expected_push_url`, with an empty value selecting
|
||||
existing behavior. Carry it only into the publication request.
|
||||
2. Immediately after resolving/capturing `endpoint.PushURL`, compare exact strings.
|
||||
Report expected and resolved values through a publication preflight error.
|
||||
Add `ErrUnexpectedPushURL` as a public sentinel using the existing shared-error
|
||||
ownership pattern so callers can use `errors.Is`.
|
||||
3. Keep later endpoint rechecks and reconciliation intact. Update GoDoc,
|
||||
publication guidance, and the profile reference.
|
||||
|
||||
**Verification:** Omitted/matching/mismatching values, Git `insteadOf` resolution,
|
||||
separate fetch/push URLs, exact spelling differences, mismatch before Go/callbacks
|
||||
or tag creation, and a local-only `Check` that ignores the publication expectation.
|
||||
Existing endpoint-change and uncertain-push tests keep their ownership.
|
||||
|
||||
## Stage 5: Check committed Go formatting
|
||||
|
||||
**Completion:** Complete. `ValidationSpec.GoFormat` and profile
|
||||
`validation.go_format` run `go/format` on regular Go blobs from the captured
|
||||
commit. Findings identify unformatted paths; parser and inspection failures
|
||||
retain their causes, and the check leaves repository contents unchanged.
|
||||
|
||||
**Outcome:** A declaration replaces tracked-file formatting loops.
|
||||
|
||||
1. Add `GoFormat` and `validation.go_format` with working executor integration.
|
||||
2. Load the shared captured inventory and apply `format.Source` to regular `.go`
|
||||
blobs. Compare original and formatted bytes, preserving repository contents.
|
||||
3. Return `go-format` findings for affected paths and preserve parser/inspection
|
||||
causes. Update usage and formatting-convention documentation.
|
||||
|
||||
**Verification:** Formatted and unformatted files, parse errors, vendor/nested
|
||||
source, unusual filenames, committed versus worktree bytes, disabled/default
|
||||
behavior, API/profile parity, and failure before later product/build work.
|
||||
|
||||
## Stage 6: Select committed workspace-file inspection
|
||||
|
||||
**Completion:** Complete. `Validation.ModuleDistribution.WorkspaceFiles` and
|
||||
`validation.module_distribution.workspace_files` report committed blob entries
|
||||
named `go.work` or `go.work.sum`, including nested paths and symlinks. The rule
|
||||
inspects the captured candidate independently of `GOWORK` and leaves the Go
|
||||
workspace environment and vendor behavior unchanged.
|
||||
|
||||
**Outcome:** One distribution rule works independently of the Go environment.
|
||||
|
||||
1. Add `ModuleDistributionValidationSpec.WorkspaceFiles` and the matching JSON
|
||||
group/field. The remaining rule is added in Stage 7.
|
||||
2. Inspect committed blob entries named `go.work` or `go.work.sum`, including
|
||||
nested and symlink entries. Report paths using `workspace-files`.
|
||||
3. Keep testing's existing workspace setting and consumer vendor choices in their
|
||||
current owners. Document the distinction between environment and distribution.
|
||||
|
||||
**Verification:** Either workspace filename, nested paths, symlink names,
|
||||
committed files with `GOWORK=off`, uncommitted files excluded from inspection,
|
||||
selection disabled, and shared API/profile execution. Use meaningful rule cases
|
||||
rather than retesting Git enumeration mechanics.
|
||||
|
||||
## Stage 7: Select filesystem replacement inspection
|
||||
|
||||
**Completion:** Complete. `Validation.ModuleDistribution.LocalReplacements` and
|
||||
`validation.module_distribution.local_replacements` parse committed `go.mod`
|
||||
declarations, including nested/vendor files and committed symlink declarations.
|
||||
Filesystem replacements report their declaration path, line, directive, and
|
||||
target as `local-replacements`; versioned replacements are permitted. Parse and
|
||||
inspection failures retain their causes, and this rule is independent of both
|
||||
workspace-file selection and `GOWORK`.
|
||||
|
||||
**Outcome:** The second distribution rule parses actual module declarations.
|
||||
|
||||
1. Add `ModuleDistribution.LocalReplacements` and the equivalent profile field.
|
||||
Prepare `golang.org/x/mod v0.40.0`, module sums, and required OSS notices.
|
||||
2. Parse committed `go.mod` files with `modfile.Parse`, including nested/vendor
|
||||
declarations. Resolve symlink declarations within the candidate; report an
|
||||
inspection error when their selected contents cannot be obtained locally.
|
||||
3. Identify filesystem replacements by the parsed replacement's absent version;
|
||||
permit versioned replacements. Report path, directive/source location, and
|
||||
target through `local-replacements`, preserving parse/inspection causes.
|
||||
4. Document independent distribution selections and their inspection scope.
|
||||
|
||||
**Verification:** Single and block directives, comments, quoted paths, relative
|
||||
and absolute filesystem targets, versioned replacements, nested declarations,
|
||||
valid/broken symlinks, parse failure, and all independent boolean combinations.
|
||||
The rule applies to candidate contents even when testing disables workspace use.
|
||||
|
||||
## Stage 8: Inspect individual committed file sizes
|
||||
|
||||
**Completion:** Complete. `Validation.FileSize` and `validation.file_size` enable
|
||||
a per-blob decimal-byte limit with a 1,000,000-byte default, strict greater-than
|
||||
comparison, and literal repository-relative file/directory exclusions. The check
|
||||
uses captured blob sizes, counts symlink link text, omits gitlinks, and reports
|
||||
one oversized file with its measurement. Nil disables the check, and historical
|
||||
or aggregate repository size is outside its scope.
|
||||
|
||||
**Outcome:** Optional limits and intentional path exceptions are operational.
|
||||
|
||||
1. Add `FileSizeValidationSpec`, `ValidationSpec.FileSize`, and matching JSON
|
||||
fields according to the declaration table. Validate nonnegative byte limits.
|
||||
2. Use shared blob sizes for regular files and symlink link-text blobs. Apply
|
||||
literal file/directory exclusions. On an oversized blob, return `file-size`
|
||||
with its path and existing `FileSizeMeasurement` fields; reporting one offending
|
||||
file per failure fits the current diagnostic model.
|
||||
3. Document decimal bytes, strict greater-than comparison, exclusions, and
|
||||
current-candidate scope. Preserve default disabled behavior.
|
||||
|
||||
**Verification:** Below/at/above limits, the exact 1,000,000-byte enabled default,
|
||||
zero/custom/negative limits, nil versus empty objects, directory/path boundaries,
|
||||
literal metacharacters, unmatched exclusions, small binaries, symlink sizes, and
|
||||
omitted submodule sizes. Historical and aggregate size do not become release gates.
|
||||
|
||||
## Stage 9: Implement internal Markdown parsing and anchors
|
||||
|
||||
**Completion:** Complete. Goldmark now records parsed links, images, reference
|
||||
uses, use-site locations, and collision-free heading anchors behind an internal
|
||||
per-candidate document cache. Its behavior remains unselected until the later
|
||||
validation-integration stage.
|
||||
|
||||
**Outcome:** A parser with source positions and documented anchor semantics is ready.
|
||||
|
||||
1. Add `github.com/yuin/goldmark/v2 v2.1.6`, prepared dependencies, and applicable
|
||||
OSS notices. Keep parser types inside internal implementation.
|
||||
2. Parse links/images, reference uses, headings, and source positions into small
|
||||
internal records. Derive visible heading text and apply the convention above.
|
||||
3. Cache parsed records/anchors per candidate document. Keep this stage internal;
|
||||
Stage 11 adds the public selection once complete checking works.
|
||||
4. Compare fixtures with PromptKit's starting examples. Record intended refinements
|
||||
in the roadmap until the public behavior lands, avoiding a second regex parser.
|
||||
|
||||
**Parser refinements:** PromptKit's starting script scans inline links, images,
|
||||
and ATX headings with regular expressions. The Goldmark parser also records
|
||||
resolved full, collapsed, and shortcut reference uses at each source use site.
|
||||
Heading anchors use decoded visible AST text, include inline code,
|
||||
exclude raw HTML tags, and support Setext headings. Parser-recognized CommonMark
|
||||
autolinks are recorded alongside inline and reference links. Repeated-heading
|
||||
suffixes skip identifiers already used by another heading.
|
||||
|
||||
**Verification:** Inline/reference forms and images, escaped/parenthesized
|
||||
and angle-bracket destinations, optional titles, code fences/inline code,
|
||||
Unicode/entity headings, ATX/Setext headings, repeated headings and suffix
|
||||
collisions, and source use-site locations including repeated reference uses.
|
||||
Undefined references and HTML prose remain governed by parser interpretation.
|
||||
|
||||
## Stage 10: Implement internal destination and fragment checking
|
||||
|
||||
**Completion:** Complete. The internal checker resolves committed destinations,
|
||||
checks supported fragments, preserves inspection errors, and reports distinct
|
||||
outside-checkout and submodule observations. Stage 11 exposes this checker
|
||||
through public and profile selections and the shared executor.
|
||||
|
||||
**Outcome:** Committed Markdown navigation is checked with boundary observations.
|
||||
|
||||
1. Resolve parsed local URI components through `CandidateTree.ResolveDestination`.
|
||||
Apply escaping/query/fragment rules above and use actual resolved identities
|
||||
for target-document anchor lookup.
|
||||
2. Check committed existence and supported heading fragments, recording source
|
||||
path/location/target. Produce `markdown-links` failures and distinct nonfailure
|
||||
observations for outside-checkout and submodule contents.
|
||||
3. Implement optional checkout-boundary enforcement internally. Preserve the
|
||||
distinction between external URIs, checkout escapes, and uninspected submodules.
|
||||
4. Reuse remediated symlink/cancellation/local-object behavior. Keep parsing,
|
||||
resolution, and rule evaluation in ordinary internal functions.
|
||||
|
||||
**Resolution refinement:** URI query components do not participate in path
|
||||
checking. Compare fragments after one percent-decoding pass and lowercase them
|
||||
to preserve PromptKit's starting anchor matching.
|
||||
|
||||
**Verification:** Valid/missing files and anchors, same-document/empty fragments,
|
||||
percent-escaped paths and fragments, query strings, directories and non-Markdown
|
||||
files, outside links with both settings, and submodule observations. Check how
|
||||
resolver results and inspection errors become Markdown findings, preserving
|
||||
causes and cancellation. Use representative committed-tree integration cases
|
||||
and verify unchanged candidate/worktree bytes. Existing candidate-tree and Git
|
||||
tests own detailed absolute-path, symlink-parent, cycle, neighboring-file,
|
||||
missing-object, and traversal-cancellation cases.
|
||||
|
||||
## Stage 11: Expose Markdown selection and complete validation integration
|
||||
|
||||
**Completion:** Complete. `ValidationSpec.Markdown` and
|
||||
`validation.markdown` select the shared committed-link checker through both
|
||||
public operations and CLI profile commands. Omitted/null settings disable the
|
||||
check; an empty object enables it, and the boundary option maps explicitly.
|
||||
Warnings use the shared output writer, while Markdown failures stop product
|
||||
checks and builds. GoDoc, profile, consumer, CLI, and internal documentation
|
||||
now describe the operational behavior.
|
||||
|
||||
**Outcome:** All agreed validation selections work through both public operations.
|
||||
|
||||
1. Add `MarkdownValidationSpec`, `ValidationSpec.Markdown`, and their JSON fields.
|
||||
Enable on a non-nil group/empty object and map the boundary boolean explicitly.
|
||||
2. Wire the checker and nonfailure observations into the shared executor/output
|
||||
writer. Reuse existing facade/CLI diagnostic formatting and exit classification.
|
||||
3. Document the newly operational Markdown selection in its canonical owners.
|
||||
Review earlier stages' GoDoc, configuration, check/publish guides, CLI reference,
|
||||
internal inventory, and examples for consistency across combined selections.
|
||||
4. Use self-contained fixtures representing Audita defaults/artifacts, ConfigKit's
|
||||
race/vet/compilation, and PromptKit's shared settings plus example assertions.
|
||||
Document how consumers remove duplicate generic commands when adopting settings.
|
||||
|
||||
**Verification:** Equivalent Go/profile declarations, nil/empty/null Markdown
|
||||
settings, warnings with successful results, boundary failures before product/build
|
||||
work, all-zero compatibility, representative combined selections, one suite and
|
||||
one additional-check callback. Run the compiled API/dependency check, including
|
||||
`buildinfo`'s standard-library/runtime-only dependency boundary.
|
||||
|
||||
## Stage 12: Build the CI tool from verified released module configuration
|
||||
|
||||
**Completion:** Complete. The maintained tag workflow verifies and checks out
|
||||
the event tag before reading module files, then confirms the ReleaseKit module
|
||||
selection and builds its CLI with temporary alternate module metadata outside
|
||||
the source tree. The delivery command retains the event arguments and exit
|
||||
status, and the cleanup trap removes its module copies and executable.
|
||||
|
||||
**Outcome:** The standard template has one tool-version declaration.
|
||||
|
||||
1. Revise `examples/woodpecker/tag-delivery.yml` into a compact bootstrap/delivery
|
||||
step. Use available Git to validate/fetch the explicit event tag, compare its
|
||||
peeled commit to the full provider object ID using existing case-insensitive
|
||||
object-ID semantics, check out that commit detached, and confirm HEAD and
|
||||
the existing clean tagged-source requirement. This ensures module files
|
||||
actually belong to the verified release before selecting the tool.
|
||||
Do this before reading/resolving the application module or executing Go.
|
||||
2. Apply the agreed CI tool bootstrap approach: create a disposable directory
|
||||
outside the source checkout, copy its `go.mod` and existing `go.sum`, and use
|
||||
an alternate `-modfile` for tool resolution/build.
|
||||
Run from the verified source with `GOWORK=off` and `GOTOOLCHAIN=local`.
|
||||
3. Confirm the ReleaseKit module is already selected by that module configuration
|
||||
using `go list -m`; then build its `cmd/releasekit` package without an `@version`
|
||||
suffix. Allow ordinary network-capable module preparation in the temporary
|
||||
metadata copies (`-mod=mod`). Respect selected require/replace relationships.
|
||||
4. Invoke the resulting native executable's existing `ci-deliver` with the event
|
||||
repository, commit, and tag. Keep delivery credentials in the existing delivery
|
||||
step and use an exit cleanup trap for temporary metadata and executable files.
|
||||
5. Remove the independent `RELEASEKIT_VERSION` workflow setting. Preserve current
|
||||
Go-image customization, destination/profile ownership, and delivery outcomes.
|
||||
Keep the bootstrap Git block small; the built tool retains its runtime guards.
|
||||
|
||||
**Verification:** Execute maintained template commands with a local tag/module
|
||||
fixture and instrument Go/transport operations. Prove wrong tag/commit stops
|
||||
before module resolution/build, a dirty module cannot select a different tool,
|
||||
the verified checkout selects the tool, module metadata and source remain
|
||||
unchanged, and the executable/temporary files are cleaned up. Tool metadata
|
||||
preparation is separate from offline candidate checks. Include a representative
|
||||
case that verifies invocation of the selected executable with the event arguments
|
||||
and propagation of its exit status. Existing delivery tests own hosted behavior.
|
||||
|
||||
## Stage 13: Verify upgrades, retries, and bootstrap variants
|
||||
|
||||
**Completion:** Complete. The tag workflow is exercised against a local module
|
||||
proxy with two tool versions, an older tagged configuration after the default
|
||||
branch upgrades, and a versioned replacement. Missing tool-only dependency
|
||||
checksums are prepared in temporary module metadata. The ReleaseKit source
|
||||
workflow verifies its tag before self-bootstrap and writes the executable
|
||||
outside the checkout. Delivery, configuration, and CLI guidance now distinguish
|
||||
tool bootstrap from application dependency preparation and describe
|
||||
immutable-source retries and installed-tool use.
|
||||
|
||||
**Outcome:** Tool selection follows the triggering release across supported uses.
|
||||
|
||||
1. Extend Stage 12's bootstrap fixtures with a local module proxy for two tool
|
||||
versions and tagged consumer module configurations. Execute the maintained
|
||||
workflow body against both.
|
||||
Keep live infrastructure outside the default test suite.
|
||||
2. Verify a retry of an older tag still selects that tag's module configuration
|
||||
when the default branch has upgraded. Include missing tool-only checksums and
|
||||
an existing versioned replacement to protect source-based resolution.
|
||||
3. Align `releasekit-source-delivery.yml` with source verification before self
|
||||
bootstrap and temporary output. Preserve self-bootstrap from `./cmd/releasekit`
|
||||
and separately installed-tool guidance using the existing command.
|
||||
4. Update delivery/configuration/CLI guidance and maintained templates together.
|
||||
Explain compatible Go environments, dependency preparation, immutable-source
|
||||
retries, and the distinct tool/app artifact preparation steps.
|
||||
|
||||
**Verification:** Two dependency versions, older-source retries, self bootstrap,
|
||||
and separately installed tool, using the shared bootstrap fixtures. Existing
|
||||
delivery and publication tests retain ownership of source-only pages, binary
|
||||
delivery, destination handling, and publication states. Add integration coverage
|
||||
for any new interaction introduced by bootstrap changes. An application without
|
||||
a declared ReleaseKit dependency uses the installed-tool integration.
|
||||
|
||||
## Stage 14: Migrate Audita's local CI integration
|
||||
|
||||
**Completion:** Complete. Audita commit `17421bc` makes both local and hosted
|
||||
bootstraps resolve ReleaseKit v0.1.0 from the consumer's module configuration.
|
||||
The existing Go image, `GITEA_RELEASE_TOKEN` secret, release profile, caller
|
||||
arguments, and native tool status are preserved. The local wrapper uses
|
||||
temporary alternate module metadata and cleans it up before executing the tool.
|
||||
Audita's runbook now describes the module-selected workflow.
|
||||
|
||||
**Verification:** Audita's `go test ./scripts -count=1`,
|
||||
`bash -n scripts/release.sh`, and real `bash scripts/release.sh version` passed;
|
||||
the wrapper reported `releasekit v0.1.0` and left source module files unchanged.
|
||||
ReleaseKit's `TestWoodpeckerTagDeliveryTemplate` and
|
||||
`TestWoodpeckerTagDeliveryUsesTaggedModuleVersion` passed with local Git and
|
||||
module-proxy fixtures. Both repositories passed their relevant diff checks.
|
||||
|
||||
**Outcome:** Audita's local wrapper and CI select the same module-declared tool.
|
||||
|
||||
1. Read `../audita` orientation/policies and inspect its worktree before editing.
|
||||
Adapt `.woodpecker/release.yml` to the maintained module-based template,
|
||||
preserving its Go image, Gitea secret name, and release profile.
|
||||
2. Retain its existing released ReleaseKit module selection for this migration;
|
||||
that version already supplies `ci-deliver`. Make any necessary adjustments to
|
||||
`scripts/release.sh` for the selected bootstrap metadata approach, preserving
|
||||
arguments and native executable exit behavior. Keep generated tool output
|
||||
outside the candidate source where needed.
|
||||
3. Verify the consumer's actual wrapper/workflow using local tagged fixtures and
|
||||
prepared module caches. Confirm matching tool selection, preserved arguments
|
||||
and exit status, and unchanged source files. Review the diff for preservation
|
||||
of the release profile and binary targets. Existing consumer and ReleaseKit
|
||||
tests retain ownership of source validation and hosted delivery behavior.
|
||||
4. Commit the focused migration in Audita with a plain English message. Record
|
||||
its commit and local verification in this plan's implementation status.
|
||||
|
||||
**Verification:** The actual adapted consumer declarations use one dependency
|
||||
version; local and CI bootstraps agree and retain existing caller arguments/status
|
||||
semantics. Keep integration fixtures self-contained in ReleaseKit's default suite.
|
||||
This migration uses an existing release and requires no intermediate publication
|
||||
or live Woodpecker/Gitea run to complete the stage.
|
||||
|
||||
## Stage 15: Audit the completed v0.2.0 implementation
|
||||
|
||||
**Completion:** Complete. All ten release-roadmap items map to implemented API,
|
||||
profile, execution, diagnostics, canonical documentation, and focused behavioral
|
||||
evidence. The audit confirms default zero-value behavior, independent
|
||||
module-distribution selections, one coordinated Go suite, source-only
|
||||
compilation/delivery, and expected-push preflight. Review found no unintended
|
||||
defaults, restrictions, or stronger guarantees. Audita's migration is recorded
|
||||
at `17421bc`.
|
||||
|
||||
**Verification:** `go test ./...` and `go run ./internal/apicheck` passed.
|
||||
Local Markdown destinations and fragments resolved across the documentation;
|
||||
dependency versions, source revisions, attribution entries, and license texts
|
||||
were checked. Maintained Woodpecker examples passed their offline fixtures.
|
||||
|
||||
**Outcome:** The entire scoped feature set is implemented and locally verified.
|
||||
|
||||
1. Match every row in the roadmap/stage table to implemented settings, execution,
|
||||
diagnostics, current documentation, and focused behavioral evidence. Verify
|
||||
all-zero compatibility, independent distribution choices, one coordinated Go
|
||||
suite, source-only compilation/delivery, and selected endpoint preflight.
|
||||
2. Review new code and tests for unintended defaults, restrictions, caps, or
|
||||
stronger guarantees. Preserve user choice and the existing facade boundaries.
|
||||
3. Run `go test ./...` and `go run ./internal/apicheck`. Add further integration
|
||||
coverage only for a concrete remaining risk. Check documentation links,
|
||||
fragments, whitespace, dependency notices, and maintained examples.
|
||||
4. Update statuses in this plan, the release roadmap, and the model roadmap to
|
||||
reflect actual completion, including the Audita migration evidence. Update
|
||||
canonical current-behavior owners as needed and remove stale prospective text.
|
||||
5. Commit the completed unit, report each stage's outcome and remaining work,
|
||||
and finish with a clean workspace while preserving any unrelated user changes.
|
||||
The subsequent architecture review and release/testing decisions follow here.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None.
|
||||
@@ -1,149 +0,0 @@
|
||||
# Validation API and profile model
|
||||
|
||||
Status: Complete for the agreed v0.2.0 shared validation model. Every selection
|
||||
and execution path described here is implemented and locally verified; broader
|
||||
consumer adoption remains in the product roadmap.
|
||||
|
||||
This roadmap describes the shared model that enables the optional validation
|
||||
capabilities in the [v0.2.0 roadmap](v0.2.0.md). It owns their common API,
|
||||
configuration, execution, and diagnostic design. The release roadmap owns each
|
||||
capability's purpose and scope. The [implementation plan](implementation.md)
|
||||
owns the stages and the agreed API rollout.
|
||||
|
||||
## Rationale and v0.1.0 baseline
|
||||
|
||||
ReleaseKit v0.1.0 exposes `Check` and `Publish` through the root facade. Both
|
||||
accept `ReleaseRequest` and use shared candidate-validation machinery. Validation
|
||||
runs the standard offline Go suite, followed by `AdditionalChecks` when supplied.
|
||||
Selected executable builds follow validation. The CLI maps profile `checks`
|
||||
commands to the additional-check callback.
|
||||
|
||||
This provides a common procedure and a product-specific extension point. The
|
||||
request and profile have structured selections for race testing, separate full
|
||||
vet, package compilation, formatting, Markdown, module distribution, and file
|
||||
size. Publication also supports an expected push endpoint.
|
||||
|
||||
The model lets consumers declare their choices once while ReleaseKit owns
|
||||
execution and coordination. This follows [ADR 0002](../adr/0002-routine-releases.md):
|
||||
shared capabilities should reduce application code and routine developer
|
||||
decisions. The facade boundaries in [ADR 0001](../adr/0001-public-facade.md)
|
||||
provide the existing architectural foundation.
|
||||
|
||||
Optional capabilities can serve a small subset of consumers when they remove
|
||||
application-owned release mechanics and have clear scope, compact configuration,
|
||||
and proportionate maintenance costs.
|
||||
|
||||
## Target end state
|
||||
|
||||
### One validation specification
|
||||
|
||||
The facade-owned `ValidationSpec` on `ReleaseRequest` has a corresponding
|
||||
`validation` object in the release profile. Typed Go fields and ordinary JSON
|
||||
settings express the same supported selections. Related choices, including
|
||||
base-test and vet settings, are grouped so their relationship is clear.
|
||||
|
||||
The specification includes the agreed capabilities in the
|
||||
[release roadmap](v0.2.0.md), including optional Markdown boundary enforcement,
|
||||
independent module-distribution rules, and file-size settings. Its zero value
|
||||
and an omitted profile object preserve current default validation. Consumers
|
||||
enable optional checks according to their product needs.
|
||||
|
||||
Go callers and CLI users receive equivalent validation behavior. The CLI owns
|
||||
profile parsing and presentation; the facade owns the public types and contracts;
|
||||
internal implementation owns execution. The [implementation plan](implementation.md)
|
||||
records the selected field names, representations, and completed rollout.
|
||||
|
||||
### Shared coordination
|
||||
|
||||
`Check` and `Publish` pass the same specification through one internal validation
|
||||
path bound to the captured candidate. ReleaseKit constructs the selected Go
|
||||
commands, manages its shared environment, determines execution order, and
|
||||
propagates failures and cancellation.
|
||||
|
||||
Race selection changes the one base suite invocation. Selecting a separate
|
||||
full-vet pass automatically omits test-time vet. Package-compilation targets
|
||||
express compatibility checks independently of executable artifact selection.
|
||||
Consumers obtain this coordination through their declarations.
|
||||
|
||||
Keep the executor straightforward and internal, with ordinary functions for
|
||||
the selected capabilities. The public model expresses validation choices;
|
||||
ReleaseKit maintains their execution procedure. Existing candidate rechecks,
|
||||
offline validation, and source-publication outcomes retain their meaning.
|
||||
|
||||
### Candidate-content inspection
|
||||
|
||||
File-oriented checks share candidate-file enumeration and inspection where
|
||||
useful. Their scope is the captured candidate, and inspection remains offline
|
||||
and read-only. Inspect committed candidate contents and define symlink and
|
||||
submodule handling explicitly in the shared inspection model. Module-distribution
|
||||
rules inspect the files being released independently of the environment used
|
||||
to run Go commands. Markdown boundary
|
||||
validation operates independently of neighboring checkout contents.
|
||||
|
||||
Keep each check's settings together: Markdown validation owns its optional
|
||||
boundary rule; module-distribution validation owns its independent rule
|
||||
selections; file-size validation owns its limit and path exclusions. The
|
||||
[release roadmap](v0.2.0.md) defines the scope and defaults of each capability.
|
||||
|
||||
### Clear responsibility boundaries
|
||||
|
||||
| Concern | Model owner |
|
||||
| --- | --- |
|
||||
| Base tests, full vet, and package compilation | Shared validation specification |
|
||||
| Formatting, Markdown links, module distribution, and file size | Shared validation specification |
|
||||
| Product-specific assertions and example checks | Existing `AdditionalChecks` callback and profile `checks` |
|
||||
| Expected authoritative push destination | Publication settings and endpoint handling |
|
||||
| Executable package, binary name, and artifact targets | Build declaration |
|
||||
| Hosted destination and credentials | Delivery settings |
|
||||
|
||||
`AdditionalChecks` and profile `checks` remain available for substantive
|
||||
consumer behavior. Shared capabilities use the validation specification.
|
||||
Preserve the current behavior of existing declarations as the new options land.
|
||||
|
||||
The expected-endpoint feature remains a publication guard, and `Check` remains
|
||||
local-only. Selecting package-compilation checks leaves a source-only consumer's
|
||||
deliverable selection unchanged. Tool installation and dependency preparation
|
||||
remain separate from offline candidate validation.
|
||||
|
||||
### Consistent diagnostics
|
||||
|
||||
Shared validation failures identify the check and expose useful details to Go
|
||||
callers. File-oriented checks provide source locations and actionable findings
|
||||
where applicable, including relevant paths, directives, and measured values.
|
||||
The CLI presents those details consistently through the ordinary candidate-check
|
||||
and publication commands.
|
||||
|
||||
Use a small facade-owned error model with stable check identity and support for
|
||||
underlying error causes and cancellation. Preserve `errors.Is` and `errors.As`
|
||||
behavior across internal conversions and facade wrapping. Exact error types
|
||||
and diagnostic fields are proposed in the [implementation plan](implementation.md).
|
||||
|
||||
Validation failures and publication outcomes have distinct meanings. Existing
|
||||
publication states continue to describe whether publication was attempted,
|
||||
confirmed, conflicted, or remains uncertain. The model preserves the existing
|
||||
failure-stopping behavior of the candidate workflow.
|
||||
|
||||
## Implementation
|
||||
|
||||
The [implementation plan](implementation.md) records the completed rollout and
|
||||
verification. The facade and CLI profile expose equivalent selections for the
|
||||
single test suite, separate full vet, package compilation, formatting, Markdown,
|
||||
module distribution, file size, and the expected publication endpoint. Shared
|
||||
execution, ordering, diagnostics, cancellation, and failure stopping are
|
||||
implemented by the owners described above. The maintained Woodpecker template
|
||||
and Audita's local wrapper use the module-selected ReleaseKit version; see the
|
||||
[v0.2.0 roadmap](v0.2.0.md) and [delivery guide](../consumers/delivery.md).
|
||||
|
||||
## Adoption evidence
|
||||
|
||||
Self-contained integration fixtures evaluate all three known consumer shapes:
|
||||
Audita's default validation and executable builds; ConfigKit's selected test,
|
||||
vet, and library compilation checks; and PromptKit's shared validation plus
|
||||
substantive example assertions. Audita's module-selected CI migration is
|
||||
committed at `17421bc`; the other consumer migrations remain separate adoption
|
||||
work.
|
||||
|
||||
The model gives each adopting consumer a small declaration and the same routine
|
||||
release operation. Shared execution and diagnostics cover the agreed v0.2.0
|
||||
capabilities while product-specific work remains in the existing extension
|
||||
point.
|
||||
@@ -1,210 +1,43 @@
|
||||
# ReleaseKit: shared release process
|
||||
# ReleaseKit adoption and deployment roadmap
|
||||
|
||||
Status: The v0.2.0 implementation, policy adoption, and architecture
|
||||
remediation are complete. Audita's module-selected local and CI integration is
|
||||
committed at `17421bc`; broader consumer adoption and live deployment remain.
|
||||
Status: Pending consumer adoption and live deployment. The v0.2.0 implementation
|
||||
and its remediation are complete.
|
||||
|
||||
This roadmap records the shared release-process opportunity identified in
|
||||
PromptKit, ConfigKit, Audita, Notarius, Narratio, and Scriptorium on 2026-09-29,
|
||||
and the remaining adoption goals. The [internal package inventory](../internal/overview.md)
|
||||
records implemented capability owners and behavioral evidence. The
|
||||
[architecture policy](../policy/architecture.md) and
|
||||
[ADR 0001](../adr/0001-public-facade.md) own the facade boundaries and rationale.
|
||||
The initial foundation, policy adoption, and remediation plans are preserved
|
||||
in Git history; the current v0.2.0 completion evidence is in the
|
||||
[implementation plan](implementation.md).
|
||||
The [v0.2.0 release note](../releases/v0.2.0.md) summarizes the implemented
|
||||
capabilities. The [internal inventory](../internal/overview.md) records their
|
||||
owners and local verification. Completed plans and review findings remain in
|
||||
Git history. The [architecture policy](../policy/architecture.md) and accepted
|
||||
ADRs own the selected architectural constraints.
|
||||
|
||||
## Opportunity
|
||||
## Remaining work
|
||||
|
||||
All six repositories follow the same base release policy. Their release scripts
|
||||
repeat stable-version parsing, candidate and release-note checks, local and
|
||||
remote tag checks, validation of one captured commit, explicit Git publication,
|
||||
and recovery guidance for uncertain pushes. They differ in publication approach,
|
||||
tag type, validation commands, and artifact delivery. The mechanics of embedding
|
||||
a release version and cross-building an application are further candidates for
|
||||
standardization.
|
||||
- Choose the broader consumer integration test plan and migration sequence for
|
||||
PromptKit, ConfigKit, Notarius, Narratio, and Scriptorium. Evaluate API clarity,
|
||||
product-specific checks, and the infrastructure removed from each repository.
|
||||
- Adopt the common publication, validation, runtime-version, build, and delivery
|
||||
conventions where they apply. Keep product identity, compatibility decisions,
|
||||
and substantive application checks with each consumer.
|
||||
- Provision delivery credentials and activate ReleaseKit and consumer Woodpecker
|
||||
workflows as part of deployment. The maintained consumer template selects
|
||||
tooling from the released application's module configuration.
|
||||
- Verify live Gitea delivery and Woodpecker execution. Current verification uses
|
||||
local Git and HTTP fixtures; live deployment remains unverified.
|
||||
- Measure realized reductions in consumer release infrastructure after migration.
|
||||
Audita's module-selected local and CI integration is committed at `17421bc`.
|
||||
|
||||
If the projects deliberately standardize publication approach and tag type,
|
||||
ReleaseKit can own most of the repeated release-process code. The current six
|
||||
repositories contain 942 lines of release shell scripts and 742 lines of
|
||||
dedicated release tests, or 1,684 lines total. A directional estimate is that
|
||||
roughly 1,000–1,250 lines could leave those repositories: about 450–500 lines
|
||||
of publication scripts, 150–250 lines of checks and builders, and 400–500 lines
|
||||
of repeated publication tests. ReleaseKit would gain its own implementation and
|
||||
tests, so this is a reduction in local code, not a net line-count saving.
|
||||
## Proposals and deferred work
|
||||
|
||||
## Selected publication standard
|
||||
|
||||
1. Prepare and commit a version-matched note at `docs/releases/<version>.md`.
|
||||
2. Publish the candidate commit to authoritative `main` before invoking the
|
||||
release command.
|
||||
3. Run one command that checks the candidate and unused stable version, runs
|
||||
that repository's offline candidate validation once, and rechecks mutable
|
||||
state.
|
||||
4. Create an annotated tag at the validated commit with a message derived from
|
||||
the checked-in note. Push only that exact tag object to the authoritative
|
||||
endpoint. A successful tag push completes the source release.
|
||||
5. Treat hosted release pages and binary assets as asynchronous delivery with
|
||||
their own status. Do not poll CI or require artifact availability to declare
|
||||
the source release complete.
|
||||
|
||||
This would replace Audita's atomic branch-and-tag push, ConfigKit's and
|
||||
Notarius's branch push during the release command, and Audita's, Notarius's,
|
||||
and Narratio's lightweight tags. Those changes require updates to each
|
||||
repository's adopted release policy and procedure; they are not merely code
|
||||
cleanup.
|
||||
|
||||
## Architecture
|
||||
|
||||
[ADR 0001](../adr/0001-public-facade.md) owns the accepted facade decision.
|
||||
The [architecture policy](../policy/architecture.md) owns the adopted
|
||||
responsibility and dependency rules, including the runtime version boundary.
|
||||
The root `releasekit` package provides the public facade for candidate
|
||||
validation, source publication, selected-target builds, and tagged-source
|
||||
delivery. The Gitea page and asset-delivery client is integrated through that
|
||||
facade and the CLI. The separate public `buildinfo` package provides lightweight
|
||||
runtime version access.
|
||||
|
||||
Each facade owns its public named types and documented contracts. Public
|
||||
operations, inputs, outcomes, errors, and callbacks express deliberately
|
||||
selected consumer needs. Handles retain private implementation state; explicit
|
||||
forwarding and conversions connect the public contracts to internal
|
||||
representations.
|
||||
|
||||
Git operations, Go toolchain execution, Gitea integration, and orchestration
|
||||
bookkeeping belong under Go's `internal/` boundary. Dependency direction runs
|
||||
from the facades into internal implementation, with internal collaborators using
|
||||
contracts defined inside that boundary. Implementation packages can evolve
|
||||
while the supported public contracts retain their compatibility obligations.
|
||||
|
||||
The `buildinfo` facade keeps runtime version access lightweight. Applications
|
||||
read their embedded version through its supported accessor. ReleaseKit's builder
|
||||
and runtime implementation own the linker symbol and injection mechanism
|
||||
together.
|
||||
|
||||
The `buildinfo` facade follows three constraints:
|
||||
|
||||
- Its public API exposes only runtime information justified by consumer needs.
|
||||
- Its implementation uses the standard library and a small internal dependency
|
||||
graph independent of release orchestration.
|
||||
- Dependency checks protect that boundary, and build-and-run integration tests
|
||||
verify that the builder injects the selected version and the public accessor
|
||||
reports it correctly.
|
||||
|
||||
The release executable calls the orchestration facade and handles command
|
||||
parsing, output, and exit codes. Library errors and outcomes report meaningful
|
||||
publication state, including partial progress and uncertainty. Go declarations
|
||||
and GoDoc own exact public API contracts; additional public packages and
|
||||
extension interfaces require a deliberate decision grounded in durable consumer
|
||||
needs.
|
||||
|
||||
Compiled-export and dependency checks protect facade ownership.
|
||||
External-package behavioral tests protect error identity, value ownership,
|
||||
callback lifetime, and observable outcomes across forwarding and conversions.
|
||||
|
||||
## Shared tool boundary
|
||||
|
||||
Provide a versioned ReleaseKit executable backed by a Go library. Existing
|
||||
shell entry points can become short invocations of that executable. A library
|
||||
alone would still require a caller in every shell-driven repository.
|
||||
|
||||
ReleaseKit should own:
|
||||
|
||||
- stable-version parsing and committed-note identity checks;
|
||||
- authoritative Git endpoint resolution, candidate capture, clean `main` and
|
||||
remote-branch agreement checks, and unused local/remote tag checks;
|
||||
- one validation invocation bound to the captured candidate, followed by cheap
|
||||
rechecks before publication;
|
||||
- annotated-tag creation and verification, explicit tag-object push, and one
|
||||
bounded authoritative-ref check after a failed or ambiguous push;
|
||||
- a standard version accessor in the public `buildinfo` facade, backed by
|
||||
release-build injection of the selected tag;
|
||||
- a cross-build API that accepts the application's main package and selected
|
||||
targets, initially Linux amd64, Linux arm64, and macOS arm64 (Go's
|
||||
`darwin/arm64`), including an empty set for source-only projects;
|
||||
- consistent release build flags and asset naming, plus a host-runnable build
|
||||
that checks the executable's reported version; and
|
||||
- Git publication tests using temporary local remotes, including remote
|
||||
advancement, rejected pushes, lost acknowledgments, and unavailable remotes.
|
||||
|
||||
Each repository should retain its product name, compatibility decisions,
|
||||
candidate-specific checks, main package, selected build targets, delivery
|
||||
declaration, and a small test of its ReleaseKit wiring. For example, PromptKit
|
||||
exercises its consumer examples. Applications would adapt their existing
|
||||
version output to use the `buildinfo` accessor; one agreed version command
|
||||
or flag would let ReleaseKit smoke-test a host-runnable build the same way.
|
||||
Cross-built binaries would use the same injection mechanism, but compilation
|
||||
alone would not establish that they run correctly on another platform.
|
||||
ReleaseKit should run the selected checks and builds without silently adding
|
||||
binary gates to source-only projects.
|
||||
|
||||
The build API should own the mechanics rather than require each application to
|
||||
provide a custom linker symbol or shell loop. The initial target list reflects
|
||||
the current projects, not a permanent limit on future platforms. It should
|
||||
support both candidate cross-build checks and artifact builds from the tagged
|
||||
source, using the same version and target selection.
|
||||
|
||||
## Woodpecker and Gitea delivery
|
||||
|
||||
A common tag-triggered Woodpecker workflow can run ReleaseKit against the
|
||||
tagged source. Repository-local YAML should declare the pinned tool image and
|
||||
credentials; each repository's ReleaseKit configuration should declare its
|
||||
delivery destination and any binary main package and target set. ReleaseKit can
|
||||
own version injection, cross-builds, checksum generation, and delivery. All
|
||||
projects should receive hosted Gitea
|
||||
release pages. Source-only repositories declare zero binary assets and deliver
|
||||
the committed release note without a binary build or checksum manifest.
|
||||
|
||||
The shared delivery command should create or find the release for the tag,
|
||||
use the checked-in note, and add declared binary assets and their checksum
|
||||
manifest where applicable. A retry should inspect existing assets, verify
|
||||
matching content, add only missing items, and stop on a conflict.
|
||||
An existing checksum manifest must remain consistent with any later addition.
|
||||
The release and its attachments are separate remote operations, so partial
|
||||
delivery must be expected and reported clearly.
|
||||
|
||||
Audita, Narratio, and Scriptorium currently use the Woodpecker release plugin
|
||||
with `file-exists: skip` and `overwrite: false`. Those settings avoid deliberate
|
||||
replacement by filename, but they do not prove that a rebuilt file has the
|
||||
same bytes as a previously published file. Content comparison would be a
|
||||
reason to implement a shared Gitea delivery client rather than rely solely on
|
||||
the plugin's skip behavior.
|
||||
|
||||
Hosted pages are selected for source-only projects, including PromptKit,
|
||||
ConfigKit, Notarius, and ReleaseKit. Adoption adds a page deliverable and delivery
|
||||
credentials to their procedures while preserving successful tag publication as
|
||||
source completion. The initial implementation should support both page-only and
|
||||
binary delivery through the same facade and command.
|
||||
|
||||
## Failure states
|
||||
|
||||
ReleaseKit should report source publication and artifact delivery separately:
|
||||
|
||||
| Event | Result |
|
||||
| --- | --- |
|
||||
| Candidate validation or a pre-push guard fails | No release was published; correct and validate the candidate again. |
|
||||
| Tag push reports success | Source release is complete; delivery may still be pending. |
|
||||
| Tag push fails or its acknowledgment is lost | Query the authoritative ref once. Confirm success only if the exact intended tag object is present on the intended commit; otherwise report failed or unknown status and retain the local tag. |
|
||||
| Woodpecker or Gitea delivery fails after tag publication | Keep the source release successful. Retry missing delivery from the immutable tag after checking existing content. |
|
||||
| Published source or content needs correction | Publish a new version; never replace content under the published version. |
|
||||
|
||||
## Consumer adoption target
|
||||
|
||||
All six projects should use the same selected publication, runtime version,
|
||||
build, and delivery conventions where those responsibilities apply. Repository
|
||||
entry points should contain only tool invocation and product-specific settings
|
||||
or checks. Shared mechanics and their repeated tests belong in ReleaseKit.
|
||||
|
||||
Application runtime code should obtain version information through `buildinfo`.
|
||||
Source-only libraries need no runtime import or automatic binary deliverable.
|
||||
Projects declaring binaries should use the common target selection and version
|
||||
injection; hosted delivery should use content-aware retries for both page-only
|
||||
and binary releases.
|
||||
Existing published tags, notes, pages, and assets retain their historical contents.
|
||||
|
||||
Consumer policy and procedure changes should describe the deliberately adopted
|
||||
standard and its compatibility impact. Adoption should demonstrate reduced local
|
||||
infrastructure and one coherent release model.
|
||||
- Optional recognizable-credential checks remain an unevaluated suggestion from
|
||||
PromptKit's feature request. Evaluate their detection scope, synthetic-fixture
|
||||
handling, false-positive costs, and maintenance benefit before selecting shared
|
||||
support. The proposal establishes no mandatory credential gate.
|
||||
- ReleaseKit executable binary distribution remains deferred until deliverables
|
||||
are deliberately selected. Selecting binaries would require delivery
|
||||
declarations, target checks, automation responsibilities, and corresponding
|
||||
release policy and procedure updates.
|
||||
- Evaluate a maintained ReleaseKit CI image or specialized validation/build
|
||||
settings when a demonstrated consumer need justifies their maintenance cost
|
||||
under [ADR 0002](../adr/0002-routine-releases.md).
|
||||
|
||||
## Representative migration review
|
||||
|
||||
@@ -226,40 +59,3 @@ The self-contained ReleaseKit fixtures exercise a meaningful source-only
|
||||
compatibility check through local Git publication, and a `buildinfo` binary
|
||||
consumer with selected targets through local HTTP delivery. These are separate
|
||||
publication and delivery operations.
|
||||
|
||||
## Remaining work
|
||||
|
||||
- Use the [v0.1.0 baseline](../releases/v0.1.0.md) for initial consumer
|
||||
integration under the [maintainer procedure](../release.md). Consumers that
|
||||
adopt the maintained tag workflow select ReleaseKit through the tagged
|
||||
source's `go.mod` rather than a separate workflow version value.
|
||||
- Choose the broader consumer integration test plan and migration sequence.
|
||||
Evaluate API clarity, product-specific checks, and the infrastructure removed
|
||||
from each consuming repository.
|
||||
- Provision delivery credentials and activate consumer Woodpecker workflows
|
||||
as part of deployment. The tagged consumer's module configuration selects
|
||||
the ReleaseKit version used by the maintained workflow.
|
||||
- Verify live Gitea delivery and Woodpecker execution. Existing verification uses
|
||||
local Git and HTTP fixtures; no live deployment has been verified.
|
||||
- Keep ReleaseKit executable binary distribution deferred until deliverables
|
||||
are deliberately selected. Selecting binaries would require delivery
|
||||
declarations, target checks, automation responsibilities, and corresponding
|
||||
release policy and procedure updates.
|
||||
- Evaluate a maintained ReleaseKit CI image or specialized validation/build
|
||||
settings when a demonstrated consumer need justifies their maintenance cost
|
||||
under [ADR 0002](../adr/0002-routine-releases.md).
|
||||
|
||||
## Reviewed implementations
|
||||
|
||||
- [PromptKit release script](../../../promptkit/scripts/release.sh),
|
||||
[checker](../../../promptkit/scripts/release-check.sh)
|
||||
- [ConfigKit release script](../../../ConfigKit/scripts/release.sh),
|
||||
[checker](../../../ConfigKit/scripts/release-check.sh)
|
||||
- [Audita release script](../../../audita/scripts/release.sh),
|
||||
[Woodpecker job](../../../audita/.woodpecker/release.yml)
|
||||
- [Notarius release script](../../../notarius/scripts/release.sh),
|
||||
[checker](../../../notarius/scripts/check-release-source.sh)
|
||||
- [Narratio release script](../../../narratio/scripts/release.sh),
|
||||
[Woodpecker job](../../../narratio/.woodpecker/release.yml)
|
||||
- [Scriptorium release script](../../../scriptorium/scripts/release.sh),
|
||||
[Woodpecker job](../../../scriptorium/.woodpecker/release.yml)
|
||||
|
||||
@@ -1,430 +0,0 @@
|
||||
# ReleaseKit implementation remediation
|
||||
|
||||
Status: All nine findings addressed.
|
||||
|
||||
The v0.2.0 review covers committed state `edd670e` and the implementation
|
||||
commits after `89981ab`, against the [implementation plan](implementation.md),
|
||||
[feature roadmap](v0.2.0.md), [model roadmap](model.md), accepted ADRs, and
|
||||
applicable repository policies. Both ReleaseKit and Audita had clean worktrees
|
||||
when inspected. The review changed only this document; the resolutions below
|
||||
record subsequent remediation.
|
||||
|
||||
## Foundation review history
|
||||
|
||||
Reviewed committed implementation `f53354b`, covering the eight foundation
|
||||
commits after `0c7129a`, against the [implementation plan](implementation.md),
|
||||
[model roadmap](model.md), accepted ADRs, and applicable repository policies.
|
||||
The worktree was clean when review began. This document records required fixes;
|
||||
production code was unchanged during the review.
|
||||
|
||||
## Foundation architecture assessment
|
||||
|
||||
The root orchestration facade and independent `buildinfo` runtime facade retain
|
||||
their intended dependency direction. Both candidate operations share request
|
||||
conversion and `internal/candidate.Validate`. Candidate capture, product
|
||||
callbacks, builds, and rechecks retain their owners; `internal/validation` owns
|
||||
the default Go suite, structured failures, and committed-tree inspection.
|
||||
Publication retains endpoint guards, tag operations, and recovery. The CLI
|
||||
shares profile conversion and owns output and exit classification.
|
||||
|
||||
The public error types belong to the root facade, and conversion preserves the
|
||||
underlying error chain. Candidate inventory reads committed entries and blobs,
|
||||
with separate handling for symlinks and gitlinks. Its default validation path
|
||||
does not load that inventory.
|
||||
|
||||
The absent `ValidationSpec`, request/profile selections, optional checkers, CI
|
||||
tooling changes, and expected-endpoint option are intentionally deferred under
|
||||
the agreed incremental rollout. Their absence is consistent with foundation
|
||||
scope. The defects below affect the implemented foundation, including helpers
|
||||
that subsequent checkers will use.
|
||||
|
||||
## 1. P2: Expanding symlink cycles do not terminate or honor cancellation
|
||||
|
||||
**Resolution:** Addressed. The resolver tracks active symlink expansions,
|
||||
releases them before traversing the remaining destination, and checks context
|
||||
cancellation during traversal. Regression coverage includes direct and mutual
|
||||
expanding cycles, finite repeated links, and cancellation.
|
||||
`go test ./internal/validation` passed.
|
||||
|
||||
**Owner:** [candidate destination resolver](../../internal/validation/tree.go),
|
||||
`CandidateTree.ResolveDestination`, especially the restart loop and cycle key.
|
||||
|
||||
The cycle key combines the symlink path with the unresolved suffix. For a
|
||||
committed symlink `loop -> loop/child`, resolving `loop` visits suffixes of
|
||||
increasing length. The key never repeats. Cached link reads do not consult the
|
||||
context, and the resolver loop has no cancellation check. Resolution can keep
|
||||
consuming CPU and memory after cancellation.
|
||||
|
||||
**Evidence:** A temporary overlay test using committed-entry metadata and
|
||||
cached symlink text confirmed that the operation neither returned a cycle
|
||||
classification nor stopped within 150 ms, despite a 20 ms context deadline.
|
||||
Existing tests cover a two-link cycle whose suffix stays constant.
|
||||
|
||||
**Required remediation:** Detect recursive symlink expansion using the active
|
||||
expansion chain and honor context cancellation during traversal. Preserve
|
||||
legitimate finite paths that encounter a symlink again after an earlier
|
||||
expansion has completed. Keep cycle detection separate from any arbitrary
|
||||
hop/path-length limit; such a limit was not requested.
|
||||
|
||||
**Verification:** Add focused cases for direct and mutual expanding cycles,
|
||||
finite repeated symlink traversal, and cancellation. Keep the fixture local
|
||||
and bounded even when testing the broken behavior.
|
||||
|
||||
## 2. P2: Path cleanup changes symlink traversal and checkout classification
|
||||
|
||||
**Resolution:** Addressed. Destination components and symlink targets are
|
||||
traversed in order, with parent traversal applied to resolved directories.
|
||||
Missing entries and regular-file traversal remain observable. Regression tests
|
||||
cover both destination and symlink-target parent components and confirm that
|
||||
neighboring files do not change classification.
|
||||
`go test ./internal/validation` passed.
|
||||
|
||||
**Owner:** [candidate destination resolver](../../internal/validation/tree.go),
|
||||
initial destination construction and construction after symlink expansion.
|
||||
|
||||
`path.Join`/`path.Clean` eliminate `..` components before intervening symlinks
|
||||
are resolved. This changes the destination rather than resolving it. It can
|
||||
also discard a symlink that crosses the checkout boundary.
|
||||
|
||||
**Evidence:** With `docs/link -> ../nested/inner`, resolving
|
||||
`docs/link/../file.md` returns `docs/file.md` instead of `nested/file.md`.
|
||||
With `link -> ../neighbor`, `link/../README.md` is incorrectly classified as
|
||||
the captured root's `README.md`, hiding its outside-checkout destination.
|
||||
Both failures were reproduced with overlay tests. PromptKit's starting
|
||||
convention resolves paths before checking their relation to the checkout.
|
||||
|
||||
**Required remediation:** Walk path components and symlink expansions in order.
|
||||
Apply parent traversal to the resolved directory, retaining missing-file and
|
||||
non-directory observations where traversal encounters them. Derive checkout
|
||||
classification from that traversal, using candidate entries throughout.
|
||||
|
||||
**Verification:** Cover `..` following internal and external symlinks and
|
||||
following missing or regular-file components. Assert resolved identities and
|
||||
boundary classifications independently of neighboring filesystem contents.
|
||||
|
||||
## 3. P2: Committed-file inspection can fetch from a promisor remote
|
||||
|
||||
**Resolution:** Addressed. Candidate tree, size, and blob reads share a local
|
||||
Git command helper that disables lazy fetching and transport access per child
|
||||
process. Missing blobs report local unavailability, and Git process causes
|
||||
remain wrapped. Partial-clone tests cover missing blobs and missing trees,
|
||||
instrument transport attempts, and verify the object database stays unchanged.
|
||||
`go test ./internal/git ./internal/validation` passed.
|
||||
|
||||
**Owner:** [Git source readers](../../internal/git/source.go), `ReadTree`,
|
||||
`populateBlobSizes`, and `ReadBlob`.
|
||||
|
||||
The new readers invoke ordinary Git object-reading commands without suppressing
|
||||
automatic fetching of missing promisor objects. Inspecting a filtered checkout
|
||||
can therefore initiate remote access during the promised offline operation.
|
||||
Successful fetching can also populate the checkout's object database.
|
||||
|
||||
**Evidence:** A local `--filter=blob:none --no-checkout` clone contained commit
|
||||
and tree objects but no blobs. Its promisor URL was replaced with a synthetic
|
||||
SSH destination, and a local SSH stub recorded attempts and exited. Calling
|
||||
`ReadCandidateTree` invoked that stub through `cat-file --batch-check` and
|
||||
returned a promisor-fetch error. No external host was contacted. Ordinary
|
||||
fully populated repository tests do not exercise this behavior.
|
||||
|
||||
**Required remediation:** Make these candidate object reads explicitly local
|
||||
and suppress lazy fetching using a mechanism supported by the applicable Git
|
||||
version. Report unavailable local objects with preserved causes. Keep source
|
||||
preparation and network-capable publication/delivery operations in their
|
||||
existing separate boundaries; a global ban on partial clones is unnecessary.
|
||||
|
||||
**Verification:** Inspect a local filtered-clone fixture with unavailable blobs
|
||||
and an instrumented remote transport. Assert that metadata/content requests
|
||||
fail locally when necessary and never invoke that transport. Retain successful
|
||||
reads from fully populated candidates.
|
||||
|
||||
## 4. P2: Public and CLI error presentation loses diagnostic information
|
||||
|
||||
**Resolution:** Addressed. Public errors use the internal diagnostic formatter
|
||||
with explicit conversions, including findings, targets, directives,
|
||||
measurements, and causes. Matching converted diagnostics reuse their contextual
|
||||
cause's rendering once. The CLI preserves outer wrappers, and callback errors
|
||||
retain their public identity. Regression tests cover both candidate operations
|
||||
and caller-created errors with and without causes.
|
||||
`go test . ./cmd/releasekit ./internal/validation ./internal/apicheck` and
|
||||
`go run ./internal/apicheck` passed.
|
||||
|
||||
**Owners:** [public diagnostics](../../validation_error.go),
|
||||
`ValidationError.Error` and its formatter; [CLI presentation](../../cmd/releasekit/main.go),
|
||||
`candidateFailureText`; [internal formatting](../../internal/validation/diagnostic.go).
|
||||
|
||||
Two branches lose information:
|
||||
|
||||
- A caller-created `ValidationError` with a cause returns only `Cause.Error()`.
|
||||
Its check, findings, and measurement disappear from the textual diagnostic.
|
||||
Converted built-in failures happen to work because their retained internal
|
||||
cause already formats those details.
|
||||
- The CLI extracts an inner `ValidationError` with `errors.As` and formats that
|
||||
inner value. For a callback-supplied public error, this drops the candidate
|
||||
wrapper added by `candidate.Validate`.
|
||||
|
||||
The public and internal formatters also duplicate the finding/measurement
|
||||
formatting procedure, making it easier for their behavior to diverge.
|
||||
|
||||
**Evidence:** A public error with check `go-format`, a `main.go:3` finding, and
|
||||
cause `inspection failed` renders only `inspection failed`. A candidate-wrapped
|
||||
callback diagnostic loses its captured-commit context through
|
||||
`candidateFailureText`. Both failures were reproduced with temporary overlay
|
||||
tests. Existing tests exercise only converted Go-suite failures.
|
||||
|
||||
**Required remediation:** Share diagnostic formatting behind the facade with
|
||||
explicit conversions. Preserve the full contextual chain when presenting an
|
||||
error and include caller-supplied structured detail alongside its cause.
|
||||
Ensure converted built-in failures render once. Retain `errors.Is`/`errors.As`
|
||||
and existing exit/publication classifications.
|
||||
|
||||
**Verification:** Cover public errors with and without causes, callback errors
|
||||
with candidate context, and converted built-in failures. Assert useful fields,
|
||||
cause identity, context, and absence of duplicate diagnostics without fixing
|
||||
complete message wording as a contract.
|
||||
|
||||
## 5. P2: Absolute paths inside the checkout are classified as outside
|
||||
|
||||
**Resolution:** Addressed. Absolute destinations and symlink targets within the
|
||||
captured repository directory map to candidate paths before component
|
||||
traversal. Absolute paths with similar external prefixes remain outside.
|
||||
Regression tests also retain symlink-before-parent semantics and demonstrate
|
||||
that removed committed files resolve while live-only files remain missing.
|
||||
`go test ./internal/validation` passed.
|
||||
|
||||
**Owner:** [candidate destination resolver](../../internal/validation/tree.go),
|
||||
the absolute-destination and absolute-symlink branches.
|
||||
|
||||
Both branches classify every path beginning with `/` as outside the checkout.
|
||||
This substitutes path syntax for the requested checkout boundary. An absolute
|
||||
path naming a file inside the captured repository is also labeled outside by this
|
||||
classification. A later boundary-enforcing checker would consequently apply
|
||||
an additional restriction that the user did not select.
|
||||
|
||||
**Evidence:** For repository directory `/checkout/project` with captured
|
||||
`README.md`, the resolver classifies `/checkout/project/README.md` as
|
||||
outside-checkout. An overlay test confirmed this. PromptKit's starting checker
|
||||
uses resolved containment and accepts an existing absolute destination within
|
||||
its checkout; the user selected that convention as the starting specification.
|
||||
The implementation plan calls for checkout-boundary classification and
|
||||
committed-file access, without establishing an absolute-path prohibition.
|
||||
|
||||
**Required remediation:** Map absolute destinations and symlink targets that
|
||||
name paths within the captured repository directory back to candidate-relative
|
||||
paths, then resolve against committed entries. Classify actual external paths
|
||||
as outside without reading them. A different absolute-path policy requires an
|
||||
explicit scope decision.
|
||||
|
||||
**Verification:** Cover absolute direct destinations and absolute symlinks
|
||||
inside and outside the captured root, including similar root prefixes. Use
|
||||
committed entries for existence; neighboring files remain irrelevant.
|
||||
|
||||
## 6. P3: Future Go command behavior appears in implemented internal documentation
|
||||
|
||||
**Resolution:** Addressed. The internal guide describes current environment
|
||||
reuse and links to the roadmap for proposed command coordination and Markdown
|
||||
behavior. Its implemented executor, candidate-file mechanics, and checker
|
||||
integration guidance remain in place. Local links and fragments were checked.
|
||||
|
||||
**Owner:** [shared validation guide](../internal/validation.md),
|
||||
`Prospective Go command recipe`.
|
||||
|
||||
The section describes race, separate vet, and package-compilation behavior that
|
||||
has not been implemented. Although it is labeled prospective, the
|
||||
[documentation policy](../policy/documentation.md) assigns future behavior to
|
||||
`docs/roadmap/` and limits other documents to their implemented boundary.
|
||||
|
||||
**Required remediation:** Replace the future command recipe with a link to the
|
||||
roadmap's coordination design. Keep the internal guide's implemented executor,
|
||||
environment reuse, candidate-file mechanics, and checker integration procedure.
|
||||
Document exact command behavior in its canonical owners when the capabilities
|
||||
land.
|
||||
|
||||
**Verification:** Review the guide against the current executor and check its
|
||||
links. Preserve the distinction between foundation completion and completed
|
||||
optional features.
|
||||
|
||||
## Foundation review evidence and limits
|
||||
|
||||
- `go test ./...` passed; unchanged packages used cached results.
|
||||
- `go run ./internal/apicheck` passed.
|
||||
- Recent production-code, test, and documentation diffs were inspected. The
|
||||
existing tests protect default execution, callback failure handling, facade
|
||||
error identity, publication state, and representative committed-tree cases.
|
||||
- Temporary Go overlays outside the worktree reproduced the additional cases
|
||||
above against current code. Their expected failures are review evidence,
|
||||
not changes to the committed test suite.
|
||||
- No new universal release gate, public validator-registration framework,
|
||||
consumer-check requirement, or change to publication completion was found.
|
||||
Finding 5 identifies an additional boundary restriction; findings 1–4
|
||||
identify failures to satisfy the intended behavior. Finding 6 concerns
|
||||
documentation ownership.
|
||||
|
||||
This review evaluates the completed foundation. It does not establish that the
|
||||
remaining v0.2.0 features have been implemented or that their eventual checker
|
||||
semantics are verified.
|
||||
|
||||
## v0.2.0 architecture assessment
|
||||
|
||||
The intended package and ownership boundaries are implemented. The root
|
||||
`releasekit` facade owns requests, validation selections, diagnostics, and
|
||||
publication/delivery outcomes. The separate `buildinfo` facade depends on the
|
||||
standard library and `internal/runtimeinfo`; its graph remains independent of
|
||||
orchestration and the new parsing dependencies.
|
||||
|
||||
`Check` and `Publish` use the same request conversion and
|
||||
`internal/candidate.Validate`. `internal/validation` coordinates one native
|
||||
test suite, selected full vet and static package compilation, and selected
|
||||
committed-file checks. Formatting, distribution, file-size, and Markdown checks
|
||||
share candidate inventory and lazy blob access. Goldmark and `x/mod/modfile`
|
||||
remain internal dependencies. Product callbacks, artifact building and version
|
||||
injection, publication guards/recovery, and hosted delivery retain their owners.
|
||||
The expected push URL is compared exactly in publication preflight; local
|
||||
checking ignores it. The CLI owns profile conversion, presentation, and exits.
|
||||
|
||||
The consumer Woodpecker template verifies tagged source before selecting the
|
||||
tool through temporary module metadata. Audita's local wrapper and workflow
|
||||
adopt that approach in commit `17421bc`; the inspected declarations preserve
|
||||
its existing dependency version, image, secret name, and release profile.
|
||||
|
||||
All ten feature areas are present. The review identified three behavior gaps
|
||||
within Markdown validation and self-bootstrap. Finding 8 imposed unrequested
|
||||
existence/boundary checks on image alternative text. Finding 9 effectively
|
||||
required a prepopulated tool module cache. The review found no
|
||||
additional public package, validator-registration framework, universal optional
|
||||
check, arbitrary inspection limit, or change to source-publication completion.
|
||||
|
||||
## 7. P2: Heading anchors omit autolink display text
|
||||
|
||||
**Resolution:** Addressed. Heading extraction includes autolink display labels.
|
||||
Parser coverage includes URL/email headings and surrounding text; committed
|
||||
fragment checks cover both forms. The new cases failed before the fix, and
|
||||
`go test ./internal/validation` passed afterward.
|
||||
|
||||
**Owner:** [Markdown heading extraction](../../internal/validation/markdown.go),
|
||||
`markdownHeadingText`, lines 115–139.
|
||||
|
||||
The agreed convention derives anchors from visible heading text. The extractor
|
||||
handles text and code spans and recurses through formatting nodes, but Goldmark's
|
||||
`ast.AutoLink` stores its visible text in `Label` and has no text children.
|
||||
URL and email autolinks therefore disappear from the heading before slugging.
|
||||
|
||||
**Evidence:** A temporary overlay probe against the current checker used:
|
||||
|
||||
```markdown
|
||||
# <https://example.invalid>
|
||||
[section](#httpsexampleinvalid)
|
||||
```
|
||||
|
||||
The computed anchor was the empty string, and the section link failed with
|
||||
`heading anchor does not exist`. The same failure occurred for a heading
|
||||
`# <maintainer@example.invalid>` and fragment `#maintainerexampleinvalid`.
|
||||
Existing anchor tests cover text, code, formatting, entities, Unicode, and
|
||||
duplicates, while existing autolink coverage only checks URL extraction.
|
||||
|
||||
**Required remediation:** Include an autolink's display label in heading text
|
||||
before applying the existing normalization and duplicate-anchor algorithm.
|
||||
Preserve the current HTML, code-span, and ordinary link-label handling.
|
||||
|
||||
**Verification:** Add parser coverage for URL and email autolinks inside headings,
|
||||
including surrounding text, and a representative committed-fragment check.
|
||||
Keep external destination availability outside this offline capability.
|
||||
|
||||
## 8. P2: Image alternative text creates additional release requirements
|
||||
|
||||
**Resolution:** Addressed. Destination extraction records an image source and
|
||||
skips its alternative-text children. Regression coverage exercises nested
|
||||
images/links, missing anchors, and outside-checkout label syntax under both
|
||||
boundary settings. Real linked images still report missing sources and link
|
||||
targets. The regression failed before the fix, and
|
||||
`go test ./internal/validation` passed afterward.
|
||||
|
||||
**Owner:** [Markdown link extraction](../../internal/validation/markdown.go),
|
||||
`parseMarkdown`, especially the image branch and AST traversal at lines 65–110.
|
||||
|
||||
After recording an image destination, the walker continues through the image's
|
||||
label children and records nested link/image syntax as independent destinations.
|
||||
Those children contribute plain alternative text to the rendered image. The
|
||||
checker consequently requires files and anchors that the document does not
|
||||
navigate to or load, and boundary enforcement can also reject those labels.
|
||||
|
||||
**Evidence:** With only `image.png` committed, this valid Markdown is rejected
|
||||
for missing `missing.png`:
|
||||
|
||||
```markdown
|
||||
](image.png)
|
||||
```
|
||||
|
||||
Goldmark's own renderer produces `<img src="image.png" alt="inner">`.
|
||||
Similarly, `](image.png)` renders an image with alternative
|
||||
text `label`, while ReleaseKit records and validates `missing.md` as a link.
|
||||
Temporary overlay probes confirmed both extraction and rendering; the first
|
||||
case also reproduced the checker failure against committed Git contents.
|
||||
|
||||
**Required remediation:** Record the outer image destination and treat its label
|
||||
as alternative text during destination extraction. Preserve real linked images:
|
||||
`[](guide.md)` has an image source and an enclosing link target
|
||||
that both require validation. This change removes the unintended requirement
|
||||
without narrowing supported Markdown syntax.
|
||||
|
||||
**Verification:** Cover nested image/link syntax in alternative text, including
|
||||
an outside-checkout label destination under boundary enforcement. Verify that
|
||||
real linked images still report missing image sources and missing link targets.
|
||||
|
||||
## 9. P1: ReleaseKit's source-delivery bootstrap fails with an empty module cache
|
||||
|
||||
**Resolution:** Addressed. Self-bootstrap uses normal Go dependency access for
|
||||
its readonly tool build after tag verification. The maintained workflow test
|
||||
starts with an empty module cache and a local HTTP module proxy, builds a tool
|
||||
with an external dependency, and verifies execution, clean tagged source, and
|
||||
temporary-output cleanup. A wrong commit stops before Go or proxy access. The
|
||||
regression failed before the fix and passed afterward. The delivery guide now
|
||||
describes tool dependency access and its separation from offline validation.
|
||||
The uncached offline suite, `go run ./internal/apicheck`, and local documentation
|
||||
link/fragment checks passed after all three fixes.
|
||||
|
||||
**Owners:** [source-delivery workflow](../../examples/woodpecker/releasekit-source-delivery.yml),
|
||||
lines 27–31; [workflow verification](../../cmd/releasekit/woodpecker_test.go),
|
||||
`TestWoodpeckerSourceDeliveryTemplateSelfBootstraps`; and the
|
||||
[delivery guide](../consumers/delivery.md#woodpecker-tag-workflows).
|
||||
|
||||
The source template sets `GOPROXY=off` and `GOSUMDB=off` before building the tool
|
||||
and provides no tool dependency preparation. ReleaseKit now imports Goldmark and
|
||||
`x/mod` through validation, so the standard Go image needs those modules to build
|
||||
`./cmd/releasekit`. On a fresh runner the workflow stops before `ci-deliver` and
|
||||
the hosted note page is never delivered. The previous dependency-free tool did
|
||||
not expose this problem. The guide describes cache mounts as optional, while
|
||||
the current implementation effectively requires a prepopulated module cache.
|
||||
|
||||
**Evidence:** Running the template's build command against `edd670e`, with a
|
||||
temporary empty `GOMODCACHE` and its workspace/toolchain/proxy settings, returned
|
||||
exit 1. Both dependencies reported `module lookup disabled by GOPROXY=off`.
|
||||
The existing self-bootstrap test builds a synthetic command that imports only
|
||||
`fmt` and `os`, so it cannot detect missing tool dependencies.
|
||||
|
||||
**Required remediation:** Allow ordinary tool dependency preparation after tag
|
||||
verification. A network-capable readonly tool build or an explicit preparation
|
||||
step can populate the module cache while preserving tagged source. Honor normal
|
||||
Go proxy/private-module/cache settings. Keep offline candidate validation and
|
||||
application artifact compilation in their existing owners. Update the template
|
||||
and guidance together; a prewarmed cache remains an optional deployment choice.
|
||||
|
||||
**Verification:** Exercise the maintained self-bootstrap commands with an empty
|
||||
module cache and a local module proxy serving a real external tool dependency.
|
||||
Verify preparation follows tag/commit verification, the executable runs, tagged
|
||||
module files remain unchanged, and temporary output is cleaned up. Existing
|
||||
delivery tests retain ownership of hosted page behavior.
|
||||
|
||||
## v0.2.0 review evidence and limits
|
||||
|
||||
- Reviewed recent production, test, template, and documentation changes and
|
||||
their shared request, execution, and dependency boundaries.
|
||||
- `GOPROXY=off GOSUMDB=off GOTOOLCHAIN=local go test -count=1 ./...` passed.
|
||||
- `go run ./internal/apicheck` passed. Direct dependency inspection of
|
||||
`buildinfo` confirmed its standard-library/runtime-only graph.
|
||||
- Inspected Audita commit `17421bc` and its actual local and CI bootstrap files.
|
||||
- Temporary overlay tests outside the worktree reproduced findings 7 and 8.
|
||||
Goldmark's renderer confirmed the alternative-text semantics. A separate
|
||||
temporary empty module cache reproduced finding 9. These probes are review
|
||||
evidence; production code and the committed test suite remain unchanged.
|
||||
- Existing tests passed but omitted these cases at review time. The resolutions
|
||||
above record completed fixes and regression coverage.
|
||||
@@ -1,299 +0,0 @@
|
||||
# ReleaseKit v0.2.0 roadmap
|
||||
|
||||
Status: Implemented and locally verified. Stages 1–15 are complete; see the
|
||||
[implementation plan](implementation.md) for the completion record. Audita's
|
||||
module-selected local and CI integration is committed at `17421bc`. Broader
|
||||
consumer adoption, architecture review, hosted deployment, and release tagging
|
||||
remain separate work.
|
||||
|
||||
This roadmap catalogs improvements to ReleaseKit v0.1.0. Each item records its
|
||||
rationale, target state, and relevant scope decisions. The
|
||||
[implementation plan](implementation.md) owns the staged work and verification
|
||||
evidence.
|
||||
|
||||
The priorities in [ADR 0002](../adr/0002-routine-releases.md) guide this work:
|
||||
minimize application-owned release code, duplicated mechanics, and routine
|
||||
developer decisions through a standard, minimal API.
|
||||
|
||||
## 1. Establish the shared validation API and profile model
|
||||
|
||||
### Rationale and baseline at plan start
|
||||
|
||||
The shared validation foundation and its remediation are complete. ReleaseKit
|
||||
has common candidate execution, facade-owned diagnostics, committed-file
|
||||
inspection, and a product-specific additional-check extension point. The
|
||||
optional v0.2.0 capabilities now have functioning API/profile selections and
|
||||
checker implementations.
|
||||
|
||||
The [validation-model roadmap](model.md) records this enabling work and its
|
||||
rationale. A common model lets consumers declare choices once and receive
|
||||
ReleaseKit's shared execution and coordination.
|
||||
|
||||
### Target end state
|
||||
|
||||
A facade-owned validation specification and corresponding profile object
|
||||
express the agreed optional checks with consistent defaults and behavior.
|
||||
ReleaseKit owns coordination and diagnostics through the existing `Check` and
|
||||
`Publish` operations. Product-specific checks, publication expectations,
|
||||
artifact builds, and delivery retain their distinct responsibilities.
|
||||
|
||||
The implemented API and profile provide equivalent declarations for the
|
||||
validation capabilities below through the existing shared foundation.
|
||||
|
||||
## 2. Use the application's module-selected ReleaseKit version in CI
|
||||
|
||||
### Rationale and baseline at plan start
|
||||
|
||||
At the v0.1.0 planning baseline, the maintained CI template selected ReleaseKit
|
||||
through a separate `RELEASEKIT_VERSION` value and invoked its command with an
|
||||
explicit `@version`.
|
||||
|
||||
Audita demonstrates the resulting duplication: its local release wrapper builds
|
||||
ReleaseKit using the application's module dependencies, while CI independently
|
||||
selects ReleaseKit v0.1.0. A dependency upgrade can leave CI using an older tool.
|
||||
Maintainers must remember to coordinate both declarations.
|
||||
|
||||
Using the application's module-selected version for both paths gives upgrades
|
||||
one dependency declaration and keeps local publication and CI delivery aligned.
|
||||
Stages 12–14 changed the maintained template and Audita's workflow to this
|
||||
approach; the current [adoption guidance](../consumers/delivery.md#woodpecker-tag-workflows)
|
||||
describes it.
|
||||
|
||||
### Target end state
|
||||
|
||||
For applications that declare ReleaseKit as a module dependency, the standard
|
||||
CI integration uses the ReleaseKit version selected by the released source's
|
||||
module configuration. The workflow verifies the triggering tag and commit and
|
||||
checks out that source before resolving and building the release tool.
|
||||
|
||||
Local publication and CI delivery use the same module-based selection approach.
|
||||
Updating the application's ReleaseKit dependency updates both paths. The
|
||||
consumer workflow supplies the CI event, environment, and credentials; the
|
||||
application profile continues to supply product and delivery settings.
|
||||
|
||||
Tool bootstrap and dependency preparation remain distinct from offline
|
||||
validation and builds. Source publication and hosted delivery retain separate
|
||||
outcomes. ReleaseKit's own source bootstrap and consumers using a separately
|
||||
installed tool remain supported use cases.
|
||||
|
||||
Audita adopted the module-based integration as the first consumer migration in
|
||||
commit `17421bc`.
|
||||
|
||||
The maintained template and Audita's first migration now use one ReleaseKit
|
||||
module declaration for local and hosted integration.
|
||||
|
||||
## 3. Select one base test invocation, including race testing
|
||||
|
||||
### Rationale and baseline at plan start
|
||||
|
||||
ReleaseKit always runs its standard offline Go suite before additional product
|
||||
checks. ConfigKit selects race-enabled testing for its release validation.
|
||||
PromptKit requests the same capability for its concurrent execution and
|
||||
backend-capacity management.
|
||||
Expressing that selection as an additional check would execute the suite twice
|
||||
and leave the application coordinating shared validation mechanics.
|
||||
|
||||
A small declarative selection lets consumers retain their chosen validation
|
||||
while ReleaseKit owns the procedure and runs the suite once.
|
||||
|
||||
### Target end state
|
||||
|
||||
The public Go API and profile support selecting race testing for the single
|
||||
base Go test invocation. With no selection, the current default applies.
|
||||
`Check` and `Publish`, including their CLI forms, use the same selection.
|
||||
|
||||
ReleaseKit constructs the invocation and owns candidate capture, full-suite
|
||||
scope, offline execution, ordering, and failure reporting. Additional product
|
||||
checks remain available after shared validation. Selecting race testing reports
|
||||
unavailable prerequisites clearly and preserves the selected validation.
|
||||
|
||||
The API and profile now let ConfigKit and PromptKit select a race-enabled suite
|
||||
once and remove the corresponding consumer-owned test invocation when they
|
||||
adopt the selection.
|
||||
|
||||
## 4. Offer a separate full vet pass
|
||||
|
||||
### Rationale and baseline at plan start
|
||||
|
||||
ConfigKit and PromptKit currently run a full `go vet` pass in addition to their
|
||||
test suites. ReleaseKit relies on test-time vet unless a consumer supplies an
|
||||
additional command. That leaves consumers coordinating vet coverage and
|
||||
repeated work.
|
||||
|
||||
### Target end state
|
||||
|
||||
A public API and profile option selects a separate full vet pass within shared
|
||||
candidate validation. ReleaseKit automatically omits test-time vet when that
|
||||
pass is selected. The base suite runs once, followed by the selected vet pass,
|
||||
with failures reported through the ordinary check and publication flow.
|
||||
|
||||
The option preserves current defaults for consumers that leave it unset.
|
||||
ReleaseKit owns the offline command and its coordination with base testing.
|
||||
|
||||
The API and profile now support replacing ConfigKit's and PromptKit's separate
|
||||
vet commands and manual test-time vet settings with one declarative choice.
|
||||
|
||||
## 5. Verify package compilation for selected targets
|
||||
|
||||
### Rationale and baseline at plan start
|
||||
|
||||
ReleaseKit's existing build declaration selects executable artifacts and their
|
||||
delivery. ConfigKit is a source-only library that checks package compilation
|
||||
for Linux amd64 and arm64. Its current release script owns the cross-target
|
||||
build loop even though the underlying mechanics are shared across consumers.
|
||||
|
||||
### Target end state
|
||||
|
||||
The public API and profile can declare optional package-compilation targets
|
||||
independently of executable artifacts. ReleaseKit compiles the module's packages
|
||||
for those targets within candidate validation, after the selected test and vet
|
||||
work. `Check` and `Publish` share this behavior and report compilation failures
|
||||
through their existing outcomes.
|
||||
|
||||
Package compilation uses the existing pure-Go build baseline (`CGO_ENABLED=0`).
|
||||
|
||||
A source-only library retains page-only delivery. Package-compilation checks
|
||||
require no binary name, version smoke command, or artifact manifest. Successful
|
||||
compilation establishes build compatibility; execution on a target remains a
|
||||
separate concern. Consumers select targets for their support commitments.
|
||||
|
||||
The API and profile now let ConfigKit declare its two Linux targets and remove
|
||||
its release-specific compilation loop when it adopts the selection.
|
||||
|
||||
## 6. Check an optional expected publication endpoint
|
||||
|
||||
### Rationale and baseline at plan start
|
||||
|
||||
ReleaseKit resolves and captures the selected remote's push endpoint and
|
||||
rechecks it during publication. ConfigKit additionally declares an expected
|
||||
authoritative destination in its release script. Retaining that expectation
|
||||
outside ReleaseKit would duplicate destination-resolution work.
|
||||
|
||||
### Target end state
|
||||
|
||||
An optional public API and profile setting declares the expected publication
|
||||
destination. `Publish` compares it exactly with the effective push URL resolved
|
||||
by Git before candidate validation and publication. A mismatch produces a clear
|
||||
failure.
|
||||
The existing captured-endpoint, recheck, and recovery machinery continues to
|
||||
govern the operation.
|
||||
|
||||
The expectation applies to the publication destination. Fetch configuration
|
||||
retains its existing semantics, and `Check` retains its local-only behavior.
|
||||
Consumers that omit the expectation keep the current remote-selection model.
|
||||
|
||||
Consumers can now declare the intended push destination without maintaining
|
||||
their own publication preflight logic.
|
||||
|
||||
## 7. Offer Go formatting validation
|
||||
|
||||
### Rationale and baseline at plan start
|
||||
|
||||
PromptKit maintains a shell loop that enumerates tracked Go files and checks
|
||||
their formatting. ReleaseKit currently leaves this generic mechanism to
|
||||
consumer-owned additional checks. Shared support would remove that script
|
||||
fragment and provide consistent diagnostics across applications.
|
||||
|
||||
### Target end state
|
||||
|
||||
An optional public API and profile selection enables formatting validation for
|
||||
tracked Go source using ordinary `gofmt` conventions. `Check` and `Publish`,
|
||||
including their CLI forms, apply the same check within candidate validation.
|
||||
The check runs offline, reports affected paths, and leaves files unchanged.
|
||||
|
||||
Consumers select the capability once and rely on ReleaseKit for enumeration,
|
||||
format checking, and failure reporting. Existing validation defaults remain
|
||||
unchanged when the option is unset.
|
||||
|
||||
PromptKit can now remove its local formatting loop and select the shared check
|
||||
through its release profile when it adopts the capability.
|
||||
|
||||
## 8. Offer offline Markdown-link validation
|
||||
|
||||
### Rationale and baseline at plan start
|
||||
|
||||
PromptKit's largest generic validation block is a local Markdown-link checker.
|
||||
It owns parsing, destination resolution, heading anchors, and diagnostics.
|
||||
ReleaseKit currently leaves these mechanics to consumer-owned additional checks.
|
||||
|
||||
Sharing the check would remove a locally maintained parser and give consumers
|
||||
one documented convention for validating navigation within their documentation.
|
||||
Consumers that require documentation to remain within the checkout also need
|
||||
a shared option to enforce that boundary.
|
||||
|
||||
### Target end state
|
||||
|
||||
An optional public API and profile selection checks tracked Markdown documents
|
||||
for local destinations and supported heading fragments within the checkout.
|
||||
`Check` and `Publish`, including their CLI forms, use the same offline,
|
||||
read-only validation and report the source file, location, and target of each
|
||||
problem.
|
||||
|
||||
ReleaseKit owns a documented link and heading-anchor convention that consumers
|
||||
can follow, using PromptKit's current conventions as the starting specification.
|
||||
The supported behavior accounts for common inline and reference links, code
|
||||
examples, escaped destinations, and duplicate headings. External
|
||||
website availability is outside the check's scope.
|
||||
|
||||
By default, links outside the checkout are classified and reported as outside
|
||||
the shared check's scope. An optional setting makes local destinations outside
|
||||
the checkout a validation failure, using the same parser and diagnostics.
|
||||
Boundary validation remains independent of neighboring checkout contents.
|
||||
Existing validation defaults remain unchanged when the option is unset.
|
||||
|
||||
PromptKit can now replace its local Markdown checker with a profile selection
|
||||
and rely on shared parsing rules and diagnostics when it adopts the capability.
|
||||
|
||||
## 9. Offer module-distribution checks
|
||||
|
||||
### Rationale and baseline at plan start
|
||||
|
||||
PromptKit checks that released source is independent of neighboring checkouts
|
||||
by excluding committed workspace files and local filesystem module replacements.
|
||||
ReleaseKit's offline Go environment controls validation execution; inspecting
|
||||
the distributed candidate requires separate checks that consumers currently own.
|
||||
|
||||
Shared inspection would remove these local checks and provide consistent
|
||||
diagnostics for consumers with the same distribution requirements.
|
||||
|
||||
### Target end state
|
||||
|
||||
The public API and profile offer independently selectable rules for committed
|
||||
workspace files (`go.work` and `go.work.sum`) and local filesystem replacements
|
||||
in committed module declarations. Each selected rule reports offending paths
|
||||
and, where applicable, module directives through shared candidate validation.
|
||||
|
||||
The replacement rule permits versioned module replacements. Workspace use and
|
||||
vendoring retain their existing behavior unless affected by a selected rule.
|
||||
The checks inspect candidate contents independently of the Go test environment.
|
||||
`Check` and `Publish`, including their CLI forms, apply the same offline,
|
||||
read-only checks. Omitted selections preserve current defaults.
|
||||
|
||||
PromptKit can now declare its distribution requirements and remove the
|
||||
corresponding consumer-owned checks when it adopts the selections.
|
||||
|
||||
## 10. Offer an individual-file-size check
|
||||
|
||||
### Rationale and baseline at plan start
|
||||
|
||||
Unintentionally committed binaries and large assets can increase the size of
|
||||
released source. ReleaseKit currently leaves file-size inspection to consumers.
|
||||
A shared check would catch oversized files while allowing each consumer to
|
||||
declare its intended size limit and exceptions.
|
||||
|
||||
### Target end state
|
||||
|
||||
An optional public API and profile selection checks individual tracked files
|
||||
in the current candidate. When enabled, the default limit is 1 MB (1,000,000
|
||||
bytes); consumers can configure the limit and explicit repository-relative
|
||||
path exclusions for intentional large files. A file exceeding the limit fails
|
||||
validation with its path, observed size, and configured limit.
|
||||
|
||||
The check measures file size. Small binaries remain subject to ordinary review.
|
||||
Its scope is the current candidate's files; historical objects and aggregate
|
||||
repository size remain separate concerns. `Check` and `Publish`, including
|
||||
their CLI forms, use the same offline, read-only inspection. The check is
|
||||
disabled by default.
|
||||
|
||||
Consumers can now catch oversized candidate files through a small declaration
|
||||
and remove corresponding local inspection code when they adopt the check.
|
||||
Reference in New Issue
Block a user