ci: use dedicated release App token to publish releases (#28553)

## Problem

The `Publish release` step fails with `HTTP 403: Resource not accessible
by integration` because the default `GITHUB_TOKEN` cannot create the
release tag under the active tag-create protection ruleset.

## Change

Use a dedicated GitHub App token for the `Publish release` step:

- Add a `Generate release App token` step using `secrets.RELEASE_APP_ID`
/ `secrets.RELEASE_APP_PRIVATE_KEY`.
- Switch only that step's `GITHUB_TOKEN` to the minted App token.

## Required before merge (admin)

1. Create the release GitHub App (least privilege) and install it on
`coder/coder`.
2. Configure `RELEASE_APP_ID` / `RELEASE_APP_PRIVATE_KEY`.
3. Add the App to the tag-create protection ruleset bypass list.

Refs coder/security-automation#297.
This commit is contained in:
Jakub Domeracki
2026-08-25 16:32:01 +02:00
committed by GitHub
parent 7fc9a6e449
commit be9f8592eb
+15 -1
View File
@@ -541,6 +541,18 @@ jobs:
gcloud storage cp "./build/${detached_signature}" "gs://releases.coder.com/coder-cli/${version}/${cli_name}.asc"
done
# Mint a short-lived installation token from the dedicated release
# GitHub App. The default GITHUB_TOKEN (github-actions[bot]) cannot be
# added to the "Auto-imported tag create protections" ruleset bypass
# list, so `gh release create` fails to create the tag with a 403. The
# App is added to that ruleset's bypass list as an Integration actor.
- name: Generate release App token
id: release_app_token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
- name: Publish release
run: |
set -euo pipefail
@@ -579,7 +591,9 @@ jobs:
--release-notes-file "$CODER_RELEASE_NOTES_FILE" \
"${files[@]}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Use the dedicated release App token (github-actions[bot] is blocked
# from creating tags by the tag-create protection ruleset).
GITHUB_TOKEN: ${{ steps.release_app_token.outputs.token }}
CODER_GPG_RELEASE_KEY_BASE64: ${{ secrets.GPG_RELEASE_KEY_BASE64 }}
VERSION: ${{ steps.version.outputs.version }}
CREATED_LATEST_TAG: ${{ steps.build_docker.outputs.created_latest_tag }}