Files
releasekit/docs/roadmap/forge-boundary.md

6.9 KiB

Roadmap: separate shared delivery from forge adapters

Status: accepted; implementation has not started.

The implementation plan owns stages, concrete design choices, task sequencing, and verification.

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 exposes GiteaDestination through DeliveryRequest.Destination and converts it into gitea.Destination.
  • internal/delivery 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 combines Gitea HTTP operations with hosted-tag verification, matching-page acceptance, release creation, and reconciliation of ambiguous creates.
  • assets.go and 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 and public Go declarations document the baseline contracts. Current behavioral tests provide regression coverage to assess against those contracts. The architecture policy 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 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.

Behavioral scope and compatibility

The refactor preserves the existing Gitea delivery contracts for complete note bodies, retained existing titles, stable release state, content conflicts, unrelated attachments, additive retries, and source-only or binary delivery. Read-only inspection failures and unresolved writes retain their distinct outcomes. Recovery retains write history, including confirmed progress after an ambiguous create. The current integration guide owns the concrete protocol and follow-up lookup behavior.

Local verification reuse, streaming, cancellation, stream closure, temporary build ownership, and upload cleanup remain part of the affected workflow. Credential environment/file selection and forbidden-file validation retain their existing responsibilities. Backend-specific address validation stays with that backend.

The public destination replacement and required forge selection are deliberate API and configuration changes for the next minor release. Migration guidance describes the consumer edits under the project's direct-cutover approach. Current contract documents and examples change with implementation; historical release notes retain their original contents.

Completion means shared delivery and asset policy have independent internal ownership, Gitea implements the backend boundary, existing Gitea contracts work through it, and the neutral public destination and explicit selection are consistent across the API, configuration, examples, and documentation.

Additional forge implementations and compatibility claims belong to later work. Release preparation and publication continue under the existing procedure.