Plan module-scoped release support
This commit is contained in:
241
docs/roadmap/module-releases.md
Normal file
241
docs/roadmap/module-releases.md
Normal file
@@ -0,0 +1,241 @@
|
||||
# Roadmap: release individual Go modules
|
||||
|
||||
Status: planned feature; open recommendations await resolution.
|
||||
|
||||
## Purpose
|
||||
|
||||
Implement [ADR 0005](../adr/0005-module-release-scope.md) so a consumer can check
|
||||
and publish 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 describes the target and the work from the current baseline. It
|
||||
does not select a ReleaseKit release version or prescribe a staged implementation
|
||||
plan. Recommendations under Open Decisions are proposals, not accepted contracts.
|
||||
|
||||
## Current baseline
|
||||
|
||||
The baseline is ReleaseKit v0.3.0 plus accepted ADR 0005; module selection is
|
||||
not implemented.
|
||||
|
||||
- `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.
|
||||
|
||||
The existing candidate capture, declarative validation, exact-object publication,
|
||||
and outcome reporting provide the foundation. Scope and identity need to be
|
||||
carried through those paths together.
|
||||
|
||||
## 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
|
||||
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.
|
||||
Dependency preparation and sibling release ordering remain consumer activities.
|
||||
|
||||
The feature covers individual releases. Batch publication, automatic release
|
||||
selection, dependency-driven versioning, and arbitrary tag templates remain
|
||||
outside this roadmap. Artifact and hosted-delivery integration is an open scope
|
||||
decision below. This work adds no consumer-installation, proxy-availability, CI,
|
||||
or hosted-delivery completion gate.
|
||||
|
||||
## Work needed
|
||||
|
||||
### 1. Establish a shared module and release identity
|
||||
|
||||
**Rationale:** One resolved identity prevents checks and publication from using
|
||||
different interpretations of the selected module or tag.
|
||||
|
||||
**Target:** Distinct repository directory, module directory, semantic version,
|
||||
and complete tag are available throughout candidate handling and public evidence.
|
||||
|
||||
**Work:** Add an optional repository-relative module selection to the public
|
||||
request and profile, with root defaults. Resolve it against the captured
|
||||
repository and committed module declaration. 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`.
|
||||
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.
|
||||
|
||||
### 2. Apply one validation scope
|
||||
|
||||
**Rationale:** Consumers should select the release unit once and receive
|
||||
consistent validation across enabled checks.
|
||||
|
||||
**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.
|
||||
|
||||
**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.
|
||||
Retain repository access 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.
|
||||
|
||||
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. Determine relevant shared release materials through
|
||||
existing conventions; shared files should not pull in an entire parent tree.
|
||||
Keep the optional checks optional and retain their existing individual rules,
|
||||
error identities, cancellation, and cause propagation apart from the intended
|
||||
scope change. Resolve boundary identification and path conventions below before
|
||||
finalizing these contracts.
|
||||
|
||||
### 3. Bind notes and publication to the resolved identity
|
||||
|
||||
**Rationale:** Different modules can use the same semantic version while
|
||||
publishing distinct source identities and release notes.
|
||||
|
||||
**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. 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.
|
||||
|
||||
### 5. 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-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.
|
||||
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.
|
||||
|
||||
Update GoDoc, CLI/configuration references, check/publication guides, adoption
|
||||
examples, and recovery guidance together. Explain root-module scope changes in
|
||||
the release note and migration guidance. 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.
|
||||
|
||||
## Open Decisions
|
||||
|
||||
### 1. How should nested module boundaries be recognized?
|
||||
|
||||
**Recommendation:** 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. Specify treatment of
|
||||
vendored content and fixture modules before implementation: vendored material
|
||||
remains part of the selected module's file-check inputs, while nested fixture
|
||||
modules can be exercised through the parent's tests or product checks. A
|
||||
repository-level workspace file outside a selected nested module's scope would
|
||||
not fail that module's workspace-file check merely because it exists.
|
||||
|
||||
The tradeoff is that a nested fixture module can be excluded from generic file
|
||||
checks even when it has no independent release. That distinction needs clear
|
||||
documentation and representative tests.
|
||||
|
||||
**Alternative:** Declare independently released module directories explicitly
|
||||
and exclude only those boundaries. This distinguishes products from fixtures
|
||||
precisely and keeps fixture files in their parent's generic validation. It adds
|
||||
a declaration consumers must maintain and coordinate with their module layout.
|
||||
It is viable if real consumers need that distinction enough to justify the
|
||||
configuration.
|
||||
|
||||
### 2. Which directory anchors relative paths and product commands?
|
||||
|
||||
**Recommendation:** Anchor module selection and profile lookup at the repository;
|
||||
anchor module-owned validation settings, such as 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. This makes a
|
||||
per-module profile self-contained while retaining unambiguous findings.
|
||||
|
||||
Existing root profiles retain their meaning. Nested-module launchers would use
|
||||
the provided repository context when invoking shared scripts. Document these
|
||||
rules together rather than adding a path-base switch to each check.
|
||||
|
||||
**Alternative:** Keep configuration paths and product-command execution
|
||||
repository-relative, while shared check inputs remain module-scoped. This
|
||||
preserves the current conventions and makes shared script invocation direct.
|
||||
It requires module prefixes in otherwise module-specific settings and makes
|
||||
moving or copying profiles more cumbersome. Both choices can implement the
|
||||
accepted validation scope.
|
||||
|
||||
### 3. Should nested-module builds and hosted delivery ship with publication?
|
||||
|
||||
**Recommendation:** Deliver the requested source-only `Check` and `Publish`
|
||||
capability first. Keep existing root build/delivery workflows working and document
|
||||
the supported boundary. For that initial increment, report an unsupported
|
||||
nested-module artifact-build request before validation or publication rather
|
||||
than building the root product under the nested module's release identity.
|
||||
This proposed limitation requires an explicit scope decision; it is not imposed
|
||||
by ADR 0005. Package compilation remains part of module validation and is covered
|
||||
by this roadmap.
|
||||
|
||||
This meets CommandKit's immediate need with a focused change, at the cost of
|
||||
requiring follow-up work for consumers needing nested-module artifacts or hosted
|
||||
pages. Review shared profile handling so unsupported delivery paths do not
|
||||
silently interpret a nested module as the root product.
|
||||
|
||||
**Alternative:** Extend artifact builds and hosted delivery in the same release.
|
||||
This gives every release operation the same module model immediately. It adds
|
||||
work on build paths, semantic-version injection, receipts, tag verification,
|
||||
note/source URLs, dependency preparation, and CI profile/tool selection. The
|
||||
maintained tag filter and root-only bootstrap also need adaptation. This is a
|
||||
viable cohesive release if those consumers are ready; it expands the sprint
|
||||
beyond the source-only publication request. Delivery remains asynchronous under
|
||||
either choice.
|
||||
Reference in New Issue
Block a user