Git ワークフロー・デプロイ運用
CLAUDE.md から外出し。ブランチ運用・clasp 環境分離・デプロイ手順の詳細を集約する。
ブランチ運用
main— 本番ブランチ。直接 push 禁止。PR 経由でのみマージ- 作業ブランチは目的別プレフィックス + 短い説明
- GitHub Actions (
deploy.yml) は main push 時に自動デプロイ。docs/***.mdはトリガー対象外
ブランチ命名規則
| プレフィックス | 用途 | 例 |
|---|---|---|
feat/ | 新機能の追加 | feat/add-sync-tool |
fix/ | バグ修正 | fix/cc-header-mismatch |
refactor/ | リファクタリング(動作変更なし) | refactor/modular-monolith |
docs/ | ドキュメントのみの変更 | docs/update-file-paths |
chore/ | 設定・CI/CD・雑務 | chore/update-gitignore |
コード変更時の順序
git commit— ローカルにコミットnpm run push:dev— 開発用 GAS にソース push- GAS 上で動作確認 — UI / メニュー / ログから挙動を検証
git push— 動作確認済みコードを GitHub に push- PR 作成 → レビュー → main マージ
動作未確認のコードを GitHub に push しない。 prod デプロイは main マージ時の GitHub Actions で自動実行される。
GAS 環境分離 (Prod / Dev)
本番データの誤操作を防ぐため、GAS プロジェクトを本番用・開発用に分離している。
- 環境判定: GAS スクリプトプロパティ
ENVの値で決まる(dev→ 開発、未設定 orprod→ 本番) - 環境依存値の参照:
Envモジュール (mas/000_infra/001_env.js) 経由で一元取得(ADR-0013 参照)Env.name()/Env.isDev()/Env.isProd()— 環境判定Env.spreadsheetId()— 対象スプレッドシート IDEnv.geminiApiKey()— Gemini API キーEnv.receiptFolderId()/Env.setReceiptFolderId()— 領収書フォルダ ID
- clasp 環境切替:
.clasp.dev.json/.clasp.prod.jsonをclasp-switch.shで.clasp.jsonにコピーして切り替え
npm-scripts(デプロイ操作)
| コマンド | 動作 |
|---|---|
npm run push:dev | 開発用 GAS にソースを push (Web アプリ URL は更新されない) |
npm run push:prod | 本番用 GAS にソースを push (Web アプリ URL は更新されない) |
npm run deploy:dev | push:dev + Web アプリ deployment 更新 (共有 /exec URL に反映) |
npm run deploy:prod | push:prod + Web アプリ deployment 更新 (共有 /exec URL に反映) |
npm run open:dev | 開発用 GAS エディタを開く |
npm run open:prod | 本番用 GAS エディタを開く |
npm run status | 現在の .clasp.json がどちらの環境か確認 |
deploy:* は Web アプリとして共有されている /exec URL を最新コードで更新する。deployment ID は scripts/deploy.sh で dev/prod 別に管理。コード変更なしでも実行可能(バージョン番号のみ進む)。
PR rebase + force-with-lease push のオペレーション
PR ブランチを最新 main に追従させる際の rebase + force-with-lease push 手順。scripts/hooks/pre_bash_guard.sh が --force / --force-with-lease を含む push を自動実行から技術的にブロックしているため、AI Agent から直接 push できない。docs/_internal/06_ops/failure_patterns.md #42 (PR #873 で実発生) の対策として明文化。
手順
- AI Agent 側: rebase + コンフリクト解消まで実施
git checkout main && git pull origin main git checkout <feature-branch> git rebase main # コンフリクトがあれば解消 → git add → git rebase --continue - AI Agent 側: ローカル検証を pass させる (例: docs 系)
LOCAL=1 node scripts/docs-build.mjs # → Built N pages node scripts/docs-nav-lint.mjs # → 0 WARN / 0 FAIL node scripts/adr-lint-doc-consistency.mjs # → 0 WARN / 0 FAIL (ADR 系) - ユーザに
!prefix で手動実行を依頼:以下を ! prefix で実行してください: ! git push --force-with-lease origin <feature-branch>!prefix で sandbox 外から実行することでpre_bash_guardhook を経由しない (CLAUDE.md L「不可逆禁止 + PreToolUse Hook」由来の意図的な設計) - AI Agent 側: push 完了後、remote 反映を確認
gh pr view <PR番号> --json mergeable,headRefOid # mergeable: "MERGEABLE" / headRefOid: ローカル HEAD と一致mergeableの確定待ちはnode scripts/pr-merge-check.mjs --pre <PR番号>でも可 (UNKNOWN を抜けるまでポーリングする)。下記「PR merge 前後の定型照合」を参照。 - AI Agent 側: CI green 確認後、ユーザの「マージ」明示指示でのみ merge (自動マージ禁止規約)
gh pr checks <PR番号> --watch # CI green 待ち gh pr merge <PR番号> --squash --delete-branch
通常 push との違い
- 通常の
git push(force でない) は hook 対象外 → AI Agent から自動実行 OK --force/--force-with-leaseを含む push のみ手動依頼が必要git push -u origin <branch>(新規ブランチの初回 push) は force ではないため自動実行 OKgh pr merge自体は hook 対象外だが、feedback_pr_merge_disciplineでユーザ明示指示必須
よくあるケース: PR が CONFLICTING になった時
- PR のコンフリクト確認:
node scripts/pr-merge-check.mjs --pre <N>で確定値を取得 (CONFLICTINGは exit 1 で報告) - 上記手順 1-2 で rebase + ローカル検証
- 手順 3 でユーザに force-with-lease push を依頼
- PR が
MERGEABLEに戻ることを確認 (gh pr view <N> --json mergeable,headRefOid) - CI 再走を待って merge
PR merge 前後の定型照合 (pr-merge-check)
PR を merge する前後で毎回確認する 2 点を scripts/pr-merge-check.mjs の 1 コマンドにまとめてある。詳しい仕様はスクリプト先頭のコメントが大元なので、ここでは使い方だけ示す。
merge 前: merge 可否の確定を待つ
node scripts/pr-merge-check.mjs --pre <PR番号>
mergeableがUNKNOWNのあいだは GitHub が再計算中の暫定値。確定するまで最大 60 秒ポーリングして確定値を報告するCONFLICTINGのまま merge を待つと CI が発火しない。green に見えても未検証なので exit 1 で止める。解消手順は「main を取り込む → 生成物を再生成する → push する」- 判定が確定しても、CI green とユーザの「マージ」明示指示は別に確認する
merge 後: 取り込み漏れの照合
node scripts/pr-merge-check.mjs --post <PR番号> [期待SHA]
- merge commit の第 2 親が PR の head と一致するかを照合する。push イベントの遅延で古い head が merge される取り込み漏れを検知できる (#1791 で実発生)
期待SHAにローカルで push した控え (git rev-parse HEAD) を渡すと、検証済みのローカルがそのまま merge されたことまで確認できる- squash / rebase merge は第 2 親を持たないため照合できない。このリポの標準は merge commit 方式
clasp push 失敗の切り分け
clasp push (および npm run push:dev / deploy:dev) で push が走っていないと疑われる時の切り分け。npm run deploy:* は push:* && deploy.sh の && 連結で、push が "Skipping push." と表示しつつ exit 0 で抜けると deploy.sh が無批判に走り「✅ Deploy complete」を出す ため、ログを tail -3 で切ると気づけない (failure_patterns.md #43)。tail -30 以上で出力全体を確認する。
ケース A: 認証切れ (invalid_grant / invalid_rapt)
- ユーザーに
! clasp login --creds creds.jsonの実行を依頼 - ブラウザ操作が必要なため、Claude Code は自律実行不可
ケース B: manifest invalid → silent skip (clasp 3.x の罠)
Skipping push. だけ表示されて他にエラーが見えない場合、mas/appsscript.json の enum 値が不正で manifest validation が落ちている可能性が高い。
webapp.accessの有効値はUNKNOWN_ACCESS/DOMAIN/ANYONE/ANYONE_ANONYMOUS/MYSELFの 5 つのみ。ANYONE_WITH_GOOGLE_ACCOUNT等の口語表現は受け付けられないoauthScopesの部分宣言も自動検出を完全オフにする副作用あり (failure_patterns.md #26)- 切り分け: 直近で
mas/appsscript.jsonを触っていないか git log で確認 →clasp push --forceを試して silent skip しないか観察 → デプロイ後の HAR/console で新シンボル grep して bundle 同一性を verify
この症状が出たら最初に「修正が反映されていない」をコード問題と誤診せず deploy 状況を疑う (CLAUDE.md "Definition of Done" #1 / #5)。
テストランナー
- 配置:
mas/900_test/901_test_runner.js - prod デプロイ時は GitHub Actions で
mas/900_test/ディレクトリごと削除(本番に持ち込まない) - テストケース追加は
901_test_runner.jsを直接編集 - 実行は GAS エディタの関数選択 → 実行 (UI 操作)
docs コミットの軽微マーカー [skip-news](news 一覧との連動・ADR-0136)
docs サイトの「最新更新ページ (What's New)」一覧は、各ページの更新日時を「本文が最後に意味的に変わったコミット」から計算する。誤字直しのような軽微な修正で日時を動かしたくない場合は、コミットメッセージの 1 行目に [skip-news] を含める。
docs(adr): 参照先の表記揃え [skip-news]
fix(docs): 誤字修正 (受け取り→受取) [skip-news]
- 効果: そのコミットは news 一覧の更新日時の計算から除外される(一覧の日時は前回の本文変更コミットのまま)。
- 非強制: 付け忘れても一覧の日時が動くだけで、何も壊れない。lint・コミットフックの強制はない。
- 適用範囲: news 一覧のみ。PR 単位の全変更を記録する「ドキュメント変更履歴 (doc_changelog)」には適用されない。git 履歴自体も不変。
- 遡及しない: マーカーを付けた時点から効く。過去のコミットには効かない。
- 実質変更に付けない: 読者に見せるべき変更(設計変更の記録・方針追記など)への誤付与は誤除外として月次集計の監視対象(月 2 件以上で ADR-0136 撤退条件 #1 発動)。
- 自動キーワードはない:
typo/style:/chore:等の subject キーワードでは除外されない(ADR-0136 受理前精査で chore/style コミットの 94.1% が実質変更を含むと判明したため不採用)。 - 言及にも効く点に注意: 判定は字面一致のため、実質変更のコミットで本機能に言及する場合は subject に角括弧つきの字面を書かない(「skip-news マーカー」のように書く)。本実装のコミットがこの誤爆を踏み、subject を修正した実例。
- 判定パターンの正典は
scripts/generate-doc-news.mjsのMINOR_COMMIT_PATTERNS。変更する場合は本節を同一 PR で更新する。
関連ドキュメント
docs/test/02_integration_test.md— 統合テスト手順docs/dev/dev_mas-096_clasp_push_protection.md— clasp push 保護docs/dev/dev_mas-195_pre_push_hook.md— pre-push 自動チェックdocs/_internal/workspace_rules.md— 並行開発時のコンフリクト防止docs/_internal/hooks_setup.md— Claude Code Hooks (LLM 行動の技術的強制ガード)