5f3a71cade
build / build (push) Successful in 26s
背景:本仓此前没有任何版本/构建元信息 —— 没有 ldflags 注入、也没有产物可读的 版本号,"线上跑的是哪个提交"答不出来;"这次改了什么、怎么验收"也没有载体。 落地: - CHANGELOG.md:**版本号的唯一来源**(正本 §6.1:版本号只准有一处)。刻意不放 VERSION 文件、也不靠 git tag —— CI 是 `git fetch --depth 50`,取不到 tag, `git describe` 会静默退化。每个已发布版本必须有两节:### 改了什么 与 ### 怎么验收。 - scripts/version.py:从 CHANGELOG 顶部解析版本号;解析不到即非 0 退出(构建据此失败)。 - scripts/check_changelog.py:结构自检(两节齐、带日期、版本号不重复且严格递减、 小节不为空),带 --self-test 反向自检。 - internal/version:三个构建期注入变量 + 契约测试(注入的号必须等于 CHANGELOG 顶部)。 - Makefile:build 带 -ldflags 注入;verify 增加 changelog-check 与 version-contract。 - Dockerfile:ARG VERSION/COMMIT_SHA/BUILD_TIME + ldflags(未透传时落 dev —— 故意显眼, 好过看起来正常的假版本号)。 - CI:新增「版本与变更记录契约」步,并显式断言契约测试真的 PASS(被跳过的断言等于没有断言)。 - docs/提交规范.md(ci_gate.py 的报错文案一直在指它)、docs/agents/traps.md(7 条实测陷阱)。 验证(都真跑过): - make version → 0.1.0;make changelog-check → 合规 - make version-contract → PASS;注入 9.9.9(CHANGELOG 里没有)→ FAIL(反向自检) - 删掉真实 CHANGELOG 的「怎么验收」小节 → 报红(对真实文件做,不只是夹具) - go build ./... 与 go vet ./internal/version/... 通过 未做(会与在审 PR #2 冲突,待其合并后在 main 上补): - GET /version 端点(internal/httpapi/server.go)与 cmd/api 的 -version 开关 - compose.yaml 透传 build args(当前由 compose 构建的镜像会报 dev) ⚠️ 未跑 make verify 全量(含 go test ./... 与前端),CI 是本次的测试证据。
51 lines
2.1 KiB
Makefile
51 lines
2.1 KiB
Makefile
GO ?= go
|
||
|
||
# 版本号的唯一来源是仓库根的 CHANGELOG.md(正本 §6.1:版本号只有一个来源)。
|
||
# 刻意**不用** `git describe --tags`:CI 检出是 `git fetch --depth 50`,取不到 tag,
|
||
# 那会让版本号在本地正常、在 CI 上静默退化(见 docs/agents/traps.md trap-5)。
|
||
VERSION ?= $(shell python3 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)
|
||
LDFLAGS := -X knowledge-governance/internal/version.Number=$(VERSION) -X knowledge-governance/internal/version.CommitSHA=$(COMMIT_SHA) -X knowledge-governance/internal/version.BuildTime=$(BUILD_TIME)
|
||
|
||
.PHONY: test vet build web-test web-typecheck web-build verify version changelog-check version-contract image
|
||
|
||
test:
|
||
$(GO) test ./...
|
||
|
||
vet:
|
||
$(GO) vet ./...
|
||
|
||
build:
|
||
$(GO) build -trimpath -ldflags "$(LDFLAGS)" ./cmd/...
|
||
|
||
web-test:
|
||
npm --prefix web test
|
||
|
||
web-typecheck:
|
||
npm --prefix web run typecheck
|
||
|
||
web-build:
|
||
npm --prefix web run build
|
||
|
||
# 本地门禁:一条命令跑完、**串行**、失败即停(正本 §3.1)。CI 的 build 作业跑同一套。
|
||
verify: changelog-check test vet build version-contract web-test web-typecheck web-build
|
||
|
||
# 打印当前版本号(唯一来源:CHANGELOG.md 顶部那个已发布版本)
|
||
version:
|
||
@python3 scripts/version.py
|
||
|
||
# 变更记录结构自检:每个已发布版本都必须有「改了什么」「怎么验收」两节
|
||
changelog-check:
|
||
@python3 scripts/check_changelog.py
|
||
|
||
# 版本契约:注入进二进制的号必须等于 CHANGELOG 顶部(不注入时该用例会 SKIP,属正常)
|
||
version-contract:
|
||
$(GO) test -ldflags "$(LDFLAGS)" -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) .
|