From 02278dab1728d5a5279e7689aa03fe2691a0e0f3 Mon Sep 17 00:00:00 2001 From: darken Date: Fri, 1 May 2026 08:47:48 +0200 Subject: [PATCH] chore(ci): Use GitHub App token for release-prepare push --- .claude/rules/release.md | 15 ++++++++++++ .github/workflows/release-prepare.yml | 33 ++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/.claude/rules/release.md b/.claude/rules/release.md index f93a1bff..885748a4 100644 --- a/.claude/rules/release.md +++ b/.claude/rules/release.md @@ -54,6 +54,21 @@ bats tools/release/bump.bats `bump.sh` enforces strict `versionCode` monotonicity, so re-using a code is impossible without manually editing `version.properties`. +## Auth setup + +`release-prepare.yml` Job 2 uses a GitHub App token (not `GITHUB_TOKEN`) to push the bump commit and tag. The App identity is in the rulesets' bypass list, which is what allows the push to bypass branch protection + tag-creation restrictions. + +Required org secrets (set on the d4rken-org organization, accessible to `capod`): + +- `RELEASE_APP_ID` — numeric ID of the `d4rken-org-releaser` GitHub App +- `RELEASE_APP_PRIVATE_KEY` — full `.pem` contents (including BEGIN/END lines) + +The App is installed on this repo and added as a bypass actor to: +- The main-branch ruleset (PR + status check requirements) +- The tag ruleset (creation restriction on `v*`) + +Other apps in the org can reuse the same App + secrets — just install the App on each repo and add it to that repo's rulesets' bypass lists. + ## Defense in depth `release-tag.yml` includes `validate-tag` which: (1) regex-checks `github.ref_name`, (2) runs `bump.sh --mode=check`, (3) asserts the parsed name matches the tag. Manual `gh workflow run release-tag.yml --ref vfoo` or hand-pushed tags fail before any build. diff --git a/.github/workflows/release-prepare.yml b/.github/workflows/release-prepare.yml index f5b9851a..31d8b77f 100644 --- a/.github/workflows/release-prepare.yml +++ b/.github/workflows/release-prepare.yml @@ -134,10 +134,8 @@ jobs: if: ${{ !inputs.dry_run }} runs-on: ubuntu-22.04 permissions: - contents: write - actions: write + contents: read env: - GH_TOKEN: ${{ github.token }} INPUT_BUMP_KIND: ${{ inputs.bump_kind }} INPUT_VERSION_TYPE: ${{ inputs.version_type }} INPUT_VERSION_OVERRIDE: ${{ inputs.version_override }} @@ -145,13 +143,31 @@ jobs: NEW_CODE: ${{ needs.compute-and-validate.outputs.new_code }} CURRENT_NAME_AT_PLAN: ${{ needs.compute-and-validate.outputs.current_name }} steps: + - name: Mint App token + id: app-token + uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 #v3.1.1 + with: + app-id: ${{ secrets.RELEASE_APP_ID }} + private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} + + - name: Resolve bot identity + id: bot + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + run: | + set -euo pipefail + slug=$(gh api /app --jq .slug) + user_id=$(gh api "/users/${slug}%5Bbot%5D" --jq .id) + echo "user_name=${slug}[bot]" >> "$GITHUB_OUTPUT" + echo "user_email=${user_id}+${slug}[bot]@users.noreply.github.com" >> "$GITHUB_OUTPUT" + - name: Checkout main with credentials uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 with: ref: main fetch-depth: 0 persist-credentials: true - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ steps.app-token.outputs.token }} - name: Re-validate after approval wait run: | @@ -188,9 +204,12 @@ jobs: ./tools/release/bump.sh --mode=check --expected-current="${NEW_NAME}" - name: Configure git identity + env: + BOT_USER_NAME: ${{ steps.bot.outputs.user_name }} + BOT_USER_EMAIL: ${{ steps.bot.outputs.user_email }} run: | - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git config user.name "${BOT_USER_NAME}" + git config user.email "${BOT_USER_EMAIL}" - name: Commit and tag run: | @@ -205,6 +224,8 @@ jobs: git push --atomic origin "HEAD:refs/heads/main" "refs/tags/v${NEW_NAME}" - name: Dispatch release-tag.yml + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | set -euo pipefail gh workflow run release-tag.yml --ref "v${NEW_NAME}" -f dry_run=false