| name | project-sync-issues |
| description | Issue/PR の状態とプロジェクト Status の自動同期を設定する。モード A は `Fandhe-AI/actions/project-sync` Composite Action を使う `.github/workflows/project-sync.yml` を生成 (PAT または GitHub App トークン)。モード B は既存の不整合を一括補正。「自動同期セットアップ」「PR レビュー時に In Review 化」「ボードと Issue の状態を同期」などで使用。 |
| model | sonnet |
| user-invocable | true |
project-sync-issues
GitHub Actions ワークフローファイルを生成し、Issue/PR の状態変更をプロジェクトの Status フィールドに自動同期します。手動での一括補正モードも提供します。
前提条件
- 対象の GitHub Project がリポジトリにリンクされていること
gh CLI がインストールされ、認証済みであること(project スコープ付き)
フロー
ユーザーに実行モードを確認する:
- 自動同期セットアップ — GitHub Actions ワークフローを生成(初回推奨)
- 手動一括補正 — 現在の不整合を一括修正(スポット実行用)
モード A: 自動同期セットアップ
Step A-1: プロジェクト情報を取得する
gh repo view --json owner -q '.owner.login'
gh project list --owner <owner> --format json
ユーザーに対象プロジェクトの番号を確認する。
Step A-2: 認証シークレットを案内する
GitHub Actions から Projects API にアクセスするには GITHUB_TOKEN では不足するため、以下のいずれかが必要:
方法 1: Personal Access Token(個人/小規模向け)
- GitHub Settings → Developer settings → Personal access tokens → Fine-grained tokens
- 必要なスコープ:
project(読み書き)+ issues(読み書き)+ pull_requests(読み書き)
- リポジトリの Settings → Secrets and variables → Actions →
PROJECT_TOKEN として登録
方法 2: GitHub App トークン(Organization 向け・推奨)
- GitHub App を作成し、Organization に
Projects: Read and write 権限を付与
- ワークフロー内で
actions/create-github-app-token を使用してトークンを生成
Step A-3: GitHub Actions ワークフローを生成する
Fandhe-AI/actions/project-sync Composite Action を使用する。.github/workflows/project-sync.yml を生成する。
参照方式(内製 action は @latest、サードパーティ action は固定 SHA):
Fandhe-AI/actions/*(本スキルでは project-sync)は組織内で管理・レビューされる内製 action のため @latest タグ参照とする(SHA pin は廃止済み。オーナー決定)。一方、サードパーティ action(actions/create-github-app-token 等)は @main / @vN 等の可動参照ではなく、検証済みのコミット SHA で固定する。生成のたびに最新 SHA を動的取得して埋め込む方式は、取得時点で上流が侵害・意図せず改変されていた場合にそのコードをそのまま導入先へ伝播させてしまう。そのためワークフロー生成時は以下のレビュー済み固定 SHA を定数として使用し、動的な最新 SHA 取得は行わない:
| Action | 固定 SHA | 対応バージョン |
|---|
actions/create-github-app-token | fee1f7d63c2ff003460e3d139729b119787bc349 | v2.2.2 |
上記 SHA は導入時点でコード内容(action.yml・参照スクリプト全文)を実際に取得・精査したうえで固定した値である。SHA を更新する必要がある場合のみ(生成のたびには実行しない)、以下の手順で変更内容そのものを精査してから本ファイルの定数とワークフロー例を更新する(対象はサードパーティ action のみ。Fandhe-AI/actions/project-sync は @latest 参照のため SHA 更新手順の対象外):
gh api repos/actions/create-github-app-token/commits/main --jq '.sha'
gh api repos/actions/create-github-app-token/compare/<旧SHA>...<新SHA> --jq '.files[] | {filename, patch}'
gh api repos/actions/create-github-app-token/contents/action.yml?ref=<新SHA> --jq '.content' | base64 -d
差分パッチと action.yml(および参照スクリプト全文)を実際に読み、意図しない変更・不審なコマンド追加がないことを人手で確認する。可能であれば署名・リリース provenance(gh attestation verify 等)も確認する。確認が取れた場合のみ、上記の固定 SHA 表と後続のワークフロー例内 uses: 行のコメント(対応バージョン)を合わせて更新する。Fandhe-AI/actions/project-sync は @latest 参照のためこの精査手順は不要(組織内で管理・レビューされる前提でオーナーが受容済み)。
PAT を使用する場合:
name: Project Sync
on:
issues:
types: [opened, closed, reopened]
pull_request:
types: [opened, closed, ready_for_review, review_requested]
permissions:
contents: read
jobs:
sync:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Sync project status
uses: Fandhe-AI/actions/project-sync@latest
with:
project-number: '<number>'
project-owner: '<owner>'
token: ${{ secrets.PROJECT_TOKEN }}
GitHub App を使用する場合(推奨):
name: Project Sync
on:
issues:
types: [opened, closed, reopened]
pull_request:
types: [opened, closed, ready_for_review, review_requested]
permissions:
contents: read
jobs:
sync:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Generate token
id: token
uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
owner: '<owner>'
- name: Sync project status
uses: Fandhe-AI/actions/project-sync@latest
with:
project-number:
カスタム Status オプション名を使用する場合:
Status オプション名がデフォルト(Todo / In Progress / In Review / Done)と異なる場合は inputs で指定する:
- name: Sync project status
uses: Fandhe-AI/actions/project-sync@latest
with:
project-number: '<number>'
project-owner: '<owner>'
token: ${{ secrets.PROJECT_TOKEN }}
status-todo: 'バックログ'
status-in-progress: '作業中'
status-in-review: 'レビュー中'
status-done: '完了'
Step A-4: ステータスマッピングを確認する
生成するワークフローのデフォルトマッピング:
| イベント | アクション | Status |
|---|
| Issue | opened | Todo |
| Issue | closed | Done |
| Issue | reopened | Todo |
| PR | opened | In Progress |
| PR | ready_for_review | In Review |
| PR | review_requested | In Review |
| PR | closed (merged) | Done |
| PR | closed (not merged) | Todo |
ユーザーの要望に応じてマッピングをカスタマイズする。
Step A-5: ワークフローファイルを配置する
mkdir -p .github/workflows
ユーザーにコミット・プッシュを案内する。
モード B: 手動一括補正
プロジェクトと Issue/PR の現在の状態を比較し、不整合を一括修正する。自動同期セットアップ後の初回補正や、手動変更の反映に使用する。
Step B-1: プロジェクトアイテムを取得する
gh project item-list <number> \
--owner <owner> \
--format json \
--limit 999
Step B-2: Issue/PR の現在状態を確認する
Issue/PR タイプのアイテムに対して現在の状態を確認:
gh issue view <issue-url> --json state,labels,assignees
gh pr view <pr-url> --json state,isDraft,reviewRequests,merged
Step B-3: 状態の不一致を検出する
以下の不一致パターンを検出:
- Issue が closed だがプロジェクトの Status が Done でない → Done に更新
- Issue が open だがプロジェクトの Status が Done → Todo に更新
- PR がマージ済みだが Status が Done でない → Done に更新
- PR にレビューリクエストがあるが Status が In Review でない → In Review に更新
Step B-4: リポジトリの未追加 Issue/PR を検出する
gh issue list --state open --json number,url,title --limit 999
gh pr list --state open --json number,url,title --limit 999
プロジェクトのアイテム URL と比較して未追加分を特定する。
Step B-5: ユーザーに同期内容を確認する
検出結果を表示:
## 同期内容
### ステータス更新(N 件)
- #42: ソーシャルログイン — Status: In Progress → Done(Issue closed)
- #45: バグ修正 — Status: Done → Todo(Issue reopened)
- #50: リファクタリング PR — Status: In Progress → In Review(レビュー依頼済み)
### 新規追加(M 件)
- #55: 新機能リクエスト (Issue)
- #56: ドキュメント更新 PR
実行しますか?
Step B-6: 同期を実行する
gh project field-list <number> --owner <owner> --format json
gh project item-edit \
--id <item-id> \
--field-id <status-field-id> \
--project-id <project-id> \
--single-select-option-id <option-id>
gh project item-add <number> \
--owner <owner> \
--url <issue-or-pr-url> \
--format json
Step B-7: 同期結果を報告する
| 操作 | 件数 |
|---|
| ステータス更新 | N 件 |
| 新規追加 | M 件 |
| 変更なし | K 件 |
注意事項
- 認証: GitHub Actions から Projects API へのアクセスには
GITHUB_TOKEN では不足。PAT または GitHub App トークンが必要
- PAT 有効期限: fine-grained PAT は最大1年。定期ローテーション推奨
- ビルトインワークフローとの併用:
project-init でビルトインワークフロー(closed→Done, merged→Done)を有効化済みの場合、Actions ワークフローと二重に発火するが、同じ値への更新なので実害はない
- PR ライフサイクル: ビルトインワークフローは closed/merged のみ対応。opened→In Progress, review_requested→In Review は Actions でのみ自動化可能
- プライベートリポジトリ: org の Settings → Actions → General でプライベートリポジトリからの Action 共有を許可する必要あり
- 手動補正モードは同期前に必ずユーザーの確認を得る
- DraftIssue タイプのアイテムは同期対象外(実 Issue が存在しないため)
- ネットワークを要する(主に API 経由。後述の「sandbox 環境での実行」節を参照)
- サードパーティ action は必ずコミット SHA で固定する:
@main / @vN 等の可動参照は生成しない。上流のタグ付け替え・ブランチ改変が未検証のまま流れ込むサプライチェーンリスクを避けるため(SHA 更新時は差分を確認してから更新する)。Fandhe-AI/actions/*(内製 action)は @latest 参照とする(組織内で管理・レビューされるため。SHA pin は廃止済み。オーナー決定)
- permissions は最小権限で明示する: workflow レベルで
contents: read を明示する。同期処理自体は PROJECT_TOKEN / GitHub App トークン側の権限で動作するため、GITHUB_TOKEN への追加権限は不要
検証
モード A 完了後: .github/workflows/project-sync.yml が存在し、YAML が正しく記述されていること。加えて以下を確認する:
uses: 行の参照方式が正しいこと(Fandhe-AI/actions/* は @latest、それ以外(サードパーティ)は40桁の16進数コミット SHA で固定。サードパーティ側は @main・@v2.2.2・@master・任意ブランチ名等の可動参照が残っていないことを積極的に検証する):
f=.github/workflows/project-sync.yml
total=$(grep -c 'uses:' "$f")
fandhe_total=$(grep -cE 'uses:\s*Fandhe-AI/actions/' "$f")
fandhe_ok=$(grep -cE 'uses:\s*Fandhe-AI/actions/[^@[:space:]]+@latest([[:space:]]|#|$)' "$f")
other_total=$((total - fandhe_total))
other_pinned=$(grep -E 'uses:' "$f" | grep -vE 'Fandhe-AI/actions/' \
| grep -cE 'uses:\s*[^@[:space:]]+@[0-9a-f]{40}([[:space:]]|#|$)' || true)
if [ "$total" -eq 0 ]; then
echo "NG: 検証対象の uses: 行が見つからない(workflow 生成に失敗している可能性)" >&2
exit 1
elif [ "$fandhe_total" -eq "$fandhe_ok" ] && [ "$other_total" -eq "$other_pinned" ]; then
echo OK
else
echo "NG: 参照方式が不正な uses: 行がある(fandhe_total=${fandhe_total}, fandhe_ok=${fandhe_ok}, other_total=${other_total}, other_pinned=${other_pinned})" >&2
exit 1
fi
が出力されること( 行が 1 件以上存在し、 行はすべて 、それ以外の行はすべて 40 桁 SHA 固定)。 が出力された場合は workflow の生成内容を見直す
コミット・プッシュ後に GitHub Actions の実行履歴で初回トリガーが確認できれば完了。
モード B 完了後: Step B-7 の結果表で「変更なし: 0 件以上」が表示されていること。以下で最終状態を確認する:
gh project item-list <number> --owner <owner> --format json --limit 999
sandbox 環境での実行
このスキルはネットワーク越しの GitHub 操作(同期 workflow のコミット・プッシュ、gh project item-edit 等の一括補正)を必須とする。該当コマンドはコマンド単位で sandbox 無効にして実行する。ネットワーク遮断を解除できない環境では実行できない。