Skip to content

feat(release): add pr-release.yml, the release PR and what it has to start - #106

Merged
blink-admin merged 1 commit into
mainfrom
feat/release-pr-workflow
Sep 28, 2026
Merged

blink-admin merged 1 commit into
mainfrom
feat/release-pr-workflow

Conversation

@grimen

@grimen grimen commented Sep 27, 2026

Copy link
Copy Markdown
Collaborator

What and why

Nothing GITHUB_TOKEN creates starts a workflow. A release PR opened with it gets a pull_request run that never has a job, and nothing listening for release: published runs. So every release-please caller starts its CI on the release PR, and its follow-on workflows at a cut tag, by workflow_dispatch.

This repository does that in self-release.yml. The template does it again in cd-release.yml, as four inline steps with the same fromJSON('') workaround, and its copy has already diverged: no App token, and it reads pr rather than prs.

.github/workflows/pr-release.yml (new) does it once. Its Release job:

  • mints an App token when RELEASE_TAGGER_APP_ID and RELEASE_TAGGER_APP_PRIVATE_KEY are both set (optional; RELEASE_PLEASE_TOKEN, then github.token, otherwise);
  • runs release-please in manifest mode (config-file, manifest-file);
  • writes paths released: … to the job summary;
  • reads the root release PR into the outputs pr-number and pr-branch;
  • starts ci-workflow (default ci.yml, empty for none) on every release PR the push touched;
  • starts each dispatch-on-release line (workflow.yml key=value …, {tag} filled in, # and blank lines skipped) at the new tag.

Outputs: release-created, tag-name, paths-released, pr-number, pr-branch. Every shell step is a script with its own bats file:

  • scripts/release/dispatch-release-pr-ci.sh: moved from scripts/self/, now takes CI_WORKFLOW instead of naming self-ci.yml.
  • scripts/release/release-pr-read.sh (new): an empty, non-object or incomplete pr output is fatal.
  • scripts/release/dispatch-at-tag.sh (new): validates every line before starting anything, then tries every dispatch and fails if any failed.
  • scripts/release/release-summary.sh (new).

self-release.yml now calls ./.github/workflows/pr-release.yml from the same commit:

  • ci-workflow: self-ci.yml and the App secrets;
  • the later jobs read release-created and tag-name;
  • the dev-config publish is gated on paths-released naming packages/dev-config.

This changes this repository's own release path. Its first real run is the next push to main after merge, which should rebuild the open release PRs and dispatch self-ci.yml on them, as today.

Not breaking for consumers: a new workflow.

How to verify

  • make check passes: exit 0.
  • test/dispatch-at-tag.bats (new, 7 cases):
    • lines become gh workflow run … --ref TAG -f … with {tag} filled in;
    • blank, padded and # lines are skipped;
    • a line with no workflow file, or a field that is not key=value, fails before anything starts;
    • an empty list fails;
    • one failed dispatch fails the step after the rest were tried;
    • missing TAG or GH_REPO is named.
  • test/release-pr-read.bats (new, 4 cases): outputs are written; empty or unset, non-object and incomplete inputs are fatal and write nothing.
  • test/release-summary.bats (new, 3 cases).
  • test/dispatch-release-pr-ci.bats: now at the new path; two new cases (CI_WORKFLOW decides the workflow; missing, it fails before any dispatch).
  • test/workflow-shape.bats:
    • new rule: the job's three writes; the CI dispatch gated on prs_created and ci-workflow, reading prs; the tag dispatch gated on release_created and dispatch-on-release, at tag_name; the PR read and pr-number wiring; the App token only with its secrets;
    • on the published list;
    • contents: write now asked for by four jobs;
    • major-tag compares release-created.
  • test/self-workflows.bats: self-release.yml calls the local workflow with self-ci.yml and the three secrets; the CI workflow it names exists; the dev-config gate; the rehearsal gate on release-created.
  • test/consumer-contract.bats: every input is in the guide's table.
  • Diagrams parse (6 blocks, docs/consumer-guide.md and AGENTS.md).

Docs

  • docs/consumer-guide.md:
    • a pr-release.yml section: why, inputs, outputs, secrets, the caller example, and the merge-method note;
    • "Release workflows": seven becomes eight, and the diagram gains the workflow and its edge;
    • the "release here" diagram's labels.
  • AGENTS.md:
    • the layout (the script moved to scripts/release/);
    • the release bullet and its sequence diagram.
  • README.md: the table row and the counts.

The template adopts it after it moves its pin to the release carrying this: cd-release.yml becomes the caller in the guide, with dispatch-on-release holding the beta start and its web-deploy line inside the init markers.

Checklist

  • PR title is a Conventional Commit with a valid scope
  • make check passes locally
  • Every behaviour this PR adds or changes is tested here
  • Every script has its own test file that runs it and covers each exit path
  • docs/consumer-guide.md updated: a new workflow
  • Every doc and diagram that shows the release PR flow is updated
  • Not breaking for consumers

…start

Nothing GITHUB_TOKEN creates starts a workflow: a release PR opened with
it gets a pull_request run that never has a job, and nothing listening
for `release: published` runs. So every release-please caller starts its
CI on the release PR, and its follow-ons at a cut tag, by
workflow_dispatch. This repository did that in self-release.yml; the
template did it again in cd-release.yml, as four inline steps with the
same fromJSON('') workaround.

pr-release.yml is that job, once: release-please (as the RELEASE_TAGGER
App when its optional secrets are set), the root release PR's number and
branch as outputs, `ci-workflow` started on every release PR the push
touched, and `dispatch-on-release` - one `workflow.yml key=value` per
line, `{tag}` filled in - started at the new tag. Every shell step is a
script with its own bats file: dispatch-release-pr-ci.sh moves from
scripts/self to scripts/release and takes the workflow's name, and
release-pr-read.sh, dispatch-at-tag.sh and release-summary.sh are new.

self-release.yml now calls it from the same commit, with ci-workflow
self-ci.yml, and gates the dev-config publish on paths-released.
@grimen
grimen force-pushed the feat/release-pr-workflow branch from 89dbdd0 to 831c9df Compare September 28, 2026 10:12
@blink-admin
blink-admin merged commit 8250bc2 into main Sep 28, 2026
10 checks passed
@blink-admin
blink-admin deleted the feat/release-pr-workflow branch September 28, 2026 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants