GitHub Actions:ワークフローの push が「GH013: Repository rule violations found」で断られる
ステップがコミットかタグを push し、そのブランチのルールが断りました。押していたのは、たいていバージョンの更新、変更履歴、作ったデータ、整形ツールの直しです。GH013 はルールセットから、GH006 は昔からのブランチの保護から来ます。トークンには書く権限がありました。ルールは例外の一覧(bypass list)に無い全員にかかり、GITHUB_TOKEN はその一覧に入れられません。なので push には、別の主体か、ブランチへの別の入り方か、別のブランチが要ります。
見え方
remote: error: GH013: Repository rule violations found for refs/heads/main. remote: Review all repository rules at https://github.com/OWNER/REPO/rules?ref=refs%2Fheads%2Fmain remote: - Changes must be made through a pull request. remote: - 7 of 7 required status checks are expected. ! [remote rejected] HEAD -> main (push declined due to repository rule violations)
これは vow-lang の定期のリリースです(#1915)。ブランチの保護では、1行目が remote: error: GH006: Protected branch update failed for refs/heads/main. になります。そのあとの行が、push を断ったルールの名前です:
- 「Changes must be made through a pull request.」(変更はプルリクエストで)
- 「Required status check "…" is expected.」か「N of N required status checks are expected.」(必須のステータスチェックが無い):チェックはそのコミットそのもので先に通っている必要があり、ジョブの中で作ったコミットはまだどこでもチェックされていないので、プルリクエストが必須でなくても push は断られます(hexgate #297)。
- 「Changes must be made through the merge queue」(変更はマージキューで・talos-hq/clud #2518)。
- 「Commits must have verified signatures」(コミットに検証済みの署名が要る):ジョブの中の
git commitで作ったコミットには署名がありません(fullsend #9062)。
コミットそのものはできているので、push の前のステップは正常に見えます。Scottcjn/rustchain-bounties では、毎週のスナップショットが5週間、計算されては捨てられていました(#17026)。
GITHUB_TOKEN が例外になれない理由
ドキュメントは、ルールセットの例外の一覧に入れられる相手を挙げています:リポジトリの管理者とオーナー、maintain か write のロール、チーム、GitHub App、Dependabot。GITHUB_TOKEN は組み込みの GitHub Actions のインテグレーションのもので、これは自分のアカウントにインストールされたものではありません。truvity/github-structure はこれを入れようとして、422 Actor GitHub Actions integration must be part of the ruleset source or owner organization を受け取りました(#80)。hexgate はリリースを1回出すためにルールを止め、main はチェックの無いままになりました。
1. 例外の一覧に入れた GitHub App
Contents の読み書きを持つ GitHub App を作ってリポジトリにインストールし、ルールセットの例外の一覧に足して、そのトークンで push します。bidabil/1min-Getway は、semantic-release のジョブのために、そうした App を main の例外になれる唯一の主体にしました(#139)。opencode の stats のジョブは、publish のジョブがすでに使っていた App のトークンで push するようになりました(#55270)。
- uses: actions/create-github-app-token@v3
id: app
with:
client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
- uses: actions/checkout@v7
with:
token: ${{ steps.app.outputs.token }}
- run: |
git commit -am "chore: release"
git push
- App のトークンでの push はワークフローを起動します。
GITHUB_TOKENでの push はしません。opencode はそのために stats のコミットに[skip ci]をつけ、1min-Getway は逆に、タグでイメージのビルドが始まるようにそれを使いました。 - App の鍵を使えるものは、どれもルールを越えて push できるようになります。鍵は environment か、それが要る1つのジョブにだけ置きます。
2. プルリクエスト
新しいブランチに push してプルリクエストを開けば、ルールはそのままです。meal-planner は、まず push を試し、答えが GH013 か GH006 なら、ブランチと gh pr create に切り替えます(#151)。
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v7
- run: ./update-stats.sh
- env:
GH_TOKEN: ${{ github.token }}
run: |
branch="bot/stats-${{ github.run_id }}"
git switch -c "$branch"
git commit -am "Update stats"
git push origin "$branch"
gh pr create --base main --head "$branch" --title "Update stats" --body "From run ${{ github.run_id }}"
GITHUB_TOKENがプルリクエストを開けるのは、「Allow GitHub Actions to create and approve pull requests」が入っているときだけです(Settings > Actions > General)。ドキュメントによると、個人のアカウントに作った新しいリポジトリでは切れています。rustchain-bounties では切れていたので、そのジョブは別のトークンを使っています。- ドキュメント:「When a pull request is created or updated by a workflow using
GITHUB_TOKEN,pull_requestevents with theopened,synchronize, orreopenedactivity types create workflow runs that require approval.」(GITHUB_TOKEN を使うワークフローがプルリクエストを作るか更新すると、その pull_request の実行は承認が要る)。必須のチェックは、書く権限のある人がプルリクエストの画面でその実行を承認するまで待ちます。 - コミットのメッセージの
[skip ci]は、プルリクエストのワークフローも止めるので、必須のチェックは「expected」のままになります(rustchain-bounties はこれを外しました)。 - ルールがマージキューを求めているなら、プルリクエストもキューを通す必要があります(talos-hq/clud)。
3. 検証済みの署名:コミットを GitHub に作らせる
ジョブの中の git で作ったコミットは、ジョブが自分の鍵で署名しない限り、どのトークンでも署名がありません。ボットの署名の検証についてのドキュメントでは、それは「will only work if the request is verified and authenticated as the GitHub App or bot and contains no custom author information, custom committer information, and no custom signature information」(GitHub App かボットとして認証されたリクエストで、作者・コミッター・署名を独自に指定していないときだけ働く)です。なので、GitHub App のトークンを使い、API でコミットを作ります。たとえば GraphQL の createCommitOnBranch で、fullsend はインストールの処理をこれに切り替えました(#9062 がその変更にリンクしています)。上のブランチのルールについては、App が例外の一覧に入っているか、プルリクエストを通す必要がやはりあります。
4. main に置かなくてよいデータ
グラフ・スナップショット・キャッシュは、ルールのかからないブランチに置けます。homelab-monitor は星の数のグラフを孤立した star-history ブランチにコミットし、README はそこの raw のファイルを指します(#351)。scheduled-archive-runner はスナップショットを slot-snapshots ブランチに移しました(#20)。ルールセットのブランチのパターンが、新しいブランチに当たらないかを確かめます。
公開は push のあとに
hexgate のリリースは、PyPI に公開してから、バージョンの更新とタグを push していました。push が断られたので、0.3.2 は PyPI にあるのに、タグも main のバージョンの更新も GitHub のリリースもありませんでした(#297)。取り消せないステップより前に、push かプルリクエストを置きます。
見分け方
- 「remote: Permission to … denied to github-actions[bot]」と 403:トークンがまったく書けませんでした(「Permission … denied to github-actions[bot]」)。
- 「refusing to allow a GitHub App to create or update workflow」:push が
.github/workflows/の下のファイルを変えています(「refusing to allow a GitHub App to create or update workflow」)。 - 「Push cannot contain secrets」のついた GH013:プッシュ保護がコミットの中にシークレットを見つけました。ブランチのルールではないので、コミットからシークレットを取り除きます。
失敗したジョブを IntelliJ IDEA から見るなら
Pipeline Inbox for GitHub Actions Workflows は、Lesstep が作っている JetBrains IDE(2024.1 以降)のプラグインです。すべてのリポジトリの実行を、ジョブ・ステップと一緒に IDE のツールウィンドウに並べ、いまのブランチの実行はステータスバーに出ます。読むのは無料、失敗したジョブの再実行・キャンセル・ワークフローの実行・デプロイのレビューは Pro(月 US$1.50・30日の無料試用つき)です。
GitHub と GitHub Actions は GitHub, Inc. の商標、IntelliJ IDEA は JetBrains s.r.o. の商標です。このページは GitHub, Inc.・JetBrains のいずれとも提携しておらず、承認も受けていません。
ほかに:「Permission … denied to github-actions[bot]」 · 「refusing to allow a GitHub App」 · 「Resource not accessible by integration」 · IntelliJ IDEA で使える GitHub Actions のプラグインの比較 · English