358 lines
20 KiB
Markdown
358 lines
20 KiB
Markdown
# Roadmap: release individual Go modules
|
|
|
|
Status: planned feature; scope decisions resolved.
|
|
|
|
## 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 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.
|
|
|
|
## 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
|
|
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.
|
|
|
|
## 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 once at the operation entry point.
|
|
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.
|
|
|
|
### 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. 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.
|
|
|
|
### 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. 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. 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.
|
|
|
|
### 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.
|
|
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.
|
|
|
|
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.
|
|
|
|
## 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.
|
|
|
|
### 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. 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.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
### 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.
|