Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion .github/workflows/update-lang-fix-psr-and-sync-version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,28 @@ concurrency:
cancel-in-progress: false

permissions:
contents: write
# `read`, and deliberately not `write`, because nothing here uses the ambient
# GITHUB_TOKEN any more: the checkout, the commit/push and the version badge
# all run on GitHub App tokens. What this line really controls now is who can
# CALL this workflow.
#
# A reusable workflow's `permissions:` is a REQUEST, and GitHub refuses the
# call outright when a caller grants less -- it is a hard startup error, not a
# silent capping:
#
# The workflow is requesting 'contents: write', but is only allowed
# 'contents: read'.
#
# No jobs run, no logs are produced, and the run just shows "a workflow file
# issue" -- which is how fogproject's merge stub failed on its first two real
# merges while asking for the correct, least-privilege `contents: read`.
#
# So do not raise this back to `write` to be safe. Raising it forces every
# caller to grant write for a token none of them use, and breaks at startup
# any caller that does not. If a step here ever genuinely needs the ambient
# token, give that step its own App token instead, the way the badge step
# does.
contents: read

env:
# Pinned, not "latest". An unpinned formatter is a second source of drift:
Expand Down
6 changes: 6 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ don't "simplify" those back to the default `GITHUB_TOKEN` just because the call
`workflow_call`/`workflow_dispatch`, and `pull_request: types: [closed]` (a merge — which the
bot's direct push is not) are all safe for the same reason, and all three are in use. The
test to apply to a new trigger is that one question, not whether it happens to be a cron.
- A reusable workflow's `permissions:` block is a **request**, and a caller granting less is a
hard startup error — `The workflow is requesting 'contents: write', but is only allowed
'contents: read'` — not a silent capping. No jobs run and no logs are written, so it surfaces
only as "a workflow file issue". Keep a reusable workflow's request as low as it genuinely
needs (these workflows do their writing with App tokens, so `contents: read` is usually
right); raising it forces every caller to grant the same, and breaks the ones that don't.
- Separately from that safety question, check **which ref a trigger is read from** before
relying on it. Most events — including `pull_request_target`, `schedule` and
`workflow_dispatch` — are read only from the repository's default branch, so a workflow file
Expand Down