Skip to content

Spec: phpboyscout/cicd v0.11 — releaser-pleaser component

  • Repository: gitlab.com/phpboyscout/cicd
  • Released as: v0.11.0 (minor — one additive component).
  • Driver: v0.10.8 gave every cicd component a schedule → never rule guard so a Renovate schedule runs renovate-self only. But Go consumers (go-tool-base, keyrx) drive their Release MR with the external apricote/releaser-pleaser/run component, whose rule is $CI_COMMIT_BRANCH == "<branch>" — which still matches a schedule running on the default branch. We don't control that component, so the only alternatives were a bespoke per-repo rules: override (which we explicitly want to avoid) or wrapping it as our own component. This spec does the latter.

Context

release-plz (Rust, v0.10.3) is already our own component wrapping an external release driver; renovate-self (v0.8) wraps renovate/renovate. A releaser-pleaser component is the missing Go sibling — same pattern, so both release drivers carry our conventions and the schedule guard by construction.

Decisions

D1 — Thin wrapper over apricote's image

The component runs ghcr.io/apricote/releaser-pleaser:$image_version and invokes rp run --forge=gitlab --branch=… --extra-files=… --updaters=…, mirroring apricote's templates/[email protected]. apricote's interruptible: true and resource_group: releaser-pleaser are kept — they are correct (the tool is idempotent and acts on shared global state). Inputs:

Input Default Purpose
image_version v0.8.0 apricote releaser-pleaser image tag (Renovate-tracked).
stage release CI stage.
branch main Release target; passed to rp run --branch.
token $RELEASER_PLEASER_TOKEN GITLAB_TOKEN. See D2.
if $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH Gate. See D3.
extra_files "" rp run --extra-files.
updaters "" rp run --updaters.
needs [] Job dependencies (array), as apricote.

D2 — Token follows the v0.5 convention, no _RUNTIME alias

token defaults to "$RELEASER_PLEASER_TOKEN" and threads to the GITLAB_TOKEN job variable. Unlike renovate-self, no _RUNTIME alias is needed: the env var (GITLAB_TOKEN) and the CI variable (RELEASER_PLEASER_TOKEN) have different names, so there is no self-referencing job-variable collision (the bug v0.10.7 fixed for renovate only arises when the job variable and the group variable share a name).

RELEASER_PLEASER_TOKEN must not be $CI_JOB_TOKEN — a tag pushed by CI_JOB_TOKEN does not fire downstream tag pipelines (GitLab loop-prevention), so the goreleaser / release-asset job would never run. Same constraint already documented for the consumers and in CLAUDE.md.

D3 — Gate via an if input, with the schedule guard ahead of it

rules:
  - if: '$CI_PIPELINE_SOURCE == "schedule"'
    when: never
  - if: '$[[ inputs.if ]]'

The default if ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH) matches apricote's behaviour for the common case (branch = main = the default branch). Exposing it as an input (rather than hardcoding apricote's $CI_COMMIT_BRANCH == "<branch>") keeps the component consistent with release-plz / renovate-self and lets the self-test override the gate. The schedule guard sits ahead of it and is not overridable — the v0.10.8 invariant holds: a scheduled pipeline runs renovate-self only. (A consumer releasing from a non-default branch sets both branch and if.)

D4 — Self-test: failure-path, mirrors renovate-self

Running releaser-pleaser for real mutates a Release MR. The self-test overrides if: 'true', supplies a dummy token, and tolerates the authentication failure via allow_failure.exit_codes. Any other exit (image pin wrong, bad interpolation, missing rp binary) fails the pipeline. The exit code is confirmed against the first self-test run and pinned. Like renovate-self, no fixture directory is needed — the component operates on the repo itself, not a fixture artefact.

D5 — cicd's own release stays on the external component (for now)

The cicd repo's root .gitlab-ci.yml keeps using apricote/releaser-pleaser/[email protected] for its own Release MR in this MR — dogfooding our own @v0.11.0 would be a chicken-and-egg pin (the tag doesn't exist until this merges). Switching cicd to its own component (and thereby silencing the root pipeline's own schedule churn) is a clean follow-up once v0.11.0 is tagged.

D6 — Versioning

A new additive component → v0.11.0 (minor). Pre-1.0 caveat from v0.1 still applies.

Consumers (post-release)

Project Before After v0.11.0
go-tool-base apricote/releaser-pleaser/[email protected] phpboyscout/cicd/[email protected]
keyrx apricote/releaser-pleaser/[email protected] phpboyscout/cicd/[email protected]

No per-repo schedule override anywhere; the component carries the guard. rust-tool-base is unaffected (it uses release-plz).

Follow-up

  • Switch the cicd root pipeline to its own [email protected] (D5), removing the last schedule-fired release job in the org.
  • Task 2: the broader branch / tag / MR churn audit, including the root self-test fan-out on schedule.