202 lines
11 KiB
Markdown
202 lines
11 KiB
Markdown
# Roadmap: separate shared delivery from forge adapters
|
|
|
|
Status: proposed; implementation has not started.
|
|
|
|
## Objective and scope
|
|
|
|
Introduce an internal boundary between shared hosted-release delivery and the
|
|
Gitea implementation. The result should support adding another forge through
|
|
an adapter while reusing ReleaseKit's release and asset-delivery policy.
|
|
|
|
ReleaseKit's `Publish` operation validates and publishes source through Git.
|
|
Its `Deliver` operation verifies tagged source and delivers release notes and
|
|
declared assets to a hosting service. This refactor concerns the latter operation
|
|
and its composition through the existing public facade and CLI.
|
|
|
|
Gitea is the concrete backend for this work. Forgejo, GitHub, GitLab, and other
|
|
backends remain future implementation work. The boundary should express the
|
|
operations used by the current delivery workflow and allow refinement when a
|
|
second backend supplies concrete requirements.
|
|
|
|
## Current baseline
|
|
|
|
The source baseline is `ac78e7d`, following the published v0.5.0 module migration
|
|
and the subsequent token-file and forbidden-file changes.
|
|
|
|
- [delivery.go](../../delivery.go) exposes `GiteaDestination` through
|
|
`DeliveryRequest.Destination` and converts it into `gitea.Destination`.
|
|
- [internal/delivery](../../internal/delivery/delivery.go) resolves source
|
|
identity, checks tagged source, reads notes, coordinates builds, and directly
|
|
calls `gitea.Client` for release and asset operations. Its result conversion
|
|
and failure classification use Gitea-owned internal types.
|
|
- [release.go](../../internal/gitea/release.go) combines Gitea HTTP operations
|
|
with hosted-tag verification, matching-page acceptance, release creation,
|
|
and reconciliation of ambiguous creates.
|
|
- [assets.go](../../internal/gitea/assets.go) and
|
|
[upload.go](../../internal/gitea/upload.go) combine HTTP operations with
|
|
manifests, local-file verification, remote-content comparison, asset
|
|
observations, upload sequencing, and retry bookkeeping.
|
|
- CLI credential resolution supplies an explicit token from the configured
|
|
environment variable or token file. The profile describes a Gitea repository;
|
|
it has no forge selector.
|
|
|
|
The [Gitea integration guide](../integrations/gitea.md) and public Go declarations
|
|
document the baseline contracts. Current behavioral tests provide regression
|
|
coverage to assess against those contracts. The
|
|
[architecture policy](../policy/architecture.md) governs facade ownership and
|
|
dependency direction.
|
|
|
|
## Targeted end state
|
|
|
|
### Neutral public destination and explicit forge selection
|
|
|
|
Replace `GiteaDestination` with a facade-owned neutral destination type, such as
|
|
`DeliveryDestination`, and require explicit forge selection in the public API
|
|
and delivery configuration. Gitea is the sole supported selection initially.
|
|
An omitted, blank, or unsupported selection produces a validation error; Gitea
|
|
is selected explicitly rather than inferred from a default or destination URL.
|
|
|
|
The destination represents the addressing and credentials needed for current
|
|
delivery through neutral public names. Concrete backend construction uses the
|
|
selected forge. Additional backends may extend that model when their addressing
|
|
and protocol requirements are implemented.
|
|
|
|
### Shared delivery responsibilities
|
|
|
|
Shared internal code owns:
|
|
|
|
- Captured source identity, local tag/commit checks, committed release notes,
|
|
managed or prebuilt artifact coordination, and local artifact verification.
|
|
- The existing logical rules for accepting matching hosted content, reporting
|
|
conflicts, creating missing content, and reconciling uncertain writes.
|
|
- Manifest generation, content comparison, and asset observations used to decide
|
|
which declared assets require delivery.
|
|
- Aggregation into the existing public delivery outcomes and asset categories.
|
|
|
|
These operations consume backend-neutral internal values and operations. The
|
|
generic delivery workflow has no dependency on `internal/gitea`. The facade or
|
|
private composition code constructs the concrete backend and supplies it to
|
|
shared delivery.
|
|
|
|
### Backend responsibilities
|
|
|
|
The Gitea adapter owns destination validation specific to Gitea, API routes,
|
|
authentication headers, request and response formats, pagination, multipart
|
|
uploads, attachment downloads, and HTTP-specific error interpretation.
|
|
|
|
The internal contract supplies the logical operations needed to inspect a
|
|
hosted tag, find or create a release, enumerate assets, read asset content, and
|
|
upload an asset. Release and asset references carry backend-owned handles;
|
|
shared orchestration works with logical identity and content rather than
|
|
interpreting Gitea's positive integer IDs.
|
|
|
|
The contract also carries the evidence needed for existing recovery behavior:
|
|
whether a write was attempted, whether its outcome is established or uncertain,
|
|
and actionable failure information. Generic code interprets delivery outcomes;
|
|
the adapter interprets protocol responses. A logical backend operation may
|
|
involve multiple HTTP requests.
|
|
|
|
The operations and values stay internal under the existing facade policy.
|
|
Current Gitea behavior is the concrete compatibility target. This work does
|
|
not establish compatibility guarantees for unimplemented forges or a public
|
|
plugin protocol.
|
|
|
|
## Work required
|
|
|
|
### 1. Define the internal seam and dependency direction
|
|
|
|
- Inventory the data and operations currently crossing from `internal/delivery`
|
|
into `internal/gitea`, including asset identities, inspections, failure
|
|
categories, release references, and write-attempt evidence.
|
|
- Introduce a small internal contract shared by orchestration and adapters.
|
|
Choose its package placement to keep dependencies acyclic. Exact private
|
|
package and method names can follow the implementation's responsibilities.
|
|
- Represent the observed release data needed by current comparisons without
|
|
making Gitea wire structures part of the generic model. Keep numeric-ID and
|
|
repository-path-segment validation with the Gitea implementation.
|
|
- Put concrete backend construction in composition code, using the explicitly
|
|
selected forge from the neutral public destination.
|
|
|
|
### 2. Extract shared policy and artifact mechanics
|
|
|
|
- Move manifest generation and local content verification to shared internal
|
|
ownership, reusing the existing artifact package where appropriate.
|
|
- Move matching-page decisions, remote-content comparisons, missing-asset
|
|
selection, upload sequencing, reconciliation decisions, and result
|
|
aggregation out of the Gitea HTTP implementation.
|
|
- Preserve the current Gitea behavior for complete note bodies, existing page
|
|
titles, stable release state, content conflicts, unrelated attachments,
|
|
source-only delivery, and managed or prebuilt binary delivery.
|
|
- Preserve current write-history and uncertainty handling. In particular, a
|
|
read-only inspection failure and an unresolved write retain their distinct
|
|
meanings. Keep existing Gitea reconciliation behavior where the integration
|
|
contract specifies it, including the current follow-up lookup behavior.
|
|
- Retain the existing reuse of local verification and streamed content hashing
|
|
as responsibilities move. Preserve cancellation, stream closure, temporary
|
|
output ownership, and cleanup around uploads.
|
|
|
|
### 3. Adapt Gitea and reconnect the facade and CLI
|
|
|
|
- Replace `GiteaDestination` with the neutral facade-owned destination and add
|
|
required forge selection to the public API and delivery profile. Validate
|
|
omitted, blank, and unsupported selections without assuming Gitea.
|
|
- Implement the internal contract with the Gitea client. Keep Gitea JSON
|
|
decoding, HTTP status interpretation, URL escaping, credential forwarding,
|
|
redirect behavior, and upload transport in the adapter.
|
|
- Map protocol errors into shared outcomes while retaining useful causes and
|
|
Gitea HTTP details. Preserve documented diagnostics and cancellation behavior;
|
|
use existing contracts to decide which wording or interactions are meaningful.
|
|
- Reconnect `Deliver`, CLI `deliver` and `ci-deliver`, managed builds, and
|
|
prebuilt delivery through the same shared workflow and concrete Gitea adapter.
|
|
- Continue resolving credentials in the CLI and passing them explicitly. Token
|
|
environment/file selection and forbidden-file validation retain their
|
|
existing responsibilities.
|
|
|
|
### 4. Align tests and documentation with ownership
|
|
|
|
- Retain Gitea HTTP fixture tests for routes, payloads, authentication,
|
|
pagination, escaping, redirects, malformed responses, and transport failures.
|
|
- Move tests of manifests, content comparison, conflict handling, and result
|
|
aggregation to the shared layer as those responsibilities move. Use small
|
|
controlled backends where protocol-independent recovery needs an external
|
|
boundary; reuse existing behavioral cases and consolidate redundant coverage.
|
|
- Retain representative public-facade and CLI workflows proving that Gitea
|
|
page-only delivery, binary delivery, tagged retries, and failure reporting
|
|
continue to work through the assembled boundary with explicit Gitea selection.
|
|
Cover missing, blank, and unsupported selections in destination validation.
|
|
- Update the internal inventory and delivery documentation when implementation
|
|
lands. Keep Gitea protocol details in the integration guide and shared
|
|
orchestration details in internal documentation. Update public GoDoc,
|
|
configuration, examples, and ReleaseKit's own profile for the neutral
|
|
destination and explicit Gitea selection. Supply migration guidance in the
|
|
next minor release for the public type replacement and profile changes,
|
|
consistent with the project's direct-cutover approach.
|
|
- Record the accepted architectural boundary in an ADR when its design is
|
|
settled, following the [documentation policy](../policy/documentation.md#architecture-decision-records).
|
|
|
|
## Verification and completion
|
|
|
|
Follow the [testing policy](../policy/testing.md) and reuse existing tests where
|
|
they protect the relevant behavior. Run focused checks while moving
|
|
responsibilities, then the complete offline suite and compiled
|
|
API/dependency-boundary checks from the [development guide](../development.md#validation).
|
|
The final full-suite run also covers the affected executable workflows.
|
|
|
|
Review the resulting imports and data flow as well as test results: generic
|
|
orchestration and artifact policy should consume the internal contract, with
|
|
Gitea transport selected through composition. Exercise an internal test backend
|
|
at that seam to verify that shared logic can operate independently of the Gitea
|
|
client. Keep the test collaborator proportionate to the cases it protects.
|
|
|
|
Completion means the shared workflow and asset policy have independent internal
|
|
ownership, the Gitea adapter implements the boundary, the existing Gitea
|
|
contracts pass through that boundary, and documentation describes the resulting
|
|
structure. The neutral public destination and required forge selection are
|
|
reflected consistently in declarations, profiles, examples, and migration
|
|
guidance.
|
|
|
|
This is an architectural refactor of the implemented Gitea delivery path.
|
|
Support claims and compatibility testing for additional forges belong to the
|
|
work that implements those backends. Release preparation and publication
|
|
continue under the [existing procedure](../release.md).
|