5.5 KiB
ADR 0005: Select a Go module as the unit of release
Status
Accepted.
Date
2026-10-09
Context
A Go repository can contain independently versioned modules. CommandKit plans to release its core and optional integrations from one repository. Each module needs its own validation, release note, semantic version, and Git tag.
ReleaseKit currently couples the semantic version to the Git tag and uses the repository directory for Go validation and release-note discovery. Supporting independent modules through consumer-owned publication code would duplicate ReleaseKit's responsibilities.
ADR 0002 prioritizes routine releases with little application-owned code or recurring decision-making. ADR 0003 establishes shared declarative validation. Module selection should give those checks a coherent release scope.
Decision
Each check or publication invocation selects one Go module within a Git repository. Omitted module selection means the repository-root module. The public Go API and CLI/profile interface express the same selection. Consumers can use small per-module profiles through a shared launcher.
ReleaseKit distinguishes the repository directory, selected module directory,
semantic version, and complete Git tag. It derives the tag using Go's module
tag conventions and the selected module's committed declaration. Derivation
accounts for major-version directories. For example, a module in
integrations/ckconfig at v0.2.0 uses the tag
integrations/ckconfig/v0.2.0. A module declared with a /v2 suffix and stored
in integrations/ckconfig/v2 uses integrations/ckconfig/v2.0.0 for v2.0.0.
The semantic version identifies the module release. The complete tag identifies its source in the shared repository and governs uniqueness, tag creation, publication, source links, and recovery. Candidate evidence, publication results, and CLI output identify the selected module and both version and tag, alongside the existing commit and publication evidence. Failure outcomes retain the resolved identity for recovery.
Release notes belong at <module-directory>/docs/releases/<version>.md and
identify the product and semantic version in their title. ReleaseKit reads the
selected note from the captured candidate. Root-module releases retain the
existing note layout and unprefixed tags. Modules can publish equal semantic
versions through their distinct notes and tags.
Mandatory and optional release validation share the selected module's scope. Go tests, selected vet, and package compilation execute in that module with the existing offline environment. File checks inspect the module's committed contents and relevant release materials. Independently released nested modules are excluded from their parent's validation scope. Selecting the root module follows the same rule.
A check may inspect referenced material outside the selected module when needed to validate an in-scope item. Resolving a Markdown link to shared repository documentation does not add that destination's documents to the validation input set. The checkout remains the boundary for checks of outside-checkout links. Shared release materials follow established conventions and documented consumer requirements.
Product-specific checks receive the selected module context and repository context for deliberate composition checks. ReleaseKit applies module selection consistently across its shared checks, avoiding separate scope settings for each check.
Publication guards cover the shared repository: cleanliness, branch, candidate commit, authoritative endpoint, and the complete selected tag. The standard suite runs once for the selected candidate and module. Successful source-tag publication remains the completion point, with existing failure and uncertain publication outcomes preserved. Consumers prepare released sibling dependencies and choose their publication order.
Alternatives considered
- Consumer-owned module publication gives each application responsibility for tag conventions, validation, and recovery, duplicating shared mechanics.
- Module-local Go execution with repository-wide optional validation lets unrelated modules block a selected release and gives checks inconsistent scopes.
- Independent scope settings for each check require consumers to coordinate multiple declarations of the same release boundary.
- Coordinated multi-module publication adds release-set and dependency-ordering responsibilities beyond the demonstrated need for individual releases.
Consequences
Consumers describe the module and product being released while ReleaseKit owns the common procedure. Existing single-module repositories retain their default behavior. Root modules containing independently released nested modules gain module-scoped validation; release notes and migration guidance must explain that change.
The shared candidate and publication paths must carry module scope and separate version and tag identity throughout validation, diagnostics, and recovery. Verification must cover root defaults, nested-module failures, equal versions across modules, major-version directories, validation boundaries, and exact-tag publication outcomes.
GoDoc and consumer documentation will own exact API and scope contracts. Configuration and CLI documentation will own profile fields, commands, and output. Implementation planning will define interactions with artifact builds and hosted delivery. ReleaseKit's maintainer release policy continues to govern ReleaseKit's own releases; consumers document their adopted module conventions.