Remove completed module release roadmaps and review notes
This commit is contained in:
@@ -1,158 +0,0 @@
|
||||
# CommandKit feature request: publish individual modules in a shared repository
|
||||
|
||||
Status: requested upstream capability; not an implemented ReleaseKit contract.
|
||||
|
||||
## Consumer context
|
||||
|
||||
CommandKit uses ReleaseKit v0.3.0 for source-only publication. CommandKit is
|
||||
still an unreleased prototype and is preparing to separate its core from
|
||||
optional integrations into three independently versioned Go modules:
|
||||
|
||||
| Repository directory | Module path | Illustrative version | Corresponding Git tag |
|
||||
| --- | --- | --- | --- |
|
||||
| Root | `gitea.maximumdirect.net/eric/CommandKit` | `v0.1.0` | `v0.1.0` |
|
||||
| `integrations/ckconfig` | `gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig` | `v0.2.0` | `integrations/ckconfig/v0.2.0` |
|
||||
| `integrations/ckprompt` | `gitea.maximumdirect.net/eric/CommandKit/integrations/ckprompt` | `v0.1.0` | `integrations/ckprompt/v0.1.0` |
|
||||
|
||||
These versions illustrate independent numbering; they are not selected initial
|
||||
release versions. Integration versions will describe their own changes rather
|
||||
than matching either CommandKit core or upstream library versions.
|
||||
|
||||
The dependency direction is `ckprompt` toward `ckconfig` and core, and
|
||||
`ckconfig` toward core. Consumers should acquire only their selected integrations
|
||||
and their dependencies. Each integration therefore needs its own module files,
|
||||
validation, release notes, and publication identity. More integration modules may
|
||||
follow without requiring a new publication mechanism for each one.
|
||||
|
||||
Go requires repository-subdirectory prefixes on nested module version tags.
|
||||
The semantic module version remains `vMAJOR.MINOR.PATCH`; the complete Git tag
|
||||
additionally identifies the module directory. See the
|
||||
[Go module reference](https://go.dev/ref/mod#vcs-version).
|
||||
|
||||
## Issue with the current publication contract
|
||||
|
||||
ReleaseKit's documented [CLI](../cli.md), [profile](../config.md), and
|
||||
[publication API](../consumers/publish.md) assume one release version/tag and
|
||||
one standard Go suite. Release notes use repository-root
|
||||
`docs/releases/<version>.md`, and publication accepts stable
|
||||
`vMAJOR.MINOR.PATCH` rather than a nested module's prefixed tag.
|
||||
|
||||
Changing the product name or choosing another profile does not provide a
|
||||
separate module directory, semantic version, and Git tag identity. Running the
|
||||
root module's suite also does not validate packages belonging to nested modules.
|
||||
|
||||
CommandKit would otherwise need to implement its own integration publication
|
||||
path, duplicating functionality already owned by ReleaseKit. We would prefer
|
||||
ReleaseKit to support selecting one Go module within the shared repository.
|
||||
|
||||
## Requested feature
|
||||
|
||||
Support checking and publishing one explicitly selected module per invocation,
|
||||
through the public library API and native CLI/profile interface. The request is
|
||||
about observable behavior; ReleaseKit should select its own internal design.
|
||||
|
||||
### Repository and module selection
|
||||
|
||||
- Distinguish the Git repository from the selected module's directory within it.
|
||||
- Keep repository state, candidate commit, branch, remote, and publication guards
|
||||
scoped to the shared repository.
|
||||
- Execute the standard Go validation suite in the selected module. Its tests,
|
||||
and any selected module-specific vet or package compilation, should operate on
|
||||
that module rather than implicitly validating only the repository-root module.
|
||||
- Preserve ordinary root-module publication when no nested module is selected.
|
||||
- Permit a shared repository launcher to choose small per-module profiles without
|
||||
requiring separate Git repositories or duplicated publication logic.
|
||||
|
||||
### Version and tag identity
|
||||
|
||||
- Accept the selected module's semantic version separately from its repository
|
||||
subdirectory, deriving the corresponding Go module tag from those inputs.
|
||||
- Use the complete tag for uniqueness checks, tag creation, publication, and
|
||||
failed or ambiguous publication recovery.
|
||||
- Make both module version and complete tag identifiable in public results and
|
||||
CLI output, alongside the candidate commit and existing publication evidence.
|
||||
- Allow modules to publish different versions and to release individually.
|
||||
Equal semantic versions in different modules identify different tags.
|
||||
|
||||
No arbitrary tag-template language is needed by CommandKit. Standard Go module
|
||||
tag conventions meet its requirements.
|
||||
|
||||
### Release notes
|
||||
|
||||
Support a distinct committed note for each module release, even when two modules
|
||||
use the same semantic version. CommandKit's preferred layout is module-local
|
||||
`docs/releases/<version>.md`, for example:
|
||||
|
||||
```text
|
||||
docs/releases/v0.1.0.md
|
||||
integrations/ckconfig/docs/releases/v0.2.0.md
|
||||
integrations/ckprompt/docs/releases/v0.1.0.md
|
||||
```
|
||||
|
||||
Validate the selected note against its product and semantic version in the
|
||||
captured candidate. The complete tag remains the immutable source identity for
|
||||
note links, licensing links, and publication recovery. A documented explicit
|
||||
note-path setting would also be acceptable if module-local discovery is not the
|
||||
selected public design.
|
||||
|
||||
Document how module version, complete tag, note title, and note location relate;
|
||||
align affected release-policy language with the selected conventions rather than
|
||||
treating the current single-module note path as an obstacle.
|
||||
|
||||
### Validation and completion
|
||||
|
||||
Run the selected module's standard suite once for the publication candidate,
|
||||
retaining ReleaseKit's offline validation and existing publication outcome model.
|
||||
Additional product checks may cover CommandKit-specific composition or dependency
|
||||
boundaries without repeating the selected standard suite.
|
||||
|
||||
CommandKit will prepare dependencies before offline validation. Its published
|
||||
modules will require actual released dependency versions; local workspace
|
||||
composition is useful during development but does not establish ordinary consumer
|
||||
resolution. For releases requiring new sibling versions, CommandKit can publish
|
||||
core, then `ckconfig`, then `ckprompt`, preparing each candidate as needed.
|
||||
|
||||
Successful source-tag publication should remain the completion point. This
|
||||
request does not add CI polling, hosted release pages, artifact delivery, module
|
||||
proxy availability, or consumer installation as publication completion gates.
|
||||
|
||||
## Illustrative consumer interface
|
||||
|
||||
Conceptually, a request would supply:
|
||||
|
||||
```text
|
||||
Repository: /work/CommandKit
|
||||
Module directory: integrations/ckconfig
|
||||
Product: CommandKit ConfigKit integration
|
||||
Module version: v0.2.0
|
||||
```
|
||||
|
||||
ReleaseKit would select that module's suite and committed note, and publish
|
||||
`integrations/ckconfig/v0.2.0` for the captured repository candidate. Exact Go
|
||||
field names, CLI options, and profile syntax remain ReleaseKit design choices.
|
||||
CommandKit could then expose a small convenience launcher such as
|
||||
`./scripts/release ckconfig v0.2.0`; that is illustrative consumer syntax, not a
|
||||
request for ReleaseKit to hard-code CommandKit's module names.
|
||||
|
||||
## Acceptance scenarios
|
||||
|
||||
1. Publish the root module using ordinary unprefixed tags and existing defaults.
|
||||
2. Publish either nested integration with its Go-required prefixed tag and its
|
||||
own committed note, without publishing unrelated module tags.
|
||||
3. Identify validation failures from the selected nested module and prevent its
|
||||
publication, even if the root suite would pass.
|
||||
4. Publish two modules using the same semantic version without note or tag
|
||||
collisions; preserve existing guards against reusing a published full tag.
|
||||
5. Report the complete selected tag in known-failure or unresolved-publication
|
||||
results so recovery addresses the exact destination and tag object.
|
||||
|
||||
## Follow-up possibilities
|
||||
|
||||
Publishing an explicit set of independently versioned modules in one operation
|
||||
could later reduce repeated repository checks and support coordinated releases.
|
||||
Batch or atomic multi-tag publication is not needed for this initial request.
|
||||
Neither are automatic module discovery, dependency-driven version selection,
|
||||
matching version numbers, or a generic release-orchestration framework.
|
||||
|
||||
CommandKit can adopt single-module selection first and revisit release sets when
|
||||
concrete maintenance needs justify them.
|
||||
@@ -1,797 +0,0 @@
|
||||
# Implementation plan: individual Go module releases
|
||||
|
||||
Status: complete; all 15 stages implemented and locally verified.
|
||||
|
||||
The subsequent [remediation review](remediation.md) records post-implementation
|
||||
findings, corrections, and their verification. The baseline and stage accounts
|
||||
below retain the implementation sequence.
|
||||
|
||||
## Objective and authority
|
||||
|
||||
Implement the complete target in the [module-release roadmap](module-releases.md),
|
||||
including its resolved decisions, and [ADR 0005](../adr/0005-module-release-scope.md).
|
||||
The [CommandKit request](commandkit-feature-request.md) supplies consumer context.
|
||||
The implementation covers checking, publication, standalone and composite builds,
|
||||
prebuilt receipts, hosted delivery, CLI profiles, launchers, and Woodpecker.
|
||||
|
||||
This document is an ordered implementation guide for a Luna coding agent.
|
||||
Complete Stage 1 through Stage 15 in order. Each stage is a focused implementation
|
||||
unit with its own behavioral verification. Intermediate stages represent partial
|
||||
implementation; completion means that all stages are complete. Proceed through
|
||||
the plan without pilot integrations, intermediate releases, external actions, or
|
||||
human review gates. Architecture review and subsequent adoption testing follow
|
||||
completion of this plan.
|
||||
|
||||
Read [development](../development.md) and the applicable policies before working.
|
||||
Use the codebase graph for code discovery and inspect the current source before
|
||||
editing. Follow the [agent policy](../policy/agents.md) for scoped commits after
|
||||
completed nonempty units. Record completion under each stage with a short account
|
||||
of the change and verification. Keep behavior documentation aligned as each
|
||||
capability lands; the feature roadmap owns the desired scope and policy choices.
|
||||
|
||||
## Baseline and implementation boundaries
|
||||
|
||||
The starting point is the v0.3.0 implementation with accepted module-release
|
||||
decisions. Current entry points are the root facade's `Check`, `Publish`, `Build`,
|
||||
`Deliver`, `PrepareTaggedCheckout`, and `PrepareBuildDependencies`.
|
||||
|
||||
| Current owner | Change needed |
|
||||
| --- | --- |
|
||||
| `check.go`, `publish.go`, `build.go`, `delivery.go`, `preparation.go` | Facade-owned selection and evidence types, explicit conversions. |
|
||||
| `internal/candidate`, `internal/publish` | Committed module identity, module-local notes, full-tag publication and recovery. |
|
||||
| `internal/validation` | One selected input set, full repository reference lookup, selected-module Go execution. |
|
||||
| `internal/git`, `internal/preparation` | Literal full-tag operations and shared tagged-source verification. |
|
||||
| `internal/gotool`, `internal/build`, `internal/artifact` | Operation-local Go settings, normalized build settings, module-based execution and output. |
|
||||
| `internal/delivery`, `internal/gitea` | Committed delivery identity, module-bound artifacts, full-tag hosted identity. |
|
||||
| `cmd/releasekit`, `cmd/releasekit/internal/cli` | Profile mapping, command context, receipts, CI event handling. |
|
||||
| `examples/woodpecker/`, consumer guides | Root defaults and module-selected bootstrap from tagged source. |
|
||||
| `internal/apicheck` | Compiled facade ownership and dependency checks for the current API. |
|
||||
|
||||
Keep implementation behind the existing facades. `buildinfo` keeps its small
|
||||
independent runtime dependency graph. Use the existing pure-Go build baseline,
|
||||
standard version injection, target rules, error causes, publication outcomes,
|
||||
and delivery recovery behavior. Network-capable preparation remains separate
|
||||
from offline validation and compilation.
|
||||
|
||||
The feature is a clean API and receipt cutover. Update callers and fixtures to
|
||||
the current interface directly. Migration is documentation for the next release.
|
||||
Implement individual module releases without batch publication, automatic module
|
||||
discovery, dependency ordering, arbitrary tag templates, or compatibility shims.
|
||||
|
||||
## Concrete interface and ownership choices
|
||||
|
||||
These choices settle routine design details needed to execute the stages. GoDoc
|
||||
and canonical references become their owners when the corresponding code lands.
|
||||
|
||||
### Selection and evidence
|
||||
|
||||
- Add `ModuleDir string` to `ReleaseRequest`, `BuildRequest`, and
|
||||
`DeliveryRequest`. Input values are repository-relative; omission or `.` selects
|
||||
the repository-root module. Keep `Version` as the stable semantic version.
|
||||
- Add `ModuleDir`, `ModulePath`, and `Tag` to `Candidate`, `PublicationResult`,
|
||||
`BuildResult`, and `DeliveryResult`. Result `ModuleDir` is the resolved absolute
|
||||
execution directory; `ModulePath` is the declared import path; `Tag` is the
|
||||
complete derived Git tag. Retain existing repository, commit, and outcome
|
||||
fields, adding `RepositoryDir` to results that currently lack it.
|
||||
- Use one private identity value in `internal/releaseidentity`, containing the
|
||||
absolute repository and module directories, canonical repository-relative
|
||||
module subdirectory, declared module path, semantic version, complete tag, and
|
||||
repository-relative note path. Source commit remains captured operation
|
||||
evidence. Facades own their exported types and explicitly convert this value.
|
||||
- Add `SharedFiles []string` to `ValidationSpec`. Profile syntax is
|
||||
`validation.shared_files`; profile module selection is top-level `module_dir`.
|
||||
Preserve nil versus non-nil empty slices through all conversions and JSON
|
||||
round trips. Existing `--config` selects the profile; the initial CLI adds no
|
||||
separate module override.
|
||||
- Change `PrepareBuildDependencies` to accept a facade-owned
|
||||
`DependencyPreparationRequest` containing `RepositoryDir` and `ModuleDir`.
|
||||
Preparation selects the working-tree module directory and performs the
|
||||
existing network-capable preparation there. It needs no release version or tag.
|
||||
- Replace `TaggedCheckoutRequest.Version` with `Tag`. Add `VerifyOnly bool`:
|
||||
the default prepares the checkout, while `true` performs read-only verification
|
||||
of an already prepared checkout against `Tag` and `ExpectedCommit`.
|
||||
- Add optional `DeliveryRequest.ExpectedTag` for the CI event's literal tag.
|
||||
Delivery compares it with the resolved tag before builds or hosted requests.
|
||||
Ordinary callers omit it. The field expresses exact event identity.
|
||||
|
||||
Identity derivation is shared; operation prerequisites remain with their owners.
|
||||
Check and publication read declarations from the captured commit. Delivery reads
|
||||
committed declarations from its source checkout and verifies the derived tag.
|
||||
Standalone builds read working-tree declarations. Composite builds receive the
|
||||
owner's already resolved identity. Populate evidence as it becomes available,
|
||||
including on errors; an unresolved field remains unset.
|
||||
|
||||
### CLI events, receipts, and consumer mapping
|
||||
|
||||
- `check`, `publish`, `build`, and ordinary `deliver` continue to accept a
|
||||
semantic `VERSION`. `ci-deliver` accepts a complete `TAG`; its last path
|
||||
component supplies the semantic version and its full value supplies
|
||||
`ExpectedTag`. The selected profile supplies the physical module directory.
|
||||
- Add `ci-deliver --prepared` to select `VerifyOnly`. The maintained workflows
|
||||
use it after bootstrap's verified checkout. Standalone `ci-deliver` retains
|
||||
checkout preparation by default. Both paths require `--commit` and perform
|
||||
fresh read-only tag, HEAD, cleanliness, and expected-commit checks.
|
||||
- Add optional `--expected-module DIR` to `publish` and `ci-deliver` for mapped
|
||||
launchers. Compare its normalized repository-relative selection with the
|
||||
profile's selection before application work. This equality expectation binds
|
||||
the bootstrap module to the profile; module selection still comes from the
|
||||
profile. Root-only invocations omit it.
|
||||
- Keep `.releasekit-build.json` as the private receipt filename. The new schema
|
||||
requires `schema_version: 1`, absolute `module_dir`, declared `module_path`,
|
||||
and complete `tag`, alongside the existing fields. The current unversioned
|
||||
receipt is rejected with regeneration guidance. Implement one schema reader.
|
||||
- For the maintained multi-module example, use a small committed
|
||||
`release-modules.tsv` shared by the launcher and CI. Each row contains four
|
||||
tab-separated fields: selector, event-tag shell pattern, repository-relative
|
||||
physical module directory, repository-relative profile path. Use `.` for root.
|
||||
A shared POSIX shell helper reads the table for either a selector or an event
|
||||
tag. An event must match exactly one row; ambiguity is a selection error.
|
||||
Tag patterns select a row; the library remains the authority for tag derivation.
|
||||
The maintained example owns this integration declaration.
|
||||
Root-only consumers continue without a mapping file or helper.
|
||||
|
||||
For example, root v0/v1 and root `v2` directory layouts can use separate rows
|
||||
with patterns `v[01].*` and `v2.*`. A nested `/v2` module can map
|
||||
`integrations/ckconfig/v2.*` to either physical layout. Keep patterns quoted and
|
||||
evaluate them as shell patterns without `eval`. Document the table's literal
|
||||
tab-separated syntax. No matching pattern changes the derived release tag.
|
||||
|
||||
## Stage 1: Implement shared identity derivation and literal tag operations
|
||||
|
||||
**Outcome:** One internal owner derives release identity for both source modes;
|
||||
Git primitives accept full tag names independently of semantic-version rules.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Introduce `internal/releaseidentity` with a selection resolver and shared pure
|
||||
derivation. Resolve module paths once from repository-relative input, with
|
||||
ordinary normalization and a final location inside the repository. Keep root
|
||||
defaults. Require the selected module's own declaration; do not silently
|
||||
fall back to an ancestor module or require a repository-root `go.mod` for a
|
||||
nested selection.
|
||||
2. Provide committed and working-tree declaration readers. Reuse existing Git
|
||||
committed-file and reference resolution where needed. Preserve cause and
|
||||
cancellation handling. Do not fetch module metadata or infer identity from
|
||||
the remote host, a root module declaration, or a directory-name registry.
|
||||
3. Extract the module directive with the existing `modfile.ModulePath` helper
|
||||
and apply `module.SplitPathVersion`/`module.CheckPathMajor`. Full `go.mod`
|
||||
inspection retains its selected validation owner. Retain stable-version
|
||||
syntax and use the shared module-path major-version rules.
|
||||
Derive the tag prefix from the physical repository-relative directory,
|
||||
removing a final physical major-version component only when it equals the
|
||||
declaration's slash major suffix. Distinguish a normal directory named `v2`
|
||||
from a physical `/v2` layout using the declaration. Retain standard special
|
||||
path-major handling supplied by `x/mod`.
|
||||
4. Derive `<module>/docs/releases/<version>.md` from the physical directory,
|
||||
including a physical major-version directory. Keep tag prefix and note path
|
||||
as distinct values. The
|
||||
[Go module reference](https://go.dev/ref/mod#vcs-version) and
|
||||
[path-major helpers](https://pkg.go.dev/golang.org/x/mod/module#CheckPathMajor)
|
||||
define the relevant Go rules.
|
||||
5. Replace Git's version-shaped tag validation with literal tag-reference
|
||||
validation using Git's reference rules. Rename parameters and internal
|
||||
fields that actually represent tags. Preserve exact ref/object operations,
|
||||
supported tag object types, and repository-state checks. Semantic-version
|
||||
validation stays at release identity boundaries.
|
||||
|
||||
**Verification:** Owner tests cover root, nested, root physical `v2`, nested
|
||||
physical `v2`, `/v2` declarations without physical major directories, a normal
|
||||
directory named `v2`, incompatible version majors, normalized selection, missing
|
||||
or malformed declarations, and selection outside the repository. Test committed
|
||||
versus working-tree readers and full slash-containing Git refs. Update synthetic
|
||||
fixtures that need genuine module declarations. Run affected package tests.
|
||||
|
||||
**Completed:** Added shared committed and working-tree module identity derivation,
|
||||
module-local note paths, and literal Git tag-reference validation. Verified root,
|
||||
nested, physical-major, and ordinary `v2` layouts, committed versus working-tree
|
||||
declarations, and slash-containing local and remote tag operations. `go test ./...`
|
||||
passes.
|
||||
|
||||
## Stage 2: Carry identity through facade types and candidate capture
|
||||
|
||||
**Outcome:** Candidate capture supplies module-local notes and recoverable identity
|
||||
through the public facade.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Add the selection and evidence fields specified above to facade-owned types
|
||||
and their internal counterparts. Use focused conversion helpers where they
|
||||
remove repeated evidence construction. Preserve `errors.Is`/`errors.As`
|
||||
behavior and existing callback signatures using facade-owned `Candidate`.
|
||||
2. In `internal/candidate.Capture`, capture repository state and commit, resolve
|
||||
committed identity once, then read the selected module's committed note and
|
||||
apply existing product/version title validation. Use the full tag for the
|
||||
local unused-tag guard.
|
||||
3. Return progressively populated candidate evidence when later capture,
|
||||
validation, or recheck work fails. Update the public `Check` conversion so
|
||||
it preserves returned evidence alongside the error instead of replacing it
|
||||
with an empty candidate.
|
||||
4. Pass identity through candidate validation and post-validation callbacks.
|
||||
Keep clean `main`, repository-wide status, capture/recheck behavior, and note
|
||||
bytes with their current owners. Prepare internal request wiring for later
|
||||
validation and build stages without adding alternate legacy paths.
|
||||
5. Update compiled API checks and fixtures for the chosen facade declarations.
|
||||
Keep internal identity types out of exported signatures and fields.
|
||||
|
||||
**Verification:** Root notes retain their path and title. A nested candidate uses
|
||||
its own note, including a physical major directory. Note/title/tag conflicts and
|
||||
later validation failures retain available module, version, tag, and commit
|
||||
evidence. An unrelated sibling worktree change still fails the repository guard.
|
||||
Run candidate/facade tests and `go run ./internal/apicheck`.
|
||||
|
||||
**Completed:** Added module selection and identity evidence to the facade and
|
||||
internal request/result types. Candidate capture now reads the selected
|
||||
committed declaration and module-local note, guards the complete local tag, and
|
||||
preserves available evidence through callbacks and later failures. Verified
|
||||
nested physical-major capture, sibling cleanliness, facade error evidence,
|
||||
`go test . ./internal/candidate`, and `go run ./internal/apicheck`.
|
||||
|
||||
## Stage 3: Publish and reconcile the complete selected tag
|
||||
|
||||
**Outcome:** Publication addresses one module's exact tag and retains its current
|
||||
known-failure, confirmed, and unknown outcomes.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Thread captured identity through `internal/publish`; use `Tag` for remote
|
||||
uniqueness, annotated-tag creation, exact-object push, and reconciliation.
|
||||
Continue using `Version` for product/version messages where it is semantic.
|
||||
2. Preserve the authoritative endpoint, expected push URL comparison, remote
|
||||
branch/commit guards, local rechecks, bounded reconciliation, and tag object
|
||||
evidence. These checks verify state against the captured identity and do not
|
||||
invoke identity derivation again.
|
||||
3. Populate `PublicationResult` identity before later failures and preserve it
|
||||
through facade conversions. Recovery output identifies the full tag and
|
||||
authoritative endpoint rather than constructing a ref from the version.
|
||||
|
||||
**Verification:** Publish two modules with the same version at the same captured
|
||||
commit to a temporary local remote; only their separate intended tags appear.
|
||||
Reject reuse of the full tag. Add representative nested-tag rejected-push and
|
||||
unknown-outcome evidence cases. Reuse existing endpoint and lost-acknowledgment
|
||||
tests for unchanged recovery mechanics. Run publication and Git tests.
|
||||
|
||||
**Completed:** Publication now uses the captured full tag for remote uniqueness,
|
||||
local annotated-tag creation, exact-object push, and reconciliation. Recovery
|
||||
errors identify the full tag and authoritative endpoint, while publication
|
||||
results retain identity through preflight and later failures. Verified two
|
||||
modules publishing the same version at one commit, full-tag reuse rejection,
|
||||
nested rejected and unknown outcomes, and `go test . ./internal/git ./internal/publish`.
|
||||
|
||||
## Stage 4: Construct the selected committed file inputs
|
||||
|
||||
**Outcome:** One ordered path set defines automatic validation inputs, while the
|
||||
full committed repository remains available for reference lookup.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Add scope selection beside `CandidateTree` metadata handling. Select entries
|
||||
beneath the module directory, excluding descendants belonging to nested
|
||||
committed `go.mod` boundaries. Boundary detection uses locations and does
|
||||
not parse unrelated declarations. Treat vendored contents as selected-module
|
||||
material; vendored `go.mod` entries do not establish exclusion boundaries.
|
||||
2. Preserve the complete repository index and committed resolver separately.
|
||||
Add a selected-input view used by checks; avoid replacing the complete tree
|
||||
with a filtered map that breaks cross-module links or committed symlinks.
|
||||
3. Resolve `SharedFiles` once against committed entries. Apply the roadmap's
|
||||
optional defaults, replacement list, explicit empty list, missing-explicit
|
||||
errors, and explicit cross-module file selection. Literal paths identify
|
||||
individual files; metacharacters have no selection semantics. Retain existing
|
||||
symlink/reference behavior where applicable.
|
||||
4. Merge selected module entries and shared files in stable repository-path
|
||||
order, deduplicating by committed path. Preserve per-path context when
|
||||
different paths share a blob. A referenced destination joins the input set
|
||||
only through independent module or explicit-file selection.
|
||||
5. Create inputs only when enabled file checks or explicit shared-file validation
|
||||
require them. An explicit missing file fails even with all file checks off;
|
||||
a default-only request with no file checks needs no file-input construction.
|
||||
Keep lazy blob access, operation context, cancellation, and reader cleanup.
|
||||
|
||||
**Verification:** Scope tests cover root and nested modules, independent sibling
|
||||
and nested fixture modules, vendor inclusion, optional defaults, replacement,
|
||||
empty, missing explicit, duplicates, and selected files in another module.
|
||||
Use committed files rather than worktree presence. Show that full lookup still
|
||||
resolves an excluded module's destination. Metadata-only selection starts no
|
||||
batch content reader. Run validation tree/scope tests.
|
||||
|
||||
**Completed:** Added a sorted, deduplicated committed input view for the selected
|
||||
module and explicit shared files while retaining full-tree reference lookup.
|
||||
Nested module boundaries exclude their descendants, vendored modules remain
|
||||
included, and shared-file defaults, replacement, empty selection, and missing
|
||||
committed files follow the roadmap. Verified root and nested scopes, worktree-only
|
||||
file rejection, cross-module references, lazy content reads, `go test ./internal/validation ./internal/candidate .`,
|
||||
and `go run ./internal/apicheck`.
|
||||
|
||||
## Stage 5: Apply selected inputs to every optional file check
|
||||
|
||||
**Outcome:** Formatting, workspace, local replacement, file-size, and Markdown
|
||||
checks use the same selected inputs with their existing individual rules.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Update checker iteration to consume the selected-input view from Stage 4.
|
||||
Retain the full repository resolver for targeted source and destination reads.
|
||||
An unrelated sibling declaration or root workspace file outside a nested
|
||||
module's inputs does not independently fail that module's check.
|
||||
2. Translate module-relative file-size exclusions once into canonical
|
||||
repository-relative paths before checker execution. Preserve existing literal
|
||||
file/directory exclusion matching, limits, findings, and check order.
|
||||
3. Retain formatter selection, symlink treatment, committed replacement
|
||||
inspection, Markdown syntax and fragment rules, boundary observations,
|
||||
source locations, cause propagation, and the existing per-blob caches.
|
||||
Diagnostics remain repository-relative; Markdown links remain relative to
|
||||
each source document.
|
||||
4. Keep content-reader cleanup attributed to the last check that actually read
|
||||
content. Do not reintroduce full raw-content retention or per-check tree
|
||||
scans merely to carry module scope.
|
||||
5. Give explicit shared-file selection errors a public validation identity
|
||||
`shared-files`, with the selected repository-relative path and cause. Add its
|
||||
facade conversion and CLI presentation through the existing failure model.
|
||||
Shared-file selection itself enables no content check.
|
||||
|
||||
**Verification:** Place real violations inside and outside selection and show
|
||||
that only in-scope inputs fail each selected checker. Cover shared files under
|
||||
enabled checks, module-relative exclusions, and a cross-module Markdown heading
|
||||
read that leaves unrelated destination documents unchecked. Equal Markdown blobs
|
||||
at different paths keep distinct relative-link findings. Confirm selection
|
||||
errors with content checks disabled and preserve cancellation/cleanup regressions.
|
||||
Run affected validation and facade tests.
|
||||
|
||||
**Completed:** Formatting, workspace, local-replacement, file-size, and Markdown
|
||||
checks now iterate the selected committed inputs. Targeted reads still resolve
|
||||
against the full repository tree. File-size exclusions are translated from the
|
||||
selected module to repository-relative paths, and shared-file failures preserve
|
||||
their public check, path, and cause. Updated file-size guidance and verified
|
||||
in-scope and out-of-scope findings, shared inputs, cross-module anchors, reader
|
||||
cleanup, facade conversion, `go test ./internal/validation .`, and
|
||||
`go run ./internal/apicheck`.
|
||||
|
||||
## Stage 6: Execute Go validation in the module with reusable local settings
|
||||
|
||||
**Outcome:** One selected standard suite runs in the module, and later composite
|
||||
builds can reuse its effective Go environment.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Change validation Go command directories to resolved `ModuleDir`. Preserve
|
||||
offline, readonly, workspace-disabled behavior and selected race, full vet,
|
||||
target compilation, output, and command ordering.
|
||||
2. Introduce a small operation-local lazy Go-tool owner alongside the existing
|
||||
`gotool.Tool`. Candidate validation and subsequent build callbacks share it;
|
||||
delivery and standalone builds own separate instances. It acquires settings
|
||||
only when a Go command needs them.
|
||||
3. Reuse the discovered tool while effective environment inputs are unchanged.
|
||||
Retain a snapshot of inherited environment and the persistent Go settings
|
||||
source used for discovery; after consumer callbacks, compare those inputs
|
||||
and rediscover if they changed. Use simple value/file comparisons within
|
||||
this owner. Keep preparation's network-capable settings separate. Introduce
|
||||
neither a public session object nor a process-global tool cache.
|
||||
4. Pass the private owner through internal candidate/build coordination. Preserve
|
||||
repository-wide state rechecks and the single shared validation invocation.
|
||||
|
||||
**Verification:** A failing nested test suite prevents its release while root
|
||||
tests pass. An unrelated sibling failing suite does not run. Selected vet and
|
||||
compile targets use the same module and existing baseline. Observe one standard
|
||||
suite and reused discovery in an unchanged validation/build operation; changing
|
||||
environment inputs through an additional callback triggers fresh settings.
|
||||
Run Go-tool, validation, and candidate coordination tests.
|
||||
|
||||
**Completed:** Go validation commands now run from the captured module
|
||||
directory. Candidate checks and publication share a lazy operation-local Go
|
||||
settings owner with their later build callbacks; standalone and managed delivery
|
||||
builds acquire separate owners. The owner reuses discovery while the inherited
|
||||
environment and selected `GOENV` file stay unchanged, and refreshes after
|
||||
consumer callbacks when either changes. Nested-module fixtures now include
|
||||
packages for selected-module validation. Verified one suite and shared discovery
|
||||
through candidate build coordination, environment and persistent-file refresh,
|
||||
nested-suite failure and sibling isolation, selected vet/compile command
|
||||
directories and compile baseline, `go test ./...`, and
|
||||
`go run ./internal/apicheck`.
|
||||
|
||||
## Stage 7: Build the selected module and bind output evidence
|
||||
|
||||
**Outcome:** Standalone and composite builds use the correct declaration source,
|
||||
version injection, path base, and identity.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Make public standalone `Build` resolve working-tree identity once, then call
|
||||
an internal build path that consumes resolved identity. Candidate and managed
|
||||
delivery builds call that path with committed identity and their Go-tool
|
||||
owner. They do not call standalone resolution as a nested operation.
|
||||
2. Consolidate normalized build settings in `internal/artifact`, including main
|
||||
package, binary name, and normalized target pairs. Reuse this representation
|
||||
for execution, evidence, later receipt binding, and settings comparisons.
|
||||
Preserve supported target and artifact-name rules.
|
||||
3. Build main packages from `ModuleDir`; resolve relative ordinary output there,
|
||||
with default `<module>/dist`. Keep absolute output usable. Candidate and
|
||||
managed delivery output, including disposable native smoke output, stays
|
||||
outside the entire repository through the existing temporary-directory owner.
|
||||
4. Use semantic `Version` for linker injection, filenames, and exact native
|
||||
version checks. Populate build identity before later errors and retain partial
|
||||
artifacts, produced-byte digests, compiler evidence, and source observations.
|
||||
An empty target set performs no compiler or Go-environment discovery.
|
||||
5. Preserve standalone modified-source support and existing `SourceVerified`
|
||||
observations. A build does not require a note, unused tag, clean `main`, or
|
||||
publication. Delivery still requires verified committed tagged source.
|
||||
|
||||
**Verification:** Build and run a nested native consumer using `buildinfo` and
|
||||
cross-compile one supported second target. Filenames and output contain the
|
||||
semantic version and retain ordinary filename components. Cover dirty declaration
|
||||
changes and a new uncommitted module directory for standalone builds, committed
|
||||
identity for composites, empty targets, and partial failures. Confirm temporary output is
|
||||
outside the repository even with a nested selection and source-local `TMPDIR`.
|
||||
Run build and runtime-boundary tests.
|
||||
|
||||
**Completed:** Standalone builds now resolve working-tree module identity once;
|
||||
candidate and managed delivery builds consume their committed identity and Go
|
||||
tool owner through the resolved build path. Normalized build settings are shared
|
||||
by execution and delivery evidence. Builds run from `ModuleDir`, use module-based
|
||||
output paths, and keep temporary native smoke output outside the repository.
|
||||
Verified nested native version output, a second cross target, dirty declarations,
|
||||
new uncommitted nested modules, empty targets, temporary-output fallback and
|
||||
cleanup, full `go test ./...`, `go run ./internal/apicheck`, and `git diff --check`.
|
||||
|
||||
## Stage 8: Deliver module-local notes and assets to full-tag pages
|
||||
|
||||
**Outcome:** Page-only, managed-build, and API prebuilt delivery share committed
|
||||
module identity and existing recovery behavior.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Capture checkout commit and resolve committed identity once in delivery;
|
||||
inspect the derived literal tag against that checkout. Compare optional
|
||||
`ExpectedTag`. Keep historical lightweight tags, detached checkouts, clean
|
||||
source, and the existing post-build source recheck.
|
||||
2. Read and validate the module-local committed note. Populate delivery evidence
|
||||
as resolution progresses, including build and hosted failures. Use Stage 7's
|
||||
resolved build path for managed builds.
|
||||
3. Bind prebuilt results to repository, module directory, declared module path,
|
||||
version, tag, commit, and existing artifact/settings evidence. Require
|
||||
`SourceVerified` for binary delivery and preserve caller ownership of files.
|
||||
4. Give Gitea requests a distinct full-tag field; stop applying stable-version
|
||||
syntax to that field. Use the literal tag for hosted tag lookup, release
|
||||
lookup/create, and conflicts. Titles remain from the version-bearing note.
|
||||
Encode tags at HTTP/source-route owners and verify escaped slash behavior.
|
||||
5. Preserve one local digest-and-size verification before hosted requests,
|
||||
deterministic manifests, remote exact comparisons, additive retries, and
|
||||
existing failure states. Page-only delivery performs no application build,
|
||||
Go environment discovery, application download, receipt, or manifest work.
|
||||
|
||||
**Verification:** Local HTTP fixtures receive correctly encoded nested tags and
|
||||
their semantic-version note titles. Two module tags at one commit create
|
||||
separate pages. Cover nested managed builds and reject an API prebuilt result
|
||||
for another module before hosted requests. Reuse established tampering, conflict,
|
||||
partial/unknown, historical-tag, and cleanup tests. Run delivery/Gitea tests.
|
||||
|
||||
**Completed:** Delivery now captures checkout identity once, derives the
|
||||
selected module's committed tag and note path, compares an optional expected
|
||||
full tag, and returns module evidence through local and hosted failures. Managed
|
||||
and prebuilt binary results bind to the same repository, module, version, tag,
|
||||
commit, settings, and source verification; the CLI carries that identity through
|
||||
its existing private receipt. Gitea uses the literal full tag and escapes
|
||||
slashes in hosted routes. Verified two module pages at one commit, nested notes
|
||||
and slash tags, mismatched expected tags and prebuilt identities, preserved
|
||||
delivery recovery cases, `go test ./...`, `go run ./internal/apicheck`, and
|
||||
`git diff --check`.
|
||||
|
||||
## Stage 9: Replace receipts with the module-bound schema
|
||||
|
||||
**Outcome:** CLI prebuilt delivery uses one current receipt format and one
|
||||
delivery-owned content verification pass.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Implement the schema specified above in CLI receipt read/write and public
|
||||
build conversions. Keep the existing private filename and write/partial-build
|
||||
lifecycle. Require all identity fields, even for a root build.
|
||||
2. Validate the schema version, field structure, source identity relationships,
|
||||
normalized settings, artifact declarations, and receipt/output location.
|
||||
Check internal tag/module/version consistency through shared pure derivation
|
||||
using recorded identity, without resolving a new operation's source.
|
||||
3. Reject old/unversioned or unknown-schema receipts with guidance to regenerate
|
||||
through the updated build command. Do not migrate or accept their old shape.
|
||||
4. Remove artifact content hashing from receipt loading and adjacent prebuilt
|
||||
declaration/comparison work. Loading validates declared paths and digests;
|
||||
Stage 8 delivery verifies actual bytes and sizes before any hosted request.
|
||||
Build-time hashing records produced bytes independently.
|
||||
5. Reuse normalized settings in profile-to-receipt comparisons. Keep structural
|
||||
validation distinct from source verification and actual asset verification.
|
||||
|
||||
**Verification:** Round-trip a root and nested receipt. Reject old schema,
|
||||
malformed identity, and mismatched module or settings. A loaded receipt with
|
||||
changed or missing artifact bytes fails during delivery before hosted requests.
|
||||
Protect verification ownership through an observable read boundary rather than
|
||||
tests tied to private helper choreography. Run receipt and CLI prebuilt tests.
|
||||
|
||||
**Completed:** Replaced the unversioned receipt with schema version 1 and pure
|
||||
recorded-identity checks for module path, physical directory, version, and full
|
||||
tag. Receipt loading now validates structure and normalized settings without
|
||||
opening artifacts; delivery remains responsible for verifying artifact bytes
|
||||
and sizes before hosted requests. Old and unknown schemas require regeneration.
|
||||
Verified root and nested receipts, malformed identity and settings, changed and
|
||||
missing artifacts, `go test ./...`, `go run ./internal/apicheck`, and
|
||||
`git diff --check`.
|
||||
|
||||
## Stage 10: Map profiles and product commands to module operations
|
||||
|
||||
**Outcome:** Local check, publication, and build commands express the new API with
|
||||
small profiles and module context.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Add strict profile decoding and mapping for `module_dir` and
|
||||
`validation.shared_files`. Omission/null versus explicit empty selections
|
||||
survive loading, copying, serialization, and facade mapping. Do not use
|
||||
`omitempty` serialization that collapses explicit empty shared-file lists.
|
||||
2. Keep profile lookup relative to the repository, including `--config`, and
|
||||
pass module-relative owned paths to the common normalization boundary. Avoid
|
||||
resolving identity a second time in CLI mapping.
|
||||
3. Run configured product commands with `Candidate.ModuleDir` as CWD. Keep
|
||||
existing version/commit context and add `RELEASEKIT_REPOSITORY_DIR`,
|
||||
`RELEASEKIT_MODULE_DIR`, `RELEASEKIT_MODULE_PATH`, and `RELEASEKIT_TAG`.
|
||||
Supply captured context without modifying the parent process environment.
|
||||
4. Update check/publication/build diagnostics and recovery text to identify module,
|
||||
semantic version, and full tag as available. Preserve existing native exit
|
||||
classifications and presentation of underlying validation failures.
|
||||
Implement `publish --expected-module` as a profile-selection comparison using
|
||||
the shared path normalization, without another declaration resolution.
|
||||
5. Apply the dependency preparation request cutover and its facade conversions.
|
||||
Preparation resolves selection without release-note or publication prerequisites.
|
||||
|
||||
**Verification:** CLI profiles select root/nested API requests; explicit empty
|
||||
lists survive round trips. Product commands observe module CWD and both contexts.
|
||||
Relative profile lookup remains repository-based and build output module-based.
|
||||
Missing explicit files fail without enabling checks. Verify nested failure
|
||||
diagnostics and retain a minimal root profile with no new required fields.
|
||||
Run CLI profile, command, preparation, and compiled API checks.
|
||||
|
||||
**Completed:** Profiles now map `module_dir` and `validation.shared_files`,
|
||||
preserving nil versus explicit empty selections through JSON and facade copies.
|
||||
Candidate commands run from the selected module with repository, module, path,
|
||||
version, commit, and full-tag context. `publish --expected-module` compares
|
||||
normalized profile selection before callbacks, and delivery/build map the profile
|
||||
module through their facades. Dependency preparation now accepts a
|
||||
repository/module request and runs in that module. Verified nested CLI checks and
|
||||
build selection, explicit missing shared files, mismatch rejection before
|
||||
product commands, module-targeted preparation, `go test ./...`,
|
||||
`go run ./internal/apicheck`, and documentation whitespace checks.
|
||||
|
||||
## Stage 11: Implement full-tag CI delivery and prepared-checkout verification
|
||||
|
||||
**Outcome:** The CLI can prepare a complete event tag or reuse a verified
|
||||
bootstrap checkout, then deliver the selected module.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Update `ci-deliver` parsing to accept full `TAG`, required expected commit,
|
||||
and optional `--prepared`. Validate literal ref syntax and stable terminal
|
||||
version separately; ordinary commands still accept semantic versions.
|
||||
2. Implement `TaggedCheckoutRequest.Tag` and `VerifyOnly` in preparation. Share
|
||||
read-only verification between both modes; default preparation fetches the
|
||||
exact tag and detaches its expected commit, then verifies. Verify-only checks
|
||||
matching tag, HEAD, clean repository, and expected commit without fetch or
|
||||
checkout. Preserve default remote selection and existing failure causes.
|
||||
3. Load the profile from the prepared source using repository-based path rules.
|
||||
Compare optional `--expected-module` with its normalized selection before
|
||||
application dependency preparation; mismatch is a profile-selection error.
|
||||
Pass its module selection, parsed semantic version, and event `ExpectedTag`
|
||||
into delivery. Delivery owns committed identity resolution and exact mapping
|
||||
verification. Keep ordinary `deliver` free of checkout/download preparation.
|
||||
4. Prepare application dependencies in the selected module only for binary
|
||||
profiles. Continue reading delivery credentials only for delivery; preparation
|
||||
and configuration failures retain their existing CLI classifications.
|
||||
5. Update prebuilt CLI delivery to compare the new receipt and normalized profile
|
||||
settings, then delegate actual source/asset validation to the facade.
|
||||
|
||||
**Verification:** Standalone CI delivery prepares a nested event tag. Prepared
|
||||
mode succeeds offline without repeat fetch or checkout and rejects wrong commit,
|
||||
dirty source, missing/moved tag, and inconsistent profile module. Verify detached
|
||||
historical delivery, module-targeted dependencies for binaries, and page-only
|
||||
application-preparation omission. Run preparation and CLI delivery tests.
|
||||
|
||||
**Completed:** CI delivery now accepts literal full tags and derives the stable
|
||||
semantic version from the final path component. Tagged checkout preparation
|
||||
shares read-only tag, HEAD, expected-commit, and cleanliness verification with
|
||||
the offline `--prepared` mode. CI profiles load from that checkout, optional
|
||||
`--expected-module` is compared before application dependency preparation, and
|
||||
the event tag is passed through delivery for exact identity checks. Binary
|
||||
dependency preparation remains module-targeted and page-only profiles skip it.
|
||||
Verified nested tag preparation, prepared CLI delivery without a remote, wrong
|
||||
commit and dirty/missing/moved tag rejection, profile parsing, full `go test
|
||||
./...`, `go run ./internal/apicheck`, and `git diff --check`.
|
||||
|
||||
## Stage 12: Preserve the small root-module workflow
|
||||
|
||||
**Outcome:** Existing root-only consumers retain a small launcher, profile, and
|
||||
module-selected CI bootstrap under the current interface.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Update `examples/woodpecker/tag-delivery.yml` and the self-bootstrap source
|
||||
example to use prepared CI delivery after exact event checkout verification.
|
||||
Keep root module files and default root profile selection.
|
||||
2. Retain temporary alternate module metadata outside the repository, tagged-source
|
||||
tool selection, workspace/toolchain controls, compatible Go image selection,
|
||||
and credential handling. Tool bootstrap's network access remains separate
|
||||
from offline application compilation.
|
||||
3. Keep ReleaseKit's own `scripts/release`, root profile, and maintainer procedure
|
||||
consistent where affected. Root consumers need no module map, extra required
|
||||
configuration, or additional routine decisions.
|
||||
4. Update root workflow tests for the receipt/API cutover and prepared mode.
|
||||
Reuse existing synthetic tool modules and isolated module cache helpers.
|
||||
|
||||
**Verification:** Execute the root launcher/API/profile representative flows and
|
||||
both maintained root workflow harnesses. Bootstrap and retry select tooling from
|
||||
the original tagged module after the default branch changes. Confirm subsequent
|
||||
delivery performs read-only checks without repeating checkout preparation.
|
||||
Use local remotes/proxies and temporary `GOMODCACHE`, never live CI or credentials.
|
||||
|
||||
**Completed:** Both maintained root Woodpecker templates now verify and detach
|
||||
the exact event tag before invoking `ci-deliver --prepared`, so delivery repeats
|
||||
the source checks without fetching or changing checkout state. Updated workflow
|
||||
tests assert the prepared flag while retaining local proxy coverage for the
|
||||
tagged ReleaseKit selection, self-bootstrap, retry behavior, and source-only and
|
||||
binary delivery. Verified the root profile and compiled API boundaries, the
|
||||
maintained workflow harnesses, `go test ./...`, and `git diff --check`.
|
||||
|
||||
## Stage 13: Add a shared multi-module declaration and local launcher example
|
||||
|
||||
**Outcome:** Consumers select modules through small declarations with one maintained
|
||||
helper shared by local release commands and CI.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Add `examples/multi-module/` with root and integration profiles, the specified
|
||||
TSV mapping, and POSIX shell selection helper. Include a physical-major
|
||||
directory selection to demonstrate the distinction between module and tag.
|
||||
2. Have the helper select by local selector or full event tag and return the
|
||||
physical directory/profile. Share parsing and selection rather than copying
|
||||
cases into separate launcher and workflow code. Keep unknown selectors and
|
||||
ambiguous events as configuration errors.
|
||||
3. Add a small shared launcher that chooses the row, bootstraps the tool from the
|
||||
selected module's local configuration using temporary alternate module files,
|
||||
and invokes publication with repository context, `--config`,
|
||||
`--expected-module`, and semantic version. Module selection comes from the
|
||||
profile; the expectation verifies table/profile agreement. The library
|
||||
validates derived release identity.
|
||||
4. Supply dependency preparation guidance before offline checks and illustrative
|
||||
sequential core/integration publication when a sibling version must exist.
|
||||
The launcher does not infer dependency order or repeat the standard suite.
|
||||
|
||||
**Verification:** Run selection and launcher harnesses with local temporary
|
||||
repositories and isolated dependency proxies. Cover root/nested selection,
|
||||
physical-major mapping, unknown/ambiguous selection, quoted paths, and profile
|
||||
agreement. Verify the selected module supplies the tool dependency and publication
|
||||
receives its semantic version/profile. Shell patterns never become arbitrary
|
||||
library tag templates. Update example guidance with the implemented format.
|
||||
|
||||
**Completed:** Added the multi-module profiles, four-column tab-separated
|
||||
mapping, shared POSIX selector, and launcher. The mapping covers root and
|
||||
nested integration tags plus a physical `/v2` module layout. The launcher
|
||||
copies selected module metadata outside the checkout, builds the ReleaseKit
|
||||
version selected by that module, and passes the mapped profile and
|
||||
`--expected-module` to publication. Guidance covers per-module dependency
|
||||
preparation and sequential releases where a sibling dependency is required.
|
||||
Verified selector and ambiguity behavior, unknown selections, paths with
|
||||
spaces, the physical-major row, and an isolated local-proxy launcher run that
|
||||
proved the selected module's tool version and publication arguments. Also
|
||||
passed `sh -n`, `go test ./...`, `go run ./internal/apicheck`, and
|
||||
`git diff --check`.
|
||||
|
||||
## Stage 14: Bootstrap and deliver mapped module tags in Woodpecker
|
||||
|
||||
**Outcome:** A maintained multi-module workflow uses the same declaration and
|
||||
tagged module selection for local publication, delivery, and retries.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Add a multi-module Woodpecker example under `examples/multi-module/`, with tag
|
||||
filters for its root and nested selections. Keep the simpler root template.
|
||||
2. Verify the literal event tag and peeled event commit, detach and check clean
|
||||
source, then load the mapping/helper from that verified checkout. Select the
|
||||
physical module and profile before tool bootstrap. Do not derive physical
|
||||
module location merely by removing the final tag component.
|
||||
3. Copy the selected module's `go.mod`/`go.sum` to temporary bootstrap metadata
|
||||
outside the whole checkout; run bootstrap from that module. Build the
|
||||
ReleaseKit dependency chosen there, then invoke `ci-deliver --prepared` with
|
||||
repository, selected profile, expected physical module, expected commit, and
|
||||
full event tag.
|
||||
4. Exercise page-only and binary declarations through the same workflow. Keep
|
||||
source verification, dependency preparation, and credential handling with
|
||||
their established owners. A retry reads the triggering release's mapping,
|
||||
profile, module files, and selected tool rather than the default branch.
|
||||
|
||||
**Verification:** Workflow harnesses cover nested source-only and binary delivery,
|
||||
root fallback in the separate simple template, and both physical layouts of a
|
||||
major-version module. Change default-branch mapping and tool versions after a
|
||||
tag and verify retry still uses its original selection. Fail inconsistent mapping
|
||||
through the library's exact tag check. Isolate every synthetic dependency consumer
|
||||
with test-owned `GOMODCACHE`; use local HTTP fixtures and local Git remotes.
|
||||
|
||||
**Completed:** Added the multi-module Woodpecker workflow with full root and
|
||||
nested tag filters, exact peeled-tag commit verification, and selection from the
|
||||
verified checkout. Bootstrap uses the mapped physical module's committed Go
|
||||
metadata and profile, then invokes prepared CI delivery with the expected module,
|
||||
commit, and full tag. Added the binary core v2 example and documented committed
|
||||
module checksums for clean binary delivery. Workflow harnesses cover nested
|
||||
page-only and binary delivery, physical and virtual `/v2` module layouts, a retry
|
||||
after default-branch mapping and tool changes, and an inconsistent mapping
|
||||
rejected by exact event-tag validation. Tests use local Git remotes, local HTTP
|
||||
delivery fixtures, a local module proxy, and test-owned `GOMODCACHE`. Verified
|
||||
`go test ./...`, `go run ./internal/apicheck`, shell syntax, and `git diff --check`.
|
||||
|
||||
## Stage 15: Complete consumer documentation and verify the whole cutover
|
||||
|
||||
**Outcome:** The supported interface, examples, migration guidance, and behavioral
|
||||
evidence describe the complete implemented feature.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Update GoDoc, [CLI](../cli.md), [configuration](../config.md),
|
||||
[consumer guides](../consumers/), [Gitea integration](../integrations/gitea.md),
|
||||
internal owner documents, examples, and recovery guidance at their canonical
|
||||
owners. Explain module selection, semantic version versus full tag, declared
|
||||
versus physical module identity, note/source/license links, path bases,
|
||||
boundaries, shared-file semantics, preparation, and receipt ownership.
|
||||
2. Write the next release's pending notes and migration guidance.
|
||||
A release version is not selected by this feature;
|
||||
keep the draft under roadmap ownership until release preparation assigns its
|
||||
`docs/releases/<version>.md` destination. Include API/profile updates, the
|
||||
preparation signature and tag field changes, receipt regeneration, CI mapping
|
||||
and prepared mode, and root-module exclusion of nested fixture module files.
|
||||
Keep immutable historical release notes intact.
|
||||
3. Verify ReleaseKit's own root-module release procedure still satisfies its
|
||||
adopted policy. Consumer guidance explains module-local note adaptation;
|
||||
this feature does not change the source-push completion point or introduce
|
||||
live-service adoption/release gates. Correct stale baseline facts in owner
|
||||
documents touched by the feature, including the declared Go minimum.
|
||||
4. Audit the acceptance coverage below. Add only missing representative assembled
|
||||
flows or owner-level cases with a concrete remaining risk. Reuse existing
|
||||
recovery, cancellation, HTTP conflict, and facade-boundary tests; avoid a
|
||||
Cartesian product of every module layout, check, target, and failure.
|
||||
5. Run the normal offline `go test ./...` suite and
|
||||
`go run ./internal/apicheck` from the repository root. Validate affected local
|
||||
documentation links/fragments and examples, and run `git diff --check`.
|
||||
Record the final results and feature completion in the roadmap/plan, then
|
||||
commit the completed unit. Completion is the implementation and local
|
||||
evidence; tagging, deployment, live CI, and consumer rollout remain later work.
|
||||
|
||||
**Verification:** Match every acceptance row to concrete test or review evidence,
|
||||
record the full-suite and compiled API check results, and confirm that the
|
||||
implemented examples and canonical documentation agree with the current API.
|
||||
|
||||
**Completed:** Updated facade GoDoc, consumer and CLI/configuration guidance,
|
||||
Gitea and internal ownership documents, recovery guidance, and maintained
|
||||
examples for module selection, full tags, path bases, shared files, preparation,
|
||||
and receipt ownership. Added pending next-release notes with migration guidance
|
||||
and corrected the current Go minimum facts. Release preparation promoted those
|
||||
notes to [the v0.4.0 release note](../releases/v0.4.0.md).
|
||||
Audited acceptance coverage against
|
||||
the stage-owned tests and reviewed ReleaseKit's root release procedure against
|
||||
the adopted release policy; no new release gates were added. Verified
|
||||
`go test ./...`, `go run ./internal/apicheck`, local links and heading fragments
|
||||
in 13 changed Markdown documents, multi-module shell/config/module syntax, and
|
||||
`git diff --check`.
|
||||
|
||||
### Acceptance coverage audit
|
||||
|
||||
| Requirement | Primary stage/evidence owner |
|
||||
| --- | --- |
|
||||
| One resolution per operation, committed versus working-tree declarations, major layouts, version/tag distinction | Stages 1, 2, 7; identity tests and composite coordination. |
|
||||
| Root defaults, own-module declaration, no root declaration required for nested selection | Stages 1, 2, 12; resolver and representative root/nested workflows. |
|
||||
| Module-local notes; equal versions at one commit; only intended tag; full-tag reuse and recovery | Stages 2, 3; candidate/publication local Git fixtures. |
|
||||
| Repository-wide guards and progressive failure evidence | Stages 2, 3, 8; facade conversion and operation failure tests. |
|
||||
| One selected Go suite, vet/compile/module CWD, offline environment reuse | Stage 6; validation and Go-tool tests. |
|
||||
| Nested boundaries, fixtures, vendor, shared defaults/replacement/empty, committed presence, missing explicit files without checks | Stages 4, 5, 10; scope, checker, and profile round-trip tests. |
|
||||
| Path deduplication, equal-blob contextual findings, cross-module lookup without expanded inputs, module-relative exclusions | Stages 4, 5; selected-view and reference tests. |
|
||||
| Existing selective caches, reader cancellation and cleanup attribution | Stages 4, 5; retained regression coverage. |
|
||||
| Semantic binary versions, module output paths, temporary output outside the whole repository, empty/partial builds | Stage 7; real native consumer and cross-compilation evidence. |
|
||||
| New-only receipt schema and module/settings/source binding; one local delivery content pass | Stages 8, 9, 11; receipt/prebuilt/tamper fixtures. |
|
||||
| Distinct hosted pages, slash tags and source links, page-only and binary delivery, unchanged partial/retry outcomes | Stage 8; HTTP fixtures and retained recovery tests. |
|
||||
| Repository/profile versus module path bases; both product-command contexts; simple root configuration | Stages 10, 12; command/profile/root workflow tests. |
|
||||
| Exact event checkout, prepared read-only reuse, physical-major mapping, tagged-source retries and tool selection | Stages 11–14; preparation and workflow harnesses. |
|
||||
| Facade ownership, independent `buildinfo`, documentation and migration guidance, complete offline suite | Stages 2, 7, 10, 15; compiled API checks and final review. |
|
||||
|
||||
No required product decisions remain open. The interface choices above provide
|
||||
the starting specification; local implementation details may evolve within the
|
||||
feature roadmap and repository policies.
|
||||
@@ -1,335 +0,0 @@
|
||||
# Roadmap: release individual Go modules
|
||||
|
||||
Status: implemented; post-implementation findings and corrections are recorded
|
||||
in the [remediation review](remediation.md). Release version remains unselected.
|
||||
|
||||
## Purpose
|
||||
|
||||
Implement [ADR 0005](../adr/0005-module-release-scope.md) so a consumer can check,
|
||||
publish, build, and deliver one selected Go module in a shared repository through
|
||||
ReleaseKit's API and CLI. CommandKit's core and optional integrations provide the initial
|
||||
consumer case. Each invocation should require only module selection, product
|
||||
settings, and a semantic version, with ReleaseKit owning the common mechanics.
|
||||
|
||||
This roadmap records the feature's target and resolved scope and ownership
|
||||
decisions. The [implementation plan](implementation.md) records the completed
|
||||
stages; [remediation](remediation.md) records review corrections. Current behavior
|
||||
belongs in the [consumer guides](../consumers/), [CLI](../cli.md),
|
||||
[configuration](../config.md), and facade GoDoc.
|
||||
|
||||
## Historical starting baseline
|
||||
|
||||
Work started from ReleaseKit v0.3.0 plus accepted ADR 0005. At that starting
|
||||
point, module selection was unimplemented and the following baseline applied.
|
||||
|
||||
- `ReleaseRequest` selects a repository, product, and version. `Candidate` and
|
||||
`PublicationResult` expose the version without a distinct module or tag name.
|
||||
- Candidate capture reads `docs/releases/<version>.md` from the captured commit.
|
||||
Local and remote uniqueness checks, tag creation, push, and reconciliation use
|
||||
the version as the Git tag.
|
||||
- The shared validation path runs tests, selected vet, and package compilation
|
||||
from the repository directory. Optional content checks inspect the committed
|
||||
repository tree, including nested-module contents.
|
||||
- Profiles support shared validation and additional commands. CLI product
|
||||
checks run from the repository directory with candidate/version context.
|
||||
- Artifact builds and delivery also use repository/version assumptions. The
|
||||
consumer Woodpecker template selects `refs/tags/v*` and bootstraps ReleaseKit
|
||||
from repository-root module files.
|
||||
|
||||
Candidate capture, declarative validation, exact-object publication, and outcome
|
||||
reporting provided the foundation for carrying scope and identity through all
|
||||
operations.
|
||||
|
||||
## Targeted end state
|
||||
|
||||
An invocation selects one module and one semantic version. Omitted selection
|
||||
means the repository-root module. For example:
|
||||
|
||||
| Selected directory | Semantic version | Complete tag | Committed release note |
|
||||
| --- | --- | --- | --- |
|
||||
| Root | `v0.1.0` | `v0.1.0` | `docs/releases/v0.1.0.md` |
|
||||
| `integrations/ckconfig` | `v0.2.0` | `integrations/ckconfig/v0.2.0` | `integrations/ckconfig/docs/releases/v0.2.0.md` |
|
||||
| `integrations/ckprompt` | `v0.1.0` | `integrations/ckprompt/v0.1.0` | `integrations/ckprompt/docs/releases/v0.1.0.md` |
|
||||
|
||||
All mandatory and selected optional release checks use the selected module's
|
||||
scope. Independently released nested modules are excluded from their parent's
|
||||
automatic validation inputs. Shared file selections follow the
|
||||
[resolved shared-file rules](#shared-file-validation-inputs). Checks may read
|
||||
referenced material elsewhere in the captured repository without adding that
|
||||
material's surrounding files to the input set. The checkout remains the boundary for outside-checkout link checks.
|
||||
|
||||
Repository cleanliness, branch, candidate commit, remote endpoint, and publication
|
||||
guards remain repository-wide. The complete selected tag governs uniqueness,
|
||||
publication, and recovery. A successful source-tag push remains completion.
|
||||
Consumers prepare dependencies before offline candidate validation and choose
|
||||
sibling release ordering. Dependency preparation for delivery targets the
|
||||
selected module through the existing preparation operation when needed.
|
||||
|
||||
The feature covers individual releases. Batch publication, automatic release
|
||||
selection, dependency-driven versioning, and arbitrary tag templates remain
|
||||
outside this roadmap. Artifact builds, hosted delivery, and CI use the same
|
||||
selected module and release identity. Delivery remains asynchronous and supports
|
||||
both page-only and binary profiles. This work adds no consumer-installation,
|
||||
proxy-availability, CI, or hosted-delivery publication completion gate.
|
||||
|
||||
## Capability requirements
|
||||
|
||||
### Module and release identity
|
||||
|
||||
Repository directory, physical module directory, declared module path, semantic
|
||||
version, and complete Git tag are distinct and available throughout operations
|
||||
and public evidence. Shared derivation follows standard Go conventions, including
|
||||
major-version layouts with and without a physical major directory. A `/v2`
|
||||
module at either `integrations/ckconfig` or `integrations/ckconfig/v2` uses
|
||||
`integrations/ckconfig/v2.0.0` for `v2.0.0`. Failure evidence retains resolved
|
||||
identity alongside existing commit, endpoint, phase, state, and tag-object fields
|
||||
as available. Facade conversions preserve underlying causes.
|
||||
|
||||
### Coherent validation scope
|
||||
|
||||
Tests, vet, and package compilation execute in the selected module with offline
|
||||
and workspace-disabled settings. Formatting, distribution checks, file size,
|
||||
and Markdown share ordered committed module and selected shared-file inputs.
|
||||
Product checks receive the selected module's context. File checks retain complete
|
||||
repository lookup for targeted reference reads. Existing optional check rules,
|
||||
error identities, cancellation, and causes apply within that scope.
|
||||
|
||||
### Notes, publication, and recovery
|
||||
|
||||
Each module's committed note identifies its product and semantic version at
|
||||
its module-local note path. Local and remote uniqueness, annotated tag creation,
|
||||
exact-object push, and bounded reconciliation address the complete tag.
|
||||
Repository-wide guards and publication outcomes remain in place. Different
|
||||
modules can use equal semantic versions with distinct notes and tags.
|
||||
|
||||
### Builds, receipts, and hosted delivery
|
||||
|
||||
Standalone builds, candidate build checks, managed delivery builds, and prebuilt
|
||||
delivery use the selected module. Module-owned execution and output paths use
|
||||
that module's directory. Binaries report semantic versions; hosted pages and
|
||||
source links use full tags and module-local notes. Builds and receipts carry
|
||||
module and source evidence. Delivery validates that evidence and actual artifact
|
||||
content before hosted requests, retaining page/asset conflicts, additive retries,
|
||||
and partial outcomes. Page-only profiles require no application binary or
|
||||
Go environment discovery.
|
||||
|
||||
### CLI and module-selected CI
|
||||
|
||||
Profiles express the API's module and shared-file selections through existing
|
||||
profile lookup. Product commands receive both module and repository context.
|
||||
A small shared launcher selects profiles and semantic versions. Mapped CI
|
||||
selects the physical module and profile from the verified tagged checkout before
|
||||
bootstrapping its selected tool. Local launchers and CI share one consumer
|
||||
selection declaration. ReleaseKit verifies selection against derived identity.
|
||||
Root-only consumers retain default bootstrap and profile behavior without a map.
|
||||
Retries use the original tagged source's selection and tool configuration.
|
||||
|
||||
### Complete adoption guidance and behavioral evidence
|
||||
|
||||
Canonical API, CLI, configuration, consumer, integration, and recovery documents
|
||||
and maintained examples describe the complete interface. The next release's
|
||||
migration guidance covers API and profile updates, receipt regeneration, CI
|
||||
selection, and root-module scope changes, including nested fixture modules.
|
||||
Focused owner tests and representative assembled workflows establish the target
|
||||
behavior with local repositories, HTTP fixtures, and isolated synthetic dependency
|
||||
caches. The [implementation plan](implementation.md#acceptance-coverage-audit)
|
||||
owns the concrete acceptance coverage and execution steps.
|
||||
|
||||
## Resolved decisions
|
||||
|
||||
### Resolve identity once
|
||||
|
||||
Each ReleaseKit operation resolves repository directory, selected module
|
||||
directory and declaration, semantic version, and complete tag once through
|
||||
shared resolution logic. Pass that identity through candidate handling,
|
||||
validation, callbacks, publication, builds, receipts, delivery, and evidence.
|
||||
Subsystems consume the resolved module and tag. Repository-state, tagged-source,
|
||||
and artifact verification continue against that identity through their existing
|
||||
guards.
|
||||
|
||||
### Operation prerequisites and identity
|
||||
|
||||
Shared resolution supplies module and tag identity to each operation.
|
||||
Candidate checking and publication retain clean source on the primary branch,
|
||||
committed release notes, and their existing unused-tag checks. Delivery
|
||||
retains clean tagged-source verification and supports historical releases and
|
||||
detached checkouts. Ordinary builds retain their support for modified source
|
||||
and operate independently of release-note and publication prerequisites.
|
||||
|
||||
Composite operations pass resolved identity to their internal collaborators.
|
||||
Standalone operations use the same resolver at entry, with declaration source
|
||||
selected by the operation as described below.
|
||||
|
||||
### Declaration source by operation
|
||||
|
||||
Candidate checks, publication, and tagged delivery resolve identity from
|
||||
committed module declarations. Standalone builds read the selected module's
|
||||
working-tree `go.mod`, so their identity corresponds to the declaration Go
|
||||
uses for compilation. This supports local development of changed module paths
|
||||
and new module directories before commit.
|
||||
|
||||
The operation selects the declaration source and uses shared identity derivation
|
||||
logic. Composite candidate and delivery builds receive their already resolved
|
||||
committed identity. Existing source-verification observations remain in place;
|
||||
delivery requires a build verified against its committed tagged source.
|
||||
|
||||
### One validation input set and full repository lookup
|
||||
|
||||
Construct file inputs when enabled checks or explicit shared-file validation
|
||||
need them. Compute module boundaries and the ordered, deduplicated input set
|
||||
once using committed metadata. File checks consume that set. Keep the full
|
||||
repository lookup available for targeted reads and reference resolution, with scoped reader
|
||||
ownership and cancellation preserved.
|
||||
|
||||
Deduplicate inputs by path. Reuse parsed results by blob identity while retaining
|
||||
each source path's findings and relative destinations. This preserves the
|
||||
existing selective caches and avoids retaining all inspected raw content.
|
||||
|
||||
### Version and tag boundaries
|
||||
|
||||
Keep semantic version and complete tag distinct in internal requests and evidence.
|
||||
Version injection, artifact filenames, smoke checks, and note titles use the
|
||||
semantic version. Git publication, recovery, and hosted release identity use
|
||||
the complete tag. URL construction belongs to each protocol owner, which encodes
|
||||
the literal tag for its route. Verify slash-containing tags in API and source
|
||||
links.
|
||||
|
||||
### Failure evidence
|
||||
|
||||
Populate available module, version, tag, and commit evidence as resolution
|
||||
progresses. Later failures retain that evidence alongside the operation's
|
||||
existing phase, endpoint, tag-object, and outcome fields as available. Shared
|
||||
facade conversions preserve these fields and the underlying error causes.
|
||||
|
||||
### Go environment ownership
|
||||
|
||||
Lazily discover effective Go settings for the selected module and reuse them
|
||||
within the operation's validation and build phases when environment inputs are
|
||||
unchanged. Ownership and reuse are operation-local. Dependency preparation keeps
|
||||
its separate network-capable environment. Page-only delivery retains its path
|
||||
without Go-tool discovery or application dependency preparation.
|
||||
|
||||
### Build settings, receipts, and asset verification
|
||||
|
||||
Normalize build settings once and reuse that representation for execution,
|
||||
receipt binding, and comparisons. The new receipt format binds module identity
|
||||
alongside existing source and artifact evidence. Loading validates structure,
|
||||
identity, and file declarations. Delivery owns the content-verification pass
|
||||
before hosted requests, for both API and CLI callers.
|
||||
|
||||
Build-time hashing records the produced bytes; delivery-time verification
|
||||
establishes that the selected files still match them. Candidate and managed
|
||||
delivery output stays outside the whole repository. Ordinary output paths use
|
||||
the selected module's path base.
|
||||
|
||||
### CI bootstrap and checkout ownership
|
||||
|
||||
For module-mapped workflows, use one small committed consumer selection
|
||||
declaration shared by the launcher and CI. Bootstrap verifies the triggering
|
||||
tag and commit, selects the physical module and profile, and builds the tool
|
||||
from that module's configuration. ReleaseKit verifies selection against the
|
||||
derived identity.
|
||||
|
||||
The workflow prepares the checkout before tool bootstrap. Subsequent delivery
|
||||
reuses that checkout with fresh read-only source checks. Standalone CI delivery
|
||||
performs preparation when needed. Share verification behavior across these
|
||||
entry paths, keeping root defaults and tagged-source selection on retries.
|
||||
|
||||
### Simple single-module experience
|
||||
|
||||
Ordinary root-module consumers use the new interface's defaults: omitted module
|
||||
selection means the repository root, the complete tag equals the semantic
|
||||
version, notes use `docs/releases/<version>.md`, and validation and builds run
|
||||
from the root module. Shared-file defaults apply with input deduplication.
|
||||
Root-tag CI uses the ordinary profile and repository-root tool bootstrap.
|
||||
|
||||
Routine use requires no additional configuration fields, module mapping
|
||||
declarations, or recurring consumer decisions. A representative root-module
|
||||
profile, launcher, and CI workflow remain equally small after migration.
|
||||
Consumers supply their existing product facts through the new interface.
|
||||
One-time API updates and receipt regeneration belong in the next release's
|
||||
migration guidance under the clean-cutover decision below.
|
||||
|
||||
### Module boundaries
|
||||
|
||||
Use committed nested `go.mod` locations as module boundaries for ordinary source
|
||||
directories. This follows Go's module structure and avoids a second registry of
|
||||
independently versioned products. Vendored material remains part of the selected
|
||||
module's file-check inputs. Nested fixture modules are excluded from automatic
|
||||
parent file checks and can be exercised through the parent's tests or product
|
||||
checks. Document this distinction and verify representative cases.
|
||||
|
||||
A repository-level workspace file outside the selected nested module's scope
|
||||
does not fail that module's workspace-file check merely because it exists.
|
||||
Shared release materials and referenced destinations receive the targeted
|
||||
inspection described above.
|
||||
|
||||
### Shared file-validation inputs
|
||||
|
||||
Provide an optional shared-file list in the public request and profile. Its
|
||||
selection applies only to shared file-validation inputs. Existing validation
|
||||
selections control which checks are enabled. Enabled checks retain their rules,
|
||||
and Go tests, vet, and package compilation retain the selected module's scope.
|
||||
|
||||
| Selection | Shared files added automatically |
|
||||
| --- | --- |
|
||||
| Omitted list | Repository-root `COPYRIGHT`, `LICENSE`, and `docs/oss/attribution.md`, when present. |
|
||||
| Explicit list | The listed files replace the defaults. |
|
||||
| Explicit empty list | No shared files. |
|
||||
|
||||
In Go, a nil slice selects the defaults; a non-nil empty slice selects none.
|
||||
In JSON, omission or `null` selects the defaults; `[]` selects none. Preserve
|
||||
this distinction through profile mapping and facade conversions, including
|
||||
slice copying and profile serialization. Resolve the defaults once. Exact field
|
||||
names belong in API design.
|
||||
|
||||
Paths are repository-relative literal file paths. This initial selection
|
||||
supports individual files. Resolve presence and file identity from the captured
|
||||
committed tree. Missing explicitly selected files produce a configuration or
|
||||
validation error identifying the selected path, including when optional file
|
||||
checks are disabled. Defaults are optional when absent.
|
||||
|
||||
Deduplicate the combined module and shared-file inputs by committed path, so a
|
||||
file already in module scope or repeated in the list is checked once. Explicit
|
||||
selection may name a file in another module; include that file alone. Reference
|
||||
resolution continues to inspect destinations using existing rules and leaves
|
||||
those destinations outside the input set unless independently selected.
|
||||
|
||||
### Relative paths and product commands
|
||||
|
||||
Anchor module selection and profile lookup at the repository. Anchor
|
||||
module-owned validation and build paths, including file-size exclusions, and
|
||||
configured product-command execution at the selected module. Keep diagnostic
|
||||
file paths repository-relative and expose both directories to product commands.
|
||||
Markdown destinations remain relative to their source documents.
|
||||
Normalize selections and resolve path bases at a shared boundary. Translate
|
||||
file selections and exclusions to canonical repository-relative paths before
|
||||
checks consume them. Use module-based filesystem paths for execution and output,
|
||||
and retain repository-relative diagnostic paths through conversions.
|
||||
|
||||
Root profiles use the repository-root module by default. Nested-module launchers
|
||||
use the provided repository context for shared scripts. These conventions keep
|
||||
per-module profiles self-contained without adding per-check path-base switches.
|
||||
|
||||
### Complete operation support
|
||||
|
||||
Implement module selection across checking, publication, artifact builds,
|
||||
hosted delivery, and CI in this feature. The target is a coherent release API
|
||||
for root and nested modules. CommandKit's current source-only use supplies an
|
||||
adoption case while the feature supports the full existing release workflow.
|
||||
|
||||
Feature completion includes all of these operations. Omitted module selection
|
||||
uses the root module, and source publication and asynchronous delivery retain
|
||||
their separate outcomes.
|
||||
|
||||
### Clean API and receipt cutover
|
||||
|
||||
Implement one current API and module-bound receipt format as the complete
|
||||
supported interface after cutover. Consumers update their calls, profiles, and
|
||||
CI declarations to that interface and regenerate prior receipts through the
|
||||
updated build operation. Compatibility shims and legacy receipt readers are
|
||||
outside the implementation scope.
|
||||
|
||||
Migration means guidance supplied in the next release's documentation. That
|
||||
guidance explains the required consumer changes and the root-module validation
|
||||
scope change; implementation completion covers the new interface directly.
|
||||
@@ -1,587 +0,0 @@
|
||||
# Remediation: module release implementation review
|
||||
|
||||
Status: complete; all fifteen findings addressed and verified.
|
||||
The initial review examined `90559fe`, compared with planning baseline `dbfae9e`.
|
||||
The follow-up repository audit examined `6b0b8ce`, including those corrections.
|
||||
|
||||
## Scope and evidence
|
||||
|
||||
The [feature roadmap](module-releases.md) and
|
||||
[implementation plan](implementation.md) define the intended module-release
|
||||
architecture. Most of that architecture is implemented: the two public facades,
|
||||
shared module/tag derivation, scoped committed inputs with full reference lookup,
|
||||
module-based Go execution, full-tag publication and hosted delivery, current-only
|
||||
receipts, and tagged-source workflow selection.
|
||||
|
||||
The ordinary offline `go test ./...` suite and `go run ./internal/apicheck`
|
||||
passed with Go 1.26.8. The findings below also use source inspection and temporary
|
||||
fixtures outside the checkout. Publication reproduction used a private local
|
||||
bare repository. No ReleaseKit source or real release refs were changed.
|
||||
|
||||
Each issue describes required work and verification. Preserve the selected
|
||||
scope, existing error causes, publication/delivery outcomes, facade boundaries,
|
||||
and clean API cutover. These corrections add no release, live-service, or human
|
||||
review gates. Each completion record describes the correction and verification.
|
||||
|
||||
## Issue 1: Resolve the actual Git repository root before release identity (P1)
|
||||
|
||||
Status: complete. Category: architecture gap and incorrect publication.
|
||||
|
||||
**Completion:** Source operations and CLI profile selection resolve the containing
|
||||
Git checkout root before module selection. Regression tests verify that a child
|
||||
directory cannot bypass a failing root suite or publish its tag, explicit nested
|
||||
selection binds its own source and tag, aliases and independent worktrees retain
|
||||
their identity, and dependency preparation works without Git. The focused public
|
||||
API tests and candidate, delivery, CLI, and profile suites pass offline.
|
||||
|
||||
**Evidence:** [candidate capture](../../internal/candidate/check.go) treats
|
||||
`filepath.Abs(request.RepositoryDir)` as the repository root, and
|
||||
[selection resolution](../../internal/releaseidentity/identity.go) uses that
|
||||
directory as its base. Git committed-file paths are relative to the actual Git
|
||||
root. Go commands instead execute in the supplied directory.
|
||||
|
||||
A temporary repository had a failing root suite, a passing module at
|
||||
`apps/widget`, and a root release note. `Check` from the actual root failed.
|
||||
`Check` with `RepositoryDir` set to `apps/widget` and omitted module selection
|
||||
succeeded, reporting the root module's declared path and unprefixed `v0.1.0`
|
||||
tag while executing the nested suite. `Publish` with that request successfully
|
||||
pushed the root tag to the private fixture remote. The declared release unit
|
||||
and validated release unit therefore differ.
|
||||
|
||||
**Required change:** Resolve the containing Git checkout's actual root at source
|
||||
operation boundaries, then anchor repository-relative module and note paths to
|
||||
that root. Carry that resolved repository identity through checks, publication,
|
||||
builds, delivery, and CLI profile lookup. Normalize an input directory within the
|
||||
checkout rather than introducing a blanket prohibition on such inputs. Keep
|
||||
dependency preparation's own prerequisites separate; this correction should not
|
||||
require a Git checkout merely to prepare a Go module's dependencies.
|
||||
|
||||
**Verification:** Repeat the failing-root/passing-nested fixture through both
|
||||
`Check` and `Publish`, including default CLI invocation from a nested directory.
|
||||
Omitted selection must validate the actual root module and prevent publication
|
||||
when that suite fails. Explicit nested selection must bind its declaration,
|
||||
note, suite, and prefixed tag consistently. Retain symlinked checkout and
|
||||
independent worktree behavior.
|
||||
|
||||
## Issue 2: Preserve standalone Build error classification and partial evidence (P2)
|
||||
|
||||
Status: complete. Category: regression and incomplete failure evidence.
|
||||
|
||||
**Completion:** Standalone builds classify invalid versions before source access
|
||||
and retain resolved selection and normalized build settings on identity failures.
|
||||
Working-tree derivation preserves progressive identity evidence. Native CLI
|
||||
validation reports invalid-version status 2 before repository access. Focused
|
||||
API, native CLI, parser, identity, cancellation, and partial-artifact tests pass
|
||||
offline.
|
||||
|
||||
**Evidence:** [public Build](../../build.go) now calls working-tree identity
|
||||
resolution before the internal builder. Invalid stable versions are returned by
|
||||
`Derive` as ordinary formatted errors, bypassing the existing
|
||||
`ErrInvalidVersion` identity. An API request with `bad-version` produced
|
||||
`errors.Is(err, releasekit.ErrInvalidVersion) == false`; the compiled CLI exited
|
||||
1 rather than its documented invalid-version status 2.
|
||||
|
||||
The same entry point returns only `Version` when identity resolution fails.
|
||||
Selecting an existing nested directory with an invalid `go.mod` returned empty
|
||||
repository and module fields, although both directories had already been
|
||||
resolved. This contradicts the roadmap's progressive failure-evidence decision
|
||||
and loses supplied build facts that the previous build boundary retained.
|
||||
|
||||
**Required change:** Preserve the existing invalid-version error at the build
|
||||
entry boundary, including its classification before unrelated filesystem work.
|
||||
Return available selection and build evidence when later declaration or identity
|
||||
work fails. Share the appropriate conversion/resolution facts without resolving
|
||||
the declaration again or inventing stronger source-verification guarantees.
|
||||
|
||||
**Verification:** Add API and native CLI cases for invalid versions, plus a
|
||||
declaration failure after successful directory selection. Assert error identity,
|
||||
exit classification, and available result fields. Keep cancellation causes and
|
||||
later partial-artifact behavior intact.
|
||||
|
||||
## Issue 3: Use the module path base for relative prebuilt assets (P2)
|
||||
|
||||
Status: complete. Category: incomplete module path adoption.
|
||||
|
||||
**Completion:** Build output and CLI prebuilt assets share the selected module's
|
||||
directory resolver. CLI and pending migration guidance describe the common base.
|
||||
Local hosted regression tests verify root and nested relative build/delivery
|
||||
pairs, absolute output, module binding, and rejection of changed artifact content
|
||||
before hosted requests. Existing receipt/content checks and nested build cases
|
||||
pass offline.
|
||||
|
||||
**Evidence:** [CLI prebuilt delivery](../../cmd/releasekit/main.go) joins a
|
||||
relative `--assets` directory to `invocation.Repository`. Builds now resolve
|
||||
relative `--output` from the selected module. A nested profile's successful
|
||||
`build --output dist v0.1.0` wrote
|
||||
`apps/widget/dist/.releasekit-build.json`; the corresponding
|
||||
`deliver --assets dist v0.1.0` attempted to open the repository-root receipt and
|
||||
failed. The documented build/deliver pair therefore uses incompatible bases.
|
||||
|
||||
**Required change:** Resolve relative prebuilt asset directories from the same
|
||||
selected module base as build output, using shared path normalization. Preserve
|
||||
absolute directories and repository-relative profile lookup. Document the base
|
||||
in the CLI owner and update affected examples and migration guidance.
|
||||
|
||||
**Verification:** Exercise a nested profile's relative build/output and delivery
|
||||
pair using a local hosted fixture. Include the omitted root selection and an
|
||||
absolute caller-owned asset directory. Verify module binding and content checks
|
||||
still happen before hosted requests.
|
||||
|
||||
## Issue 4: Compare receipt repository identity consistently through aliases (P2)
|
||||
|
||||
Status: complete. Category: regression from mixed path normalization.
|
||||
|
||||
**Completion:** Receipt source and location comparisons use filesystem directory
|
||||
identity, accepting aliases of the same checkout or output directory. Regression
|
||||
tests build and deliver through a checkout symlink, retry through its physical
|
||||
path, and reject different repositories and modules. Receipt structure, exact
|
||||
release binding, and delivery-owned content checks remain intact. Receipt and
|
||||
assembled prebuilt-delivery cases pass offline.
|
||||
|
||||
**Evidence:** Release identity canonicalizes repository symlinks, so generated
|
||||
receipts record the physical repository directory.
|
||||
[`BuildReceipt.MatchesBuild`](../../cmd/releasekit/internal/cli/receipt.go) only
|
||||
applies `filepath.Abs`/`Clean` to the supplied repository. A fixture built normally
|
||||
and delivered with `--repo` pointing to a symlink of that same checkout, with
|
||||
an absolute asset directory, failed the preliminary repository/settings comparison.
|
||||
The delivery facade's shared resolver would identify the same repository.
|
||||
|
||||
**Required change:** Use consistent resolved repository identity for receipt
|
||||
comparison, or leave source identity comparisons with the delivery owner that
|
||||
already resolves and verifies them. Preserve structural receipt checks and exact
|
||||
module/version/tag/commit binding. Avoid adding another declaration resolution
|
||||
or a requirement that callers use one textual spelling of a checkout path.
|
||||
|
||||
**Verification:** Build and deliver through the same symlinked checkout argument,
|
||||
and through its equivalent physical path. Both must identify the same source;
|
||||
a genuinely different repository or module must still fail before hosted work.
|
||||
|
||||
## Issue 5: Keep Go environment reuse lazy and proportionate (P2)
|
||||
|
||||
Status: complete. Category: additional validation gates and unrequested restrictions.
|
||||
|
||||
**Completion:** Go discovery happens on acquisition for actual Go work. Completed
|
||||
callbacks trigger no additional discovery; settings-file snapshot failures disable
|
||||
reuse while preserving the Go tool's accepted configurations. Regression tests
|
||||
cover check/publication completion after Go leaves PATH, subsequent builds needing
|
||||
rediscovery, the final callback, unreadable GOENV snapshots, normal environment
|
||||
and persistent-file changes, and cancellation. Focused public cases and complete
|
||||
candidate and Go-tool suites pass offline.
|
||||
|
||||
**Evidence:** [candidate coordination](../../internal/candidate/check.go) and
|
||||
[publication](../../internal/publish/publish.go) eagerly call
|
||||
[`Owner.Refresh`](../../internal/gotool/owner.go) after callbacks. A candidate
|
||||
with successful standard validation and a successful additional callback that
|
||||
left Git available but removed Go from `PATH` failed during rediscovery, although
|
||||
no subsequent Go command or build was selected. `Acquire` already detects changed
|
||||
inputs before actual Go work.
|
||||
|
||||
The owner also requires its settings-file snapshot to be readable. With `GOENV`
|
||||
set to a directory, existing `gotool.New` and the Go discovery commands succeeded,
|
||||
while `NewOwner(...).Acquire` failed on the added `os.ReadFile`. Go's acceptance
|
||||
of its configuration has become narrower through a cache bookkeeping step.
|
||||
|
||||
**Required change:** Rediscover changed settings when a subsequent Go command
|
||||
needs them. Preserve successful callback/operation completion when no more Go
|
||||
work remains. Make snapshot limitations disable safe reuse or otherwise follow
|
||||
the Go tool's effective behavior; they should not independently reject a
|
||||
configuration that discovery accepts. Retain operation-local ownership, normal
|
||||
settings-change detection, offline compilation, and separate preparation settings.
|
||||
|
||||
**Verification:** Cover a completed validation operation whose callback changes
|
||||
environment inputs with no later build, and one whose subsequent build actually
|
||||
needs rediscovery. Compare owner discovery with the underlying Go-tool behavior
|
||||
when persistent settings cannot be snapshotted. Keep existing settings-change
|
||||
and cancellation tests.
|
||||
|
||||
## Issue 6: Avoid requiring downloadable module paths for ordinary main modules (P2)
|
||||
|
||||
Status: complete. Category: unrequested restriction.
|
||||
|
||||
**Completion:** Identity derivation uses Go import-path lexical validation and
|
||||
retains path-major compatibility. A valid non-domain main module now completes
|
||||
candidate checking, native standalone compilation, and hosted page-only delivery
|
||||
against a local fixture. Qualified and local major-version derivation, missing
|
||||
and malformed declarations, and incompatible majors pass their focused offline
|
||||
regression tests.
|
||||
|
||||
**Evidence:** [`Derive`](../../internal/releaseidentity/identity.go) adds
|
||||
`module.CheckPath`, including its requirement for a dot in the first path element.
|
||||
A standard main module declared as `module example` passed `go test ./...` but
|
||||
was rejected by standalone `Build` before any Go work. The
|
||||
[Go module reference](https://go.dev/ref/mod#module-paths) permits main modules
|
||||
that are not fetched as dependencies to use valid package paths.
|
||||
|
||||
The selected requirement is stable-version and path-major tag derivation.
|
||||
Deriving a root or physical-directory tag does not require the declaration to
|
||||
be a downloadable network module. No user decision imposed that extra
|
||||
restriction on executable applications or local builds.
|
||||
|
||||
**Required change:** Validate the declaration and path-major facts needed by
|
||||
identity derivation using Go's appropriate lexical rules for the supported
|
||||
operations. Preserve standard major-version consistency. Remove the accidental
|
||||
downloadability prerequisite rather than adding a consumer bypass setting.
|
||||
|
||||
**Verification:** Exercise a valid non-domain main module through standalone
|
||||
build and representative check/page delivery, alongside ordinary qualified
|
||||
module paths. Continue rejecting missing/invalid declarations and incompatible
|
||||
major identities for the selected release convention.
|
||||
|
||||
## Issue 7: Resolve committed identity from committed material (P2)
|
||||
|
||||
Status: complete. Category: declaration-source divergence and added prerequisites.
|
||||
|
||||
**Completion:** Shared Git reference traversal now serves validation and committed
|
||||
module identity. Committed selection follows directory and declaration links
|
||||
using targeted object reads; working-tree builds retain filesystem selection.
|
||||
CLI mapping and prebuilt path selection use committed directory facts. Regression
|
||||
tests cover captured links, changed working declarations, cycles, checkout
|
||||
boundaries, unavailable blobs, cancellation, and ordinary/prepared CI page-only
|
||||
delivery from a sparse checkout without Go. The complete offline suite and
|
||||
compiled public API/dependency checks pass.
|
||||
|
||||
**Evidence:**
|
||||
|
||||
- `FromCommittedSelection` passes raw `git show` bytes to the declaration parser.
|
||||
A committed `go.mod` symlink therefore supplies its link text. In a local
|
||||
fixture, Go validation and working-tree identity succeeded while committed
|
||||
identity reported no valid module directive. Existing committed validation
|
||||
already has reference/symlink resolution.
|
||||
- `ResolveSelection` also requires the selected module directory to exist in
|
||||
the worktree through `EvalSymlinks`. A clean, correctly tagged sparse checkout
|
||||
retained a nested module's declaration and note in Git but omitted its physical
|
||||
directory. Page-only delivery failed on `lstat` before inspecting committed
|
||||
identity. Its source was present and it needed no application compilation.
|
||||
|
||||
**Required change:** Separate filesystem execution selection from committed
|
||||
source selection where their prerequisites differ. Resolve committed declarations
|
||||
and directory/reference identity from the captured tree, retaining existing
|
||||
checkout boundaries, cycle handling, missing-object errors, and cancellation.
|
||||
Go execution may naturally require materialized source when it runs; page-only
|
||||
metadata delivery should not gain that compilation prerequisite. Keep
|
||||
working-tree builds tied to the declaration Go actually reads.
|
||||
|
||||
**Verification:** Cover an in-checkout committed declaration symlink and a
|
||||
page-only nested release from a clean sparse checkout with available committed
|
||||
objects. Verify committed/working-tree differences deliberately and retain
|
||||
reference-cycle, outside-checkout, unavailable-content, and source-tag guards.
|
||||
|
||||
## Issue 8: Preserve literal shared filenames (P2)
|
||||
|
||||
Status: complete. Category: unrequested path prohibition.
|
||||
|
||||
**Completion:** Shared selection preserves literal backslashes in committed Git
|
||||
paths. A Unix regression selects and reads such a file once despite duplicates;
|
||||
traversal, absolute paths, and directories remain invalid selections. Existing
|
||||
literal-metacharacter, missing/default/empty-list, scope, and lazy-input tests
|
||||
pass offline.
|
||||
|
||||
**Evidence:** [`normalizeSharedFile`](../../internal/validation/tree.go) rejects
|
||||
every backslash. On Linux, a committed file named `docs/notice\copy.txt` is a
|
||||
literal repository-relative file, but explicit selection failed as `shared-files`.
|
||||
The roadmap selected literal individual paths and ordinary normalization without
|
||||
globs; it did not exclude legal filename characters for committed inputs.
|
||||
|
||||
**Required change:** Preserve literal committed path characters under the chosen
|
||||
repository-path convention. Keep absolute/outside-repository and directory
|
||||
selection checks needed for the agreed scope. Introduce neither glob expansion
|
||||
nor a portability restriction on otherwise valid committed filenames.
|
||||
|
||||
**Verification:** On a filesystem where backslash is a literal filename
|
||||
character, select the committed file successfully. Retain traversal, missing
|
||||
explicit files, literal metacharacters, deduplication, and empty/default-list
|
||||
coverage.
|
||||
|
||||
## Issue 9: Separate synthetic bootstrap versions from maintained examples (P2)
|
||||
|
||||
Status: complete. Category: broken adoption example and incomplete cutover guidance.
|
||||
|
||||
**Completion:** Maintained module skeletons no longer pin synthetic releases.
|
||||
Example setup explicitly selects compatible released tooling and documents source
|
||||
verification in disposable checkouts. Workflow fixtures generate their synthetic
|
||||
declarations. Current-source tool registration and all three example profiles,
|
||||
including native version injection, pass offline; mapped launchers/workflows and
|
||||
tagged-tool retries retain isolated fixtures. Adoption and migration guidance
|
||||
cover coordinated tool/workflow upgrades and historical retries. The pending
|
||||
release notes record concrete example pins as normal version-selection work.
|
||||
|
||||
**Evidence:** All three maintained
|
||||
[multi-module declarations](../../examples/multi-module/) require ReleaseKit
|
||||
`v0.2.197`. This is a synthetic test version served by
|
||||
[`writeWorkflowToolProxy`](../../cmd/releasekit/multi_module_woodpecker_test.go),
|
||||
whose executable forwards to the separately compiled current test binary.
|
||||
A read-only query of the authoritative repository returned `v0.3.0` and no
|
||||
`v0.2.197` tag. The copyable example cannot obtain its declared release tool
|
||||
through ordinary module resolution.
|
||||
|
||||
Published pre-feature tooling also lacks the new profile/flag interface. The
|
||||
maintained workflows always pass `--prepared`, and mapped launchers additionally
|
||||
pass `--expected-module`. Migration guidance does not explain that adopting the
|
||||
new workflow requires a compatible tool declaration, or that an older tag's
|
||||
tool declaration requires its matching historical workflow for a retry.
|
||||
|
||||
**Required change:** Confine synthetic versions to test-owned module files and
|
||||
proxies. Make the maintained example's setup explicitly select a ReleaseKit
|
||||
version containing this feature, and update its concrete release dependency
|
||||
during normal release preparation when that version is selected. Keep setup
|
||||
usable for local source verification without fabricating a published release.
|
||||
Document tool/workflow cutover and historical retry guidance in the pending
|
||||
release notes and adoption owners. Maintain the clean API cutover; add no flag,
|
||||
receipt, or source-identity compatibility shim.
|
||||
|
||||
**Verification:** Tests generate their own synthetic dependency declarations
|
||||
instead of relying on fake versions committed in the copyable example. Verify
|
||||
the setup's selected tool accepts the actual new interface, using current source
|
||||
and isolated fixtures offline. Preserve tagged-source tool-version selection and
|
||||
test-owned caches. This adds no live module-service completion gate.
|
||||
|
||||
## Issue 10: Remove the repeated boundary scan from file selection (P2)
|
||||
|
||||
Status: complete. Category: code quality and avoidable computational cost.
|
||||
|
||||
**Completion:** File selection indexes boundary directories and looks up each
|
||||
entry's ancestors. Existing ordering, vendor/shared selection, full reference
|
||||
lookup, and reader/cache behavior pass the complete offline validation suite.
|
||||
A component benchmark retains 20,000 inputs with 0, 1,000, and 4,000 boundaries.
|
||||
On this host, the 4,000-boundary case decreased from about 2.73 seconds to 38
|
||||
milliseconds per selection; the new cases ranged from 29 to 38 milliseconds.
|
||||
These are illustrative measurements without timing gates or input limits.
|
||||
|
||||
**Evidence:** [`selectInputEntries`](../../internal/validation/tree.go) loops
|
||||
over all nested-module boundaries for every candidate entry. This costs
|
||||
`O(files × boundaries)` even when the retained input set is unchanged.
|
||||
Temporary committed-tree fixtures with 20,000 retained files took approximately
|
||||
0.5 seconds with no boundaries, 1.0 second with 1,000 boundaries, and 2.8 seconds
|
||||
with 4,000 boundaries. These timings include metadata reads and are illustrative
|
||||
local measurements, not performance contracts.
|
||||
|
||||
**Required change:** Use direct ancestor-boundary lookup or another straightforward
|
||||
path-based selection that avoids scanning every unrelated boundary for each file.
|
||||
Preserve one ordered input set, vendor handling, path deduplication, explicit
|
||||
shared files, full reference lookup, and selective content-reader ownership.
|
||||
|
||||
**Verification:** Retain the existing scope behavior tests and add a representative
|
||||
component benchmark varying boundary count with the retained file count fixed.
|
||||
Verify the algorithmic improvement without adding timing thresholds, input caps,
|
||||
or new validation policies.
|
||||
|
||||
## Issue 11: Reconcile documentation with implemented scope and status (P3)
|
||||
|
||||
Status: complete. Category: incomplete documentation adoption and misleading contracts.
|
||||
|
||||
**Completion:** Facade GoDoc and canonical API, CLI, configuration, Gitea, and
|
||||
internal guidance describe selected inputs, full-tag uniqueness, module-local
|
||||
notes, shared-file scope, committed references, and lazy Go reuse consistently.
|
||||
The feature roadmap identifies its historical baseline and completed stages,
|
||||
with this review recording the corrections. Consumer-owned license layouts and
|
||||
note links are distinguished from optional validation defaults. ReleaseKit's
|
||||
root release policy and procedure retain their existing requirements. Reviewed
|
||||
root/nested examples, verified local links/fragments across 37 Markdown documents,
|
||||
checked example JSON/shell syntax and whitespace, and passed the final complete
|
||||
offline suite and compiled API/dependency checks.
|
||||
|
||||
**Evidence:**
|
||||
|
||||
- [Configuration](../config.md), [CLI](../cli.md),
|
||||
[check guidance](../consumers/check.md), and
|
||||
[publication guidance](../consumers/publish.md) still describe formatting as
|
||||
including nested-module source. `Check` GoDoc similarly says local-replacement
|
||||
inspection includes nested modules. Automatic input selection now excludes
|
||||
independent nested modules, retaining vendor and explicitly selected files.
|
||||
- Check guidance retains the old short-version wording for note location and
|
||||
tag uniqueness. The new identities use physical module-local notes and full
|
||||
tags, allowing equal semantic versions across modules.
|
||||
- [The feature roadmap](module-releases.md) still says the feature is planned
|
||||
and module selection is not implemented, while the implementation plan claims
|
||||
completion. Its baseline needs to be identified as the starting baseline.
|
||||
- [Gitea guidance](../integrations/gitea.md) presents root shared-license and
|
||||
footer locations as an unconditional layout. Describe the default convention
|
||||
and consumer-owned note links accurately; shared-file validation selection
|
||||
supplies neither a license-location guarantee nor automatic footer rewriting.
|
||||
|
||||
**Required change:** Refresh each affected canonical owner using the implemented
|
||||
selected-input and full-tag semantics. Mark feature status accurately, including
|
||||
these open remediation items, while retaining useful decision context and the
|
||||
historical starting baseline. Preserve ReleaseKit's own root release policy.
|
||||
Update migration/examples alongside the behavior corrections above.
|
||||
|
||||
**Verification:** Review GoDoc and canonical guidance against the current code;
|
||||
check root/nested examples, note and tag wording, roadmap status, local links,
|
||||
fragments, and Markdown whitespace. Keep exact contract definitions at their
|
||||
canonical owners.
|
||||
|
||||
## Follow-up audit
|
||||
|
||||
The follow-up reviewed module identity, candidate validation and publication,
|
||||
builds, receipts, delivery, Go/process ownership, committed reference handling,
|
||||
facade conversions, CLI/profile mapping, maintained workflows, documentation,
|
||||
and the eleven previous corrections. The complete offline suite and compiled
|
||||
API/dependency checks pass with Go 1.26.8. The additional findings below were
|
||||
reproduced with temporary local repositories, a filtered sparse clone, a Git
|
||||
transport stub, and a local HTTP server. The artifact-read evidence also used
|
||||
`strace`. This audit changes the remediation document only.
|
||||
|
||||
## Issue 12: Resolve module paths consistently across declaration sources (P2)
|
||||
|
||||
Status: complete. Category: inconsistent release-unit selection.
|
||||
|
||||
**Completion:** Filesystem selection follows symlinks before processing parent
|
||||
components, matching committed traversal. Public build, candidate check, and
|
||||
hosted page delivery now agree on the selected module and tag for `link/..`;
|
||||
dependency preparation executes in that same module. The new regression cases
|
||||
failed before the correction and pass afterward. Focused API/preparation tests
|
||||
and the complete identity/Git suites pass offline, including aliases, separate
|
||||
declaration sources, sparse selection, cycles, boundaries, and cancellation.
|
||||
|
||||
**Evidence:** [Filesystem selection](../../internal/releaseidentity/identity.go)
|
||||
cleans the joined module path before following symlinks. Committed selection
|
||||
uses [component traversal](../../internal/git/path.go), following a symlink
|
||||
before processing a subsequent `..`. The same selection can consequently
|
||||
identify different physical modules in an unchanged, clean checkout.
|
||||
|
||||
A fixture contained root and `nested` modules, a tracked directory
|
||||
`nested/deep`, and `link -> nested/deep`. With `ModuleDir: "link/.."` and
|
||||
`Version: "v0.1.0"`, public `Build` succeeded with the root module and tag
|
||||
`v0.1.0`; public `Check` succeeded with the nested module and tag
|
||||
`nested/v0.1.0`. Working-tree and committed declaration readers independently
|
||||
confirmed the difference. Dependency preparation uses the filesystem selector,
|
||||
while candidate and delivery operations use committed selection.
|
||||
|
||||
**Required change:** Give filesystem and committed selection the same component
|
||||
and symlink semantics for identical paths in an unchanged checkout. Preserve
|
||||
the agreed declaration source for each operation, support for working-tree
|
||||
changes and committed sparse selection, checkout boundaries, and progressive
|
||||
identity evidence. Module paths containing `..` need consistent resolution;
|
||||
this correction does not require prohibiting those paths.
|
||||
|
||||
**Verification:** Exercise a tracked directory symlink followed by `..` through
|
||||
standalone build, candidate check, dependency preparation, and representative
|
||||
delivery. An unchanged checkout must identify the same physical module and tag
|
||||
across operations. Retain deliberate committed/working-tree declaration
|
||||
differences, ordinary aliases, cycles, and outside-checkout failures.
|
||||
|
||||
## Issue 13: Reuse local asset verification through the complete delivery path (P2)
|
||||
|
||||
Status: complete. Category: incomplete verification ownership and redundant I/O.
|
||||
|
||||
**Completion:** Assembled delivery reuses its preflight verification through the
|
||||
internal upload path; standalone internal uploads retain local verification.
|
||||
A Linux filesystem-event regression observes one verification read and one
|
||||
upload read across public delivery and validates uploaded contents. It failed
|
||||
with three reads before the correction. Delivery/Gitea suites pass offline,
|
||||
including tampering, caller ownership, matching attachments, and partial retries.
|
||||
The complete-delivery benchmark now supplies current module identity. Its 32 MiB
|
||||
fresh-upload case measured about 352 ms before and 254 ms afterward on this host;
|
||||
these illustrative measurements introduce no timing gate.
|
||||
|
||||
**Evidence:** [Delivery](../../internal/delivery/delivery.go) calls
|
||||
`VerifyLocalAssets` before hosted requests. After release and attachment
|
||||
inspection, [UploadMissing](../../internal/gitea/upload.go) calls
|
||||
`verifyLocalAsset` again for every missing attachment. Both calls stream and
|
||||
hash each local binary. The upload then reads it a third time to send its bytes.
|
||||
Stages 8 and 9 of the [implementation plan](implementation.md) select one
|
||||
delivery-owned content-verification pass.
|
||||
|
||||
A public prebuilt-delivery fixture completed against a local HTTP server with
|
||||
one missing binary and its manifest. A system-call trace recorded three complete
|
||||
reads of the binary: the delivery preflight, the uploader's repeated verification,
|
||||
and the multipart upload. Receipt loading is already free of artifact hashing;
|
||||
the remaining duplicate sits across the delivery/Gitea boundary. The current
|
||||
asset-preflight benchmark ends before that second verification.
|
||||
|
||||
**Required change:** Reuse the completed local verification in the assembled
|
||||
delivery path so each binary receives one delivery-time digest-and-size pass
|
||||
before hosted requests, followed by its necessary upload stream. Preserve
|
||||
validation for independently used internal client operations, build-time
|
||||
hashing, deterministic manifests, actual remote-content comparison, additive
|
||||
retry behavior, caller-owned files, and existing failure outcomes.
|
||||
|
||||
**Verification:** Observe file reads across a complete public binary delivery
|
||||
with missing attachments, covering the uploader as well as preflight. Establish
|
||||
one verification read plus the upload read. Keep tampered/missing-file rejection
|
||||
before hosted requests and matching-asset/partial-retry cases. Measure the whole
|
||||
local path without timing thresholds or additional source guarantees.
|
||||
|
||||
## Issue 14: Keep committed release-note inspection within the local object boundary (P2)
|
||||
|
||||
Status: complete. Category: incomplete earlier offline-inspection correction.
|
||||
|
||||
**Completion:** Committed-file reads now use the shared local-only Git object
|
||||
runner. Filtered-clone regressions cover direct reads plus public check and
|
||||
delivery with an unavailable note, preserving the note path, Git cause, and
|
||||
captured identity while making no hosted request, transport attempt, or object
|
||||
database change. Both regressions exposed transport before the correction.
|
||||
The Git/candidate suites and focused source, page-delivery, and explicit tagged
|
||||
checkout preparation cases pass offline; ordinary note bytes and cancellation
|
||||
handling retain their existing command boundary.
|
||||
|
||||
**Evidence:** [ReadCommitFile](../../internal/git/source.go), used by candidate
|
||||
capture and delivery for release notes, executes `git show` through the ordinary
|
||||
Git runner. Its child does not receive the lazy-fetch and transport controls
|
||||
used by `ReadBlob`, committed-path lookup, tree inspection, and the batch reader.
|
||||
An unavailable note in a partial clone can therefore initiate remote transport
|
||||
during source inspection. The earlier correction in `0205001` and its partial
|
||||
clone tests cover the other object readers, leaving this entry point uncovered.
|
||||
|
||||
A clean filtered sparse clone had its root declaration and Go source locally
|
||||
available, with the committed note omitted and its blob unavailable locally.
|
||||
Public `Check` resolved the root identity, then invoked a fixture SSH transport
|
||||
while reading `docs/releases/v0.1.0.md`. The stub recorded the attempt and exited;
|
||||
the resulting error reported failure to fetch the note from the promisor remote.
|
||||
The fixture contacted no external service.
|
||||
|
||||
**Required change:** Read committed note bytes through the same local-only object
|
||||
boundary as the other source-inspection readers. Return an inspection error
|
||||
when required objects are unavailable locally, preserving path context,
|
||||
cancellation, underlying Git causes, and exact note bytes. Explicit checkout
|
||||
and dependency preparation retain their network-capable responsibilities.
|
||||
|
||||
**Verification:** Cover direct committed-file reading and representative
|
||||
candidate/delivery note inspection in filtered clones with unavailable note
|
||||
objects. A controlled transport stub must remain unused, and inspection must
|
||||
leave the object database unchanged. Existing ordinary note reads and explicit
|
||||
network-capable preparation must continue to work.
|
||||
|
||||
## Issue 15: Limit blob availability requirements to selected validation inputs (P2)
|
||||
|
||||
Status: complete. Category: module-scope leakage through eager metadata enrichment.
|
||||
|
||||
**Completion:** Tree enumeration now acquires path/type/mode/object metadata
|
||||
independently of blobs. The size check requests sizes only for selected,
|
||||
non-excluded blobs; other checks read contents and references when needed.
|
||||
Filtered sparse-clone regressions cover formatting, sizes, workspace metadata,
|
||||
explicit shared selection, exclusions, required shared contents, and required
|
||||
Markdown references. They failed before the correction and now preserve each
|
||||
check's scope and error identity without transport or object-database changes.
|
||||
Existing size, symlink, gitlink, vendor, boundary, reader/cache, and cancellation
|
||||
tests pass. The complete offline suite, compiled API/dependency check,
|
||||
documentation links, and whitespace checks pass for all four follow-up fixes.
|
||||
|
||||
**Evidence:** [ReadCandidateTreeForScope](../../internal/validation/tree.go)
|
||||
calls [ReadTree](../../internal/git/source.go) before constructing module and
|
||||
shared-file inputs. `ReadTree` asks `populateBlobSizes` for every repository blob
|
||||
and fails on any unavailable object. Excluded modules and unreferenced files
|
||||
therefore become availability prerequisites for a selected module's file checks,
|
||||
even when the selected check needs no blob sizes.
|
||||
|
||||
In a clean filtered sparse clone, the root module's source, declaration, and
|
||||
note were available; independently scoped `nested` module blobs were omitted.
|
||||
Public root `Check` succeeded with ordinary validation. Enabling `GoFormat`
|
||||
with an explicit empty shared-file list made the same check fail during size
|
||||
enumeration on the unavailable blob for `nested/deep/placeholder`. That file
|
||||
belongs to the excluded nested module and is neither a formatting input nor a
|
||||
referenced destination.
|
||||
|
||||
**Required change:** Separate full repository path/type/object metadata from
|
||||
blob enrichment. Construct the agreed input set before acquiring required blob
|
||||
sizes or contents, and inspect referenced destinations when a check actually
|
||||
needs them. Keep full lookup available without requiring every unrelated blob
|
||||
locally. Preserve selected-input ordering, boundaries, vendor/shared selection,
|
||||
size semantics, local-only reads, cancellation, and reader ownership.
|
||||
|
||||
**Verification:** Use a filtered sparse fixture with a complete selected module
|
||||
and unavailable blobs in an excluded sibling or nested module. Representative
|
||||
formatting, file-size, and explicit shared-file validation must work when their
|
||||
required inputs are available. A selected missing blob or required referenced
|
||||
destination must still produce the appropriate inspection error. Verify that
|
||||
excluded unreferenced blobs cause neither content reads nor transport.
|
||||
@@ -27,10 +27,10 @@ done
|
||||
```
|
||||
|
||||
Review and commit the generated tool, dependency, and checksum declarations.
|
||||
Release preparation records the chosen compatible version in these maintained
|
||||
module files. The feature roadmap leaves that release version to release
|
||||
preparation. The [adoption guide](../../docs/consumers/adoption.md) owns tool
|
||||
registration and coordinated tool/workflow upgrades.
|
||||
The [adoption guide](../../docs/consumers/adoption.md) owns tool registration and
|
||||
coordinated tool/workflow upgrades. The
|
||||
[v0.4.0 release note](../../docs/releases/v0.4.0.md) describes module-release
|
||||
support and migration from earlier versions.
|
||||
|
||||
## Module mapping and publication
|
||||
|
||||
|
||||
Reference in New Issue
Block a user