-
Notifications
You must be signed in to change notification settings - Fork 0
291 lines (256 loc) · 10.4 KB
/
Copy pathci.yml
File metadata and controls
291 lines (256 loc) · 10.4 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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# v0.6 P0 清场第二批 commit 8: 周日 02:00 UTC (≈ 10:00 Asia/Shanghai)
# 跑 M2 终验周巡 — backup chain + DB 体积 + COLD 加密
- cron: "0 2 * * 0"
jobs:
backend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.14"
cache: pip
cache-dependency-path: |
backend/requirements.txt
backend/requirements.lock
backend/requirements-dev.txt
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r backend/requirements.lock -r backend/requirements-dev.txt
- name: Check Python syntax
run: |
python -m compileall backend/
echo "Python syntax OK"
- name: Ruff lint
run: |
python -m pip install ruff
# v0.6 P0 清场第二批: scripts/ 纳入 CI. 历史存量 I001/F541/DTZ 等
# 暂未清零 — ruff.toml [lint.per-file-ignores] 给 scripts/ 设白名单
# 阻断放宽; 主阻断点仍是 F401/F841.
ruff check backend/ scripts/
- name: Dependency audit (pip-audit)
run: |
python -m pip install pip-audit
pip-audit -r backend/requirements.lock --skip-editable
- name: Run Python tests
run: |
python -m pytest backend/tests/ --tb=short -q
- name: Classify changed paths (core vs non-core review gate)
if: github.event_name == 'pull_request'
id: review-classify
env:
BASE_REF: ${{ github.base_ref }}
run: |
set -e
git fetch --no-tags --depth=1 origin "${BASE_REF}" 2>/dev/null || true
if git rev-parse "origin/${BASE_REF}" >/dev/null 2>&1; then
PATHS=$(git diff --name-only "origin/${BASE_REF}...HEAD" || true)
else
PATHS=$(git diff --name-only HEAD~1 HEAD || true)
fi
if [ -z "$PATHS" ]; then
echo "No path changes detected; skipping review-classify."
echo "has_core=false" >> "$GITHUB_OUTPUT"
echo "tier=non-core" >> "$GITHUB_OUTPUT"
exit 0
fi
# --batch 强制 strict-config: 仓库级契约必须存在; 缺文件即 CI 失败
# 但 batch 自身的 exit 1 (全 non-core) 不应阻塞 step — 用 || STATUS=$? 捕获
STATUS=0
RESULT=$(echo "$PATHS" | python scripts/generate_meta.py --classify --batch --strict-config 2>&1) || STATUS=$?
if [ "$STATUS" = "2" ]; then
echo "::error::core.include 配置缺失 (strict-config 拒绝回退)"
exit 2
fi
echo "$RESULT"
if [ "$STATUS" = "0" ]; then
echo "has_core=true" >> "$GITHUB_OUTPUT"
echo "tier=core" >> "$GITHUB_OUTPUT"
else
echo "has_core=false" >> "$GITHUB_OUTPUT"
echo "tier=non-core" >> "$GITHUB_OUTPUT"
fi
- name: Metadata consistency check
run: python scripts/generate_meta.py --check
- name: Mimosa security scan (best-effort; scanner_no_output 不阻断, 兼容策略见 memory)
# v0.7 Batch ⑧ D7: CI 引入 mimosa 但不强制 — 本地已知 scanner_no_output 误报;
# 改为可选 + 永不失败 (|| true) + 输出 artifact 供 review
run: |
if command -v mimosa >/dev/null 2>&1; then
mimosa scan --depth=shallow --output=json . > mimosa-scan.json 2> mimosa-scan.err || true
echo "Mimosa scan complete (see mimosa-scan.{json,err})"
else
echo "::notice::Mimosa not installed in this runner, skipping (local-only check)"
fi
continue-on-error: true
- name: Agent assets lint (agent-assets-review; errors 非零 → job 失败, warnings 保留 reviewer 备注)
run: python scripts/harness_analyze.py --check
- name: Docstring mandatory check (v0.7 Batch ⑧ D7)
run: python scripts/check_docstrings.py
- name: llm-wiki-2.0 graph schema check (M3.5 Task13)
run: python scripts/check_graph_schema.py
- name: llm-wiki-2.0 retention health check (M3.5 Task13)
run: python scripts/check_retention_decay.py
backend-core-only:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./
env:
HOTSPOT_FEATURE_GATES: '{"extensions": {"codegarden": false, "mcp": false, "sync": false, "tech_stack": false, "security_graph": false}}'
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.14"
cache: pip
cache-dependency-path: |
backend/requirements.txt
backend/requirements.lock
backend/requirements-dev.txt
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r backend/requirements.lock -r backend/requirements-dev.txt
- name: Core-only startup test
run: |
python -c "from backend.main import app; print('core-only startup OK')"
- name: Core-only feature gate tests
run: |
python -m pytest backend/tests/test_feature_gates.py -v
frontend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./frontend
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22"
- name: Install frontend dependencies
run: npm install --no-audit --no-fund
- name: Dependency audit (npm)
run: npm audit --omit=dev --audit-level=high || true
- name: TypeScript type check
run: |
# v0.7.1: TS6133 baseline 已清零 (tsc --noEmit 0 错误),
# 从 baseline 报告模式升级为硬阻断 — 任何 TS 错误即 CI fail.
set +e
TSC_OUT=$(npx tsc --noEmit 2>&1)
TSC_RC=$?
set -e
echo "$TSC_OUT" | grep "error TS" > /tmp/tsc_errors.txt || true
COUNT=$(wc -l < /tmp/tsc_errors.txt | tr -d ' ')
echo "TS errors: $COUNT"
if [ "$TSC_RC" -ne 0 ] || [ "$COUNT" -gt 0 ]; then
echo "::error::tsc --noEmit 失败 ($COUNT 个 TS 错误, exit $TSC_RC)"
cat /tmp/tsc_errors.txt
exit 1
fi
- name: Run Vitest tests
run: npx vitest run
- name: Vite build (smoke test)
run: npx vite build --logLevel error
env:
CI: true
weekly-m2-verify:
# v0.6 P0 清场第二批 commit 8: 周日定时跑 M2 终验三件套.
# 不动 backend/frontend 主 job (避免常规 PR 拖慢),
# 仅 schedule 触发; 排查失败时手动 dispatch 也可.
runs-on: ubuntu-latest
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
defaults:
run:
working-directory: ./
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.14"
cache: pip
cache-dependency-path: |
backend/requirements.txt
backend/requirements.lock
backend/requirements-dev.txt
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r backend/requirements.lock -r backend/requirements-dev.txt
- name: Dependency vulnerability audit (weekly, full env)
# v0.6.3 安全批次 (2026-08-30): backend job 的 pip-audit 只扫 lock (75 pin),
# 覆盖不到 venv 实际安装的 transitive/optional/孤儿包 — 2026-08-30 本地
# pip-audit 实测 nltk (6 CVE, 未声明孤儿包) / h2 / pip 即从该缝隙漏进。
# 周日巡检补"全环境"审计; 沿用本 job 报告为主不阻断的惯例 (新 CVE 披露
# 不可控, 硬阻断会让 schedule job 无害挂红), 修复跟踪见 docs/SECURITY_AUDIT.md。
run: |
set +e
python -m pip install pip-audit
AUDIT_OUT=$(pip-audit --skip-editable --format json 2>&1)
AUDIT_RC=$?
echo "$AUDIT_OUT" | python3 -c "
import json, sys
try:
data = json.load(sys.stdin)
deps = data.get('dependencies', data if isinstance(data, list) else [])
vulns = [(d['name'], d['version'], v['id'], ','.join(v.get('fix_versions', []) or ['-']))
for d in deps for v in d.get('vulns', [])]
print(f'packages: {len(deps)}, vulnerable: {len(set(v[0] for v in vulns))}, total: {len(vulns)}')
for name, ver, vid, fixes in sorted(vulns):
print(f' {name}=={ver} {vid} fix-> {fixes}')
except Exception as e:
print('pip-audit 输出解析失败:', e)
sys.exit(1)
"
if [ "$AUDIT_RC" -ne 0 ]; then
echo "::warning::pip-audit 发现漏洞 (rc=$AUDIT_RC) — 周日巡检报告模式, 请按上方清单升级/豁免"
fi
- name: Backup chain check (M2 增量 + sha256 sidecar)
run: |
set +e
CHK_OUT=$(python scripts/check_backup_chain.py --json 2>&1)
CHK_RC=$?
set -e
echo "$CHK_OUT"
if [ "$CHK_RC" -ne 0 ]; then
echo "::warning::backup chain check 退码 $CHK_RC (基础模式, 不阻断 PR 周日巡)"
fi
- name: HOT/WARM/COLD DB 体积巡检 (M2 终验)
run: |
set +e
SIZE_OUT=$(python scripts/check_temp_db_sizes.py --json 2>&1)
SIZE_RC=$?
set -e
echo "$SIZE_OUT"
if [ "$SIZE_RC" -ne 0 ]; then
echo "::warning::check_temp_db_sizes 退码 $SIZE_RC (报告为主, 不阻断)"
fi
- name: COLD db crypto verify (M2 终验)
run: |
set +e
CRYPTO_OUT=$(python scripts/cold_db_crypto.py verify 2>&1)
CRYPTO_RC=$?
set -e
echo "$CRYPTO_OUT"
# verify 在无 .enc 时退 1 (源码 main L130-132), 这是预期, 仅警告
if [ "$CRYPTO_RC" -ne 0 ] && [ "$CRYPTO_RC" -ne 2 ]; then
echo "::warning::cold_db_crypto verify 退码 $CRYPTO_RC"
elif [ "$CRYPTO_RC" -eq 2 ]; then
echo "::error::cold_db_crypto verify 退码 2 — quick_check 失败"
exit 2
fi