ci(release): go test 门可显式跳过(默认仍严格)

## 问题(试发布实测暴露)

把 CI/Release 带到 release/v1.3.x 后,CI 三个 job 全红,但**每个失败都是
该分支自身的旧状态,与改动无关**:

| job | 失败原因 | main 上 |
|---|---|---|
| GUI (node) | `npm error Missing script: "test"`(1.3.x 尚无该脚本)| 正常 |
| Go test | TestRealPlugin_DeepSearchKeepsSharedBackendOnStop | **通过** |
| C gates | exit 2(1.3.x 无 csrc 基础设施)| 正常 |

⇒ 给已存在的发布线补新流水线 = 用今天的门去量旧代码。硬门会让该历史
维护线**完全无法发版**,正是用户要的「推 rel 分支就出产物」被挡死。

## 改法

拆开两道门,语义不同:

- `go build ./...` —— **硬门**,不可跳过。产物不可能建立在编译失败的代码上。
- `go test ./...` —— 默认跑,但可跳过。两个来源:
  1. workflow_dispatch 的 `skip_tests` 输入
  2. **发版 commit 里写 `[skip-release-tests]`**

第二个来源是关键:决定落在**定义该次发版的那个 commit** 里,`git log` 可审计,
而不是一个随手勾的开关。跳过时输出 `::warning` 注释,让后果在 run 页可见。

## 未决(留给用户)

`release/v1.3.x` 的 deepsearch 测试失败属该线既存状态(main 已修)。是否把它
cherry-pick 回 1.3.x 属产品决策(1.3.x 是历史维护线,main 已是 1.4.0),
故本次不擅自拉回绿,只提供显式跳过通道。

actionlint 全绿。
This commit is contained in:
JianFeeeee
2026-09-29 13:40:25 +08:00
parent 8cdcbf70fb
commit 9beb3b558e

View File

@ -8,12 +8,19 @@
# 版本号来源:internal/meta/meta.go 的 Version(唯一事实源)。
# 所以发版动作 = 在 release/vX.Y.x 上把 meta.Version 改成目标版本后推送。
# 版本未变的推送(如改文档)会因 tag 已存在而**整轮跳过**,不会重复发版。
#
# 发版前的 go test 门可以显式跳过(见下面 skip_tests 的说明)。
name: Release
on:
push:
branches: ['release/**']
workflow_dispatch:
inputs:
skip_tests:
description: '跳过发版前的 go test 门(仅用于已知红的历史维护线)'
type: boolean
default: false
# 发布必须能写仓库(打 tag、建 release、传附件)。
permissions:
@ -42,10 +49,23 @@ jobs:
tag: ${{ steps.ver.outputs.tag }}
prerelease: ${{ steps.ver.outputs.prerelease }}
exists: ${{ steps.ver.outputs.exists }}
skip_tests: ${{ steps.ver.outputs.skip_tests }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
# 发版前的 go test 门为什么可以跳过:
#
# 新旧发布线的测试健康状况不同。实测 release/v1.3.x(历史维护线)上
# internal/plugins 的 TestRealPlugin_DeepSearchKeepsSharedBackendOnStop
# 失败、GUI 尚无 npm test 脚本、csrc 基础设施不存在 —— 而这三项在 main
# 上都正常。给旧线补新流水线等于用今天的门去量旧代码,硬门会让该线
# **完全无法发版**。
#
# 故:默认严格(测试必跑);发版人若确知该线测试是既存红的,可在
# 发版 commit 里写 [skip-release-tests] 显式跳过 —— 决定因此记录在
# **定义该次发版的那个 commit** 里,git 历史可审计。
# go build 仍是硬门(产物不可能建立在编译失败的代码上)。
- id: ver
name: 读取 meta.Version 并检查 tag
run: |
@ -73,6 +93,26 @@ jobs:
echo " 将为 v$V 发版"
fi
# 是否跳过发版前的 go test 门(默认不跳)。
# 两个来源:手动触发的输入,或发版 commit 里的显式标记。
# 后者使决定落在定义该次发版的 commit 上,可以从 git 历史审计。
SKIP="${{ inputs.skip_tests }}"
MARKER=0
if git log -1 --pretty=%B | grep -qF '[skip-release-tests]'; then
MARKER=1
fi
if [ "$SKIP" = "true" ] || [ "$MARKER" = "1" ]; then
echo "skip_tests=true" >> "$GITHUB_OUTPUT"
echo ""
echo " ⚠️ **已请求跳过发版前的 go test 门**"
echo " 来源:${SKIP} = true / commit 标记 = $MARKER"
echo " 后果:产物可能建立在单元测试失败的代码上。"
echo " 理由应当记录在发版 commit 的正文里。"
else
echo "skip_tests=false" >> "$GITHUB_OUTPUT"
echo " 发版前会跑 go test 门(可用 [skip-release-tests] 标记跳过)"
fi
# ── 构建 Linux 产物(amd64)──
#
# 三个 deb + 一个 tar.gz,总约 2.4GB(server/full/tar 含 719MB 模型)。
@ -99,12 +139,24 @@ jobs:
gcc --version | head -1
g++ --version | head -1
# 发版前的最后一道门:产物若建立在编译失败的代码上,发布了也没用。
- name: go build + go test(发版前验证)
# 发版前的门。
#
# go build 是**硬门**:产物不可能建立在编译失败的代码上。
# go test 默认也跑,但可在发版 commit 里写 [skip-release-tests] 跳过
# —— 历史维护线的既有红测试不应阻断该线的一切发版(详见 prepare job)。
- name: go build(硬门)
run: |
set -euo pipefail
go build ./...
go test ./... -count=1 -timeout 20m
- name: go test(发版前验证)
if: needs.prepare.outputs.skip_tests != 'true'
run: go test ./... -count=1 -timeout 20m
- name: go test 被跳过(显式声明的后果)
if: needs.prepare.outputs.skip_tests == 'true'
run: |
echo "::warning title=go test 门已跳过::本次发版未跑 go test,产物可能建立在单元测试失败的代码上。"
- name: 下载构建资产(模型 + ONNX Runtime)
run: |