changesets Release workflow 开 PR 403——org 级 Actions 开关才是真正的墙
用 changesets 管理 monorepo 版本号,Release workflow 跑了好多次都"成功"——直到某天真的有 .changeset/*.md 待消费,workflow 突然在最后一步炸了。版本 bump 分支推上去了,CHANGELOG 也写了,唯独「开 Version Packages PR」那步 403。
现象
##[error]HttpError: GitHub Actions is not permitted to create or approve pull requests.
- release.yml 里明明已经写了
permissions: pull-requests: write changeset-release/<branch>分支已经推上去(前面的步骤全部成功)- 仓库 Settings → Actions → General 里有个「Allow GitHub Actions to create and approve pull requests」复选框,但是灰的,点不动
- 之前的 Release run 从来没报过错——那是因为那些 run 都没有待消费的 changeset,changesets action 走的是"无事可做"分支,根本不触发开 PR 这一步,自然撞不到这堵墙
permissions: pull-requests: write 给的是 GITHUB_TOKEN 对 PR 内容的读写能力(评论、标签、合并等),不包含「以 GitHub Actions 身份新建 PR」这个能力。这是两套独立的权限体系。
org 在 Actions 策略里关掉了「Allow GitHub Actions to create and approve pull requests」,仓库级的那个框就会变灰锁死,无论 YAML 怎么写都无济于事。
根因
GitHub 对「Actions 能否建/批 PR」有一个独立的双层开关:
- 组织级(org owner 权限):
github.com/organizations/<org>/settings/actions→ Workflow permissions → 「Allow GitHub Actions to create and approve pull requests」 - 仓库级:只有 org 级开关打开后,仓库的那个框才解锁,仍然需要仓库管理员再勾一次
org 是上限,repo 是收口。两层任一关闭,Actions 就没有建 PR 的权力,YAML 里的 permissions 字段完全旁路不了它。
用 API 可以快速确认当前状态:
gh api /repos/<owner>/<repo>/actions/permissions/workflow
# 关键字段:can_approve_pull_request_reviews: false ← 就是这个正解
两级开关都要打开:
第一步,org owner 去组织 Settings → Actions 页勾选开关(这步只有 org owner 能做)。
第二步,开关解锁后,用 API 在仓库级设置(repo admin 即可):
gh api -X PUT /repos/<owner>/<repo>/actions/permissions/workflow \
-F default_workflow_permissions=read \
-F can_approve_pull_request_reviews=true
# 读回确认
gh api /repos/<owner>/<repo>/actions/permissions/workflowdefault_workflow_permissions 保持 read 没问题——release.yml 已经用 per-job 的 contents/pull-requests/packages: write 声明了足够的 token 权限,真正卡的只是 can_approve_pull_request_reviews。
两级都 ON 之后,下次有 changeset 推 main,Release workflow 会自动创建/更新 Version Packages PR,不再 403。验收标志:workflow 日志出现 🦋 success packages published successfully。
当下补救(不改设置也能继续发版)
bump 分支已经推上去了,用人工账号手动开 PR 绕过 Actions 权限限制:
gh pr create \
--base main \
--head changeset-release/main \
--title "Version Packages" \
--body "Bump versions per pending changesets."合并后 Release workflow 会以「无待消费 changeset」模式重跑 publish,publish 只用 GITHUB_TOKEN + packages:write,不需要建 PR 权限,完全不受影响。
合并后记得 git pull --ff-only:远端合并删了 .changeset/*.md、bump 了 package.json,本地停在合并前再提交会把已消费的 changeset 又带回去重复 bump。
一句话外卖
Actions 的
permissions: pull-requests: write和「Actions 能否建 PR」是两套独立开关,org 级策略是天花板,YAML 权限绕不过去。