Repository navigation
91 lines (86 loc) · 3.91 KB
/
Copy pathci.yml
File metadata and controls
91 lines (86 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
backend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
- run: uv sync --frozen
- name: Ruff
run: uv run ruff check src tests scripts
- name: 测试与覆盖率(门槛 100%)
run: uv run pytest -q --cov=src --cov-report=term --cov-fail-under=100
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
- run: uv sync --frozen
- name: bandit(中危及以上,配置见 pyproject [tool.bandit])
run: uvx bandit -c pyproject.toml -r src scripts -ll
- name: pip-audit(已知漏洞,含 dev 依赖)
run: uvx pip-audit --skip-editable
frontend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: web
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 10
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: 24
cache: pnpm
cache-dependency-path: web/pnpm-lock.yaml
- run: pnpm install --frozen-lockfile
- name: 依赖漏洞(生产依赖,high 及以上阻断)
run: |
# registry.npmjs.org 的审计端点偶发 ERR_SOCKET_TIMEOUT(实测连续两次
# 在 2 分钟超时后失败,同期 registry 本身可正常拉包)。重试 3 次:
# 真漏洞会稳定复现、三次都非零;网络抖动大概率第二次就过。
for i in 1 2 3; do
if pnpm audit --prod --audit-level=high; then exit 0; fi
echo "::warning::pnpm audit 第 $i 次失败(可能是 registry 网络抖动),15s 后重试"
sleep 15
done
exit 1
- run: pnpm exec tsc --noEmit
- run: pnpm exec vitest run
- run: pnpm build
compose:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: 校验 compose 语法
run: docker compose config --quiet
env:
APP_SECRET: ci-placeholder-secret
- name: 构建镜像并启动(验证 compose 可真实运行)
run: |
mkdir -p data secrets
# 容器以 uid 1001 (appuser) 运行,挂载目录必须可写,
# 否则 SQLite 打不开、服务崩溃重启,health 永远不通
sudo chown -R 1001:1001 data secrets
docker build -t coding2api:ci .
# 用户名必须是 admin:compose 的 ADMIN_USERNAMES 默认 admin,
# B5 引导要求至少一个活跃 admin,否则启动直接 Traceback。
printf 'admin:%s\n' "$(docker run --rm coding2api:ci python -c 'from src.auth.users import create_password_hash;print(create_password_hash("cipw"))')" > secrets/users.txt
# --build 必须带:否则 compose 会去 registry 拉 image: 指向的已发布镜像,
# 测的就不是本次构建的代码了(曾因此长期静默通过)。
APP_SECRET=ci-placeholder-secret docker compose up -d --build
# 120s:启动预热会真连上游拉模型列表(zen 免费层还要逐个探活)。
for _ in $(seq 1 60); do
if curl -fsS http://127.0.0.1:8000/health >/dev/null; then break; fi
sleep 2
done
# 失败排查线索:容器日志(含启动 Traceback)
docker logs coding2api --tail 80
curl -fsS http://127.0.0.1:8000/health
APP_SECRET=ci-placeholder-secret docker compose down