85 lines
4.0 KiB
Markdown
85 lines
4.0 KiB
Markdown
# ADR 0001: Own public contracts through facades
|
|
|
|
## Status
|
|
|
|
Accepted.
|
|
|
|
## Date
|
|
|
|
2026-10-05
|
|
|
|
## Context
|
|
|
|
ReleaseKit is being designed as an opinionated Go library with a release
|
|
executable. Its responsibilities include publication, cross-builds, version
|
|
injection, and artifact delivery. Consuming applications also need lightweight
|
|
access to the version embedded in their binaries.
|
|
|
|
ConfigKit and PromptKit demonstrate a facade approach in which public packages
|
|
own consumer contracts and delegate to internal implementation. This gives
|
|
maintainers room to change internal structure while preserving supported type
|
|
identity, method sets, and behavior. ReleaseKit needs that boundary from its
|
|
first implementation.
|
|
|
|
## Decision
|
|
|
|
The root `releasekit` package is the public facade for release orchestration. A
|
|
separate public `buildinfo` package is the facade for runtime version information.
|
|
Each package exposes a cohesive set of operations and values justified by
|
|
consumer needs.
|
|
|
|
Each facade defines its public named types and owns their documented behavior.
|
|
Exported signatures, fields, callbacks, and method sets use facade-owned types
|
|
and deliberately selected public dependencies. Handles retain implementation
|
|
state in private fields and expose explicitly selected methods. Forwarding and
|
|
conversion code translates between public contracts and internal representations.
|
|
|
|
Implementation packages live under Go's `internal/` boundary. Dependency
|
|
direction runs from public facades into internal implementation. Contracts shared
|
|
between implementation packages belong inside that boundary. Git operations, Go
|
|
toolchain execution, Gitea integration, and orchestration bookkeeping remain
|
|
implementation responsibilities, with package layout chosen for cohesion.
|
|
|
|
The `buildinfo` facade has a lightweight dependency graph suitable for application
|
|
runtime imports. Its version accessor is a supported public contract. ReleaseKit's
|
|
builder and runtime implementation own the linker symbol and injection mechanism
|
|
together, allowing applications to obtain their version through the accessor.
|
|
|
|
The release executable invokes the supported orchestration facade and owns
|
|
command parsing, output, and exit codes. The library returns consumer-facing
|
|
errors and outcomes that describe publication state, including partial progress
|
|
and uncertainty.
|
|
|
|
Go declarations and GoDoc own exact public API contracts. Additional public
|
|
packages and extension interfaces require a deliberate decision grounded in a
|
|
durable consumer need. Compiled-export and dependency checks protect facade
|
|
ownership; external-package behavioral tests protect consumer semantics.
|
|
|
|
## Alternatives considered
|
|
|
|
- Keep implementation in public packages: reduces forwarding work and makes
|
|
implementation declarations part of the surface contributors must maintain.
|
|
- Use aliases or embedded implementation types: reduces conversion code while
|
|
coupling consumer type identity and method sets to implementation types.
|
|
- Provide one facade for orchestration and runtime version access: offers one
|
|
import path and a shared dependency graph for both responsibilities.
|
|
- Expose a public package for each implementation component: enables direct
|
|
component reuse and expands the compatibility surface across Git, build, and
|
|
delivery machinery.
|
|
|
|
## Consequences
|
|
|
|
Consumers depend on deliberate contracts in `releasekit` and `buildinfo`.
|
|
Internal algorithms, collaborators, and package boundaries can evolve while
|
|
those contracts remain stable. Both public packages participate in ReleaseKit's
|
|
versioning and compatibility obligations.
|
|
|
|
Explicit forwarding and conversions add maintenance work. They must preserve
|
|
error identity, value ownership, callback lifetime, and observable outcomes.
|
|
Boundary checks and representative consumer tests provide evidence for those
|
|
properties as implementation proceeds.
|
|
|
|
The separate `buildinfo` facade supports runtime use with a small dependency
|
|
surface. Its integration with the builder requires tests that verify the selected
|
|
release version is injected and reported correctly.
|