Compare commits

...

3 Commits

Author SHA1 Message Date
cfdaily 4e40045f9b fix(ci): 修复notify竞态条件 - 用needs.result替代commit status查询
CI / lint (pull_request) Failing after 6s
CI / test (pull_request) Has been skipped
CI / notify-on-failure (pull_request) Successful in 4s
根因: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 触发避免双倍运行
2026-06-09 22:59:16 +08:00
cfdaily 08b6b2c4fe docs: #19 adopt simayi review suggestions (v1.1) 2026-06-09 22:53:00 +08:00
cfdaily be67c50d51 fix(ci): 去掉push触发避免双倍触发 + 修复notify误报
CI / lint (pull_request) Failing after 8s
CI / test (pull_request) Has been skipped
CI / notify-on-failure (pull_request) Successful in 3s
1. 触发器:去掉 push,只保留 pull_request(opened, synchronize)
   - 每次 push 到 PR 分支不再跑 2 次 CI
2. notify-on-failure:只有明确的 failure 状态才发通知
   - 之前:空状态/unknown/pending 都触发通知(误报根因)
   - 现在:只有 STATUS=failure 才发通知
3. venv 路径:统一用 /tmp/ci-venv-lint 和 /tmp/ci-venv-test
   - 避免 host 模式下与开发目录 .venv 冲突
2026-06-09 22:49:10 +08:00
2 changed files with 34 additions and 23 deletions
+24 -23
View File
@@ -1,9 +1,10 @@
# CI 管道 — moziplus v2.0
#
# 触发条件:
# - push(非 main 分支)
# - pull_requestopened, synchronize
#
# 注意:只保留 pull_request 触发,避免 push + pull_request 双倍触发
#
# Gitea v1.23.4 限制注意:
# - 不支持 failure() 表达式,用 always() + shell 条件判断替代
# - 不支持 concurrency / continue-on-error / timeout-minutes / permissions
@@ -13,10 +14,6 @@
name: CI
on:
push:
branches:
- '**'
- '!main'
pull_request:
types: [opened, synchronize]
@@ -29,12 +26,12 @@ jobs:
- name: Setup Python
run: |
python3 -m venv .venv
.venv/bin/pip install --quiet flake8
python3 -m venv /tmp/ci-venv-lint
/tmp/ci-venv-lint/bin/pip install --quiet flake8
- name: Lint with flake8
run: |
.venv/bin/flake8 src/ --max-line-length=120 --extend-ignore=E501
/tmp/ci-venv-lint/bin/flake8 src/ --max-line-length=120 --extend-ignore=E501
# ── Job 2: Test ──────────────────────────────────────
test:
@@ -45,15 +42,16 @@ jobs:
- name: Setup Python
run: |
python3 -m venv .venv
.venv/bin/pip install --quiet -r requirements.txt
python3 -m venv /tmp/ci-venv-test
/tmp/ci-venv-test/bin/pip install --quiet fastapi pydantic pyyaml uvicorn requests pytest pytest-asyncio httpx
- name: Run tests (exclude E2E)
run: |
.venv/bin/pytest tests/ -m "not e2e" -x -q
/tmp/ci-venv-test/bin/pytest tests/ -m "not e2e" -x -q
# ── Job 3: CI 失败通知 ───────────────────────────────
# v1.23 不支持 failure(),用 always() + shell 检查 commit status 替代
# 使用 needs.<job>.result 直接判断,不查询 commit status API
# 根因:notify 自身的 pending status 会污染 commit status 查询结果(竞态条件)
notify-on-failure:
runs-on: macos-arm64
needs: [lint, test]
@@ -62,31 +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"
if [ "$STATUS" != "success" ]; then
echo "CI failed or status unknown, 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 passed, no notification needed."
echo "No explicit failures (results: lint=$LINT_RESULT, test=$TEST_RESULT), no notification needed."
fi
@@ -69,6 +69,7 @@
- **获取完整上下文** → 用 Gitea API 拉取 Issue 详情和评论,不要只看 Mail 里的快照
### Gitea API 速查
> 其中 `{owner}/{repo}` 替换为实际仓库,如 `sanguo/sanguo_moziplus_v2`
- Issue 详情: GET /api/v1/repos/{owner}/{repo}/issues/{number}
- Issue 评论: GET /api/v1/repos/{owner}/{repo}/issues/{number}/comments
- PR diff: GET /api/v1/repos/{owner}/{repo}/pulls/{number}.diff
@@ -193,6 +194,8 @@ AGENT_IDS = {
}
# 前缀映射:@张飞 → zhangfei-dev
# 中文名映射:Agent 在 Gitea Issue 评论中可能用中文名 @mention
# 英文短名映射:Agent 可能用不带 -dev/-infra 后缀的短名
AGENT_ALIAS = {
"张飞": "zhangfei-dev",
"关羽": "guanyu-dev",
@@ -311,6 +314,13 @@ async def _handle_issue_comment(payload):
具体改动在 `_send_mail()` 函数或其调用处:工具链路由调用 `_send_mail` 时传入 `performative="request"`
**⚠️ 验证要点**:改为 request 后,Agent spawn prompt 变为 "请处理以下请求",需确认:
1. Agent 不再把工具链 Mail 当纯通知忽略
2. Agent 能正确处理「已阅型」工具链事件(如 CI 失败通知——不需要回复,但需要知道)
3. 对已关闭 PR/Issue 的延迟通知,Agent 不会尝试去处理
验证方法:部署后发一条 Issue 指派 Mail,观察 Agent 行为是否符合预期。
---
## 五、完整改动清单