# 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. ## 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, the command builds the tagged source into temporary storage and delivers the result. To use artifacts built separately, pass `--assets DIR`; the 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. 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 Maintained workflow examples are available for source-only and binary delivery: - [Source-only tag workflow](../../examples/woodpecker/tag-delivery-source-only.yml) - [Binary tag workflow](../../examples/woodpecker/tag-delivery-binary.yml) Copy one into the consumer repository's `.woodpecker/` directory. In its matrix entry, set `GO_IMAGE` to a Go image compatible with the consumer module and replace `RELEASEKIT_SOURCE` with an immutable ReleaseKit commit. The examples deliberately contain no claimed published ReleaseKit pin. Configure the Woodpecker repository secret `releasekit_gitea_token`; the workflow maps it to `RELEASEKIT_GITEA_TOKEN` only for the delivery step. The repository also needs a `delivery` profile using the default `RELEASEKIT_GITEA_TOKEN` variable. The binary profile must declare its build targets. The tag workflow fetches the event tag, verifies that the tag resolves to `CI_COMMIT_SHA`, and checks out that commit detached. Woodpecker shares the repository workspace between sequential steps, so the installed executable, Go caches, build outputs, and build receipt remain available to later steps. The workflow keeps its `.releasekit/` directory out of Git status using the checkout's local exclude file. Preparation can access the Go module proxy to install the pinned ReleaseKit executable. The binary workflow also runs `go mod download` before the build. The later `releasekit build` command runs with `GOPROXY=off` and `GOTOOLCHAIN=local`; its declared binary targets and receipt are placed in `.releasekit/assets`. Delivery then passes that directory with `--assets`. The source-only workflow skips this build step and sends the committed note page directly. Neither template runs `check` or `publish`. 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 the 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.