CI pipelines
Every release ships yasrt-linux-{amd64,arm64} and yasrt-darwin-{arm64,amd64} with SHA256SUMS and a detached cosign signature over it. The binaries are built and signed once in my pipeline; GitHub carries the same files, nothing is rebuilt there.
- Binary:
go install github.com/ohartwig/yasrt/cmd/yasrt@latestor the signed releases - Image:
registry.ole-hartwig.eu/devops/images/yasrt:1carries the binary withgit,gpgandssh-keygen - Verify:
cosign verify-blob --key <public-key> --signature SHA256SUMS.sig --insecure-ignore-tlog=true SHA256SUMS, thensha256sum -c SHA256SUMS
GitLab CI
stages: [version, build, release]
default:
image:
name: registry.ole-hartwig.eu/devops/images/yasrt:1
entrypoint: [""]
version:
stage: version
variables: { GIT_DEPTH: 0 } # yasrt needs the whole history
script: yasrt next --output .release.env
artifacts:
reports: { dotenv: .release.env }
rules: [{ if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH }]
build:
stage: build
image: your/build-image
script:
- '[ "$RELEASE_STATUS" = "release" ] || exit 0' # gate in the script, not in rules:
- make build VERSION=$RELEASE_VERSION
rules: [{ if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH }]
release:
stage: release
variables: { GIT_DEPTH: 0 }
script: yasrt release
rules: [{ if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH }]
GitLab evaluates rules: when the pipeline is created, before .release.env exists. Downstream jobs therefore gate in the script on RELEASE_STATUS. The project must allow job-token pushes (Settings → CI/CD → Job token permissions → Allow Git push requests to the repository), and whoever may merge to the default branch must be allowed to create the release tag; yasrt check verifies both. A push with the job token starts no pipeline, and that is exactly what keeps the release commit from releasing itself again.
A repository whose publishing has to run on the tag (say because a signing role's OIDC trust is limited to ref_type:tag) keeps that pipeline by having the release start it: after_release.triggers expands ${tag}, ${version} and CI variables in project, ref and variables; { project: "${CI_PROJECT_PATH}", ref: "${tag}" } starts the tag pipeline the job-token push did not.
A trigger goes out with the job token unless the entry names, with token_var, a variable holding a pipeline trigger token of the target project. The difference is who the started pipeline runs as: with the job token, as the user behind the release job, who must be allowed to start pipelines in the target project; with a trigger token, as its owner, whoever merged.
A CI/CD component of this shape (version, release, a shared defaults layer, product and tag-format as inputs) lives on my instance under devops/ci-cd-components/release-tools.
GitHub Actions and Forgejo Actions
permissions: { contents: write }
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with: { fetch-depth: 0 }
- run: yasrt next --output .release.env
- run: make build # gates on RELEASE_STATUS inside
- run: yasrt release
env: { GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} } # FORGEJO_TOKEN on Forgejo
A push with GITHUB_TOKEN starts no workflow, so the changelog commit does not release itself. Where the platform cannot be told from its variables, say --forge gitlab|github|forgejo or set YASRT_FORGE. Complete files are under docs/examples in the repository.
Next
Configuration and hooks
One line per repository, organisation defaults underneath, hooks at five points of the release.