Post-publish workflows
A post-publish workflow is one of your own GitHub Actions workflows that Release Planner runs after it publishes a release. It can be in this repository, such as one that deploys the release, or in another repository you own, such as one that updates a Homebrew formula in a tap. If it fails, the release stays published.
Set it up
Section titled “Set it up”List your workflows under post-publish in .release-planner/config.yml, then run release-planner install and commit the result:
post-publish: - workflow: deploy.yml - repository: your-org/homebrew-tap workflow: update-formula.ymlAn entry without repository is a workflow in this repository. An entry with repository is a workflow in that repository, which must belong to the same owner as every other repository you list. The workflows are yours: Release Planner doesn’t provide them, and these names are examples.
A workflow in this repository
Section titled “A workflow in this repository”It follows the same rules as a pre-publish workflow. It must:
- Accept three string inputs, which the release workflow passes in:
ref: the full SHA of the release committag: the release’s tag, such asv1.2.0version: the version without thev, such as1.2.0
- Check out
ref, so it runs the code that was released. - Run every job in the same GitHub environment, named literally on each job. The environment holds whatever the workflow needs to reach the outside world.
- Not require secrets to be passed in. The release workflow passes none, so keep them in the environment instead.
You name the environment only in the workflow, because GitHub requires it on the jobs. Release Planner reads it from there to check the environment’s settings.
For example, this workflow runs a project’s own make deploy in production:
name: Deployon: workflow_call: inputs: ref: type: string required: true tag: type: string required: true version: type: string required: truepermissions: contents: read id-token: writejobs: deploy: runs-on: ubuntu-latest timeout-minutes: 15 environment: production steps: - uses: actions/checkout@v7 with: ref: ${{ inputs.ref }} persist-credentials: false - run: make deploy VERSION="$VERSION" env: VERSION: ${{ inputs.version }}Release Planner calls your workflow with only contents: read and id-token: write, and passes it no secrets. Your workflow can read the repository and request an OIDC token, but it can’t write to the repository or publish releases. Everything else it needs comes from its environment. Keep secrets and variables there, and have your cloud provider trust only that environment’s OIDC subject.
release-planner install and release-planner check fail if a workflow is missing an input, doesn’t name the same environment on every job, or requires secrets. The release status names each workflow by its name:, such as Deploy.
Set up the environment
Section titled “Set up the environment”Set up its environment the way the pre-publish page describes:
- Deployment branches and tags: choose Selected branches and tags, with a branch rule for your release branch only.
- Required reviewers: leave off, unless you want to approve each run.
The release workflow checks the environment twice:
- On each release pull request, it warns if the environment is missing or lets anything but your release branch use it.
- After you merge, it refuses to publish if the environment is missing, unrestricted, or doesn’t let your release branch use it. A release never publishes with a post-publish workflow that can’t run.
A workflow in another repository
Section titled “A workflow in another repository”The release workflow starts it with a workflow_dispatch event on that repository’s default branch, with two string inputs:
on: workflow_dispatch: inputs: tag: description: 'Release tag, such as v1.2.0' type: string required: true version: description: 'Version without the leading v, such as 1.2.0' type: string required: trueIt starts the workflow with a GitHub App’s token, limited to that repository, rather than a personal access token.
Create the GitHub App
Section titled “Create the GitHub App”- Create a GitHub App owned by the repositories’ owner (Settings → Developer settings → GitHub Apps → New GitHub App). Turn off Webhook. Under Repository permissions, set Actions to Read and write, and leave everything else at no access.
- Install the app on the repositories your post-publish workflows are in, and no others.
- Note the app’s Client ID, and generate a private key.
Set up the dispatch environment
Section titled “Set up the dispatch environment”The jobs that start these workflows run in an environment named dispatch, which holds the app’s credentials and runs only from your release branch.
- Open Settings → Environments in the repository that releases, and choose New environment. Name it
dispatch. - Under Deployment branches and tags, add a branch rule for your release branch only.
- Add the variable
DISPATCH_APP_CLIENT_ID, set to the app’s Client ID. - Add the secret
DISPATCH_APP_PRIVATE_KEY, set to the app’s private key. - Leave Required reviewers off, unless you want to approve each run.
The release workflow warns on each release pull request if the dispatch environment is missing or doesn’t restrict branches. GitHub doesn’t let a workflow’s token read an environment’s variables or secrets, so each job checks them itself before it mints the token, and fails with a message naming both if either is missing.
When they run
Section titled “When they run”After a new release publishes, and with release assets, after the published assets are attested from your release branch. Each workflow runs in its own job, named post-publish (<workflow>) or post-publish (<repository>:<workflow>), and they run in parallel, so steps that must run in order belong in one workflow.
They don’t run for:
- prereleases, whose version has a
-suffix, such asv1.2.0-rc.1, unless the entry setsprereleases: true - notes edits to a published release
- a release that failed to publish
post-publish: - workflow: deploy-preview.yml prereleases: trueIf one fails
Section titled “If one fails”The release stays published. The release status in the release pull request’s description lists each post-publish job with ✅ or ❌ and a link to it, and a comment mentions whoever merged. Once the cause is fixed, use Re-run failed jobs on the release run: it runs only the post-publish jobs that failed, so a workflow that already ran doesn’t run twice. Publishing is skipped because it already succeeded.
Example: a Homebrew tap
Section titled “Example: a Homebrew tap”In fabricahq/homebrew-tap, a workflow update-code-rules.yml takes tag and version, downloads the release’s archives, checks they were attested by the releasing repository’s release-planner.yml on refs/heads/main, updates the formula’s URLs and checksums, and commits the change. The releasing repository lists it under post-publish with repository: fabricahq/homebrew-tap, and the GitHub App is installed on the tap only, so the release workflow can start that workflow but can’t change anything else.
Requirements
Section titled “Requirements”- A workflow in this repository can’t be
release-planner.yml, or a workflow you use for release checks, release assets, or pre-publish. - Its environment can’t be
releaseordispatch. - Every repository you list must belong to the same owner, so one GitHub App covers them.