From 4e121923eb94e207698ca0033cf3a81316db2f4e Mon Sep 17 00:00:00 2001 From: Elmehdi Aitbrahim Date: Fri, 24 Jul 2026 09:47:07 -0400 Subject: [PATCH] fix(release): grant pull-requests:read + harden PR-number parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'Compose release notes' step calls `gh api .../commits//pulls` and `.../pulls/`, which need `pull-requests: read`. The workflow only granted `contents: write`, so the default GITHUB_TOKEN got 403 'Resource not accessible by integration'; the error body was then fed back as a fake PR number, producing 'unsupported protocol scheme' and failing the release. - Add `pull-requests: read` to permissions (root cause). - Defense-in-depth: only ever append a bare numeric PR number to the list, and skip any non-numeric entry when fetching — so a future API hiccup can't crash the notes step again. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/release.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dc4985f9..b9fd6891 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,6 +15,8 @@ on: permissions: contents: write # create the tag and the release + pull-requests: read # "Compose release notes" reads merged PRs (list-PRs-for-commit + get-PR); + # without this the default GITHUB_TOKEN gets 403 "Resource not accessible by integration". jobs: release: @@ -137,8 +139,11 @@ jobs: # Every PR whose commits land in this range, de-duplicated. : > /tmp/pr-numbers.txt for sha in $(git log --format=%H "$RANGE"); do + # `grep '^[0-9]+$'` guards the file against ever holding anything but a bare PR + # number: if a `gh api` call errors (e.g. a 403), its body must never be treated as + # a "PR number" and fed back into a URL. Belt-and-braces with the numeric loop below. gh api "repos/${{ github.repository }}/commits/$sha/pulls" \ - -q '.[].number' 2>/dev/null >> /tmp/pr-numbers.txt || true + -q '.[].number' 2>/dev/null | grep -E '^[0-9]+$' >> /tmp/pr-numbers.txt || true done sort -u -n /tmp/pr-numbers.txt -o /tmp/pr-numbers.txt echo "found $(wc -l < /tmp/pr-numbers.txt) PRs in $RANGE" @@ -146,7 +151,7 @@ jobs: # Fetch each PR's title/body/labels, then compose. jq -s folds the stream into an array. : > /tmp/prs.ndjson while read -r n; do - [ -n "$n" ] || continue + case "$n" in ''|*[!0-9]*) continue ;; esac # numeric PR numbers only gh api "repos/${{ github.repository }}/pulls/$n" \ -q '{number:.number,title:.title,body:(.body // ""),labels:[.labels[].name]}' \ >> /tmp/prs.ndjson