feat(ci): 补全所有CI job失败通知 + 部署成功通知 (#229)
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 1m31s
CI/CD Pipeline / Frontend Lint (push) Successful in 2m33s
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 1m36s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Successful in 5m19s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m49s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m49s
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 1m31s
CI/CD Pipeline / Frontend Lint (push) Successful in 2m33s
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 1m36s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Successful in 5m19s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m49s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m49s
## 变更说明
基于最新 develop 分支重建的干净PR,替换旧的 #228(原分支太老,有4个文件冲突,CI也因为代码版本不一致各种出问题)。
## 改动内容
1. **新增 `scripts/ci_notify_success.py`** — 部署成功通知脚本(飞书卡片,绿色成功样式)
2. **修改 `.gitea/workflows/ci-cd.yml`**:
- 给以下 7 个 job 加上失败通知:
- Frontend Lint
- Build & Push Staging (Watchtower auto-deploy)
- Staging E2E Tests
- Staging API Integration Tests
- Build Production Runtime Images
- Deploy Production
- Production Browser E2E
- 给以下 2 个部署 job 加上成功通知(部署完成后发):
- Build & Push Staging — Staging部署成功
- Deploy Production — 生产部署成功
## 参考
- 失败通知参照已有的 Validate Code Quality And Tests 和 Integration Tests 里的 "Notify CI failure" 步骤写法
- 成功通知基于失败通知改写,调用 `scripts/ci_notify_success.py`
---------
Co-authored-by: xiaoxia <ci@xiaoxiajianji.com>
Reviewed-on: #229
This commit was merged in pull request #229.
This commit is contained in:
@@ -563,6 +563,15 @@ jobs:
|
||||
-w /workspace/apps/web \
|
||||
docker.m.daocloud.io/library/node:20 \
|
||||
sh -lc 'npx vitest run src/test'
|
||||
|
||||
- name: Notify CI failure
|
||||
if: failure()
|
||||
shell: sh
|
||||
run: |
|
||||
set +e
|
||||
echo "=== CI 失败通知 ==="
|
||||
FAILED_JOB="Frontend Lint" python3 scripts/ci_notify_failure.py
|
||||
|
||||
deploy-staging:
|
||||
name: Build & Push Staging (Watchtower auto-deploy)
|
||||
runs-on: saas
|
||||
@@ -694,6 +703,23 @@ jobs:
|
||||
echo "Branch: ${GITHUB_REF_NAME}"
|
||||
echo "Commit: ${GITHUB_SHA}"
|
||||
|
||||
- name: Notify CI success
|
||||
if: success()
|
||||
shell: sh
|
||||
run: |
|
||||
set +e
|
||||
echo "=== CI 成功通知 ==="
|
||||
SUCCESS_JOB="Staging部署成功" python3 scripts/ci_notify_success.py
|
||||
|
||||
- name: Notify CI failure
|
||||
if: failure()
|
||||
shell: sh
|
||||
run: |
|
||||
set +e
|
||||
echo "=== CI 失败通知 ==="
|
||||
FAILED_JOB="Build & Push Staging (Watchtower auto-deploy)" python3 scripts/ci_notify_failure.py
|
||||
|
||||
|
||||
|
||||
staging-e2e:
|
||||
name: Staging E2E Tests
|
||||
@@ -762,6 +788,15 @@ jobs:
|
||||
git.xiaoxiajianji.com/xiaoxia/base/playwright:v1.45.0-jammy \
|
||||
sh -lc "npm ci && npx playwright test --reporter=line --project=chromium e2e/auth.spec.ts e2e/auth-guard.spec.ts e2e/core-upload.spec.ts e2e/core-generation.spec.ts"
|
||||
|
||||
- name: Notify CI failure
|
||||
if: failure()
|
||||
shell: sh
|
||||
run: |
|
||||
set +e
|
||||
echo "=== CI 失败通知 ==="
|
||||
FAILED_JOB="Staging E2E Tests" python3 scripts/ci_notify_failure.py
|
||||
|
||||
|
||||
staging-api-tests:
|
||||
name: Staging API Integration Tests
|
||||
runs-on: saas
|
||||
@@ -827,6 +862,15 @@ jobs:
|
||||
git.xiaoxiajianji.com/xiaoxia/base/playwright:v1.45.0-jammy \
|
||||
sh -lc 'npm ci && npx playwright test --reporter=line e2e/test_auth.spec.ts e2e/test_asset.spec.ts e2e/test_project.spec.ts'
|
||||
|
||||
- name: Notify CI failure
|
||||
if: failure()
|
||||
shell: sh
|
||||
run: |
|
||||
set +e
|
||||
echo "=== CI 失败通知 ==="
|
||||
FAILED_JOB="Staging API Integration Tests" python3 scripts/ci_notify_failure.py
|
||||
|
||||
|
||||
|
||||
build-production-runtime-images:
|
||||
name: Build Production Runtime Images
|
||||
@@ -907,6 +951,15 @@ jobs:
|
||||
echo "Disk usage after cleanup:"
|
||||
df -h / | tail -1
|
||||
|
||||
- name: Notify CI failure
|
||||
if: failure()
|
||||
shell: sh
|
||||
run: |
|
||||
set +e
|
||||
echo "=== CI 失败通知 ==="
|
||||
FAILED_JOB="Build Production Runtime Images" python3 scripts/ci_notify_failure.py
|
||||
|
||||
|
||||
deploy-production:
|
||||
name: Deploy Production
|
||||
runs-on: saas
|
||||
@@ -972,6 +1025,23 @@ jobs:
|
||||
|
||||
echo "$DEPLOY_B64" | base64 -d | ssh -p 22222 -i "$key_path" "$production_user@$production_host" "IMAGE_TAG='${GITHUB_REF_NAME}' REGISTRY_TOKEN='${REGISTRY_TOKEN}' sh"
|
||||
|
||||
- name: Notify CI success
|
||||
if: success()
|
||||
shell: sh
|
||||
run: |
|
||||
set +e
|
||||
echo "=== CI 成功通知 ==="
|
||||
SUCCESS_JOB="生产部署成功" python3 scripts/ci_notify_success.py
|
||||
|
||||
- name: Notify CI failure
|
||||
if: failure()
|
||||
shell: sh
|
||||
run: |
|
||||
set +e
|
||||
echo "=== CI 失败通知 ==="
|
||||
FAILED_JOB="Deploy Production" python3 scripts/ci_notify_failure.py
|
||||
|
||||
|
||||
production-e2e:
|
||||
name: Production Browser E2E
|
||||
runs-on: saas
|
||||
@@ -1040,3 +1110,12 @@ jobs:
|
||||
-w /workspace/apps/web \
|
||||
git.xiaoxiajianji.com/xiaoxia/base/playwright:v1.45.0-jammy \
|
||||
sh -lc 'npm ci && npx playwright test --reporter=line --project=chromium e2e/auth.spec.ts e2e/auth-guard.spec.ts e2e/core-upload.spec.ts e2e/core-generation.spec.ts e2e/core-titles.spec.ts'
|
||||
|
||||
- name: Notify CI failure
|
||||
if: failure()
|
||||
shell: sh
|
||||
run: |
|
||||
set +e
|
||||
echo "=== CI 失败通知 ==="
|
||||
FAILED_JOB="Production Browser E2E" python3 scripts/ci_notify_failure.py
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
"""发送 CI 成功通知到飞书/项目群 webhook。"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
|
||||
def main() -> int:
|
||||
webhook = os.environ.get("CI_NOTIFY_WEBHOOK", "")
|
||||
if not webhook:
|
||||
print("未配置 CI_NOTIFY_WEBHOOK,跳过成功通知")
|
||||
print("如需启用,请在仓库 Settings -> Secrets and variables -> Actions 中添加 CI_NOTIFY_WEBHOOK")
|
||||
return 0
|
||||
|
||||
success_job = os.environ.get("SUCCESS_JOB", "Unknown Job")
|
||||
branch = os.environ.get("GITHUB_REF_NAME", "unknown")
|
||||
commit = os.environ.get("GITHUB_SHA", "unknown")[:8]
|
||||
actor = os.environ.get("GITHUB_ACTOR", "unknown")
|
||||
run_id = os.environ.get("GITHUB_RUN_ID", "unknown")
|
||||
repo = os.environ.get("GITHUB_REPOSITORY", "unknown")
|
||||
run_url = f"https://git.xiaoxiajianji.com/{repo}/actions/runs/{run_id}"
|
||||
|
||||
payload = {
|
||||
"msg_type": "interactive",
|
||||
"card": {
|
||||
"header": {
|
||||
"title": {
|
||||
"tag": "plain_text",
|
||||
"content": "✅ CI 构建成功",
|
||||
},
|
||||
"status": "green",
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"tag": "div",
|
||||
"text": {
|
||||
"tag": "lark_md",
|
||||
"content": (
|
||||
f"**任务**: {success_job}\n"
|
||||
f"**分支**: {branch}\n"
|
||||
f"**提交**: {commit}\n"
|
||||
f"**提交者**: {actor}\n"
|
||||
f"**Run ID**: {run_id}"
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
"tag": "action",
|
||||
"actions": [
|
||||
{
|
||||
"tag": "button",
|
||||
"text": {"tag": "plain_text", "content": "查看构建详情"},
|
||||
"url": run_url,
|
||||
"type": "primary",
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
data = json.dumps(payload).encode("utf-8")
|
||||
req = urllib.request.Request(
|
||||
webhook,
|
||||
data=data,
|
||||
headers={"Content-Type": "application/json"},
|
||||
method="POST",
|
||||
)
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=10) as resp:
|
||||
resp.read()
|
||||
print("成功通知已发送")
|
||||
except Exception as e:
|
||||
print(f"成功通知发送失败: {e}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user