Fix GitHub Actions 403 "Resource not accessible by integration" when pushing
The problem
A workflow step that commits a generated file back to the repo failed with:
remote: Write access to repository not granted.
fatal: unable to access 'https://github.com/org/repo.git/': The requested URL returned error: 403
and API calls (releases, comments) failed with 403 Resource not accessible by integration.
What didn't work
- Assuming
GITHUB_TOKENis writable by default — since 2023 its default permissions are read-only unless the workflow declares more. - Creating a personal access token for CI — works today, then expires, is scoped to a human, and shows every bot commit under that human's name.
git push https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/...— same token, same 403; the credentials were never the missing piece, the permissions were.
The fix
permissions:
contents: write # the whole fix for pushes and release uploads
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # wires GITHUB_TOKEN into git automatically
- run: |
git config user.name "release-bot"
git config user.email "bot@users.noreply.github.com"
echo "build $(date -u +%Y%m%d%H%M)" >> BUILD.txt
git add BUILD.txt
git commit -m "chore: record build"
git push
If the repo's default workflow permissions are locked to read-only in org settings, the permissions: block above overrides them per-workflow (as long as org policy allows).
Why it works
The workflow token is a GitHub App token whose grants must be declared at the workflow or job level; contents: write is what authorizes the push, and the checkout action's persisted credentials mean no manual token plumbing is needed.