Skip to content

Spec: Order release-plz:pr after release-plz:release (v0.10.4)

  • Repository: gitlab.com/phpboyscout/cicd
  • Component touched: release-plz
  • Release: patch — fix: → v0.10.4

Problem

v0.10.3 split release-plz into two jobs — release-plz:pr and release-plz:release — sharing a hidden .release-plz-base (see 2026-06-12-release-plz-split-jobs-v0.10.3.md). Both sit in the same stage with no ordering, so they run concurrently.

On the pipeline that merges a Release MR, release publishes the new crates and pushes the per-crate vX.Y.Z tags, while pr independently re-derives the next version from the repo + registry. Because they run at the same time, pr can observe the pre-publish view — the crates.io sparse-index entry and/or the freshly-pushed git tags have not propagated to pr's checkout yet — and conclude the last release is the previous version. It then opens a Release MR proposing the version release is in the middle of shipping.

Observed

On phpboyscout/rust-tool-base, after v0.5.1→v0.5.2 the release-plz:pr job repeatedly opened chore: release v0.5.2 MRs (!36, !38, !41) even though 0.5.2 was already (being) published. The MRs are spurious: they re-propose the in-flight version. They self-correct on a later pipeline once the index + tags have propagated (the next run correctly opened chore: release v0.5.3), but each one is operator noise and, if merged, would drive release to re-tag an existing version.

Decision

Make release-plz:pr depend on release-plz:release:

release-plz:pr:
  extends: .release-plz-base
  needs:
    - job: release-plz:release
      optional: true
  script: ...

needs orders pr after release within the stage (no new stage or input). On a Release-MR-merge pipeline pr now runs only once release has finished publishing + tagging, so it analyses the settled post-release state and computes the correct next version. On an ordinary push release is a fast no-op and pr follows it as before.

Both jobs share the same rules: (inputs.if), so they are always added to the pipeline together — the needs reference is never dangling. optional: true is defensive belt-and-braces against a consumer overriding one job's rules.

Behaviour notes

  • Production: a genuinely failed release (e.g. a publish error) now blocks pr. That is correct — an incomplete release should not spawn a next-version MR; the next pipeline retries both.
  • Self-test: release is allow_failure (the cicd repo has no Cargo workspace, so release-plz exits non-zero), and a needs dependent still runs after an allow_failure job, so pr is still exercised.

Scope & non-goals

  • In scope: add needs: to release-plz:pr in templates/release-plz.yml; adjust the self-test if the ordering affects it. No input-shape changes.
  • Non-goals: the v0.10.3 working-tree-isolation split (unchanged); tokens, forge, bootstrap (unchanged); any other component.

Testing

tests/release-plz/.gitlab-ci.yml includes the component against a repo with no Cargo workspace; both jobs hit the documented non-zero exit and are allow_failure-tolerated. Under this change release-plz:pr runs after release-plz:release; the allow_failure overrides on both job names still apply, and the self-test:release-plz trigger stays green. The real ordering is verified downstream: rust-tool-base bumps its pin to v0.10.4 and its next release-merge pipeline must produce no spurious same-version Release MR.