# Deliver a tagged source release Use `releasekit.Deliver` or the `deliver` command after a source tag exists. Delivery status is separate from source publication: a delivery problem does not move or remove the tag, and a retry can use the same immutable version. The operation accepts historical lightweight and annotated tags, including a detached checkout, when the checked-out `HEAD` identifies the selected tag commit. It does not require the old remote `main` to match. ## CI preparation Use `PrepareTaggedCheckout` when a disposable CI checkout must be verified against the commit that triggered the job. It fetches only the selected tag from the chosen remote (default `origin`), compares the peeled tag commit with the expected commit, and checks out that commit detached. Fetch or checkout conflicts are returned so the caller can replace or repair the workspace. Cancellation is returned to the caller; the operation does not publish a tag or hosted content. ```go err := releasekit.PrepareTaggedCheckout(ctx, releasekit.TaggedCheckoutRequest{ RepositoryDir: repositoryDir, Version: version, ExpectedCommit: ciCommit, }) if err != nil { return err } ``` For binary profiles, call `PrepareBuildDependencies(ctx, repositoryDir)` after checkout preparation and before delivery. It runs `go mod download` with workspace discovery disabled and the available compatible local Go toolchain. The operation may use the network and updates the Go module cache while preserving the caller's proxy, private-module, credential, and cache settings. If checksums are missing, Go may update `go.sum`; see the [Go Modules Reference](https://go.dev/ref/mod#go-mod-download). Cancellation and command errors are returned. Page-only profiles do not need dependency preparation. ## Command line Add a Gitea destination to the profile: ```json { "product": "Example", "delivery": { "base_url": "https://gitea.example", "owner": "example", "repository": "example", "token_env": "RELEASEKIT_GITEA_TOKEN" } } ``` Fetch and check out the immutable tag, then deliver it: ```sh git checkout --detach v1.2.3 RELEASEKIT_GITEA_TOKEN="$GITEA_TOKEN" releasekit deliver v1.2.3 ``` The CLI reads the named token variable only for `deliver`; its default name is `RELEASEKIT_GITEA_TOKEN`. It verifies the local checkout and hosted tag before creating or accepting a hosted release page. The full checked-in note is the hosted body. A retry accepts an identical page and matching attachments, adds only missing assets, and reports conflicts without replacing content. With no build targets, delivery is page-only: no builder, version smoke check, receipt, binary asset, or checksum manifest is involved. With selected targets, one `deliver` invocation builds the tagged source through the facade into temporary storage and delivers the result. To retain artifacts for a retry or separate credentials between build and delivery, use two invocations: ```sh releasekit build --output dist v1.2.3 RELEASEKIT_GITEA_TOKEN="$GITEA_TOKEN" releasekit deliver --assets dist v1.2.3 ``` The build command does not need delivery credentials. The `--assets DIR` directory must contain the private `.releasekit-build.json` receipt created by `build`. ReleaseKit checks the receipt's repository, commit, version, resolved build settings, and file hashes before making a remote request; caller-owned files remain available for retries. Ordinary `deliver` does not download application dependencies or change the checkout. The result reports `complete`, `partial`, `conflict`, `unknown`, or `not_attempted`, along with matching, uploaded, pending, conflicting, and uncertain assets when known. These are disjoint current observations: an asset appears in at most one category, and early failures may leave some declared assets unreported. `Matching` means existing content matches; `Uploaded` means an upload was confirmed during this invocation; `Pending` means known missing work; `Conflicting` means different hosted content was found; `Uncertain` means the remote state could not be resolved. Fix local or preflight failures before retrying. For partial delivery, fix the reported cause and retry the same version. Resolve an unknown remote outcome before retrying. Investigate conflicts and use a new version if the source or published content needs correction. If rebuilding could change bytes already on the server, retain the original build output and retry with `--assets DIR`. The command does not run candidate checks or publish tags. ## Go API Pass the Gitea credential explicitly. Set `Build` to a `BuildSpec` to compile selected targets as part of delivery. The facade verifies the local tag, clean checkout, and committed release note before compiling. Managed output is stored outside the checkout and removed when delivery returns. `Output` receives build progress. With no build, or with an empty target set, delivery is page-only. To deliver binaries built separately, set `Prebuilt` to the `BuildResult`. ReleaseKit checks that it identifies the selected repository, tagged commit, and version, that its source was verified clean and unchanged during compilation, and that the current files still match their recorded digests. The files remain caller-owned, so callers can retain the original bytes for retries and are responsible for cleanup. With neither artifact source, an empty managed target set, or an empty prebuilt result, delivery is page-only. Do not set both `Build` and `Prebuilt` in one request. ```go result, err := releasekit.Deliver(ctx, releasekit.DeliveryRequest{ RepositoryDir: "/work/example", Product: "Example", Version: "v1.2.3", Destination: releasekit.GiteaDestination{ BaseURL: "https://gitea.example", Owner: "example", Repository: "example", Token: token, }, Build: &releasekit.BuildSpec{ MainPackage: "./cmd/example", BinaryName: "example", Targets: []releasekit.Target{{OS: "linux", Arch: "amd64"}}, }, }) if err != nil { // Keep the returned state and any completed asset identities for recovery. return err } fmt.Println(result.State, result.ReleaseURL) ``` See the [CLI contract](../cli.md), [configuration reference](../config.md), and [Gitea integration guide](../integrations/gitea.md) for exact settings, exit codes, and transport behavior. ## Woodpecker tag workflows Use the maintained [tag-delivery workflow](../../examples/woodpecker/tag-delivery.yml) in the consumer repository's `.woodpecker/` directory. Set `GO_IMAGE` to an image with Go 1.25 or newer, Git, and a local Go version compatible with the consumer module. It uses `GOTOOLCHAIN=local`; Go does not download a different toolchain. The tag's `go.mod` must select ReleaseKit as a module dependency. Configure the Woodpecker repository secret `releasekit_gitea_token`; the template maps it to `RELEASEKIT_GITEA_TOKEN` for delivery. The repository needs a `delivery` profile. Page-only and binary behavior both use this template; the profile's build target list selects whether application binaries are built and delivered. Before running Go, the template fetches the explicit event tag, compares its peeled commit with the provider's full commit ID without regard to hex case, checks out that commit detached, and confirms the source tree is clean. It then copies the tagged `go.mod` and any `go.sum` to a temporary directory outside the checkout. `go list -m` confirms that the module selects ReleaseKit; Go uses an alternate `-modfile` to prepare dependencies and build the selected `cmd/releasekit` package without changing the tagged module files. The template invokes that executable with `CI_WORKSPACE`, `CI_COMMIT_SHA`, and `CI_COMMIT_TAG`. A cleanup trap removes the temporary metadata and executable. Tool bootstrap and application artifact preparation are separate. The bootstrap resolves and builds ReleaseKit from the tagged consumer's module configuration. Afterward, `ci-deliver` loads the profile and downloads application dependencies only when build targets are selected; it builds and delivers those targets with the note page. Source-only profiles skip application dependency downloads and binary work. Dependency preparation for binaries may use the network and may update an uncommitted checksum file in the checkout. A retry still uses the same immutable tag and that tag's module settings, even after the default branch selects a newer ReleaseKit version. If the application does not declare ReleaseKit as a module dependency, install the executable separately and invoke the same `ci-deliver` command. For ReleaseKit's own source workflow, the maintained [source-delivery template](../../examples/woodpecker/releasekit-source-delivery.yml) checks out the tag and self-bootstraps `./cmd/releasekit` into temporary storage. Its readonly tool build uses committed module metadata and can fetch missing dependencies through normal Go proxy, private-module, checksum, and cache settings. Tool bootstrap follows tag verification; offline candidate validation and application artifact compilation retain their separate environments. The normal Go module and build caches are sufficient. Cache mounts may be added as deployment configuration when they help the runner; they are not needed by the template. A separately installed executable can be installed with `go install gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit@PIN`, then run with the same arguments: ```sh releasekit ci-deliver --repo "$CI_WORKSPACE" --commit "$CI_COMMIT_SHA" "$CI_COMMIT_TAG" ``` The module-based workflow follows the ReleaseKit version selected by the tagged consumer's `go.mod`, so retries use that source's original selection. Update the consumer module configuration when adopting a newer ReleaseKit version and verify it with a tag fixture. The command and profile behavior are documented in the [CLI contract](../cli.md) and [configuration reference](../config.md). Woodpecker runs delivery after the tag event, independently from the source publication result. Read its workflow status as delivery status: a delivery failure does not undo source publication. A failed, partial, or uncertain run can be inspected and retried against the same immutable tag and commit; do not move the tag to make a retry pass. See [Woodpecker's environment reference](https://woodpecker-ci.org/docs/usage/environment) for runner-provided tag and commit variables and [workflow syntax](https://woodpecker-ci.org/docs/usage/workflow-syntax) for tag events, sequential steps, and the shared workspace.