ci-workflow
PR作成後のCI監視、失敗時の分類と対応、自動マージ、環境クリーンアップまでの完全なワークフローを定義
معلومات المصدر
- المستودع
- takemo101/compose-workflow
- آخر نشاط في المصدر
- ١٧ يناير ٢٠٢٦ في ١٢:٥٢
- لغة SKILL.md المكتشفة
- اليابانية
- النجوم
- ٠
- التفرعات
- ٠
خيارات التثبيت
يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.
مراجعة ملفات المصدر
اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.
مستكشف الملفات
2 ملفاتعرض SKILL.md
SKILL.md
تعليمات المصدر · معاينة للقراءة فقط- name
- ci-workflow
- description
- PR作成後のCI監視、失敗時の分類と対応、自動マージ、環境クリーンアップまでの完全なワークフローを定義
# CI監視ワークフロー
> **責任範囲**: CI監視 → 失敗分析 → 自動修正 → 成功時マージ
>
> | このスキル | pr-merge-workflow |
> |-----------|-------------------|
> | CIポーリング・ログ分析 | PR作成テンプレート |
> | 失敗時の自動修正 | マージ戦略選択 |
> | リトライ管理(3回) | ロールバック手順 |
> | 成功時の自動マージ呼び出し | クリーンアップ |
---
## 実行者の責任分担
| フェーズ | 実行者 | 理由 |
|---------|--------|------|
| 0-9 (実装→PR作成) | `container-worker` / `Sisyphus` | container-use環境内での作業 |
| **10 (CI監視→マージ)** | **`Sisyphus`** | GitHub API操作、環境外での監視 |
| **11 (環境クリーンアップ)** | **`Sisyphus`** | 環境管理はホスト側で実行 |
> **Note**: CI監視やPRマージは `bash` ツールでGitHub APIを呼び出す。
---
## メインフロー
```python
def post_pr_workflow(pr_number: int, env_id: str):
"""PR作成後: CI待機 → 成功:マージ&削除 / 失敗:修正(3回) / タイムアウト:報告"""
ci_result = wait_for_ci(pr_number)
if ci_result == SUCCESS:
auto_merge_pr(pr_number, env_id) and cleanup_environment(env_id)
elif ci_result == FAILURE:
if handle_ci_failure(pr_number, env_id):
# 修正成功 → マージ & 環境削除
auto_merge_pr(pr_number, env_id) and cleanup_environment(env_id)
else:
# 3回失敗 → エスカレーション(環境保持)
escalate_ci_failure(pr_number, env_id)
elif ci_result == TIMEOUT:
handle_ci_timeout(pr_number, env_id) # 環境保持
```
---
## 1. CI完了待機
```python
def wait_for_ci(pr_number: int, timeout: int = 600) -> CIResult:
"""30秒間隔でgh pr checksをポーリング(最大10分)"""
for _ in range(timeout // 30):
checks = bash(f"gh pr checks {pr_number} --json state,name")
if all_success(checks): return SUCCESS
if any_failure(checks): return FAILURE
wait(30)
return TIMEOUT
```
---
## 2. CI失敗の分類と対応
| 失敗カテゴリ | 検出パターン | 対応方法 |
|------------|-------------|---------|
| **Lint/Clippy** | `warning:`, `clippy::` | 自動修正 (`--fix`) |
| **Test失敗** | `FAILED`, `test result: FAILED` | テストコード修正 |
| **ビルドエラー** | `error[E`, `cannot find` | コード修正 |
| **フォーマット** | `Diff in`, `would have been reformatted` | `cargo fmt` |
| **環境依存** | `platform exception` | 環境再開 |
```python
def analyze_failure(log: str) -> CIFailureAnalysis:
"""CIログを分析して失敗種別を特定"""
if "clippy::" in log or "warning:" in log:
return CIFailureAnalysis(type="lint", auto_fixable=True,
fix_command="cargo clippy --fix --allow-dirty --allow-staged")
if "FAILED" in log:
return CIFailureAnalysis(type="test", auto_fixable=False)
if "error[E" in log:
return CIFailureAnalysis(type="build", auto_fixable=False)
if "would have been reformatted" in log:
return CIFailureAnalysis(type="format", auto_fixable=True, fix_command="cargo fmt")
return CIFailureAnalysis(type="unknown")
```
---
## 3. CI修正フロー
```python
MAX_CI_RETRIES = 3
def handle_ci_failure(pr_number: int, env_id: str) -> bool:
"""CI失敗 → ログ分析 → container環境で修正 → push → 再待機(最大3回)"""
for attempt in range(MAX_CI_RETRIES):
log = bash("gh run view --log-failed")
fix_in_container(env_id, analyze_failure(log))
bash("git add . && git commit -m 'fix: CI修正' && git push")
if wait_for_ci(pr_number) == SUCCESS:
return True
return False # リトライ超過 → escalate_ci_failure()
def fix_in_container(env_id: str, analysis: CIFailureAnalysis):
"""既存のcontainer環境で修正を実施"""
# 1. 環境を再開
container-use_environment_open(environment_id=env_id, ...)
# 2. リモートの最新状態を取得
container-use_environment_run_cmd(command="git pull origin HEAD")
# 3. 修正を実施
if analysis.auto_fixable:
container-use_environment_run_cmd(command=analysis.fix_command)
# 4. ローカルで検証
container-use_environment_run_cmd(command="cargo clippy -- -D warnings && cargo test")
# 5. 修正をpush
container-use_environment_run_cmd(command="git add . && git commit -m 'fix: CI修正' && git push")
```
---
## 4. 自動マージ
```python
def auto_merge_pr(pr_number: int, issue_num: int) -> bool:
"""gh pr merge --merge --delete-branch"""
result = bash(f"gh pr merge {pr_number} --merge --delete-branch")
if result.exit_code == 0:
# Issue ラベル更新: env:merged ({{skill:github-issue-state-management}} API)
bash(f"bash .opencode/skill/github-issue-state-management/scripts/issue-state.sh merged {issue_num}")
return True
return handle_merge_failure(pr_number, error=result.stderr)
```
---
## 5. エスカレーション
```python
def escalate_ci_failure(pr_number: int, env_id: str):
"""PRをDraft化、失敗ログをコメント、ユーザーに報告"""
bash(f"gh pr ready {pr_number} --undo")
bash(f"gh pr comment {pr_number} --body '⚠️ CI修正3回失敗。env_id: {env_id}'")
report_to_user(f"⚠️ PR #{pr_number} 手動確認が必要")
```
---
## 6. 環境クリーンアップ
```python
def cleanup_environment(env_id: str, pr_number: int) -> bool:
"""delete-environment スキルを実行(最大2回リトライ)"""
script = ".opencode/skill/delete-environment/scripts/delete_env.sh"
for _ in range(3):
if bash(f"bash {script} {env_id}").exit_code == 0:
report_to_user(f"✅ PR #{pr_number} マージ済み、環境 {env_id} 削除済み")
return True
wait(5)
report_to_user(f"⚠️ 環境削除失敗。手動: bash {script} {env_id}")
return False
```
> **Note**: 環境状態は GitHub Issue ラベルで管理。詳細は [github-issue-state-management](../github-issue-state-management/SKILL.md) を参照。
### クリーンアップタイミング
| 状況 | 環境の扱い |
|------|----------|
| PRマージ成功 | ✅ 即座に削除 |
| PRクローズ(マージなし) | ✅ 即座に削除 |
| CI修正中(リトライ中) | ❌ 削除しない |
| Draft PR(エスカレーション中) | ❌ 削除しない |
| PRレビュー修正待ち | ❌ 削除しない |
---
## 関連ドキュメント
| ドキュメント | 内容 |
|-------------|------|
| {{skill:pr-merge-workflow}} | PR作成〜マージ〜ロールバックの全体フロー |
| {{skill:github-issue-state-management}} | 環境状態管理(ラベル) |
| {{skill:delete-environment}} | 環境削除手順 |
---
## CLIスクリプト
**CI待機の自動化スクリプト:**
```bash
bash .opencode/skill/ci-workflow/scripts/ci-wait.sh <pr-number> [timeout-seconds]
```
| 引数 | 説明 | デフォルト |
|------|------|-----------|
| `pr-number` | PR番号 | 必須 |
| `timeout-seconds` | 最大待機時間(秒) | 600 |
**終了コード:**
| コード | 意味 |
|--------|------|
| 0 | 全CIチェック成功 |
| 1 | CIチェック失敗 |
| 2 | タイムアウト |
| 3 | 引数エラー |
**使用例:**
```bash
bash .opencode/skill/ci-workflow/scripts/ci-wait.sh 42 1800
```
عرض على GitHub