diff --git a/.github/scripts/check-pr-description.js b/.github/scripts/check-pr-description.js index 2a06c2b36..f5dabea5d 100644 --- a/.github/scripts/check-pr-description.js +++ b/.github/scripts/check-pr-description.js @@ -103,14 +103,21 @@ module.exports = async ({ github, context, core }) => { async function swapLabel(num, add, remove) { if (await labelExists(add)) { - await github.rest.issues.addLabels({ owner, repo, issue_number: num, labels: [add] }); + try { + await github.rest.issues.addLabels({ owner, repo, issue_number: num, labels: [add] }); + } catch (e) { + // Fail soft on a token that can't write labels so a label permission + // problem never masks the actual description verdict. + if (e.status !== 403) throw e; + core.warning(`Could not add "${add}" — token lacks label write here; skipping.`); + } } else { core.warning(`Label "${add}" does not exist in the repo — skipping. Create it once to enable labelling.`); } try { await github.rest.issues.removeLabel({ owner, repo, issue_number: num, name: remove }); } catch (e) { - if (e.status !== 404 && e.status !== 410) throw e; + if (e.status !== 404 && e.status !== 410 && e.status !== 403) throw e; } } diff --git a/.github/workflows/pr-description-check.yml b/.github/workflows/pr-description-check.yml index d527d6938..899d74c7a 100644 --- a/.github/workflows/pr-description-check.yml +++ b/.github/workflows/pr-description-check.yml @@ -7,12 +7,14 @@ on: # pull_request_target runs in the base-repo context (has secrets). # The checkout below pins to the base branch so no fork code is executed. # The script only reads context.payload and calls the GitHub API. -# Least privilege: contents:read for the base-ref checkout, pull-requests:read -# for pulls.get (mergeability), issues:write for label + comment management -# (PR labels and comments both go through the issues API). +# Least privilege: contents:read for the base-ref checkout, pull-requests:write +# to add/remove labels and post comments on PRs, and issues:write for the same +# on real issues. NOTE: modifying a *pull request's* labels/comments needs the +# `pull-requests` scope even though the REST path is under `/issues/{n}/...`; +# `issues:write` alone returns 403 on PRs. permissions: contents: read - pull-requests: read + pull-requests: write issues: write jobs: