Skip to content

Run it in GitLab CI

Goal: every merge to your default branch keeps a Release merge request up to date, and merging that request tags the commit that actually landed.

You need a project on GitLab, a stages: list you can add to, and a token. The component satisfies what colophon needs from a pipeline for you; this page shows where each requirement lives.

1. Provide a token

colophon needs a forge token with api and write_repository. It uses it for the API calls, the release-branch push and the tag push.

It must not be CI_JOB_TOKEN. A tag pushed with CI_JOB_TOKEN does not fire downstream tag pipelines, so your goreleaser or publish jobs would never run.

Set it as a CI/CD variable named COLOPHON_TOKEN, masked and protected.

2. Add the component

include:
  - component: gitlab.com/phpboyscout/cicd/colophon@main
    inputs:
      stage: release
      branch: main

stages:
  - lint
  - test
  - release

That is the whole setup for the common case. Pin a tag instead of main if you want releases of the component to reach you deliberately. The component adds:

Job Runs on What it does
colophon-publish the default branch A Release merge request has merged: resolve what landed on the target, tag that commit, create the release.
colophon-propose-next the default branch, after publish Re-cut the release branch from the target and open or update the Release merge request for the next release.
colophon-release-check the Release merge request's pipeline Check the merge request carries only the files colophon writes. It is the merge gate's pipeline, so the project's other jobs can stand aside there.
colophon-release the tag pipeline, with assets: true Create the release carrying links to what the build uploaded.

3. Keep the checkout full

Every job that runs the colophon binary sets GIT_DEPTH: "0", because colophon reads the history back to the last release tag, and the tags, from the checkout. (colophon-release-check runs only git and fetches the depth it needs itself.) A shallow clone is refused like this:

ERRO this checkout is shallow (depth-limited clone) hints="colophon needs the full history and tags: set GIT_DEPTH: \"0\" on the job in GitLab CI, or fetch-depth: 0 on actions/checkout in GitHub Actions"

GitLab's project default is a depth of 20, which is shallow enough to fail. The component's setting wins over the project default for its own jobs; do not override it in a default: or variables: block that reaches them. If you run colophon outside the component, set GIT_DEPTH: "0" on that job yourself.

4. Leave the order alone

publish runs before propose, and the component enforces that with needs:. It is a correctness constraint rather than a preference.

After a Release merge request merges, the release commit is on the target branch but the tag does not exist yet. In that window colophon computes the same release again. A pipeline that proposed first would re-open a Release merge request for the version about to be tagged, publish would then tag it, and that merge request would sit open forever proposing a release that has already happened.

Inputs

Every input has a default; most projects set none of them.

Input Default Notes
image registry.gitlab.com/phpboyscout/images/release-tools:vX.Y.Z Image carrying the colophon binary; the component's default is the newest the component works with.
stage release One stage is enough. Declare it in your own stages:.
branch main Target branch to release from.
token $COLOPHON_TOKEN Needs api + write_repository. Never CI_JOB_TOKEN.
if $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH Gating rule for both jobs. Set it to match if you release from a non-default branch.
author_name colophon Identity on the release commit and tag.
author_email [email protected] See author_name.
release_branch derived Empty derives colophon/release/<branch>.
propose true Set false to publish only.
publish true Set false to propose only, which is the safe half: it opens a merge request and cuts no tag.
assets false Releases carry binaries: publish --tag-only on the default branch, create the release on the tag pipeline. See Publish a release with its assets.
dist dist goreleaser's output directory; its artifacts.json names what the release should carry.
asset_base $CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/$CI_PROJECT_NAME/$COLOPHON_VERSION URL the artefacts were uploaded under, with each asset's name appended. Must match where goreleaser actually uploaded.
release_files CHANGELOG.md **/CHANGELOG.md Files a Release merge request may change; colophon-release-check fails it on anything else.

Try the safe half first

If you are migrating a project that already releases some other way, run propose on its own to begin with. It opens and updates a merge request and cuts no tag, so you can compare its answer against your existing tool without either of them acting.

include:
  - component: gitlab.com/phpboyscout/cicd/colophon@main
    inputs:
      stage: release
      publish: false

colophon plan is the even safer version of the same comparison, and runs on your laptop. See Getting started.

Running it outside the component

The component is a convenience. The commands underneath it take a token from <FORGE>_TOKEN in the environment, upper-cased from the forge name, so GITLAB_TOKEN for GitLab and GITHUB_TOKEN for GitHub.

release:
  stage: release
  image: registry.gitlab.com/phpboyscout/images/release-tools:vX.Y.Z
  variables:
    GIT_DEPTH: "0"          # a shallow checkout fails; see step 3
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  script:
    - export GITLAB_TOKEN="$COLOPHON_TOKEN"
    - colophon --ci publish --target main
    - colophon --ci propose --target main   # in ONE job this re-proposes the release just tagged; keep them separate

The two commands above sit in one job only to show the flags. Run them as two jobs, publish first, for the reason in step 4.