fix(ci): 修复notify竞态条件 - 用needs.result替代commit status查询
根因:notify-on-failure job 通过 commit status API 查询结果时, 自身的 pending status 会污染查询结果(竞态条件): 1. lint/test 都 success 2. notify 开始运行,自身状态 pending 写入 commit status 3. notify 查询 commit status → 看到 pending(自己的)≠ success 4. 误发 [CI] 失败 评论 + webhook 触发 Mail 通知 修复方案: - 不再查询 commit status API - 直接用 needs.lint.result 和 needs.test.result 判断 - 只有明确的 failure 才发通知 - 同时去掉 push 触发避免双倍运行
This commit is contained in:
+16
-14
@@ -50,8 +50,8 @@ jobs:
|
||||
/tmp/ci-venv-test/bin/pytest tests/ -m "not e2e" -x -q
|
||||
|
||||
# ── Job 3: CI 失败通知 ───────────────────────────────
|
||||
# v1.23 不支持 failure(),用 always() + shell 检查 commit status 替代
|
||||
# 修复:只有明确的 failure 才发通知,空状态/未知状态不发(避免误报)
|
||||
# 使用 needs.<job>.result 直接判断,不查询 commit status API
|
||||
# 根因:notify 自身的 pending status 会污染 commit status 查询结果(竞态条件)
|
||||
notify-on-failure:
|
||||
runs-on: macos-arm64
|
||||
needs: [lint, test]
|
||||
@@ -60,32 +60,34 @@ jobs:
|
||||
- name: Check results and notify
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
LINT_RESULT: ${{ needs.lint.result }}
|
||||
TEST_RESULT: ${{ needs.test.result }}
|
||||
run: |
|
||||
# 查询当前 commit 的 status
|
||||
STATUS=$(curl -sf \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"${{ gitea.api_url }}/repos/${{ gitea.repository }}/commits/${{ gitea.sha }}/status" \
|
||||
| python3 -c "import sys,json; print(json.load(sys.stdin).get('state',''))" 2>/dev/null || echo "")
|
||||
echo "Lint result: $LINT_RESULT"
|
||||
echo "Test result: $TEST_RESULT"
|
||||
|
||||
echo "Commit status: [$STATUS]"
|
||||
|
||||
# 只在明确 failure 时发通知(空/unknown/success/pending 都不发)
|
||||
if [ "$STATUS" = "failure" ]; then
|
||||
echo "CI explicitly failed, sending notification..."
|
||||
# 只有 lint 或 test 明确失败时才发通知
|
||||
if [ "$LINT_RESULT" = "failure" ] || [ "$TEST_RESULT" = "failure" ]; then
|
||||
echo "CI has failures, sending notification..."
|
||||
|
||||
# 如果是 PR 事件,写评论通知
|
||||
PR_NUMBER="${{ gitea.event.pull_request.number }}"
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
# 构建失败摘要
|
||||
FAILED_JOBS=""
|
||||
[ "$LINT_RESULT" = "failure" ] && FAILED_JOBS="${FAILED_JOBS}lint "
|
||||
[ "$TEST_RESULT" = "failure" ] && FAILED_JOBS="${FAILED_JOBS}test "
|
||||
|
||||
curl -sf -X POST \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${{ gitea.api_url }}/repos/${{ gitea.repository }}/issues/${PR_NUMBER}/comments" \
|
||||
-d "{\"body\": \"[CI] 失败\\n\\n分支: ${{ gitea.ref_name }}\\n触发 commit: \`${{ gitea.sha }}\`\\n请检查 CI 日志并修复。\"}" \
|
||||
-d "{\"body\": \"[CI] 失败\\n\\n分支: ${{ gitea.ref_name }}\\n触发 commit: \`${{ gitea.sha }}\`\\n失败 Job: ${FAILED_JOBS}\\n请检查 CI 日志并修复。\"}" \
|
||||
|| echo "Failed to post PR comment"
|
||||
echo "PR comment posted."
|
||||
else
|
||||
echo "Not a PR event, skipping PR comment."
|
||||
fi
|
||||
else
|
||||
echo "CI status is [$STATUS], no failure notification needed."
|
||||
echo "No explicit failures (results: lint=$LINT_RESULT, test=$TEST_RESULT), no notification needed."
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user