docs: document required GitHub App permissions and PAT scopes#416
Conversation
## What Added a "Required GitHub App permissions" subsection under the GitHub App Installation auth table listing the Contents read/write, Pull requests read/write, Metadata read, and Organization Members read permissions the action actually needs. Added a corresponding "Required PAT scopes" subsection clarifying the classic and fine-grained PAT scopes, and corrected the PAT field description that previously implied read-only access was sufficient. ## Why Until now the README left users to discover the required permissions by trial and error. When any required permission is missing, the action fails with "403 Resource not accessible by integration" on whichever API call needed it, which is opaque and hard to map back to a specific App or PAT setting. Documenting the explicit permission set up front cuts that debugging loop and removes a recurring source of issues. ## Notes - Permissions list was derived from the action's actual API calls in cleanowners.py (gh_org.is_member, repo.create_ref / create_file / update, repo.create_pull) — verifying any future call additions may shift the required permission set. - The PAT description fix may surprise users who read the old line as a hint that a read-only PAT could be used; the doc now explicitly tells them otherwise. - No code, tests, or workflow files changed — README only. Signed-off-by: jmeridth <jmeridth@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR improves the action’s user-facing documentation by explicitly listing the GitHub App permissions and PAT scopes required for the action to successfully read/update CODEOWNERS content and open pull requests, reducing “403 Resource not accessible by integration” trial-and-error setup.
Changes:
- Documented the exact required GitHub App permissions (repo metadata/contents/PRs and org members).
- Documented required classic and fine-grained PAT scopes, and updated
GH_TOKEN’s description to point to those requirements.
Show a summary per file
| File | Description |
|---|---|
| README.md | Adds explicit GitHub App permission requirements and PAT scope guidance; clarifies GH_TOKEN expectations. |
Copilot's findings
- Files reviewed: 1/1 changed files
- Comments generated: 1
| - **Repository → Pull requests**: Read & write — open PRs that suggest CODEOWNERS changes | ||
| - **Organization → Members**: Read — check whether each CODEOWNERS entry is still an organization member | ||
|
|
||
| If any of these are missing the action fails with `Error: 403 Resource not accessible by integration` on the first API call that needs the missing permission. Updating an existing App's permissions also requires the installation owner to accept the new permission request before it takes effect. |
| App must be granted these permissions: | ||
|
|
||
| - **Repository → Metadata**: Read (default) | ||
| - **Repository → Contents**: Read & write — read CODEOWNERS files; create branches and commit the placeholder CODEOWNERS file when one is missing |
There was a problem hiding this comment.
Nice catch on the read-only-token correction in the GH_TOKEN row -- that's been wrong for a while and worth fixing on its own.
One small thing on the Contents: Write rationale:
| - **Repository → Contents**: Read & write — read CODEOWNERS files; create branches and commit the placeholder CODEOWNERS file when one is missing | |
| - **Repository → Contents**: Read & write — read CODEOWNERS files; create branches and commit changes (updating existing CODEOWNERS files to remove members and creating the placeholder file when one is missing) |
I believe Contents: Write is required for the primary use case too, not just the "missing CODEOWNERS" path. commit_changes() is called from two sites in cleanowners.py -- the missing-CODEOWNERS branch (around L155) and the existing-CODEOWNERS branch that removes members (around L229) -- and both unconditionally hit repo.create_ref() plus repo.create_file() / file_contents.update(). A reader landing on the current wording could reasonably conclude they can skip Write if their repos already have CODEOWNERS files, then get 403s on the first run.
Pull Request
Proposed Changes
Added a Required GitHub App permissions subsection under the GitHub App Installation auth table that lists the exact permissions the action needs:
Added a corresponding Required PAT scopes subsection covering both classic (
repo,read:org) and fine-grained PAT setups, and corrected theGH_TOKENfield description that previously said "Must have read access to all repository you are interested in scanning" — the action also opens PRs, so read-only is insufficient.Why
Until now the README left users to discover required permissions by trial and error. When any required permission is missing, the action fails with
Error: 403 Resource not accessible by integrationon the first API call that needs it, which is opaque and hard to map back to a specific App or PAT setting. Documenting the explicit permission set up front cuts that debugging loop. Also helps installation owners know they need to accept the new permission request on the org installation after the App definition is updated.Testing
cleanowners.py:gh_org.is_member(username)→ Organization Members: Readrepo.file_contents(...)/repo.blob(...)→ Repository Contents: Readrepo.create_ref(...),repo.create_file(...),file_contents.update(...)→ Repository Contents: Writerepo.create_pull(...)→ Repository Pull requests: Writemake test→ 74 tests pass with 100% coveragemarkdownlint-cli2 --config .github/linters/.markdown-lint.yml README.md→ 0 errorsReadiness Checklist
Author/Contributor
make lintand fix any issues that you have introducedmake testand ensure you have test coverage for the lines you are introducing