SuperAPI AI Directory

project-sync-issues

Deployment & operations

View repository

Updated 10-15 16:33

About this skill

project-sync-issues

Generate a GitHub Actions workflow file to automatically synchronize Issue/PR status changes to the project's Status field. A manual bulk correction mode is also provided.

Prerequisites

  • The target GitHub Project is linked to the repository
  • gh CLI is installed and authenticated (withproject scope)

Flow

Confirm the execution mode with the user:

  • Automatic sync setup — Generate a GitHub Actions workflow (recommended for first-time setup)
  • Manual bulk correction — Correct current inconsistencies in bulk (for spot execution)

Mode A: Automatic sync setup

Step A-1: Retrieve project information

# オーナーを取得
gh repo view --json owner -q '.owner.login'

# プロジェクト番号を確認
gh project list --owner <owner> --format json

Confirm the target project number with the user.

Step A-2: Explain the authentication secret

To access the Projects API from GitHub Actions, GITHUB_TOKEN is insufficient, so one of the following is required:

Method 1: Personal Access Token (for individuals/small scale)

  1. GitHub Settings → Developer settings → Personal access tokens → Fine-grained tokens
  2. Required scopes: project(read/write) + issues(read/write) + pull_requests(read/write)
  3. Repository Settings → Secrets and variables → Actions → PROJECT_TOKEN registered as

Method 2: GitHub App token (for Organizations, recommended)

  1. Create a GitHub App and grant the Organization Projects: Read and write permission
  2. Within the workflow, use actions/create-github-app-token to generate a token

Step A-3: Generate a GitHub Actions workflow

Fandhe-AI/actions/project-sync Use Composite Action..github/workflows/project-sync.yml Generate

Reference method (in-house actions use @latest, third-party actions use pinned SHA):

Fandhe-AI/actions/*(in this skill, project-sync) is an in-house action managed and reviewed within the organization, so @latest tag reference is used (owner's decision). On the other hand, third-party actions (actions/create-github-app-token , etc.) are pinned to verified commit SHAs rather than movable references such as @main / @vN etc. The method of dynamically fetching the latest SHA and embedding it on every generation would propagate the upstream code as-is to the adopter if the upstream had been compromised or unintentionally modified at the time of fetching. Therefore,when generating workflows, use the following reviewed pinned SHAs as constants, and do not perform dynamic fetching of the latest SHA:

Action Pinned SHA Corresponding version
actions/create-github-app-token fee1f7d63c2ff003460e3d139729b119787bc349 v2.2.2

The above SHAs are values pinned after actually fetching and scrutinizing the code contents (action.ymland the full text of referenced scripts) at the time of adoption. Only when the SHA needs to be updated (do not perform this on every generation), use the following procedure to checkthe changes themselvesAfter carefully reviewing, update the constants and workflow examples in this file (the scope is third-party actions only.Fandhe-AI/actions/project-sync は @latest out of scope for the SHA update procedure as reference):

# 更新候補の最新 SHA を取得(更新作業時のみ実行。対象例: actions/create-github-app-token)
gh api repos/actions/create-github-app-token/commits/main --jq '.sha'
# 旧 SHA との差分パッチ(変更内容そのもの)を取得して精査する。ファイル名一覧だけでは不十分
gh api repos/actions/create-github-app-token/compare/<旧SHA>...<新SHA> --jq '.files[] | {filename, patch}'
# Action のエントリーポイント(action.yml)と参照される全スクリプトを新 SHA 時点の
# 内容で取得し、action が実行するコマンド・ダウンロードするバイナリ等に不審な変更が
# ないか実際に読んで確認する
gh api repos/actions/create-github-app-token/contents/action.yml?ref=<新SHA> --jq '.content' | base64 -d

Actually read the diff patch and action.yml(as well as the full text of the referenced scripts), and manually verify that there are no unintended changes or suspicious command additions. If possible, also verify the signature and release provenance (gh attestation verify etc.). Only when verification is obtained, update the fixed SHA table above and the comment (corresponding version) on the uses: lines in the subsequent workflow examples accordingly.Fandhe-AI/actions/project-sync は @latest This review procedure is unnecessary for references (on the premise that they are managed and reviewed within the organization, and the owner has accepted this).

When using a 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 }}

When using a GitHub App (recommended):

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 # v2.2.2
        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: '<number>'
          project-owner: '<owner>'
          token: ${{ steps.token.outputs.token }}

When using custom Status option names:

If the Status option names differ from the defaults (Todo / In Progress / In Review / Done), specify them in 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: Check the status mapping

Default mapping for the workflow to be generated:

Event Action 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

Customize the mapping according to the user's request.

Step A-5: Place the workflow file

mkdir -p .github/workflows
# ワークフローファイルを .github/workflows/project-sync.yml に書き出す

Guide the user to commit and push.

Mode B: Manual bulk correction

Compare the current state of the project and Issues/PRs, and correct inconsistencies in bulk. Use this for the initial correction after setting up automatic synchronization, or to reflect manual changes.

Step B-1: Retrieve project items

gh project item-list <number> \
  --owner <owner> \
  --format json \
  --limit 999

Step B-2: Check the current state of Issues/PRs

For items of type Issue/PR, check the current state:

gh issue view <issue-url> --json state,labels,assignees
gh pr view <pr-url> --json state,isDraft,reviewRequests,merged

Step B-3: Detect state mismatches

Detect the following mismatch patterns:

  • Issue is closed but the project Status is not Done → update to Done
  • Issue is open but the project Status is Done → update to Todo
  • PR is merged but Status is not Done → update to Done
  • PR has a review request but the Status is not In Review → update to In Review

Step B-4: Detect Issues/PRs not added to the repository

gh issue list --state open --json number,url,title --limit 999
gh pr list --state open --json number,url,title --limit 999

Compare with the project's item URLs to identify those not yet added.

Step B-5: Confirm the synchronization details with the user

Display the detection results:

## 同期内容

### ステータス更新(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: Execute synchronization

# フィールドメタデータを取得
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: Report the synchronization results

Operation Count
Status updates N items
Newly added M items
No changes K items

Notes

  • Authentication: For access to the Projects API from GitHub Actions, GITHUB_TOKEN is insufficient. A PAT or GitHub App token is required
  • PAT expiration: fine-grained PATs last up to 1 year. Regular rotation is recommended
  • Combined use with built-in workflows: project-init If the built-in workflow (closed→Done, merged→Done) has already been enabled, it will fire twice along with the Actions workflow, but since it updates to the same value there is no real harm
  • PR lifecycle: The built-in workflow only supports closed/merged. opened→In Progress and review_requested→In Review can only be automated via Actions
  • Private repository: In the org's Settings → Actions → General, sharing Actions from private repositories must be allowed
  • Manual correction mode must always obtain user confirmation before syncing
  • Items of type DraftIssue are excluded from sync (because no real Issue exists)
  • Requires network (mainly via API. See the "Running in a sandbox environment" section below)
  • Third-party actions must always be pinned by commit SHA: @main / @vN Mutable references such as these are not generated. This is to avoid supply chain risks where upstream tag re-pointing or branch modification flows in unverified (when updating the SHA, check the diff before updating).Fandhe-AI/actions/*(in-house action) is @latest referenced as(because it is managed and reviewed within the organization. Owner's decision)
  • permissions must be explicitly specified with least privilege: at the workflow level, contents: read must be explicitly specified. The sync process itself operates under the permissions of PROJECT_TOKEN / the GitHub App token, soGITHUB_TOKEN no additional permissions to are needed

Verification

After Mode A completes: .github/workflows/project-sync.yml exists and the YAML is correctly written. In addition, confirm the following:

  • uses: the reference style of the lines is correct (Fandhe-AI/actions/* は @latest, everything else (third-party) is pinned by a 40-character hexadecimal commit SHA. For third-party, actively verify that no @main・@v2.2.2・@masteror arbitrary branch names or other mutable references remain):
    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
    
    OK is output (uses: 1 or more lines exist, andFandhe-AI/actions/* all lines are @latest, all other lines are pinned by 40-character SHA).NG: If this is output, review the generated workflow content
  • permissions is explicitly specified: grep -c 'permissions:' .github/workflows/project-sync.yml is 1 or more
  • sync to the job timeout-minutes is set: grep -n 'timeout-minutes' .github/workflows/project-sync.yml matches 1 or more lines (missing is a CI workflow convention violation, P1)

Complete once the initial trigger can be confirmed in the GitHub Actions run history after committing and pushing.

After Mode B completes: In the result table of Step B-7, "no changes: 0 or more" is displayed. Confirm the final state with the following:

gh project item-list <number> --owner <owner> --format json --limit 999

Running in a sandbox environment

This skill requires GitHub operations over the network (committing and pushing the sync workflow,gh project item-edit bulk corrections such as these). The relevant commands are executed with the sandbox disabled on a per-command basis. It cannot be executed in an environment where network blocking cannot be lifted.