State the Checks API gap instead of prescribing an impossible tick
Fine-grained tokens have no Checks permission. GitHub's permission reference lists no Checks section and no check-run endpoint, and checks is absent from the token form's pre-fill parameters, so the earlier instruction to tick Checks: Read asked for a box that does not exist. A token created with every listed permission still could not read check runs, which is what surfaced this. The prompt now states the consequence rather than offering a remedy: gh pr checks reports commit statuses only and gh run view returns no annotations. Both degrade to empty output rather than a permission error, so without the note they read as a broken CI integration. Job logs are unaffected; they fall under Actions, which is granted. secret_scanning_alerts and vulnerability_alerts move into the pre-filled URL, leaving nothing for the operator to tick beyond repository selection.
This commit is contained in:
@@ -186,15 +186,30 @@ workflows=write actions=write statuses=read security_events=write
|
||||
secret_scanning_alerts=read vulnerability_alerts=read
|
||||
```
|
||||
|
||||
Two things the form cannot pre-fill, so the task prints them as a checklist:
|
||||
One thing the form cannot pre-fill: **Repository access → Only select repositories
|
||||
→ `api-portal`.** GitHub has no query parameter for repository selection.
|
||||
|
||||
1. **Repository access → Only select repositories → `api-portal`.** GitHub has no
|
||||
query parameter for repository selection.
|
||||
2. **Checks: Read.** The only permission the agent needs that is absent from
|
||||
GitHub's pre-fill parameter list. Without it `gh pr checks` reports no status
|
||||
rollup and `gh run view` returns no annotations — both fail as empty results
|
||||
rather than as permission errors, so a missed tick is easy to misread as a
|
||||
broken CI integration.
|
||||
### The Checks API is out of reach
|
||||
|
||||
Fine-grained tokens cannot read check runs. This is not a permission you forgot to
|
||||
grant — GitHub's permission reference has no Checks section and lists no check-run
|
||||
endpoint, so there is no box to tick. Inside the sandbox:
|
||||
|
||||
| Command | Behaviour |
|
||||
| --- | --- |
|
||||
| `gh pr checks` | shows commit statuses only, not check runs |
|
||||
| `gh run view` | returns no annotations |
|
||||
| `gh run view --log` | works — job logs fall under Actions |
|
||||
|
||||
Both degrade to empty output rather than a permission error, so they read as a broken
|
||||
CI integration unless you know why. A 403 names what it wanted in the
|
||||
`X-Accepted-GitHub-Permissions` response header.
|
||||
|
||||
Only an installation token from a GitHub App can reach the Checks API. That was
|
||||
evaluated and rejected for this workflow: minting one requires the App private key on
|
||||
every developer's machine, and device-flow user tokens — the alternative that needs no
|
||||
key — were measured and do **not** honour `repository_id`, so they reach every
|
||||
repository in the installation.
|
||||
|
||||
Generate the token and paste it at the prompt. It is read with the terminal echo off
|
||||
and piped straight into the `sbx` secret store, so it never reaches your shell history.
|
||||
|
||||
+17
-14
@@ -40,13 +40,13 @@ TOKEN_URL_PERMISSIONS=(
|
||||
vulnerability_alerts=read
|
||||
)
|
||||
|
||||
# "checks" is the one permission the agent needs that GitHub omits from the
|
||||
# pre-fill parameters, so it has to be ticked by hand. Each entry names what
|
||||
# breaks without it, because an unticked box fails later as an empty result or
|
||||
# a 403 rather than as a permission error.
|
||||
TOKEN_MANUAL_PERMISSIONS=(
|
||||
"Checks: Read - without it 'gh pr checks' reports no status rollup and"
|
||||
" 'gh run view' returns no annotations"
|
||||
# Fine-grained tokens cannot reach the Checks API at all: GitHub's permission
|
||||
# reference has no Checks section and lists no check-run endpoint, so there is
|
||||
# no box to tick. Both calls below degrade to empty output rather than a
|
||||
# permission error, which reads as broken CI unless it is called out.
|
||||
TOKEN_LIMITATIONS=(
|
||||
"gh pr checks shows only commit statuses, not check runs"
|
||||
"gh run view returns no annotations"
|
||||
)
|
||||
|
||||
usage() {
|
||||
@@ -205,17 +205,20 @@ Create a fine-grained token for $REPOSITORY.
|
||||
Everything except the repository is pre-filled. On the page:
|
||||
|
||||
1. Repository access -> Only select repositories -> ${REPOSITORY#*/}
|
||||
2. Under Permissions -> Repository permissions, tick the one the form
|
||||
cannot pre-fill:
|
||||
2. Generate token, then paste it below.
|
||||
|
||||
Every permission is pre-filled. Fine-grained tokens cannot read check runs,
|
||||
so inside the sandbox:
|
||||
EOF
|
||||
|
||||
local permission
|
||||
for permission in "${TOKEN_MANUAL_PERMISSIONS[@]}"; do
|
||||
printf ' %s\n' "$permission" >&2
|
||||
local limitation
|
||||
for limitation in "${TOKEN_LIMITATIONS[@]}"; do
|
||||
printf ' %s\n' "$limitation" >&2
|
||||
done
|
||||
|
||||
cat >&2 <<EOF
|
||||
3. Generate token, then paste it below.
|
||||
cat >&2 <<'EOF'
|
||||
|
||||
A 403 will name what it wanted in the X-Accepted-GitHub-Permissions header.
|
||||
|
||||
EOF
|
||||
|
||||
|
||||
@@ -69,11 +69,14 @@ for expected in secret_scanning_alerts=read vulnerability_alerts=read statuses=r
|
||||
fail "permission dropped out of the pre-filled URL: $expected"
|
||||
done
|
||||
|
||||
((${#TOKEN_MANUAL_PERMISSIONS[@]})) ||
|
||||
fail "the manual checklist is empty; checks is not pre-fillable and must be listed"
|
||||
((${#TOKEN_LIMITATIONS[@]})) ||
|
||||
fail "the limitations list is empty; the Checks gap must be stated"
|
||||
|
||||
printf '%s\n' "${TOKEN_MANUAL_PERMISSIONS[@]}" | grep -q 'Checks' ||
|
||||
fail "the manual checklist must name Checks"
|
||||
printf '%s\n' "${TOKEN_LIMITATIONS[@]}" | grep -q 'gh pr checks' ||
|
||||
fail "the limitations must name gh pr checks"
|
||||
|
||||
printf '%s\n' "${TOKEN_LIMITATIONS[@]}" | grep -qi 'tick\|check the box' &&
|
||||
fail "the limitations must not imply Checks can be granted"
|
||||
|
||||
if ((failures)); then
|
||||
printf '%d assertion(s) failed\n' "$failures" >&2
|
||||
|
||||
Reference in New Issue
Block a user