From 5e89289525cc6180914e828bf6ce6d66775b009c Mon Sep 17 00:00:00 2001 From: modusensus Date: Mon, 21 Sep 2026 22:50:23 +0800 Subject: [PATCH] =?UTF-8?q?ci:=20=E6=92=A4=E5=9B=9E=20CI/=E5=8F=91?= =?UTF-8?q?=E7=89=88=E7=BA=BF=E7=9A=84=20badge=20job=E2=80=94=E2=80=94bot?= =?UTF-8?q?=20=E6=8E=A8=E4=B8=8D=E8=BF=9B=E5=8F=97=E4=BF=9D=E6=8A=A4?= =?UTF-8?q?=E7=9A=84=20main?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 两个 badge job 都要把徽章改动直推 main,而 main 的规则是「4 个必过检查 + 要求分支 up-to-date + 线性历史」,job 用的 GITHUB_TOKEN(github-actions[bot]) 不是分支保护的豁免对象,绕过不了 required status checks——数字一与 README 不一致就必被拒: remote: error: GH006: Protected branch update failed for refs/heads/main. remote: - 4 of 4 required status checks are expected. 结果:每次 push 到 main 都红一次,而 4 个 test 分片全绿(test 不是红的那个); 发版线的同类 job 更早就在 v0.8.3 的 release run 里同因失败,把整个 release 判成 failed。徽章改回发版前本地 `npm run badge:sync`,与人工发布同一次提交 带上。 - ci.yml:撤掉 badge job(回到 900400e 之前)——job 图只剩 test,顶层 permissions: contents: read 之外不再有持有 contents: write 的 job - release.yml:同样撤掉 badge job,并去掉 notify 的 needs 里的 badge 与 运行摘要表里的对应行(无悬空 needs) - scripts/sync-test-badge.mjs:徽章计数从 `pass N` 改为套件总数 `tests N` ——平台条件跳过的用例(Windows 未开开发者模式时的符号链接断言)不计入 pass 但计入 tests,取总数即与 CI(ubuntu)口径一致,不必手工修数字; 顺带把 `# N 个 node:test 测试` 注释形状纳入同一处维护(此前漏刷,停在 1160) - 双 README:tests 计数 1242 / 1160 → 1247(徽章 + 两处命令注释 + 目录注释), 由脚本写入,非手改 --- .github/workflows/ci.yml | 42 ----------------------- .github/workflows/release.yml | 48 ++++----------------------- README.md | 6 ++-- dsh-mneme/README.md | 6 ++-- dsh-mneme/scripts/sync-test-badge.mjs | 30 ++++++++++------- 5 files changed, 30 insertions(+), 102 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5816e5d5..e171067a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,9 +6,6 @@ name: CI # 2. 新增 src/↔lib/ 一致性守门(scripts/check-sync.js,v0.7.9 引入的发布前校验前置到 CI)。 # 3. Codecov 只在 ubuntu+node24 一个分片跑一次(覆盖率无需每个组合都传)。 # 4. node_modules 缓存(cache-dependency-path 指向子目录的 lockfile)。 -# 5. main 徽章对齐 job:把双 README 的 tests 徽章刷成最新全量 pass 数—— -# 复用发版线的 badge:sync(脚本自带「测试不绿不刷徽章」),让数字不再 -# 只在发版时才追平。仅 push 到 main 时跑(PR 上没有可写回的对象)。 # ⚠️ 需要 package.json 配合一处小改(跨平台通配符): # dsh-mneme/package.json 的 "test": "node --test test/*.test.js" 在 Windows 的 cmd 下 # 不展开 glob。建议改为 "test": "node --test test/"(目录模式,全平台等价), @@ -66,42 +63,3 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} files: dsh-mneme/coverage/lcov.info fail_ci_if_error: false - - # 双 README 的 tests 徽章自动对齐最新全量 pass 数(复用发版线的 badge:sync, - # 脚本自带「测试不绿不刷徽章」)。只在 push 到 main 时跑:PR 上跑也刷不回 - # 基分支,反而拖慢每个 PR;已同步时脚本零改动、job 零提交。 - badge: - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - uses: actions/checkout@v4 - with: - ref: main - - - uses: actions/setup-node@v4 - with: - node-version: 24 - cache: npm - cache-dependency-path: dsh-mneme/package-lock.json - - - name: Install dependencies - working-directory: dsh-mneme - run: npm ci - - - name: Sync test badge & counts (runs full suite) - working-directory: dsh-mneme - run: npm run badge:sync - - - name: Commit & push if changed - run: | - if git diff --quiet; then - echo "badge already in sync — nothing to commit" - else - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add README.md dsh-mneme/README.md - git commit -m "chore(readme): 测试徽章自动对齐(CI main,pass 数追平)" - git push origin main - fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 03789793..50fba748 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -178,48 +178,13 @@ jobs: gh release create "v${VERSION}" --title "v${VERSION}" --notes-file notes/body.md fi - # ── 5. 徽章对齐:跑一遍全量测试,把双 README 的 tests 徽章与计数注释 ────── - # 自动刷成当前 pass 数并提交回 main——发版后徽章不再靠手工追平。 - # checkout main(徽章是对 main 的持续承诺,不属于 tag 快照);测试没跑绿 - # 时脚本以非零退出且不改任何文件。幂等:已同步则零提交。 - badge: - needs: [verify, test] - if: github.event_name == 'push' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: main - - - uses: actions/setup-node@v4 - with: - node-version: 24 - cache: npm - cache-dependency-path: dsh-mneme/package-lock.json - - - name: Install dependencies - working-directory: dsh-mneme - run: npm ci - - - name: Sync test badge & counts (runs full suite) - working-directory: dsh-mneme - run: npm run badge:sync - - - name: Commit & push if changed - run: | - if git diff --quiet; then - echo "badge already in sync — nothing to commit" - else - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add README.md dsh-mneme/README.md - git commit -m "chore(readme): 测试徽章自动对齐 v${{ needs.verify.outputs.version }}(release 流水线)" - git push origin main - fi - - # ── 6. 通知与运行摘要(接入外部通知时往这里加一步 webhook 即可)──────────── + # ── 5. 通知与运行摘要(接入外部通知时往这里加一步 webhook 即可)──────────── + # 徽章对齐不在流水线里做:main 受保护(4 个必过检查 + strict + 线性历史), + # github-actions[bot] 的 GITHUB_TOKEN 绕过不了 required status checks, + # push 必被 GH006 拒(v0.8.3 实测),改由发版前本地跑 npm run badge:sync, + # 与人工发布同一次提交带上。 notify: - needs: [verify, test, publish, release, badge] + needs: [verify, test, publish, release] if: always() runs-on: ubuntu-latest steps: @@ -234,7 +199,6 @@ jobs: echo "| test (win/linux × node 22/24) | ${{ needs.test.result }} |" echo "| publish (npm) | ${{ needs.publish.result }} |" echo "| release (GitHub) | ${{ needs.release.result }} |" - echo "| badge (auto-sync) | ${{ needs.badge.result }} |" } >> "$GITHUB_STEP_SUMMARY" # 可选:企业微信/Telegram/邮件 webhook。配置 secret(如 NOTIFY_WEBHOOK)后取消注释: # - name: Notify webhook diff --git a/README.md b/README.md index ab9e8b59..a6fe60ae 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ license CI node - tests + tests coverage Awesome

@@ -161,7 +161,7 @@ dsh web ```bash cd dsh-mneme && npm install -npm test # 1242 个测试 +npm test # 1247 个测试 npm run stress # 三轴线压测 npm run sync # src → lib 同步 ``` @@ -322,7 +322,7 @@ It works out of the box. To feel its value in five minutes: ```bash cd dsh-mneme && npm install -npm test # 1242 tests +npm test # 1247 tests npm run stress # three-axis stress test npm run sync # src → lib sync ``` diff --git a/dsh-mneme/README.md b/dsh-mneme/README.md index 35b21784..5c730318 100644 --- a/dsh-mneme/README.md +++ b/dsh-mneme/README.md @@ -5,7 +5,7 @@ [![npm version](https://img.shields.io/npm/v/@modusensus/dsh-mneme?color=blue&label=npm)](https://www.npmjs.com/package/@modusensus/dsh-mneme) [![license](https://img.shields.io/badge/license-MIT-green)](LICENSE) [![Awesome](https://awesome-dsh-plugin.com/badge.svg)](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) -[![tests](https://img.shields.io/badge/tests-1242%20passed-success)](https://github.com/slow-stack/dsh-mneme) +[![tests](https://img.shields.io/badge/tests-1247%20passed-success)](https://github.com/slow-stack/dsh-mneme) [![CI](https://img.shields.io/github/actions/workflow/status/slow-stack/dsh-mneme/ci.yml)](https://github.com/slow-stack/dsh-mneme/actions) [![node](https://img.shields.io/badge/node-22%2B-blue)](https://nodejs.org) [![npm downloads](https://img.shields.io/npm/d18m/@modusensus/dsh-mneme.svg?color=blue&label=downloads)](https://www.npmjs.com/package/@modusensus/dsh-mneme) @@ -683,7 +683,7 @@ src/ ├── api.js # HTTP 路由(Web 面板数据通道,含 /conflicts 冲突队列) └── index.js # 插件接线 lib/ # src 的同步分发产物(npm run sync;发布前由 root prepack 的 check-sync.js 校验一致性;唯一手写例外 lib/client.js——Web 面板 bundle,sync 不覆盖) -test/ # 1160 个 node:test 测试(审计与三轴线压测不变量;src↔lib 一致性由 scripts/check-sync.js 发布闸门校验) +test/ # 1247 个 node:test 测试(审计与三轴线压测不变量;src↔lib 一致性由 scripts/check-sync.js 发布闸门校验) scripts/ # e2e-dsh.js 端到端演示 · stress-dsh.js 三轴线压测 · sync-lib.js 同步 · check-sync.js 发布闸门 · benchmark-recall.js / benchmark-embed.js / benchmark-rerank.js 基准 · sync-test-badge.mjs 测试徽章 · build-runtime-manifest.mjs 运行时清单 ``` @@ -692,7 +692,7 @@ scripts/ # e2e-dsh.js 端到端演示 · stress-dsh.js 三轴线压 ```bash cd dsh-mneme npm install # 安装 peer 依赖(以 devDependencies 形式,用于本地测试) -npm test # 运行 1160 个测试 +npm test # 运行 1247 个测试 npm run stress # 三轴线压测:长会话检索 / 冲突仲裁 / 多 Agent 并发(离线 mock LLM) npm run sync # 把 src/ 同步到 lib/(发布时由 prepack 钩子自动执行) ``` diff --git a/dsh-mneme/scripts/sync-test-badge.mjs b/dsh-mneme/scripts/sync-test-badge.mjs index c877190c..fc692a4d 100644 --- a/dsh-mneme/scripts/sync-test-badge.mjs +++ b/dsh-mneme/scripts/sync-test-badge.mjs @@ -1,9 +1,12 @@ -// 发版流水线的徽章对齐(release.yml 的 badge job 调用;手动可跑 npm run badge:sync)。 +// 发版前对齐徽章(手动跑 npm run badge:sync;release.yml 不再有 badge job —— +// main 受保护,github-actions[bot] 的 GITHUB_TOKEN 绕过不了 required status +// checks,push 必被 GH006 拒)。 // // 做三件事: -// 1. 跑一遍全量测试(npm test),取最后的 `pass N` 汇总数; +// 1. 跑一遍全量测试(npm test),取套件总数(`ℹ tests N` 汇总行); // 2. 把双 README 的 tests 徽章(img.shields.io/badge/tests-N%20passed)与 -// 开发命令注释(# N 个测试 / # N tests)刷成该数字; +// 开发命令注释(# N 个测试 / # 运行 N 个测试 / # N 个 node:test 测试 / +// # N tests)刷成该数字; // 3. 有变化就写回文件(由调用方决定是否 commit/push),无变化静默退出。 // // 测试失败(fail>0 或进程非零退出)时以非零退出且不改任何文件——徽章永远 @@ -32,11 +35,14 @@ try { process.exit(1); } -// 2) 取汇总 pass 数(spec reporter 的 `ℹ pass N`;取最后一处防逐用例行干扰) -const matches = [...output.matchAll(/pass (\d+)/g)]; -const pass = matches.length ? Number(matches[matches.length - 1][1]) : 0; -if (!pass) { - console.error("无法从测试输出解析 pass 数,徽章不更新"); +// 2) 取套件总数(spec reporter 的 `ℹ tests N`;取最后一处防逐用例行干扰) +// 用总数而非 `pass N`:平台条件跳过的用例(如 Windows 未开开发者模式时的 +// 符号链接断言)在 pass 里不计、在 tests 里计入,而徽章报的是 CI(ubuntu) +// 口径 —— 用总数则本地在 Windows 跑也得到同一个数,不必手工修。 +const matches = [...output.matchAll(/ℹ tests (\d+)/g)]; +const count = matches.length ? Number(matches[matches.length - 1][1]) : 0; +if (!count) { + console.error("无法从测试输出解析套件总数,徽章不更新"); process.exit(1); } @@ -49,13 +55,13 @@ let changed = 0; for (const file of targets) { let text = readFileSync(file, "utf8"); const next = text - .replace(/tests-\d+%20passed-/g, `tests-${pass}%20passed-`) - .replace(/(#\s*)\d+( 个测试)/g, `$1${pass}$2`) - .replace(/(#\s*)\d+( tests)/g, `$1${pass}$2`); + .replace(/tests-\d+%20passed-/g, `tests-${count}%20passed-`) + .replace(/(#\s*(?:运行\s*)?)\d+( 个(?:\s*node:test)?\s*测试)/g, `$1${count}$2`) + .replace(/(#\s*)\d+( tests)/g, `$1${count}$2`); if (next !== text) { writeFileSync(file, next); changed += 1; console.log(`updated: ${file}`); } } -console.log(`pass=${pass}, files changed=${changed}`); +console.log(`tests=${count}, files changed=${changed}`);