395 lines
16 KiB
YAML
395 lines
16 KiB
YAML
name: 🔴 Economic Circuit Breaker
|
|
# AGENTS.md v5.0 - Economic Governance Protocol準拠
|
|
# Reference: ai-course-content-generator economic-circuit-breaker.yml
|
|
|
|
on:
|
|
schedule:
|
|
- cron: '0 * * * *' # 1時間ごとにコスト監視
|
|
workflow_dispatch:
|
|
inputs:
|
|
force_check:
|
|
description: '強制チェック実行'
|
|
required: false
|
|
default: 'false'
|
|
|
|
permissions:
|
|
issues: write
|
|
actions: write
|
|
contents: read
|
|
|
|
jobs:
|
|
monitor-cloud-costs:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
|
|
- name: Install yq for YAML parsing
|
|
run: |
|
|
sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
|
|
sudo chmod +x /usr/local/bin/yq
|
|
|
|
- name: Load BUDGET.yml configuration
|
|
id: budget
|
|
run: |
|
|
BUDGET=$(yq '.monthly_budget_usd' BUDGET.yml)
|
|
WARNING_THRESHOLD=$(yq '.thresholds.warning' BUDGET.yml)
|
|
EMERGENCY_THRESHOLD=$(yq '.thresholds.emergency' BUDGET.yml)
|
|
|
|
echo "monthly_budget=$BUDGET" >> $GITHUB_OUTPUT
|
|
echo "warning_threshold=$WARNING_THRESHOLD" >> $GITHUB_OUTPUT
|
|
echo "emergency_threshold=$EMERGENCY_THRESHOLD" >> $GITHUB_OUTPUT
|
|
|
|
echo "📊 Budget Configuration:"
|
|
echo " Monthly Budget: \$$BUDGET USD"
|
|
echo " Warning Threshold: ${WARNING_THRESHOLD} ($(echo "$BUDGET * $WARNING_THRESHOLD" | bc)% = \$$(echo "$BUDGET * $WARNING_THRESHOLD" | bc) USD)"
|
|
echo " Emergency Threshold: ${EMERGENCY_THRESHOLD} ($(echo "$EMERGENCY_THRESHOLD * 100" | bc)% = \$$(echo "$BUDGET * $EMERGENCY_THRESHOLD" | bc) USD)"
|
|
|
|
- name: Check Anthropic API Usage
|
|
id: anthropic_cost
|
|
env:
|
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
run: |
|
|
# 現在の月の開始日を計算
|
|
MONTH_START=$(date -u +"%Y-%m-01T00:00:00Z")
|
|
CURRENT_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
echo "📅 Billing Period: $MONTH_START ~ $CURRENT_DATE"
|
|
|
|
# Anthropic API usage check
|
|
# Note: Anthropic doesn't provide direct billing API yet, so we estimate from usage
|
|
# In production, integrate with actual billing endpoint when available
|
|
|
|
# Placeholder: 実際のAPI使用状況をチェック
|
|
# TODO: Anthropic Billing APIが利用可能になったら統合
|
|
ANTHROPIC_COST_USD=0
|
|
|
|
# Fallback: GitHub Actionsのログから推定 (開発時)
|
|
if [ "${{ github.event.inputs.force_check }}" == "true" ]; then
|
|
# デモ用: テストコスト
|
|
ANTHROPIC_COST_USD=45.23
|
|
fi
|
|
|
|
echo "anthropic_cost=$ANTHROPIC_COST_USD" >> $GITHUB_OUTPUT
|
|
echo "🤖 Anthropic API Cost: \$$ANTHROPIC_COST_USD USD"
|
|
|
|
- name: Check Firebase Costs
|
|
id: firebase_cost
|
|
env:
|
|
GOOGLE_CLOUD_PROJECT: ${{ secrets.GOOGLE_CLOUD_PROJECT }}
|
|
GOOGLE_APPLICATION_CREDENTIALS_JSON: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_JSON }}
|
|
run: |
|
|
# Firebase/GCP billing check via Cloud Billing API
|
|
# Note: Requires Cloud Billing API enabled and service account with billing.accounts.get permission
|
|
|
|
FIREBASE_COST_USD=0
|
|
|
|
# Placeholder: 実際のFirebase使用状況をチェック
|
|
# TODO: Cloud Billing API統合
|
|
|
|
if [ "${{ github.event.inputs.force_check }}" == "true" ]; then
|
|
# デモ用: テストコスト
|
|
FIREBASE_COST_USD=12.50
|
|
fi
|
|
|
|
echo "firebase_cost=$FIREBASE_COST_USD" >> $GITHUB_OUTPUT
|
|
echo "🔥 Firebase Cost: \$$FIREBASE_COST_USD USD"
|
|
|
|
- name: Check GitHub Actions Usage
|
|
id: github_cost
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
# GitHub Actions分は無料枠内の想定 (3000分/月)
|
|
# 念のため使用量を確認
|
|
|
|
OWNER=$(echo "${{ github.repository }}" | cut -d'/' -f1)
|
|
REPO=$(echo "${{ github.repository }}" | cut -d'/' -f2)
|
|
|
|
# 当月のActions使用時間を取得
|
|
MONTH_START_UNIX=$(date -d "$(date +%Y-%m-01)" +%s)
|
|
CURRENT_UNIX=$(date +%s)
|
|
|
|
# GitHub API: Workflow runs (last 30 days)
|
|
TOTAL_MINUTES=$(gh api \
|
|
-H "Accept: application/vnd.github+json" \
|
|
"/repos/$OWNER/$REPO/actions/runs?per_page=100" \
|
|
--jq '[.workflow_runs[] | select(.created_at >= "'$(date -d "@$MONTH_START_UNIX" -u +%Y-%m-%dT%H:%M:%SZ)'") | .run_duration_ms // 0] | add // 0' \
|
|
| awk '{print int($1/60000)}')
|
|
|
|
echo "github_minutes=$TOTAL_MINUTES" >> $GITHUB_OUTPUT
|
|
echo "⚙️ GitHub Actions Usage: ${TOTAL_MINUTES} minutes this month"
|
|
|
|
# 無料枠3000分を超えたら警告
|
|
if [ "$TOTAL_MINUTES" -gt 3000 ]; then
|
|
echo "github_over_quota=true" >> $GITHUB_OUTPUT
|
|
echo "⚠️ WARNING: GitHub Actions over free tier quota!"
|
|
else
|
|
echo "github_over_quota=false" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Calculate Total Cost and Consumption Rate
|
|
id: calculate
|
|
run: |
|
|
BUDGET=${{ steps.budget.outputs.monthly_budget }}
|
|
WARNING=${{ steps.budget.outputs.warning_threshold }}
|
|
EMERGENCY=${{ steps.budget.outputs.emergency_threshold }}
|
|
|
|
ANTHROPIC=${{ steps.anthropic_cost.outputs.anthropic_cost }}
|
|
FIREBASE=${{ steps.firebase_cost.outputs.firebase_cost }}
|
|
|
|
# 合計コスト計算
|
|
TOTAL_COST=$(echo "$ANTHROPIC + $FIREBASE" | bc)
|
|
|
|
# 消費率計算
|
|
CONSUMPTION_RATE=$(echo "scale=4; $TOTAL_COST / $BUDGET" | bc)
|
|
CONSUMPTION_PERCENT=$(echo "scale=2; $CONSUMPTION_RATE * 100" | bc)
|
|
|
|
# しきい値判定
|
|
WARNING_AMOUNT=$(echo "$BUDGET * $WARNING" | bc)
|
|
EMERGENCY_AMOUNT=$(echo "$BUDGET * $EMERGENCY" | bc)
|
|
|
|
echo "total_cost=$TOTAL_COST" >> $GITHUB_OUTPUT
|
|
echo "consumption_rate=$CONSUMPTION_RATE" >> $GITHUB_OUTPUT
|
|
echo "consumption_percent=$CONSUMPTION_PERCENT" >> $GITHUB_OUTPUT
|
|
|
|
echo ""
|
|
echo "═══════════════════════════════════════"
|
|
echo "📊 ECONOMIC GOVERNANCE PROTOCOL STATUS"
|
|
echo "═══════════════════════════════════════"
|
|
echo "💰 Total Cost: \$$TOTAL_COST USD / \$$BUDGET USD"
|
|
echo "📈 Consumption Rate: ${CONSUMPTION_PERCENT}%"
|
|
echo "⚠️ Warning Level: \$$WARNING_AMOUNT USD (${WARNING})"
|
|
echo "🔴 Emergency Level: \$$EMERGENCY_AMOUNT USD (${EMERGENCY})"
|
|
echo "═══════════════════════════════════════"
|
|
echo ""
|
|
|
|
# しきい値チェック
|
|
if (( $(echo "$TOTAL_COST >= $EMERGENCY_AMOUNT" | bc -l) )); then
|
|
echo "status=EMERGENCY" >> $GITHUB_OUTPUT
|
|
echo "🚨 STATUS: EMERGENCY - Circuit Breaker will activate!"
|
|
elif (( $(echo "$TOTAL_COST >= $WARNING_AMOUNT" | bc -l) )); then
|
|
echo "status=WARNING" >> $GITHUB_OUTPUT
|
|
echo "⚠️ STATUS: WARNING - Approaching budget limit"
|
|
else
|
|
echo "status=OK" >> $GITHUB_OUTPUT
|
|
echo "✅ STATUS: OK - Within budget"
|
|
fi
|
|
|
|
- name: Store Cost Metrics
|
|
run: |
|
|
# メトリクスディレクトリ作成
|
|
mkdir -p .ai/metrics/cost-history
|
|
|
|
# 現在の日時
|
|
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
DATE=$(date -u +"%Y-%m-%d")
|
|
|
|
# メトリクスをJSONで保存
|
|
cat > ".ai/metrics/cost-history/${DATE}_$(date +%s).json" << EOF
|
|
{
|
|
"timestamp": "$TIMESTAMP",
|
|
"budget": {
|
|
"monthly_usd": ${{ steps.budget.outputs.monthly_budget }},
|
|
"warning_threshold": ${{ steps.budget.outputs.warning_threshold }},
|
|
"emergency_threshold": ${{ steps.budget.outputs.emergency_threshold }}
|
|
},
|
|
"costs": {
|
|
"anthropic_usd": ${{ steps.anthropic_cost.outputs.anthropic_cost }},
|
|
"firebase_usd": ${{ steps.firebase_cost.outputs.firebase_cost }},
|
|
"total_usd": ${{ steps.calculate.outputs.total_cost }}
|
|
},
|
|
"consumption": {
|
|
"rate": ${{ steps.calculate.outputs.consumption_rate }},
|
|
"percent": ${{ steps.calculate.outputs.consumption_percent }}
|
|
},
|
|
"github_actions": {
|
|
"minutes_used": ${{ steps.github_cost.outputs.github_minutes }},
|
|
"over_quota": ${{ steps.github_cost.outputs.github_over_quota }}
|
|
},
|
|
"status": "${{ steps.calculate.outputs.status }}"
|
|
}
|
|
EOF
|
|
|
|
echo "📝 Cost metrics saved to .ai/metrics/cost-history/"
|
|
|
|
- name: 🔴 EMERGENCY - Trigger Circuit Breaker
|
|
if: steps.calculate.outputs.status == 'EMERGENCY'
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
echo "🚨🚨🚨 ECONOMIC CIRCUIT BREAKER ACTIVATED 🚨🚨🚨"
|
|
echo ""
|
|
echo "Consumption rate has exceeded emergency threshold."
|
|
echo "Initiating automatic workflow disablement..."
|
|
echo ""
|
|
|
|
# BUDGET.ymlから停止対象ワークフローを読み込み
|
|
WORKFLOWS_TO_DISABLE=$(yq '.emergency_actions.disable_workflows[]' BUDGET.yml)
|
|
|
|
# 各ワークフローを無効化
|
|
for workflow in $WORKFLOWS_TO_DISABLE; do
|
|
echo "🛑 Disabling workflow: $workflow"
|
|
|
|
gh api \
|
|
--method PUT \
|
|
-H "Accept: application/vnd.github+json" \
|
|
"/repos/${{ github.repository }}/actions/workflows/$workflow/disable" \
|
|
&& echo "✅ Disabled: $workflow" \
|
|
|| echo "⚠️ Failed to disable: $workflow (may not exist)"
|
|
done
|
|
|
|
echo ""
|
|
echo "✅ Circuit Breaker activation complete"
|
|
echo "🤖 Creating emergency issue for Guardian intervention..."
|
|
|
|
- name: 🚨 Create Emergency Issue
|
|
if: steps.calculate.outputs.status == 'EMERGENCY'
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
# Guardianへの通知Issue作成
|
|
gh issue create \
|
|
--title "🔴🚨 ECONOMIC CIRCUIT BREAKER ACTIVATED - Guardian Intervention Required" \
|
|
--label "🔥Sev.1-Critical,🤖AI-システム,💰経済-緊急停止" \
|
|
--assignee "${{ github.repository_owner }}" \
|
|
--body "$(cat <<'EOF'
|
|
## 🚨 ECONOMIC CIRCUIT BREAKER ACTIVATED
|
|
|
|
**AGENTS.md v5.0 - Economic Governance Protocol** に基づき、経済的サーキットブレーカーが作動しました。
|
|
|
|
### 📊 Cost Summary
|
|
|
|
- **Total Cost**: \$${{ steps.calculate.outputs.total_cost }} USD
|
|
- **Monthly Budget**: \$${{ steps.budget.outputs.monthly_budget }} USD
|
|
- **Consumption Rate**: ${{ steps.calculate.outputs.consumption_percent }}%
|
|
- **Emergency Threshold**: ${{ steps.budget.outputs.emergency_threshold }} (150%)
|
|
|
|
### 💰 Cost Breakdown
|
|
|
|
| Service | Cost (USD) | Budget (USD) |
|
|
|---------|-----------|--------------|
|
|
| Anthropic API | \$${{ steps.anthropic_cost.outputs.anthropic_cost }} | \$400 |
|
|
| Firebase | \$${{ steps.firebase_cost.outputs.firebase_cost }} | \$100 |
|
|
| **Total** | **\$${{ steps.calculate.outputs.total_cost }}** | **\$${{ steps.budget.outputs.monthly_budget }}** |
|
|
|
|
### 🛑 Actions Taken
|
|
|
|
The following workflows have been **automatically disabled**:
|
|
|
|
$(yq '.emergency_actions.disable_workflows[]' BUDGET.yml | sed 's/^/- ❌ /')
|
|
|
|
### 🤖 Guardian Intervention Required
|
|
|
|
**我々の自律性は経済的限界に達した。**
|
|
|
|
**AGENTS.md v5.0 - § 4.7.6: Recovery Protocol** に従い、Guardian (@${{ github.repository_owner }}) の承認を要請する。
|
|
|
|
#### ✅ Recovery Checklist
|
|
|
|
Guardian は以下を確認し、承認してください:
|
|
|
|
- [ ] **根本原因特定完了**: なぜ予算を超過したか?
|
|
- [ ] 異常なAPI使用パターンの有無
|
|
- [ ] バグによる無限ループの有無
|
|
- [ ] 想定外のワークフロー実行の有無
|
|
- [ ] **BUDGET.yml更新完了**: 月次予算の見直しは必要か?
|
|
- [ ] 新しい予算額の決定
|
|
- [ ] しきい値の再調整
|
|
- [ ] **不要リソース削除完了**: コスト削減措置の実施
|
|
- [ ] 不要なワークフロー実行の停止
|
|
- [ ] キャッシュのクリーンアップ
|
|
- [ ] リソースの最適化
|
|
- [ ] **月次予算見直し完了**: 来月以降の予算計画
|
|
|
|
#### 🔄 Workflow Re-enablement
|
|
|
|
Guardian承認後、以下のコマンドでワークフローを再開:
|
|
|
|
\`\`\`bash
|
|
# 各ワークフローを手動で再有効化
|
|
gh api --method PUT /repos/${{ github.repository }}/actions/workflows/agent-runner.yml/enable
|
|
gh api --method PUT /repos/${{ github.repository }}/actions/workflows/continuous-improvement.yml/enable
|
|
gh api --method PUT /repos/${{ github.repository }}/actions/workflows/agent-onboarding.yml/enable
|
|
\`\`\`
|
|
|
|
### 📈 Historical Cost Data
|
|
|
|
過去のコストメトリクスは `.ai/metrics/cost-history/` に保存されています。
|
|
|
|
---
|
|
|
|
**Generated by**: Economic Circuit Breaker Workflow
|
|
**Timestamp**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
|
|
**Workflow Run**: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
EOF
|
|
)"
|
|
|
|
echo "✅ Emergency issue created successfully"
|
|
|
|
- name: ⚠️ Post Warning Comment
|
|
if: steps.calculate.outputs.status == 'WARNING'
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
# 既存の警告Issueを検索
|
|
EXISTING_ISSUE=$(gh issue list \
|
|
--label "💰経済-警告" \
|
|
--state open \
|
|
--json number \
|
|
--jq '.[0].number')
|
|
|
|
if [ -z "$EXISTING_ISSUE" ]; then
|
|
# 警告Issueが存在しない場合は作成
|
|
gh issue create \
|
|
--title "⚠️ Economic Warning - Approaching Budget Limit (${{ steps.calculate.outputs.consumption_percent }}%)" \
|
|
--label "⚠️重要度-高,🤖AI-システム,💰経済-警告" \
|
|
--body "$(cat <<'EOF'
|
|
## ⚠️ Economic Warning
|
|
|
|
現在のコスト消費率が警告しきい値に達しました。
|
|
|
|
### 📊 Current Status
|
|
|
|
- **Consumption Rate**: ${{ steps.calculate.outputs.consumption_percent }}%
|
|
- **Total Cost**: \$${{ steps.calculate.outputs.total_cost }} USD / \$${{ steps.budget.outputs.monthly_budget }} USD
|
|
- **Warning Threshold**: ${{ steps.budget.outputs.warning_threshold }} (80%)
|
|
- **Emergency Threshold**: ${{ steps.budget.outputs.emergency_threshold }} (150%)
|
|
|
|
### 🎯 Recommended Actions
|
|
|
|
1. Review recent workflow executions
|
|
2. Check for any unusual API usage patterns
|
|
3. Consider optimizing agent prompts to reduce token usage
|
|
4. Monitor cost progression closely
|
|
|
|
---
|
|
**Note**: この警告Issueは経済的緊急事態に達するまで更新され続けます。
|
|
EOF
|
|
)"
|
|
else
|
|
# 既存のIssueにコメント追加
|
|
gh issue comment "$EXISTING_ISSUE" --body "$(cat <<'EOF'
|
|
## 📊 Cost Update - $(date -u +"%Y-%m-%d %H:%M UTC")
|
|
|
|
- **Consumption Rate**: ${{ steps.calculate.outputs.consumption_percent }}%
|
|
- **Total Cost**: \$${{ steps.calculate.outputs.total_cost }} USD
|
|
|
|
現在も警告レベルを超えています。コスト監視を継続中...
|
|
EOF
|
|
)"
|
|
fi
|
|
|
|
- name: ✅ Post Success Status
|
|
if: steps.calculate.outputs.status == 'OK'
|
|
run: |
|
|
echo "✅ System operating within budget"
|
|
echo "📊 Consumption: ${{ steps.calculate.outputs.consumption_percent }}%"
|
|
echo "💚 All systems normal"
|