a3a1319a11
一次性把本地与 CI 的门禁收成一条命令:make verify = python3 scripts/ci_checks.py。 两边跑的是同一份逻辑,不再各写一套步骤(两边各写一套的结局是迟早只改一边)。 14 项必需检查:identity(检出 == 事件完整 SHA,只在 CI 必需)、commits、deps-install、 format、static-go、static-web、build-go、build-web、tests-go、tests-web、contracts、 security-secrets、security-deps、manifests-locked。make list 打印清单。 三条判据写死在代码里: - 失败即停,但剩下的记 not_run 并如实写进报告;aggregate() 只认 success, 未运行/被跳过都不算通过(不适用要在清单里声明 required_in,不许运行时悄悄 skip)。 - 工具缺失、依赖没按锁装、输出解析不了 ⇒ 失败,不当成"检查通过"。 - 测试必须真跑:go test 加 -count=1 并盘点通过/跳过数;前端读 vitest 的 JSON 报告, 空套件不算通过。跳过原因会打进报告(当前 72 个集成用例因缺 TEST_DATABASE_URL 跳过)。 新增四个自带反向自检的脚本(--self-test 故意弄坏必须红): scripts/check_format.py(Go 判输出而非退出码 + 前端只能减的基线)、 scripts/check_secrets.py(只打印位置与类别,绝不打印值)、 scripts/check_deps_vuln.py(govulncheck 锁 v1.1.4 + npm audit 分级 + 到期例外)、 scripts/ci_checks.py(门禁 + 汇总)。 验证(本机实跑,全部为真实退出码): make verify → 总体 success(档案 local),identity=skipped 已在清单里声明为 CI 必需; tests-go 执行 31 个包、通过 549 / 失败 0 / 跳过 72;tests-web 106 个套件、191 个用例全过; security-deps:govulncheck v1.1.4 0 命中、npm audit 生产与全量均 0。
85 lines
4.0 KiB
Makefile
85 lines
4.0 KiB
Makefile
GO ?= go
|
||
PY ?= python3
|
||
|
||
# 版本号的唯一来源是仓库根的 CHANGELOG.md(正本 §6.1:版本号只有一个来源)。
|
||
# 刻意**不用** `git describe --tags`:CI 检出是 `git fetch --depth 50`,取不到 tag,
|
||
# 那会让版本号在本地正常、在 CI 上静默退化(见 docs/agents/traps.md trap-5)。
|
||
VERSION ?= $(shell $(PY) scripts/version.py 2>/dev/null || echo dev)
|
||
COMMIT_SHA ?= $(shell git rev-parse --short=12 HEAD 2>/dev/null || echo unknown)
|
||
BUILD_TIME ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
||
|
||
.PHONY: verify checks list \
|
||
format static-go static-web deps-install build-go build-web \
|
||
tests-go tests-web contracts security manifests-locked \
|
||
test vet build web-test web-typecheck web-build \
|
||
version changelog-check version-contract image
|
||
|
||
# ── 唯一权威门禁入口(正本 §3.1)────────────────────────────────────────
|
||
# 一条命令跑完全部必需检查、**串行**、失败即停,并产出 ci-report.json。
|
||
# CI 的 build 作业跑的就是这一条(`.gitea/workflows/build.yml` 里的 `make verify`)——
|
||
# 本地与 CI 同一份逻辑,不存在"两边各写一套,迟早只改一边"的问题。
|
||
verify:
|
||
$(PY) scripts/ci_checks.py
|
||
|
||
# 清单:哪些是必需项、在哪个档案(local / ci)下必需
|
||
list:
|
||
$(PY) scripts/ci_checks.py --list
|
||
|
||
# 门禁自身的反向自检(汇总逻辑:必需项未运行/被跳过时**不得**报全绿)
|
||
checks:
|
||
$(PY) scripts/ci_checks.py --self-test
|
||
|
||
# ── 单项(调试用)──────────────────────────────────────────────────────
|
||
# ⚠️ `make <单项>` 只跑子集,**不算全绿**:单项命令会自己在输出里说明这一点。
|
||
# 写这一组是为了"红了要知道红在哪一项",不是为了跳过整个门禁。
|
||
format:
|
||
$(PY) scripts/ci_checks.py --only format
|
||
static-go:
|
||
$(PY) scripts/ci_checks.py --only static-go
|
||
static-web:
|
||
$(PY) scripts/ci_checks.py --only static-web
|
||
deps-install:
|
||
$(PY) scripts/ci_checks.py --only deps-install
|
||
build-go:
|
||
$(PY) scripts/ci_checks.py --only build-go
|
||
build-web:
|
||
$(PY) scripts/ci_checks.py --only build-web
|
||
tests-go:
|
||
$(PY) scripts/ci_checks.py --only tests-go
|
||
tests-web:
|
||
$(PY) scripts/ci_checks.py --only tests-web
|
||
contracts:
|
||
$(PY) scripts/ci_checks.py --only contracts
|
||
security:
|
||
$(PY) scripts/ci_checks.py --only security-secrets,security-deps
|
||
manifests-locked:
|
||
$(PY) scripts/ci_checks.py --only manifests-locked
|
||
|
||
# ── 旧名字保留为别名:文档和习惯都还在引用它们 ─────────────────────────
|
||
test: tests-go
|
||
vet: static-go
|
||
build: build-go
|
||
web-test: tests-web
|
||
web-typecheck: static-web
|
||
web-build: build-web
|
||
|
||
# 打印当前版本号(唯一来源:CHANGELOG.md 顶部那个已发布版本)
|
||
version:
|
||
@$(PY) scripts/version.py
|
||
|
||
# 变更记录结构自检:每个已发布版本都必须有「改了什么」「怎么验收」两节
|
||
changelog-check:
|
||
@$(PY) scripts/check_changelog.py
|
||
|
||
# 版本契约:注入进二进制的号必须等于 CHANGELOG 顶部。
|
||
# ⚠️ 不注入时该用例会 SKIP —— 那是"本地不想被迫先构建"的便利,但**CI 必须断言它真的 PASS**
|
||
# (门禁的 contracts 项就是这么做的;被跳过的断言等于没有断言)。
|
||
version-contract:
|
||
$(GO) test -ldflags "-X knowledge-governance/internal/version.Number=$(VERSION)" \
|
||
-count=1 -run TestNumberMatchesChangelog -v ./internal/version/...
|
||
|
||
# 构建镜像。三个 build-arg 必须显式传入 —— 不传就落成 dev/unknown(故意的:
|
||
# 一个显眼的 dev 好过一个看起来正常的假版本号)。compose.yaml 的 args 透传见 PR TODO。
|
||
image:
|
||
docker build --build-arg VERSION=$(VERSION) --build-arg COMMIT_SHA=$(COMMIT_SHA) \
|
||
--build-arg BUILD_TIME=$(BUILD_TIME) -t knowledge-governance-p1:$(VERSION)-$(COMMIT_SHA) .
|