ALM(秘匿化・汎用化・CI/CD)共通スキル
コードファースト資産を安全に Git へ載せ、機械判定だけでデプロイまで到達させるための共通基盤。
プロダクト非依存であり、foundry-autopilot(Foundry エージェント)、code-apps(Code Apps)など
どのスキルからも同じ仕組みで利用できる。デプロイの実処理だけを各プロダクトスキルへ委譲する。
| 原則 | 内容 |
|---|
| テンプレートのみコミット | 追跡するのは ${VAR} 入りテンプレートだけ。実値は .env とシークレットストアにのみ存在する |
| 二重の防御 | ローカルは pre-commit(sanitize.py → check_secrets.py)、CI は決定論ゲート(review_sanitization.py) |
| 機械判定 | レビューはルールベース。人手の承認(HITL)を前提にせず、判定を再現可能にする |
| ホスティング非依存 | Git ホスティングとシークレットストアは GIT_PROVIDER / SECRET_BACKEND で差し替える |
| 最小権限 | ワークフローは permissions: を明示。contents: write はリリースジョブだけに許可する |
| 記録はリリースに残す | デプロイ結果とレビュー結果は GitHub Releases(バージョンごと)に残す。Issue には残さない |
| 設定の外出し | パス・許可リスト等は alm.config.json。スクリプト本体はどのリポジトリでも無改変で使う |
前提ツール: Python 3.10+、Git、Azure CLI(az)。
シークレットストアに応じて GitHub CLI(gh)または az extension add --name azure-devops を追加する。
事前確認(会話の最初に 1 回だけ)
本スキルの利用が確定したら、standard の共通契約に加え、
1 回の AskUserQuestion で次をまとめて確認する。
| # | 質問 | 合格条件 |
|---|
| 1 | Git provider、repository、visibility、既定 branch は何か | GitHub / Azure DevOps / その他と private / public を確定している |
| 2 | branch protection と environment approval を変更できる担当者は誰か | repository / project の管理担当者と承認者を記録している |
| 3 | secret backend と CI identity は何か | GitHub Secrets / variable group / Key Vault、OIDC / workload identity、rotation owner を確定している |
| 4 | CI が各デプロイ先へ持つ最小権限は何か | 対象環境ごとの scope、期限、role assignment 担当者を記録している |
| 5 | release、rollback、監査ログの運用は何か | version 規則、成果物保持、失敗時の戻し方、通知先を承認済みである |
personal access token や長期 client secret を既定にせず、OIDC / workload identity を優先する。
repository 管理権限、secret backend、CI identity のいずれかが未確定ならパイプラインを有効化しない。
各プロダクトスキルとの責務分担
| 担当 | 内容 | 参照先 |
|---|
alm(本スキル) | 秘匿化・汎用化・pre-commit・レビューゲート・承認・リリース記録 | 本ファイル |
foundry-autopilot | Foundry エージェント定義、ブループリント、Teams パッケージ、公開 | foundry-autopilot |
code-apps | Code Apps の実装、npm run deploy などのデプロイ手順 | code-apps |
standard | ソリューション運用・環境戦略などの上位ルール | standard |
プロダクトスキル側は「何をデプロイするか」だけを定義し、
「どう秘匿化し、どう検証し、どう承認して記録するか」は本スキルに従う。
スキル同梱スクリプト
テーマリポジトリの scripts/ へそのままコピーして使う(alm_config.py を必ず一緒に置く)。
Step 1: レイアウトを alm.config.json で宣言する
スクリプトは無改変で使い、リポジトリごとの差分は設定ファイルだけにする。
未作成なら既定値(**/*.template.* をテンプレート、.env を追跡禁止)で動く。
Copy-Item .github/skills/alm/scripts/*.py scripts/
Copy-Item .github/skills/alm/alm.config.example.json alm.config.json
| キー | 意味 | 例(foundry-autopilot) | 例(code-apps) |
|---|
forbidden_tracked | 追跡してはいけないファイル | .env, a365.generated.config.json | .env, .power/ の生成物 |
templates | ${VAR} 入りテンプレート(コミット対象) | agents/**/*.template.yaml | power.config.template.json |
rendered | レンダリング結果(追跡禁止) | agents/**/agent.yaml | power.config.json |
artifacts | ビルド生成物(追跡禁止) | teams/*.zip | dist/** |
non_secret_vars | 公開識別子(${VAR} 化しない) | AGENT_NAME, BLUEPRINT_ID | APP_NAME |
contents_write_jobs | contents: write を許可するジョブ | release | release |
Step 2: 秘匿値を .env に隔離する
.env(実値・.gitignore)と .env.example(プレースホルダーのみ・コミット対象)を作る。
雛形は references/.env.example。
- テンプレートには実値を一切書かない。環境依存値はすべて
${VAR} にする。
- 公開識別子(アプリ名・エージェント名など)は
non_secret_vars に入れる。
これを入れないと、文章中の名称まで ${VAR} に置換されてテンプレートが壊れる。
python scripts/render.py --template agents/<name>/agent.template.yaml --output agents/<name>/agent.yaml
Step 3: pre-commit ゲートを有効化する
git config core.hooksPath .githooks
#!/bin/sh
set -e
# 1. 実値入りファイルを汎用化し、シークレットストアへ同期してテンプレートをステージ
python scripts/sanitize.py --env .env --set-secrets --stage
# 2. ステージ済み差分に実値が残っていないか検査(残っていればコミット中止)
python scripts/check_secrets.py --env .env
.gitignore を含む雛形一式は references/repo-scaffold.md。
Step 4: シークレットストアを選ぶ
SECRET_BACKEND で送信先が切り替わる。Git ホスティングとは独立に選べる。
python scripts/sanitize.py --env .env --set-secrets --secret-backend github --stage
python scripts/sanitize.py --env .env --set-secrets --secret-backend azure-devops --stage
python scripts/sanitize.py --env .env --set-secrets --secret-backend keyvault --stage
| Git ホスティング | CI 定義 | シークレット保管先 | SECRET_BACKEND |
|---|
| GitHub(private) | .github/workflows/ | GitHub Actions Secrets | github |
| Azure DevOps Repos(private) | .azuredevops/ | 変数グループ(Key Vault 連携可) | azure-devops |
| その他 Git | 各 CI の規約 | Azure Key Vault | keyvault |
| ローカルのみ(PoC) | なし | .env のみ | none |
Azure へのログインは必ず OIDC / ワークロード ID フェデレーションを使い、
クライアントシークレットを保管しない。設定手順は references/ci-providers.md。
Step 5: レビューゲートを CI に組み込む
5.1 最小構成(決定論ゲートのみ)
PR で review_sanitization.py を実行し、必須ステータスチェックにする。
これだけで「実値混入」「テンプレート未汎用化」はマージできなくなる。
5.2 推奨構成(自律レビューゲート連鎖)
5 体のレビューエージェントを直列に並べ、全ゲート PASS のときだけデプロイする。
各エージェントは gate_rules.py のルールを評価するだけなので、判定は決定論的で人手承認が不要。
| ゲート | エージェント | 主なルール |
|---|
| 1. 品質 | quality-inspector | YAML の妥当性、テンプレートの構文、.env.example との整合、スクリプトの構文 |
| 2. 汎用性 | generalization-auditor | 実値混入なし、${VAR} がすべてシークレット経由、ワークフローに環境固有リテラルなし |
| 3. セキュリティ | security-reviewer | 最小権限、pull_request_target 禁止、Action 許可リスト、シークレット持ち出し検出 |
| 4. 可読性 | readability-editor | ジョブ/ステップ名、ヘッダーコメント、行長、TODO 残存 |
| 5. リリース判定 | release-gatekeeper | 上流 4 ゲートがすべて PASS か(GO / NO-GO) |
python scripts/gate_rules.py --gate quality --out .gate/quality.json
python scripts/gate_rules.py --gate release --verdict-dir .gate
python scripts/review_report.py --verdict-dir .gate --out .gate/review-report.md
ワークフロー定義・ルール一覧・プロンプトの書き方は references/review-gates.md。
Step 6: デプロイを承認付きで実行する
- 既定ブランチへのマージでデプロイジョブを起動する。
- デプロイの実処理はプロダクトスキルが定義する(
foundry-autopilot なら deploy.py、
code-apps なら npm run deploy)。ALM 側は認証・環境・順序だけを規定する。
- 承認の扱いは 2 択にする。両方を併用しない。
- 自律運用: ゲート連鎖を審査とみなし、Environment の必須レビュアーを外す。
- 有人運用: Environment に必須レビュアーを設定し、ゲート連鎖は補助にする。
Step 7: リリースとして記録する
デプロイ結果とレビュー結果は、バージョンごとの GitHub Release に残す。
- タグはデプロイしたバージョンに対応させる(例:
agent-v<version>)。
- 本文は
review_report.py が生成したレビュー結果表をそのまま使う。
- 同じバージョンを再デプロイしたときは新規作成せず
gh release edit で上書きする。
- Issue にメモを積む方式は採らない(Issue は課題管理のための場所であり、
デプロイ履歴を混ぜると課題一覧としての意味が失われる)。
flowchart TD
A[ローカル編集] --> B[git commit]
B -->|pre-commit| C[汎用化 + シークレット同期 + 漏洩検査]
C --> D[PR]
D --> E[決定論ゲート: review_sanitization]
E --> F[自律レビューゲート連鎖 5 体]
F -->|GO| G[既定ブランチへマージ]
G --> H[デプロイ(プロダクトスキルの手順)]
H --> I[GitHub Release にレビュー結果を記録]
検証チェックリスト
参考リンク