0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

組織内のdependabot.ymlを全リポジトリへ自動配信する仕組みを作った|GitHub Apps × Actions × Rulesets 実装メモ

0
Last updated at Posted at 2026-04-24

はじめに

GitHub Organization で管理するリポジトリ数が20を超えてくると、同じ設定ファイル(dependabot.ymlCODEOWNERS など)を全リポジトリに配布する仕組みの重要度が上がります。手動運用のままだとリポジトリ追加のたびにコピーが必要になり、Dependabot 設定の更新も全リポジトリに手動で PR を立てることになるためです。

今回、社内で dependabot.yml をまとめて配信する基盤を整備しました。この記事では、設計の考え方、実装、仕様の深掘りを通して確立した運用ルール、権限設計の方針をまとめます。

前提となる技術スタック:

  • GitHub Organization(中〜大規模、数十リポジトリ)
  • GitHub Apps / GitHub Actions / Organization Rulesets
  • 外部 Action として BetaHuhn/repo-file-sync-action

中央集約が必要な理由

GitHub には .github という予約された組織リポジトリがあり、 CONTRIBUTING.md や Issue / PR テンプレートなど、いくつかのファイルを organization 全体のフォールバックとして配布できます。

ところが dependabot.yml はこのフォールバック機構の対象外.github 配下に置いても、各リポジトリでは有効化されません。各リポジトリの .github/dependabot.yml を個別に置く必要があります。

この制約を踏まえ、以下を満たす配信基盤を設計しました。

  • .github リポジトリで設定を 一元管理
  • 配信先リポジトリを YAML で明示
  • 配信は GitHub Actions で自動化、PR 経由で監査性を保つ
  • 認証は 専用の GitHub App(PAT は使わない)

全体構成

.github/
├── dependabot.yml              # 配信ソース兼、自リポジトリ用の設定
├── sync-config.yml             # 配信先リポジトリの定義
└── workflows/
    └── sync-dependabot.yml     # 配信ワークフロー

フロー:

  1. .github/dependabot.yml を編集 → main に push
  2. GitHub Actions が発火し、sync-config.yml にある全リポジトリに対して sync branch を作成
  3. 各リポジトリに同期 PR が作成される
  4. PR がマージされれば各リポジトリで Dependabot が稼働

配信フロー図

実装

配信元の dependabot.yml

機能要件は以下の4点。

  • 週次で依存関係更新をチェック
  • 脆弱性対応とは別チャンネルとして扱う(アラートは即座、アップデート PR は週次)
  • クールダウン期間で新リリース直後の地雷バージョンを避ける
  • GitHub Actions のアップデートは1つの PR に集約してレビュー負担を下げる
version: 2
updates:
  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: weekly
    open-pull-requests-limit: 10
    cooldown:
      default-days: 7
    groups:
      github-actions:
        patterns:
          - "*"

cooldown.default-days: 7 は新バージョンがリリースされてから7日間経過するまで PR を作らない設定です。サプライチェーン攻撃対策として有効で、かつ脆弱性修正(security updates)には適用されないため安全性とバランスが取れています。

配信先の sync-config.yml

repo-file-sync-action が参照する設定ファイル。

group:
  files:
    - source: .github/dependabot.yml
      dest: .github/dependabot.yml
  repos: |
    owner/repo-a
    owner/repo-b
    owner/repo-c
    # ...全リポジトリを列挙

リポジトリ追加時はここを編集するだけで済む設計です。

配信ワークフロー

name: Sync dependabot.yml to all repos

on:
  push:
    paths:
      - .github/dependabot.yml
      - .github/sync-config.yml
    branches:
      - main
  workflow_dispatch:

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@<SHA>  # v6.0.2

      - uses: actions/create-github-app-token@<SHA>  # v3.1.1
        id: app-token
        with:
          app-id: ${{ vars.OPS_BOT_APP_ID }}
          private-key: ${{ secrets.OPS_BOT_PRIVATE_KEY }}
          owner: <your-org>

      - uses: BetaHuhn/repo-file-sync-action@<SHA>  # v1.21.1
        with:
          GH_INSTALLATION_TOKEN: ${{ steps.app-token.outputs.token }}
          CONFIG_PATH: .github/sync-config.yml
          COMMIT_PREFIX: "chore: "
          COMMIT_EACH_FILE: false
          PR_BODY: |
            (PRの説明文)
          PR_LABELS: sync
          TEAM_REVIEWERS: <team-slug>

Action は SHA pin で固定しました。tag は後から付け替えが可能なため、サプライチェーン対策として SHA で固定するのが安全です。

paths 指定により、ワークフロー自体(sync-dependabot.yml)を変更しても発火しません。source である dependabot.yml か配信先一覧の sync-config.yml が変更された場合のみ動きます。

GitHub App の設計と命名体系

組織自動化のための GitHub App を作るとき、用途ごとに分割するか、汎用 App で統合するか は重要な設計判断です。

比較軸

観点 単一 App 用途別に分割
権限最小化 肥大化しやすい 必要最小限を個別付与
秘密鍵漏洩時の影響範囲 全機能に波及 機能単位に限定
管理コスト 中(App作成・Secret管理が増える)
通知・監査の識別性 全操作が同じ bot 名義 機能ごとに識別可能
権限追加時の Org 承認 既存 App 権限の拡張が必要 新 App 作成で独立

採用した方針: 「汎用 bot + 将来の特化 bot への分離経路」

今回は以下の方針を採用しました。

  • 日常的な運用自動化は汎用 App にまとめる*-ops-bot として命名)
  • 本番影響が大きい操作は専用 App に切り出す(将来の *-deploy-bot / *-admin-bot / *-notify-bot

ops という語は DevOps 文脈では広義の「運用自動化」として使われ、GitHub 自動化の文脈にも馴染みます。

汎用 App の守備範囲

  • PR / Issue の非破壊的な自動化(ラベル、コメント、アサイン、Project 追加)
  • .github 配下のテンプレート・設定ファイル配信
  • リリースノート / Changelog のドラフト生成

将来、専用 App に切り出す領域

  • 本番環境のデプロイ / インフラ変更操作
  • Org Admin 権限(メンバー管理、リポジトリ作成)
  • 外部サービス連携(Slack 通知、Webhook 受信)
  • 第三者 Action に秘密鍵を渡すケース

この分離方針を 命名段階で表明しておくこと が重要でした。将来専用 App を追加したときに、汎用 bot と並立する命名階層(*-ops-bot / *-deploy-bot / *-notify-bot)が自然に成立するためです。

Variables / Secrets の権限最小化

Organization Variables と Secrets には可視性の選択肢があります。

  • All repositories: Org 内すべてのリポジトリからアクセス可能
  • Private repositories: Private リポジトリからのみアクセス可能
  • Selected repositories: 指定したリポジトリのみアクセス可能

今回の配信基盤は .github リポジトリのワークフローでのみ使う設計です。他リポジトリからアクセスする必要がないため、Selected repositories で .github のみを指定 しました。

Visibility: Selected repositories
└── .github のみ

権限最小化の原則に沿った設定で、秘密鍵が仮にワークフローログから漏れても影響範囲は .github リポジトリに閉じます。

Secret は 書き込み専用仕様(一度登録した値を読み取る API はない)なので、「旧 Secret から新 Secret に値をコピー」という操作は直接できません。秘密鍵の扱いは以下を運用ルールとしました。

  • 秘密鍵 .pem はパスワードマネージャに保管し、ダウンロードフォルダには放置しない
  • Secret への貼り付け後はクリップボードをクリアする

macOS なら:

pbcopy < ~/path-to/app-private-key.pem
# GitHub UI に Cmd+V で貼り付け
pbcopy < /dev/null  # 貼り付け後にクリップボード掃除

クリップボード履歴アプリ(Paste / Alfred / Raycast 等)に平文の秘密鍵が残る事故を防ぐため、貼り付け後の掃除は必須としています。

action の動作仕様を深掘りする

配信基盤を安定運用するには、BetaHuhn/repo-file-sync-action の動作仕様を正確に把握しておく必要があります。公式 README、action.ymlsrc/git.js を照合して挙動を確定させました。

使用した input と確定した挙動

自分たちの sync-dependabot.yml で指定している input と、その挙動を整理します。

input 指定値 挙動
SKIP_PR 未指定(default: false) sync branch を作成して PR を開く。明示的に true にしない限り default branch への直接 push は発生しない
BRANCH_PREFIX 未指定(default: repo-sync/SOURCE_REPO_NAME repo-sync/<source>/<branch> 形式の sync branch が自動生成される
CONFIG_PATH .github/sync-config.yml 配信先リポジトリの定義ファイル
TEAM_REVIEWERS <team-slug> PR 新規作成時・既存 PR 更新時の両方で reviewer 追加を試行する
OVERWRITE_EXISTING_PR 未指定(default: true) 既存 PR の titlebody のみ上書き。reviewer は温存される
COMMIT_PREFIX chore: 同期 commit のプレフィックス
COMMIT_EACH_FILE false 複数ファイル同期時に一つの commit にまとめる

v1.21 の公式 input と照合した結果

v1.21 時点で有効な input は公式に定義されているものに限られます。未定義の input は warning で無視されるため、記述時に公式リストとの照合が必要でした。今回の実装では以下を意識しました。

  • 未定義の input(例: PR_TITLE)は使わない
  • 条件付きで動く input の前提を確認する
    • 例: COMMIT_AS_PR_TITLEORIGINAL_MESSAGE: true が前提(README に "Only works if ORIGINAL_MESSAGE is true and working" と明記)

冪等性を前提とした運用

reviewer 追加が「新規作成時・既存 PR 更新時の両方で実行される」挙動を利用して、以下の運用にしました。

  • 権限設計(App の Organization permissions や team collaborator)を後から整えたあとに、sync を再実行するだけで既存 PR にも reviewer が後付けされる
  • 既存 PR を一度閉じて新規作成し直す必要はない
  • 人間が手動で追加した reviewer は OVERWRITE_EXISTING_PR: true でも温存されるため、bot と人間の追加が共存できる

確立した運用ルール

以上の深掘りを踏まえ、以下をチームの標準プロセスに追加しました。

  • 外部 Action を採用するときは README に加えて action.ymlsrc/ まで精読する
    • 未定義 input の検出
    • 条件付きオプションの前提確認
    • default 値の挙動確認
  • Action の SHA pin を徹底する
  • 新規 Action のレビュー時は v1.x の breaking change に注意する

Organization Rulesets と bypass 設計

Organization 全体で Rulesets を運用する場合、bypass_actors の設計 が自動化 bot の動作に直結します。

Rulesets の挙動を把握する

Rulesets は以下の設定で どの branch・どのリポジトリに rule が適用されるか を定義します。

{
  "conditions": {
    "ref_name": {
      "exclude": ["refs/heads/deployment/**/*", "refs/heads/apply/**/*"],
      "include": ["~ALL"]
    },
    "repository_name": {
      "include": ["~ALL"]
    }
  },
  "rules": [{ "type": "pull_request", "parameters": { ... } }]
}

ref_name.include: ["~ALL"] を指定すると すべての branch が対象になります。これが今回の重要ポイントでした。

sync 系の action は repo-sync/<source> のような branch を作ってそこに push する 動作なので、全 branch 対象の Ruleset があると sync branch への push も rule が適用されます。pull_request rule(PR 経由必須)が全 branch にかかっていると、sync branch への push まで PR 経由を要求されてしまう構造です。

bypass_actors で自動化 bot を許容する

Ruleset には bypass_actors が用意されており、ここに登録された User / Team / App(Integration)は rule を回避できます。

actor_type 用途
User 個別ユーザー(基本的に非推奨。Team 経由が良い)
Team チーム単位。admin 権限運用と相性が良い
Integration GitHub App 単位。自動化 bot の bypass はここに登録する

actor_type: "Integration" を指定する場合、actor_id には App ID(Installation ID ではなく)を使います。ここは混乱しやすいポイントです。

採用した bypass 設計

以下の設計を採用しました。

  • default branch を守る Ruleset: bypass_actors は空。人間も bot もバイパスできず、main への直接 push は一切発生しない
  • PR Approval を要求する Ruleset: bypass_actors に自動化 bot App を登録。bot は sync branch への push と PR 管理を自由に行える
  • Required workflow を要求する Ruleset: 同様に自動化 bot App を登録。必須ワークフローの完了を待たずに sync branch 操作ができる

実際の更新 API

Ruleset の更新は PUT /orgs/<org>/rulesets/<ruleset-id> を使います。PUT のペイロードには id / source / _links / created_at などの余計なフィールドを含めないよう、必要フィールドだけ抽出します。

gh api /orgs/<org>/rulesets/<ruleset-id> | \
  jq '{
    name, target, enforcement, conditions, rules,
    bypass_actors: (.bypass_actors + [
      { "actor_id": <app-id>, "actor_type": "Integration", "bypass_mode": "always" }
    ])
  }' > /tmp/ruleset_new.json

gh api /orgs/<org>/rulesets/<ruleset-id> -X PUT --input /tmp/ruleset_new.json

bypass_mode には alwayspull_request があり、sync action のように直接 git push する自動化は always を選択 します。pull_request は「PR 経由の変更のみ bypass」なので、push は対象外になります。

確立した設計原則

  • Ruleset の適用範囲は明示的に最小化~DEFAULT_BRANCHrefs/heads/main に絞るのが基本)
  • 全 branch 対象にする場合は bot 用の bypass_actors を必ず設計 に含める
  • default branch を守る Ruleset には bypass を入れない(最後の砦を残す)
  • bypass は App 単位で行う(User / Team より影響範囲を絞れる)

Team Reviewer のための権限設計

配信 PR には team 単位の reviewer を自動付与する設計にしました。これを実現するには、以下の3層で権限が揃っている必要があります。

必要な3層の権限

  1. GitHub App の Organization permissions: Members: Read
    • Team の node ID を解決するために必要
    • Org 側の owner 承認が要る
  2. Team が各リポジトリの collaborator として登録されている
    • 未登録の場合、reviewer リクエストが拒否される("Reviews may only be requested from collaborators")
  3. Repository permissions: Pull requests: Write
    • PR 自体の作成・編集

これらのうちどれか一つが欠けると reviewer 追加は API レベルで拒否されます。配信 PR の reviewer 追加を標準機能として使うなら、権限チェックをチェックリスト化しておくのが確実です。

team を全リポジトリに登録するスクリプト

for repo in $(cat .github/sync-config.yml | grep -oE "<org>/[a-zA-Z0-9_-]+"); do
  gh api "/orgs/<org>/teams/<team-slug>/repos/${repo}" -X PUT -f permission=admin
done

permissionpull / triage / push / maintain / admin から選びます。既存 team 設定と揃えるのが運用上の一貫性として良いです。

採用した権限設計原則

  • reviewer 指定を team にする場合は Org permission と collaborator 設定を必ず揃える
  • 新規リポジトリ追加時のチェックリストに「配信対象 team を collaborator に追加」を入れる
  • sync action の team reviewer 追加は冪等 なので、権限を揃えてから sync を再実行すれば既存 PR にも reviewer が後付けされる

自動マージの設計

配信 PR は機械的に生成される同一内容のファイル変更です。レビュー負荷を抑えつつ監査性を残す自動マージ設計を検討しました。

選択肢の比較

内容 採用可否
GitHub Native の Auto-merge 各リポジトリで有効化し、gh pr merge --auto --merge で設定。required checks と approval が揃えば自動マージ 検討可
Bot による admin merge Ruleset の bypass_actors に bot を登録済みなので、gh pr merge --merge で approval 要件を bypass 採用候補
SKIP_PR: true で直接 push PR を作らず default branch に直接 push 不採用

SKIP_PR: true を採用しない理由

default branch を守る Ruleset には bypass_actors を空にしておく方針としたため、bot による直接 push は技術的にも不可能です。SKIP_PR: true にするには最後の砦となる Ruleset の bypass を開ける必要があり、サプライチェーン対策として避けるべき設計です。

採用する自動マージの条件

Bot による admin merge を採用する場合、以下を守ります。

  • merge method は merge(Ruleset で allowed_merge_methods: ["merge"] を要求しているため、squash / rebase は拒否される)
  • 各リポジトリの Required status checks をパスすることが前提(Lint や Test)
  • 段階導入(初回配信は手動確認、定常運用から自動マージ)
- name: Auto-merge sync PRs
  env:
    GH_TOKEN: ${{ steps.app-token.outputs.token }}
  run: |
    while IFS= read -r repo; do
      pr=$(gh pr list --repo "$repo" --author app/<bot-slug> --label sync --state open --json number --jq '.[0].number')
      if [ -n "$pr" ]; then
        gh pr merge "$pr" --repo "$repo" --merge
      fi
    done < <(yq '.group.repos[]' .github/sync-config.yml)

確立した運用ルール・原則

今回の設計を通じて、以下をチームの標準プロセスに追加しました。

外部 Action 導入時のチェックリスト

  • README / action.yml / src/ を精読し、有効 input と動作仕様を確定する
  • SHA pin で固定する(tag は後から差し替え可能なため)
  • 条件付きオプションの前提条件を把握する(例: COMMIT_AS_PR_TITLEORIGINAL_MESSAGE 前提)

GitHub App 設計の原則

  • 命名は将来の分離を前提にカテゴリ化する(*-ops-bot / *-deploy-bot / *-admin-bot / *-notify-bot
  • 本番影響が大きい操作は専用 App に分離する
  • Organization permissions は必要最小限(Members: Read など使うもののみ付与)

Variables / Secrets の原則

  • Visibility は Selected repositories を基本とし、アクセス元リポジトリを明示する
  • 秘密鍵 .pem はパスワードマネージャで管理し、貼り付け後にクリップボードを掃除する
  • Secret の rename は不可なので、命名は最初から将来の運用を見据える

Ruleset 設計の原則

  • default branch を守る Ruleset の bypass_actors は空にする
  • 全 branch 対象の Ruleset を作る場合は、自動化 bot 用の bypass_actors を必ず設計する
  • bypass は App 単位(actor_type: Integration)で行う
  • bypass_mode は用途に応じて選択する(直接 push を伴う自動化は always

Team Reviewer の原則

  • 新規リポジトリ追加時のチェックリストに「配信対象 team を collaborator に追加」を入れる
  • GitHub App の Organization permissions: Members: Read を付与する
  • Permission は既存 team 設定と揃える(新 team を作らない限り admin に統一)

まとめ

  • .github リポジトリ + repo-file-sync-action + GitHub App で dependabot.yml の一括配信基盤を構築した
  • 設計の要は GitHub App の用途別分離方針・Variables / Secrets の可視性最小化・Ruleset の bypass_actors 設計・Team Reviewer のための3層権限
  • 仕様把握は README だけでなく action.ymlsrc/ まで照合する運用を標準化した
  • 配信基盤ができたことで、リポジトリ追加時の dependabot 設定漏れが構造的に起きない仕組みになった

今回使った BetaHuhn/repo-file-sync-actionCODEOWNERS.github/workflows/* など他のファイル配信にも使えます。Dependabot 以外のガバナンス系ファイル配信にも横展開が可能です。

参考: 設定まとめ

設定項目
dependabot.ymlinterval weekly
cooldown.default-days 7
groups github-actions: "*" でまとめる
sync-config.yml 配信先リポジトリを列挙
GitHub App permissions (Repository) Contents: Write / Pull requests: Write
GitHub App permissions (Organization) Members: Read
Variables visibility Selected repositories (.github のみ)
Secrets visibility Selected repositories (.github のみ)
Ruleset bypass_actors Team(admin)+ App(actor_type: Integration
Action の SHA pin 必須

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?