diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6fb25f2..8a5a771 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -125,9 +125,19 @@ jobs: pull-requests: write id-token: write steps: + # Minted before checkout, not after: @semantic-release/git's changelog commit-back needs a real `git push` against main, which the branch ruleset refuses for the workflow's own token — only the exadev App is a permitted bypasser. Generating it first lets checkout itself configure git's credentials with it. + - name: Generate ExaDev App token + id: app-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: ExaDev + repositories: cc-peer + - uses: actions/checkout@v5 with: - persist-credentials: false + token: ${{ steps.app-token.outputs.token }} fetch-depth: 0 - uses: pnpm/action-setup@v4 @@ -144,16 +154,6 @@ jobs: - name: Install run: pnpm install --frozen-lockfile - # The changelog commit-back pushes directly to main, which the branch ruleset refuses for the workflow token. Mint an installation token for the exadev App (the ruleset's permitted bypasser) instead. - - name: Generate ExaDev App token - id: app-token - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - owner: ExaDev - repositories: cc-peer - - name: Release env: GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} diff --git a/release.config.ts b/release.config.ts index 21d632c..6c25028 100644 --- a/release.config.ts +++ b/release.config.ts @@ -30,8 +30,15 @@ const config: GlobalConfig = { ], ["@semantic-release/changelog", { changelogFile: "CHANGELOG.md" }], ["@semantic-release/npm", { pkgRoot: "." }], - // @semantic-release/git is intentionally absent: its changelog commit-back - // pushes directly to main, which the branch ruleset refuses for any token that is not the exadev App bypasser. Re-add it together with the App-token minting in ci.yml once the App private key is available as a repo secret; until then release notes live on the GitHub release only. + // Pushes the version bump and changelog back to main as a real commit, tagged by @semantic-release/github below (which runs after, so the tag lands on this commit, not the one that triggered the release). Needs the exadev App's token, since the branch ruleset refuses a direct push to main from any other token — see ci.yml's own comment on generating it before checkout. + [ + "@semantic-release/git", + { + assets: ["CHANGELOG.md", "package.json"], + message: + "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}", + }, + ], ["@semantic-release/github", { addReleases: "bottom" }], ], };