fix(gen): 生成器修掉 gofmt 假绿、门禁统一叫 verify、缺锁即失败

生成器产出的 scripts/verify.sh 里写着 `step gofmt -l . || fail=1` ——
gofmt -l 列出不合规文件时**退出码仍是 0**,所以这一步永远是绿的。
这条假绿会跟着每个新工程走,是新仓最容易继承的一条。

改法:加 check_gofmt(),判**输出**是否为空;输出非空就列出文件并非零退出。
在生成物里实测过:故意写一个没格式化的 main.go ⇒ verify 退出码 1 且列出该文件;
gofmt -w 之后 ⇒ 退出码 0。

同时:
- Makefile 的门禁目标统一成 verify(check 保留为别名,不起第二套逻辑),
  与正本 §3.1 的"唯一入口"、以及 CI 里跑的那条命令同名。
- package.json 存在时:有锁必须 npm ci,没锁直接失败(不回落 npm install);
  没声明 format:check 也判红(前端格式必须有门禁),并提示怎么补。
- 收尾提示去掉"填 build.yml 里 deploy:test 的 TODO"—— 模板里已经没有 deploy 作业了。

顺带修一个自己踩的坑:收尾那段 heredoc 没加引号,新写的说明里带了反引号,
被 shell 先执行、整段字直接消失而退出码仍是 0。改成不用反引号,并把原因写在注释里。

验证:生成器在空目录跑通(exit 0),生成物 10 个文件齐全;
生成的门禁在空仓上退出码 1("入口待补,不算全绿"),不是静默通过。
This commit is contained in:
姚章浩
2026-10-12 00:11:41 +08:00
parent 9d7f09ff4b
commit 7f8698c16a
+26 -7
View File
@@ -47,10 +47,14 @@ export PATH="/opt/citools/go/bin:/opt/citools/bin:$PATH"
if [ -f go.mod ]; then
ran="go"
step gofmt -l . || fail=1 # 格式:CI 会因为这一条红
check_gofmt() { # ⚠️ gofmt -l 列出文件时**退出码仍是 0**:判输出,不判退出码
U="$(gofmt -l $(git ls-files '*.go' 2>/dev/null) 2>/dev/null)"
[ -z "$U" ] || { echo "未格式化的文件:"; printf '%s\n' "$U"; return 1; }
}
step check_gofmt || fail=1 # 格式:CI 会因为这一条红
step go vet ./... || fail=1 # 静态检查:类型错了后面全是噪声
step go build ./... || fail=1 # 构建:会清空产物目录,必须排在测试之前
step go test ./... || fail=1 # 单测跑的是构建产物,不是源码
step go build ./... || fail=1 # 构建
step go test ./... || fail=1 # 单测(Go 会自己编译测试程序;不是"测构建产物")
fi
if [ -f pyproject.toml ] || [ -f requirements.txt ] || [ -f setup.py ]; then
ran="$ran python"
@@ -60,7 +64,16 @@ if [ -f pyproject.toml ] || [ -f requirements.txt ] || [ -f setup.py ]; then
fi
if [ -f package.json ]; then
ran="$ran node"
step npm run format:check || fail=1
if [ -f package-lock.json ]; then
step npm ci || fail=1 # 按锁装;缺锁**不**退化成 npm install(那会重写锁文件)
else
echo "❌ 没有 package-lock.json:不接受无约束安装(先提交锁文件)"; fail=1
fi
if grep -q '"format:check"[[:space:]]*:' package.json 2>/dev/null; then
step npm run format:check || fail=1
else
echo "❌ package.json 未声明 format:check —— 前端格式没有门禁(加 prettier --check)"; fail=1
fi
step npm run build || fail=1
step npm test || fail=1
fi
@@ -80,9 +93,11 @@ mkdir -p scripts && mv scripts_verify.tmp scripts/verify.sh && chmod +x scripts/
cat > Makefile <<'MK'
# 本地门禁入口:一条命令跑完(正本 §3.1)。CI 的 build 作业跑同一套步骤。
.PHONY: check
check:
# 名字统一用 `verify`(如本环境另有一套叫 `check` 的历史习惯,让它成为别名,别起第二套逻辑)。
.PHONY: verify check
verify:
bash scripts/verify.sh
check: verify
MK
say "3/7 CI 工作流"
@@ -180,5 +195,9 @@ cat <<EOF
5) **反向自检**(正本 §3.2-3):推一个故意违规的提交,确认 gate 红、且 build 没跑
6) TODO:填 .gitea/workflows/build.yml 里 deploy:test 的 <TEST_HOST> 与读回断言
6) 部署(CD)**不在这里**:本骨架只做 CI。要部署时**另写一个**独立 workflow
(只由 workflow_dispatch 触发,且 cancel-in-progress 必须为 false),
别把 deploy 作业塞回 build.yml ——占位作业会打印 TODO 然后返回成功,那是假报成功(正本 §8)。
⚠️ 这段说明写在这里、不写进那个 heredoc 里的原因:外层 heredoc 没加引号,
反引号会被 shell 先执行 —— 上面这行原先带反引号,输出里那段字直接消失了(退出码仍是 0)。
EOF