post-merge について
post-mergeは、PRのマージ後にデプロイし、反映状況を確認するパイプライン段階です。マージ内容とチームのデプロイ設定を読み取り、設定に応じた処理とデプロイ確認タスクの起動を行います。
主な機能
- 01PR情報と変更ファイルを取得
- 02チーム設定に基づきデプロイ方式を判断
- 03設定時に手動デプロイを実行
- 04デプロイ確認を起動して反映を待機
- 05PRに状況を投稿しレポートを作成
活用シーン
- 01PRマージ後にデプロイ処理を開始
- 02チーム設定に沿って手動デプロイを実施
- 03GitHub Actionsによるデプロイの反映を確認
- 04複数のデプロイ対象ごとに確認を起動
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ fellowship-dev/ dogfooded-skills --skill post-mergeインストール後、Claude Code で/post-mergeを入力して読み込まれたか確認します。
詳細
post-merge
自律型デプロイパイプラインのステージ 1 です。PR のマージ後に実行されます。差分を読み取り、デプロイが自動か手動かを判断し、必要に応じて手動デプロイを実行した後、ライブ状態になるまでポーリングする deployment-checker ジョブをディスパッチします。
使用するタイミング
- PR がデフォルトブランチにマージされたとき、event-rules によって自動的にトリガーされます
- 手動:
/post-merge PR_NUMBER org/repo
呼び出し
/post-merge 42 fellowship-dev/pylot
引数
PR_NUMBER=$1 # PR number
REPO=$2 # org/repo
ランブック
ステップ 0:重複排除ゲート
PR=$1
REPO=$2
# Check if deployment-checker job already dispatched for this PR
EXISTING=$(ls ${PYLOT_DISPATCH_DIR:-$HOME/.local/share/pylot/missions}/pending/ \
${PYLOT_DISPATCH_DIR:-$HOME/.local/share/pylot/missions}/running/ 2>/dev/null \
| grep "deploy-check-${PR}-" || true)
if [ -n "$EXISTING" ]; then
echo "[post-merge] outcome=\"already dispatched — deploy-checker job exists\" status=success"
exit 0
fi
ステップ 1:PR のコンテキストを収集する
# Fetch PR metadata
PR_DATA=$(gh pr view $PR --repo $REPO --json number,title,mergedAt,baseRefName,headRefName,files,url,mergeCommit)
PR_TITLE=$(echo "$PR_DATA" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['title'])")
PR_SHA=$(echo "$PR_DATA" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('mergeCommit',{}).get('oid','') or '')" 2>/dev/null || true)
CHANGED_FILES=$(echo "$PR_DATA" | python3 -c "import json,sys; d=json.load(sys.stdin); print('\n'.join(f['path'] for f in d['files']))")
BASE_BRANCH=$(echo "$PR_DATA" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['baseRefName'])")
echo "PR: $PR — $PR_TITLE"
echo "SHA: $PR_SHA"
echo "Base: $BASE_BRANCH"
echo "Files changed:"
echo "$CHANGED_FILES"
ステップ 2:チームのデプロイ設定を読み取る
チームの CLAUDE.md を読み取り、このリポジトリに設定されているデプロイ方法を確認します。deploy: セクションを探します。
# Example in crew/infra/CLAUDE.md or team CLAUDE.md:
deploy:
method: auto-pull # auto-pull | github-actions | manual
health_url: "http://localhost:1337/_health"
timeout_minutes: 5
checker_script: "scripts/deployment-checker-pylot.sh"
expected_sha_field: "sha" # JSON field in health response containing deployed sha
デプロイ方法の判断ツリー:
| 方法 | アクション |
|---|---|
auto-pull | デプロイは自動です。ステップ 3 とステップ 4 をスキップします(auto-deploy.sh が deploy-check を処理します)。 |
github-actions | マージによってデプロイがトリガーされます。約 2 分待ってから、ステップ 4 に進みます。 |
manual | CTO が今すぐデプロイコマンドを実行し(ステップ 3)、その後ステップ 4 に進みます。 |
デプロイ設定が見つからない場合は、警告を出力して終了します。推測してはいけません。
ステップ 3:手動デプロイ(method = manual の場合)
method: manual の場合にのみ実行します。チーム設定からデプロイコマンドを読み取ります。
# Example: manual deploy for a Fly.io app
cd /path/to/repo && fly deploy --remote-only
# Example: manual ECR push
aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_URI
docker build -t $IMAGE . && docker push $IMAGE
実行したコマンドとその出力を記録します。
ステップ 4:deployment-checker ジョブをディスパッチする
method: auto-pull の場合は、このステップをスキップします。 auto-pull リポジトリでは、エグゼキューターの再起動後に auto-deploy.sh によって deploy-check がディスパッチされます。ここでディスパッチすると、デプロイを待つ deploy-checker がキューをブロックし、そのキューが待機対象のデプロイをブロックするという、鶏と卵のデッドロックが発生します。
他のデプロイ方法(github-actions、manual)では、新しいジョブをディスパッチします。
if [ "$DEPLOY_METHOD" != "auto-pull" ]; then
PYLOT_DIR="${PYLOT_DIR:-$HOME/projects/fellowship-dev/pylot}"
curl -sS -X POST \
-H "Authorization: Bearer $(grep '^PYLOT_DISPATCH_TOKEN=' $HOME/projects/fellowship-dev/claude-buddy/.env | cut -d= -f2)" \
-H "Content-Type: application/json" \
-d "$(python3 -c "import json; print(json.dumps({'agent':'${TEAM}.intern','task':'Check deployment for $REPO#$PR — $PR_TITLE','repo':'$REPO','context':'SHA: $PR_SHA. Health URL: $HEALTH_URL. Timeout: ${TIMEOUT_MINUTES:-5} minutes. Checker script: ${CHECKER_SCRIPT}. Run /deployment-checker $PR $REPO.'}))")" \
"http://127.0.0.1:3000/dispatch"
else
echo "[post-merge] Skipping deploy-check dispatch — auto-pull deploys are checked by auto-deploy.sh"
fi
ステップ 5:PR にコメントを投稿する
gh pr comment $PR --repo $REPO --body "$(cat <<'EOF'
**Post-merge pipeline started** 🚀
| Field | Value |
|-------|-------|
| Deploy method | \`$DEPLOY_METHOD\` |
| Health endpoint | \`$HEALTH_URL\` |
| Timeout | ${TIMEOUT_MINUTES:-5} min |
| Expected SHA | \`${PR_SHA:-unknown}\` |
Deployment checker dispatched. Will apply \`deployed\` or \`deploy-failed\` label when complete.
EOF
)"
ステップ 6:レポートを作成する
PYLOT_DIR="${PYLOT_DIR:-$HOME/projects/fellowship-dev/pylot}"
REPORT="$PYLOT_DIR/reports/$(date +%Y-%m-%d)-post-merge-$(echo $REPO | tr '/' '-')-pr${PR}.md"
cat > "$REPORT" <<EOF
# Post-Merge: $REPO PR #$PR — $PR_TITLE
**Date**: $(date +%Y-%m-%d)
**PR**: [$REPO#$PR]($PR_URL)
**SHA**: $PR_SHA
**Deploy method**: $DEPLOY_METHOD
**Deploy-checker job**: dispatched
## Changed Files
$CHANGED_FILES
## Outcome
Deploy-checker dispatched. Awaiting health confirmation.
EOF
チーム設定の参照
各チームの CLAUDE.md には deploy: セクションを含める必要があります。一般的な例:
Pylot(auto-pull)
deploy:
method: auto-pull
health_url: "http://localhost:1337/_health"
timeout_minutes: 5
checker_script: "scripts/deployment-checker-pylot.sh"
expected_sha_field: "sha"
Lexgo(GitHub Actions → Fly.io)
deploy:
method: github-actions
health_url: "https://api.lexgo.cl/_health"
timeout_minutes: 30
checker_script: "scripts/deployment-checker-lexgo.sh"
Booster-pack(ブランチプッシュ → Fly + Vercel)
deploy:
method: auto-pull
health_url: "https://api.booster-pack.dev/health"
timeout_minutes: 10
注記
- チーム設定がない場合は、何もしません。 デプロイ方法を推測してはいけません。設定がないことは、設定が必要であることを示しています。
- SHA の比較はベストエフォートです。 ヘルスエンドポイントに sha フィールドがない場合は、タイムスタンプの比較に切り替えます。
- post-merge は PR ごとに実行されます。 マージされた各 PR に対して、それぞれ専用の deploy-checker ジョブが作成されます。
- モノレポ: リポジトリに複数のデプロイ先(例:バックエンドとフロントエンド)がある場合は、デプロイ先ごとにチェッカーを 1 つディスパッチします。checker_script によって、ポーリングするデプロイ先が決まります。