Plan implementation of individual module releases
This commit is contained in:
158
docs/roadmap/commandkit-feature-request.md
Normal file
158
docs/roadmap/commandkit-feature-request.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# 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.
|
||||
647
docs/roadmap/implementation.md
Normal file
647
docs/roadmap/implementation.md
Normal file
@@ -0,0 +1,647 @@
|
||||
# Implementation plan: individual Go module releases
|
||||
|
||||
Status: ready for implementation.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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`.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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 `docs/roadmap/next-release-notes.md` as 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.
|
||||
|
||||
### 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.
|
||||
@@ -10,9 +10,9 @@ ReleaseKit's API and CLI. CommandKit's core and optional integrations provide th
|
||||
consumer case. Each invocation should require only module selection, product
|
||||
settings, and a semantic version, with ReleaseKit owning the common mechanics.
|
||||
|
||||
This roadmap describes the target and the work from the current baseline. It
|
||||
does not select a ReleaseKit release version or prescribe a staged implementation
|
||||
plan. The decisions recorded below govern the planned scope.
|
||||
This roadmap defines the target state and its scope and ownership decisions.
|
||||
The [implementation plan](implementation.md) owns the ordered work from the
|
||||
current baseline. This roadmap does not select a ReleaseKit release version.
|
||||
|
||||
## Current baseline
|
||||
|
||||
@@ -69,212 +69,68 @@ 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.
|
||||
|
||||
## Work needed
|
||||
## Capability requirements
|
||||
|
||||
### 1. Establish a shared module and release identity
|
||||
### Module and release identity
|
||||
|
||||
**Rationale:** One resolved identity prevents checks and publication from using
|
||||
different interpretations of the selected module or tag.
|
||||
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.
|
||||
|
||||
**Target:** Distinct repository directory, module directory, semantic version,
|
||||
and complete tag are available throughout candidate handling and public evidence.
|
||||
### Coherent validation scope
|
||||
|
||||
**Work:** Add an optional repository-relative module selection to the public
|
||||
request and profile, with root defaults. Resolve it against the captured
|
||||
repository and source appropriate to the operation once at the operation entry
|
||||
point. Check, publication, and delivery use committed module declarations.
|
||||
Standalone builds use the selected module's working-tree `go.mod`, following
|
||||
the [declaration-source decision](#declaration-source-by-operation).
|
||||
Pass the resolved identity through the operation's validation, publication,
|
||||
build, and delivery collaborators. Standalone operations use the same resolution
|
||||
logic. Derive tags using Go's standard module conventions, including
|
||||
major-version directories: a `/v2` module stored at `integrations/ckconfig/v2`
|
||||
uses `integrations/ckconfig/v2.0.0` for `v2.0.0`.
|
||||
The same module stored at `integrations/ckconfig` uses that complete tag too.
|
||||
Support both physical layouts and distinguish the module directory from its
|
||||
tag prefix.
|
||||
Carry the resolved identity through facade conversions, internal requests,
|
||||
callbacks, results, and CLI diagnostics. Keep semantic-version validation
|
||||
separate from full-tag handling. Exact field names belong in API design.
|
||||
Keep shared identity resolution separate from each operation's prerequisites.
|
||||
Populate resolved identity in public evidence as resolution succeeds, including
|
||||
when a later step fails.
|
||||
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.
|
||||
|
||||
### 2. Apply one validation scope
|
||||
### Notes, publication, and recovery
|
||||
|
||||
**Rationale:** Consumers should select the release unit once and receive
|
||||
consistent validation across enabled checks.
|
||||
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.
|
||||
|
||||
**Target:** Tests, vet, package compilation, formatting, distribution checks,
|
||||
file-size checks, Markdown, and product-check context all correspond to the
|
||||
selected module and its relevant release materials.
|
||||
### Builds, receipts, and hosted delivery
|
||||
|
||||
**Work:** Give the existing shared validation path both repository context and
|
||||
module scope. Run Go commands in the module directory with the existing
|
||||
offline and workspace-disabled environment. Select committed file inputs once
|
||||
under the agreed boundary convention and apply that selection to each content
|
||||
check. Build one ordered input set and retain the full repository lookup
|
||||
separately for resolving Markdown destinations and existing committed-file
|
||||
references. A link to another module may be checked for existence or its
|
||||
target heading without scanning that module's unrelated documents.
|
||||
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.
|
||||
|
||||
Update module-distribution inspection to examine the selected release's inputs.
|
||||
For example, an unrelated sibling's filesystem replacement should not fail the
|
||||
selected module's check. Add shared files through the
|
||||
[resolved selection rules](#shared-file-validation-inputs), carrying the selection
|
||||
through the public request and profile and applying it to the shared file inputs.
|
||||
Keep the optional checks optional and retain their existing individual rules,
|
||||
error identities, cancellation, and cause propagation apart from the intended
|
||||
scope change. Apply the boundary and path conventions recorded below.
|
||||
### CLI and module-selected CI
|
||||
|
||||
### 3. Bind notes and publication to the resolved identity
|
||||
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.
|
||||
|
||||
**Rationale:** Different modules can use the same semantic version while
|
||||
publishing distinct source identities and release notes.
|
||||
### Complete adoption guidance and behavioral evidence
|
||||
|
||||
**Target:** The selected module's committed note identifies its product and
|
||||
semantic version. Publication and recovery address its complete tag.
|
||||
|
||||
**Work:** Resolve module-local note paths and retain existing title validation
|
||||
and captured note bytes. Thread the complete tag through local guards, remote
|
||||
guards, annotated-tag creation, exact-object push, and bounded reconciliation.
|
||||
Include the module, version, and resolved tag in success and failure evidence
|
||||
as available, alongside commit, endpoint, phase, state, and tag object. Preserve
|
||||
the existing publication outcomes and repository checks. Root notes and tags
|
||||
retain their ordinary forms.
|
||||
|
||||
### 4. Carry module identity through builds and delivery
|
||||
|
||||
**Rationale:** A selected module should mean the same release unit throughout
|
||||
ReleaseKit's supported operations.
|
||||
|
||||
**Target:** Standalone builds, candidate build checks, direct delivery, and
|
||||
prebuilt-asset delivery all operate on the selected module. Hosted pages use
|
||||
its complete tag and module-local note; binaries report its semantic version.
|
||||
|
||||
**Work:** Extend build and delivery requests and profile mapping with the
|
||||
shared module identity. Resolve main packages and module-owned build paths
|
||||
from the module directory. Prepare build dependencies there, and preserve
|
||||
existing offline artifact compilation and version smoke checks. Reuse
|
||||
operation-local Go settings between validation and subsequent builds when
|
||||
their environment inputs match. Carry module identity through build results
|
||||
and receipts so prebuilt delivery verifies the selected module, version, tag
|
||||
where applicable, candidate commit, settings, and artifact hashes. Keep
|
||||
ordinary local builds usable without requiring a published tag.
|
||||
|
||||
Use the full tag for tagged-checkout verification, Gitea release lookup and
|
||||
creation, and source links. Use the semantic version for binary version injection
|
||||
and module release titles. Select the module-local note and retain existing
|
||||
page/asset conflict, retry, and partial-delivery behavior. Test source URLs with
|
||||
slash-containing tags. Distinct module tags can have separate Gitea pages at the
|
||||
same commit. A page-only profile continues to require no application binary.
|
||||
Use the new module-bound receipt format for prebuilt delivery. Consumers
|
||||
regenerate receipts through the updated build operation as part of the clean
|
||||
cutover described below.
|
||||
Normalize build settings once for build execution, receipt binding, and
|
||||
comparison. Receipt loading owns structure and identity validation; delivery
|
||||
owns the local content-verification pass before hosted requests. Build-time
|
||||
hashing records produced bytes independently.
|
||||
|
||||
### 5. Support module-aware CI delivery
|
||||
|
||||
**Rationale:** Local operations and tagged-source delivery need the same module,
|
||||
profile, and version selection.
|
||||
|
||||
**Target:** The maintained consumer workflow accepts root and nested-module tags,
|
||||
selects the corresponding profile, and delivers only that module's release.
|
||||
Tool selection follows the tagged module configuration under
|
||||
[ADR 0004](../adr/0004-module-selected-tooling.md).
|
||||
|
||||
**Work:** Extend tagged-checkout preparation and `ci-deliver` to distinguish the
|
||||
full event tag from the semantic version. Adapt tag filters, profile selection,
|
||||
tool bootstrap, and application dependency preparation. Use an explicit
|
||||
module/profile mapping or equivalent small consumer declaration from the
|
||||
verified tagged checkout. Resolve the physical module directory and profile
|
||||
before tool bootstrap, and keep the selection consistent with the derived tag.
|
||||
Verify the event commit before resolving that mapping and use the tagged
|
||||
source's selected module files on retries.
|
||||
Use the same small consumer selection declaration for the launcher and CI.
|
||||
Bootstrap selects the module and profile; ReleaseKit verifies their consistency
|
||||
with the derived identity. Reuse the verified checkout after tool bootstrap
|
||||
with fresh read-only source checks. Standalone `ci-deliver` owns preparation
|
||||
when it is needed.
|
||||
For ordinary root tags, use the root profile and module bootstrap defaults.
|
||||
Consumers using that pattern supply no module/profile mapping declaration.
|
||||
Preserve temporary bootstrap metadata and existing credential handling. Cover
|
||||
major-version directory layouts without assuming that trimming the tag always
|
||||
identifies the physical module directory. Include page-only and binary examples.
|
||||
|
||||
### 6. Make API and CLI adoption small and coherent
|
||||
|
||||
**Rationale:** The shared release operation should replace consumer publication
|
||||
logic with small per-module declarations.
|
||||
|
||||
**Target:** A shared launcher can select a profile and pass a semantic version;
|
||||
API consumers express the equivalent operation. Additional checks receive
|
||||
module context and repository context for explicit composition work.
|
||||
|
||||
**Work:** Map profile selection into the shared request, document relative-path
|
||||
behavior, and provide module/tag context to configured commands. Retain existing
|
||||
profile selection through `--config`; a separate CLI override for the module is
|
||||
not needed to satisfy the initial request. Add a maintained multi-module example
|
||||
showing root and integration profiles and a small shared launcher. Show dependency
|
||||
preparation before offline validation and sequential sibling releases when a
|
||||
dependency version must be published first. Keep product checks focused on
|
||||
consumer assertions instead of repeating the standard suite.
|
||||
Preserve the [simple root-module experience](#simple-single-module-experience),
|
||||
including a small
|
||||
profile, launcher, and CI workflow with no additional required declarations.
|
||||
|
||||
### 7. Verify and document the complete behavior
|
||||
|
||||
**Rationale:** This changes release identity and validation boundaries, including
|
||||
the behavior of root modules with nested modules.
|
||||
|
||||
**Target:** Representative public API and CLI workflows establish that the
|
||||
selected module is validated and only its intended tag is published.
|
||||
|
||||
**Work:** Extend existing behavioral tests using local repositories and
|
||||
remotes. Cover root defaults; nested-module failure while the root suite
|
||||
passes; equal versions across modules; major versions with and without
|
||||
physical major-version directories; full-tag reuse; and failed or unknown
|
||||
publication with the correct recovery identity. Exercise optional checks with
|
||||
violations inside and outside the selected scope, parent selection excluding
|
||||
independent nested modules, and cross-module Markdown references. Cover
|
||||
omitted, replacement, and empty shared-file lists; optional default files;
|
||||
missing explicit files; committed-tree lookup; duplicate inputs; and explicit
|
||||
files in another module. Verify selection errors when optional file checks are
|
||||
disabled, and that shared-file selection preserves enabled checks and Go
|
||||
scope. Verify that repository guards still observe changes outside the
|
||||
selected module and that module selection does not repeat the standard suite.
|
||||
Reuse existing failure tests where they already protect unchanged behavior.
|
||||
Add representative nested-module build/version-injection, new-format receipt
|
||||
ownership and cutover, Gitea page/asset, and CI tag/profile/tool-selection
|
||||
coverage. Use local HTTP servers for delivery and isolated synthetic module
|
||||
proxies for bootstrap tests. Verify that retries use the original module
|
||||
selection and full tag after the default branch changes. Verify a
|
||||
representative simple root-module API call, profile, launcher, and CI workflow
|
||||
using the new interface's defaults. Confirm that routine use adds no required
|
||||
configuration fields, mapping declarations, or consumer decisions. Give
|
||||
identity derivation, scope selection, and path conversion focused tests at
|
||||
their owners. Use representative assembled workflows and reuse existing
|
||||
failure coverage where the underlying behavior remains shared. Verify
|
||||
preserved empty lists, contextual findings for equal blobs at different paths,
|
||||
failure identity, and artifact-verification ownership. Cover standalone builds
|
||||
with modified declarations or new module directories, composite builds using
|
||||
committed identity, and source verification required for delivery.
|
||||
|
||||
Update GoDoc, CLI/configuration references, check/publication/build/delivery guides,
|
||||
adoption examples, CI templates, and recovery guidance together. Supply migration
|
||||
guidance in the next release's documentation, covering API and profile updates,
|
||||
receipt regeneration, CI mapping, and root-module scope changes, including
|
||||
exclusion of nested fixture modules from automatic file checks. Document
|
||||
semantic version versus full tag in note titles and source/licensing links.
|
||||
ReleaseKit's own maintainer policy continues to describe its root-module release;
|
||||
consumer guidance explains how
|
||||
multi-module consumers adapt their policies. Run the normal offline suite and
|
||||
public API checks for implementation changes; validate documentation links and
|
||||
examples. Synthetic dependency fixtures use isolated module caches.
|
||||
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
|
||||
|
||||
@@ -459,9 +315,9 @@ 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.
|
||||
|
||||
Implementation may proceed in stages; feature completion includes all of these
|
||||
operations. Omitted module selection uses the root module, and source publication
|
||||
and asynchronous delivery retain their separate outcomes.
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user