diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml index a03a75f1..bd348d24 100644 --- a/.github/workflows/cd.yaml +++ b/.github/workflows/cd.yaml @@ -36,8 +36,10 @@ on: concurrency: group: cd-${{ github.workflow }}-${{ github.ref }} - # 2026-03-26: 改為等待而非取消,避免 Runner _diag/pages 檔案衝突 - cancel-in-progress: false + # 2026-03-29: 改回取消,因為 Runner _diag/pages 衝突發生在 Set up job 階段 + # 等待模式 (cancel-in-progress: false) 會導致並行 Job 寫入同一診斷檔 + # 取消模式確保同一時間只有一個 workflow 在執行 + cancel-in-progress: true env: REGISTRY: 192.168.0.110:5000 diff --git a/ops/runner/README.md b/ops/runner/README.md index 59f649f0..4807b43a 100644 --- a/ops/runner/README.md +++ b/ops/runner/README.md @@ -6,25 +6,40 @@ Error: The file '/home/wooo/actions-runner-awoooi/_diag/pages/xxx.log' already exists. ``` -### 根因 -- GitHub Actions Runner 在執行 Job 時會寫入診斷日誌 -- 並行 Job 或快速連續執行可能產生 UUID 碰撞 -- 前次執行的殘留檔案未清理 +### 根因分析 (2026-03-29 完整診斷) -### 解決方案 +1. **發生時機**: "Set up job" 階段 (在任何自定義步驟之前) +2. **原因**: GitHub Actions Runner 內部 bug + - Runner 在 Job 初始化時寫入 `_diag/pages/*.log` + - 並行執行的多個 Job 可能寫入相同的 UUID 檔案 + - 這發生在我們的清理步驟執行**之前** +3. **次要問題**: `RUNNER_TEMP` 共享 + - `_work/_temp/_runner_file_commands` 在所有 Jobs 之間共享 + - 清理此目錄會導致 "Missing file at path" 錯誤 -#### 1. CD Workflow 修復 (即時生效) -每個 Job 開始前強制清理並重建 `_diag/pages` 目錄: +### 解決方案 (v3 - 最終版) + +#### 1. Workflow Concurrency (核心修復) +```yaml +concurrency: + group: cd-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true # 必須為 true! +``` + +**關鍵**: `cancel-in-progress: true` 確保同一時間只有一個 workflow 在執行 + +#### 2. Job 層清理 (輔助) +每個 Job 開始時只清理 `_diag/pages`,**不碰** `RUNNER_TEMP`: ```yaml - name: "Clean Runner Diagnostics" run: | RUNNER_ROOT=$(dirname "$(dirname "$RUNNER_TEMP")") - rm -rf "$RUNNER_TEMP"/* "$RUNNER_ROOT/_diag/pages" .claude/worktrees 2>/dev/null || true + rm -rf "$RUNNER_ROOT/_diag/pages" .claude/worktrees 2>/dev/null || true mkdir -p "$RUNNER_ROOT/_diag/pages" 2>/dev/null || true ``` -**關鍵**: 刪除整個目錄再重建,而非 `rm -rf _diag/pages/*` +**警告**: 絕對不要清理 `$RUNNER_TEMP/*`,會破壞其他 Job 的內部通訊 #### 2. Systemd Timer (背景清理) 每 5 分鐘自動清理過期的診斷檔案: