GitHub Actionsでワークフローが再トリガーされない問題 — GITHUB_TOKEN、PAT、そしてGitHub Apps

2026-03-03 hit count image

GitHub ActionsでGITHUB_TOKENを使ってpushすると他のワークフローがトリガーされない問題の原因と、 PATおよびGitHub Appsを使った解決方法を比較し、GitHub Apps設定ガイドを紹介します。

github_actions

問題の状況

Yarn Workspacesベースのモノレポでは、Dependabotがpackage.jsonのみを更新しyarn.lockを更新しないという問題があります。これを解決するため、DependabotのPRでyarn.lockファイルを自動更新するワークフローを運用していました。このワークフローはlockfileを更新してコミットをpushしますが、push後にCIワークフロー(lint、build、testなど)が再実行されない問題が発生しました。

モノレポでのDependabot運用については、以前の記事をご参照ください。

問題となったワークフローの核心部分は以下の通りです。

steps:
  - name: Checkout repository
    uses: actions/checkout@v4
    with:
      ref: ${{ github.head_ref }}
      token: ${{ secrets.GITHUB_TOKEN }} # このトークンでpushすると他のワークフローがトリガーされない

  # ... yarn.lockの更新 ...

  - name: Commit updated lockfile
    run: |
      git add yarn.lock
      git diff --staged --quiet || git commit -m "chore: update yarn.lock"
      git push  # このpushがCIをトリガーしない

原因

GitHub Actionsでデフォルトで提供されるGITHUB_TOKENでpushすると、他のワークフローがトリガーされません。 これはGitHubの意図的な設計であり、ワークフロー間の無限再帰実行を防止するためです。

When you use the repository’s GITHUB_TOKEN to perform tasks, events triggered by the GITHUB_TOKEN will not create a new workflow run.

GitHub Docs: Triggering a workflow from a workflow

つまり、GITHUB_TOKENでpushしたコミットはpushイベントやpull_requestイベントのsynchronizeタイプを発生させないため、CIワークフローが実行されません。

解決方法の比較

この問題を解決するには、GITHUB_TOKENの代わりに別の認証手段を使用する必要があります。代表的なものとしてPAT(Personal Access Token)GitHub Appsがあります。

項目PATGitHub Apps
所有者個人Organization
権限範囲ユーザーのアクセス権限に依存アプリに設定した権限のみ
トークン寿命手動設定(最大1年)自動発行、1時間後に失効
退職リスクありなし
監査追跡個人アカウントベースBot専用アカウントとして表示
Rate Limit個人アカウント共有アプリ専用(より高い制限)

方法1: PAT (Personal Access Token)

最も素早く適用できる方法です。

設定方法

PATは以下の手順で作成・設定できます。

  1. GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens
  2. Generate new tokenをクリック
  3. 設定:
    • Resource owner: Organizationを選択
    • Repository access: 対象のrepositoryのみを選択
    • Permissions:
      • Contents: Read and write
      • Pull requests: Read and write(必要な場合)
  4. 生成されたトークンをRepositoryのSettings → Secrets → Actionsに登録

ワークフローの修正

このように作成・設定したPATをactions/checkoutに渡すことで、push時に他のワークフローが正常にトリガーされます。

- name: Checkout repository
  uses: actions/checkout@v4
  with:
    ref: ${{ github.head_ref }}
    token: ${{ secrets.PAT_TOKEN }} # PATに変更

PATの欠点

PATは素早く問題を解決できますが、本番環境で長期的に運用するには以下のようなリスクがあります。

項目説明
個人アカウント依存トークン所有者が退職またはアカウントが無効化されるとCIが停止する
広い権限範囲Fine-grainedで制限しても個人のアクセス権限に依存する
手動更新が必要有効期限を設定すると定期的な更新が必要
監査追跡コミットが個人アカウントベースで追跡される

方法2: GitHub Apps(推奨)

Organization所有のGitHub Appを作成してトークンを発行する方法です。PATの欠点をすべて解消でき、本番環境で推奨される方式です。

GitHub Apps設定ガイド

GitHub Appsの設定手順は以下の通りです。

Step 1: GitHub Appの作成

OrganizationのGitHub Appを作成するには、Organization Owner権限が必要です。権限がある場合は以下の手順に従って進めます。

  1. GitHubでOrganizationページに移動
  2. SettingsDeveloper settingsGitHub AppsNew GitHub App

入力項目:

項目説明
GitHub App namemy-ci-botOrganization内でユニークな名前
Homepage URLRepository URL必須だが内部利用のためrepo URLで十分
WebhookActiveのチェックを外すCIトークン発行用なのでWebhookは不要

Permissions設定(最小権限の原則)

今回の問題を解決するために必要な最小権限は以下の通りです。残りの権限はすべて不要なため、最小権限の原則に従い必要な権限のみを付与します。

Repository permissions:

PermissionAccess用途
ContentsRead and writeコードのpush
MetadataRead-only自動選択
Pull requestsRead and writePR関連の操作が必要な場合

Organization permissions / Account permissions: すべて不要

インストール範囲

今回の問題は特定のrepositoryで発生する問題のため、GitHub Appのインストール範囲をOnly on this accountに制限します。これによりAppが他のrepositoryにインストールされることを防止できます。

  • Where can this GitHub App be installed?Only on this account

Create GitHub Appをクリックして作成を完了します。

Step 2: Private Keyの生成

GitHub Appを使用するにはApp IDとPrivate Keyが必要です。App IDはApp設定ページ上部で確認でき、Private Keyは以下の手順で生成できます。

  1. 作成したApp設定ページでApp IDをメモ(ページ上部に表示)
  2. ページ下部のPrivate keysセクション → Generate a private keyをクリック
  3. .pemファイルが自動ダウンロード

この2つの値(App ID、Private Key)が、以降のワークフローでトークンを発行する際に使用されます。

Step 3: RepositoryへのAppインストール

作成したGitHub Appを実際に使用するrepositoryにインストールする必要があります。以下の手順でGitHub Appをインストールします。

  1. App設定ページ左メニュー → Install App
  2. Organizationを選択 → Install
  3. Only select repositories → 対象repositoryを選択
  4. Installをクリック

Step 4: Secretsの登録

App IDとPrivate KeyをGitHub Actionsで使用できるようにSecretsとして登録します。

Repository Settings → Secrets and variablesActionsDependabotのそれぞれに同じSecretを登録します。

  • Actions: Settings → Secrets and variables → ActionsNew repository secret
  • Dependabot: Settings → Secrets and variables → DependabotNew repository secret
Secret Name
MY_CI_BOT_APP_IDStep 2で確認したApp ID
MY_CI_BOT_PRIVATE_KEY.pemファイルの全内容
Note

なぜ両方に登録する必要があるのか?

GitHub Actionsはワークフローをトリガーした主体によって参照するsecrets格納場所が異なります。Dependabotがトリガーしたワークフローはサプライチェーン攻撃防止のため制限されたセキュリティコンテキストで実行され、Dependabot secretsのみを参照できます。一方、通常のイベント(手動push、一般的なPR、workflow_dispatchなど)でトリガーされたワークフローはActions secretsを参照します。したがって、同一のワークフローがどの主体によってトリガーされても正常に動作するためには、両方に登録する必要があります。

GitHub Docs: Using secrets with Dependabot

.pemファイルの内容は以下のような形式です。全体をそのままコピーして登録します。

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
...
-----END RSA PRIVATE KEY-----
Tip

複数のrepositoryで同じAppを使用する場合、Organization Settings → Secretsに登録すれば共有できます。

Step 5: ワークフローの修正

actions/create-github-app-tokenアクションを使用して、ランタイムにトークンを生成します。

steps:
  # 1. checkoutはGITHUB_TOKEN(read)で — トークンを.git/configに残さない
  - name: Checkout repository
    uses: actions/checkout@v4
    with:
      ref: ${{ github.head_ref }}
      persist-credentials: false

  # 2. 依存関係のインストール(この時点で.git/configにcredentialなし → 安全)
  - name: Setup node
    uses: actions/setup-node@v4
    with:
      node-version-file: '.nvmrc'

  - name: Update lockfile
    run: yarn install --no-immutable

  # 3. push直前にのみAppトークンを生成 → 露出時間を最小化
  - name: Generate GitHub App token
    id: app-token
    uses: actions/create-github-app-token@v1
    with:
      app-id: ${{ secrets.MY_CI_BOT_APP_ID }}
      private-key: ${{ secrets.MY_CI_BOT_PRIVATE_KEY }}

  # 4. トークンでremote URLを設定してpush
  - name: Commit and push
    run: |
      git config user.name "my-ci-bot[bot]"
      git config user.email "<APP_ID>+my-ci-bot[bot]@users.noreply.github.com"
      git remote set-url origin "https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/${{ github.repository }}.git"
      git add .
      git diff --staged --quiet || git commit -m "chore: automated update"
      git push

重要なポイントは以下の通りです。

  • actions/create-github-app-token@v1がApp IDとPrivate Keyで**インストールトークン(installation token)**を発行
  • このトークンは約1時間有効で、ワークフロー実行ごとに新しく発行される
  • このトークンでpushすると他のワークフローが正常にトリガーされる
  • git commitのauthorは<app-name>[bot]形式を使用

セキュリティ: トークン露出範囲を最小化する構成

セキュリティのためには、単純にGITHUB_TOKENをGitHub Appトークンに置き換えるだけでは不十分です。トークンが露出する時間と範囲も考慮する必要があります。

actions/checkoutはデフォルトでpersist-credentials: trueのため、渡されたトークンを.git/configextraheaderに保存します。もしAppトークンでcheckoutした後にyarn installを実行すると、依存パッケージのpost-install script.git/configを読み取り、write権限を持つトークンを窃取する可能性があります。

Dependabot PRは外部パッケージを更新するものであるため、このサプライチェーン攻撃シナリオに特に脆弱です。

[危険な構成]
checkout (App token) → .git/configにトークン保存 → yarn install → post-install scriptがトークンを窃取可能

[安全な構成]
checkout (persist-credentials: false) → .git/configにトークンなし → yarn install (安全) → Appトークン生成 → push

これを防止するために以下のような構成を推奨します。

  1. persist-credentials: false: checkout時に.git/configにcredentialを保存しない
  2. トークン生成をpush直前に移動: yarn installなど外部コード実行の後にトークンを生成
  3. git remote set-urlでpush時にのみトークンを使用: トークンが必要な瞬間にのみ設定

permissionsの設定に関する注意点

GitHub Appトークンに切り替えると、ジョブのpermissionsブロックも見直す必要があります。permissionsGITHUB_TOKENに対する権限設定なので、ジョブ内でGITHUB_TOKENを使用しない場合はcontents: writeを付与する必要はありません。

# Before: GITHUB_TOKENでpushするためwrite必要
permissions:
  contents: write

# After: pushはGitHub Appトークンが担当するためreadで十分
permissions:
  contents: read

最小権限の原則に従い、実際に使用しないトークンに不要な権限を付与しないようにすることがセキュリティ強化に役立ちます。

テスト方法

GitHub Appトークンが正しく動作するか確認するため、以下のようなテストワークフローを作成して検証できます。

name: Test GitHub App Token

on:
  push:
    branches:
      - test/app-token # テスト用ブランチでのみ実行

jobs:
  test-token:
    name: Test App Token
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - name: Generate GitHub App token
        id: app-token
        uses: actions/create-github-app-token@v1
        with:
          app-id: ${{ secrets.MY_CI_BOT_APP_ID }}
          private-key: ${{ secrets.MY_CI_BOT_PRIVATE_KEY }}

      - name: Verify token was generated
        run: |
          if [ -z "${{ steps.app-token.outputs.token }}" ]; then
            echo "::error::Token generation failed"
            exit 1
          fi
          echo "Token generated successfully"

      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          token: ${{ steps.app-token.outputs.token }}

      - name: Test push (empty commit on temp branch)
        run: |
          git config user.name "my-ci-bot[bot]"
          git config user.email "<APP_ID>+my-ci-bot[bot]@users.noreply.github.com"
          git checkout -b test/app-token-verify
          git commit --allow-empty -m "test: verify GitHub App token push"
          git push origin test/app-token-verify
          echo "Push succeeded"

      - name: Cleanup temp branch
        if: always()
        run: git push origin --delete test/app-token-verify || true

テスト手順

このテストワークフローをtest/app-tokenブランチに追加してpushすると、以下の過程で設定が正しいか検証できます。

  1. 上記ワークフローファイルをtest/app-tokenブランチに追加してpush
  2. Actionsタブでワークフロー実行結果を確認
  3. 各ステップの成功・失敗で設定を検証:
    • Generate token成功 → Secrets設定が正しい
    • Checkout成功 → トークンでrepoにアクセス可能
    • Push成功 → トークンでpush可能
  4. テスト完了後にワークフローファイルを削除

トラブルシューティング

エラーメッセージ原因解決方法
could not create workflow dispatch event: HTTP 404AppがrepositoryにインストールされていないStep 3のInstall Appを確認
The permissions requested are not granted to this installationAppの権限不足App Settings → Permissionsで権限を追加
Could not resolve to a valid refPrivate Keyが間違っている.pemファイル全内容がSecretに登録されているか確認
Resource not accessible by integrationインストール範囲の問題Appが対象repositoryにインストールされているか確認

まとめ

GitHub ActionsでGITHUB_TOKENを使ってpushすると他のワークフローがトリガーされないのは、無限再帰を防止するための意図的な設計です。これを解決する方法は大きく2つあります。

方法適した状況
PAT素早い一時的な解決が必要な場合
GitHub Apps本番環境で推奨される方法

GitHub Appsは初期設定にOrganization Owner権限が必要という参入障壁がありますが、一度設定すれば個人に依存しない安全で管理しやすいトークン管理が可能です。特にDependabot PRのように外部パッケージを扱うワークフローでは、トークン露出範囲を最小化する構成まで考慮することをお勧めします。

参考資料

私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!

アプリ広報

今見てるブログを作成たDekuが開発したアプリを使ってみてください。
Dekuが開発したアプリはFlutterで開発されています。

興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。



SHARE
Twitter Facebook RSS