Files
releaser/docs/content/ci-integration.md
T
k3nnyandClaude Opus 5.5 e28434a030
ci / vet, staticcheck, test, build (push) Canceled after 0s
docs / Build and deploy docs (push) Canceled after 0s
ci(github): add GitHub Actions CI and release workflows for k3nnyfr/releaser mirror
- .github/workflows/ci.yml: same vet/staticcheck/test/build checks as Gitea CI
- .github/workflows/release.yml: same five binaries and build flags as the
  Gitea release workflow, published with gh release create
- docs: mention the GitHub mirror and both release pages; GitHub Actions
  example downloads from GitHub releases using RUNNER_OS/RUNNER_ARCH
- docs: fix broken latest/download URL, clone URL and Go version requirement

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 22:38:17 +02:00

5.5 KiB

title, weight
title weight
CI Integration 40

GitLab CI

The simplest setup uses the reusable job template shipped alongside releaser:

# .gitlab-ci.yml
include:
  - project: releaser/releaser
    file: .releaser.gitlab-ci.yml

release:
  extends: .releaser
  variables:
    GITLAB_TOKEN: $RELEASE_TOKEN   # project/group variable with api + write_repository scope

Or write it inline:

release:
  stage: release
  image: registry.example.com/releaser:latest
  rules:
    - if: $CI_COMMIT_BRANCH =~ /^release\/.+$/
  variables:
    GITLAB_TOKEN: $RELEASE_TOKEN
    GIT_DEPTH: 0                   # full history — shallow clones hide previous release tags
  script:
    - releaser
  artifacts:
    reports:
      dotenv: release.env          # exposes NEXT_VERSION to downstream jobs

Consuming NEXT_VERSION downstream

The release.env dotenv artifact exports NEXT_VERSION=<tag> automatically. Downstream jobs can use it:

deploy:
  stage: deploy
  needs:
    - job: release
      artifacts: true
  script:
    - echo "Deploying version $NEXT_VERSION"

Disable the dotenv artifact (e.g. for local runs):

releaser --release-env-file ""

Write it to a custom path:

releaser --release-env-file deploy/version.env

GitHub Actions / Gitea Actions

name: release
on:
  push:
    branches:
      - 'release/**'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0          # full history needed for tag discovery

      - name: Install releaser
        shell: bash
        env:
          RELEASER_VERSION: v1.10.0
          # On Gitea Actions, https://git.k3nny.fr/k3nny/releaser/releases/download works too.
          RELEASER_BASE_URL: https://github.com/k3nnyfr/releaser/releases/download
        run: |
          case "$RUNNER_OS" in
            Linux)   os=linux ;;
            macOS)   os=darwin ;;
            Windows) os=windows ;;
            *) echo "unsupported RUNNER_OS: $RUNNER_OS" >&2; exit 1 ;;
          esac
          case "$RUNNER_ARCH" in
            X64)   arch=amd64 ;;
            ARM64) arch=arm64 ;;
            *) echo "unsupported RUNNER_ARCH: $RUNNER_ARCH" >&2; exit 1 ;;
          esac
          ext=""
          if [ "$os" = "windows" ]; then ext=".exe"; fi
          mkdir -p "$RUNNER_TEMP/releaser"
          curl -fsSL "$RELEASER_BASE_URL/$RELEASER_VERSION/releaser-$RELEASER_VERSION-$os-$arch$ext" \
            -o "$RUNNER_TEMP/releaser/releaser$ext"
          chmod +x "$RUNNER_TEMP/releaser/releaser$ext"
          echo "$RUNNER_TEMP/releaser" >> "$GITHUB_PATH"

      - name: Run releaser
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: releaser

{{< hint warning >}} fetch-depth: 0 is required. A shallow clone (--depth 1) hides the previous tag, causing releaser to treat every commit as the first release. {{< /hint >}}

Preflight checks

releaser --check validates the release environment without releasing anything: branch resolution and pattern match, working tree state, shallow clone, remote URL parseability (the same parse the push performs — it catches shell-quoting accidents in set-url lines), which push auth would be used, configured version files, and the release target. All problems are reported at once, and the exit code is non-zero if any check fails.

Note the split with --dry-run: dry-run answers "what version would be released?" (it analyzes commits and computes the bump); --check answers "will the release plumbing work?" (everything dry-run never touches). Run --check in merge-request pipelines to catch broken CI configuration before it blocks a real release:

release:check:
  stage: test
  image: registry.example.com/releaser:latest
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  variables:
    GIT_DEPTH: 0
  script:
    - releaser --check --branch "release/0.0"   # any pattern-matching name works for validation

Shallow clones

GitLab CI checks out a shallow clone by default (GIT_DEPTH: 20), and shallow clones hide any release tag beyond the fetch depth — tag discovery would silently restart versioning at X.Y.0. releaser detects this: when the clone is shallow and no previous release tag is found, it refuses to release and asks for full history.

Fix it by fetching full history (GIT_DEPTH: 0 in GitLab CI, fetch-depth: 0 in GitHub Actions, or git fetch --unshallow). If the project genuinely has no release tag yet, pass --allow-shallow to release anyway.

A shallow clone whose history does include the latest release tag is fine — the version calculation is unaffected, and releaser proceeds normally.

Detached HEAD

CI runners check out a commit SHA, leaving the repository in detached HEAD state. releaser detects this and falls back to the branch name from the CI environment, in order:

  1. CI_COMMIT_BRANCH (GitLab CI, branch pipelines)
  2. CI_COMMIT_REF_NAME (GitLab CI)
  3. GITHUB_REF_NAME (GitHub Actions)

So on branch pipelines no extra configuration is needed. To override the detected name (or on runners that set none of these variables), pass it explicitly:

script:
  - releaser --branch "$CI_COMMIT_BRANCH"

SSH push

When pushing over SSH (git@host:... or ssh://... remotes), releaser attempts go-git SSH agent auth automatically — no extra configuration needed as long as the CI runner has an SSH agent socket available.

For HTTPS remotes without a token, releaser delegates to the system git binary so credential helpers and netrc work as expected.