npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@be-link/prepush-gate

v2.1.3

Published

客户端 pre-push 质量门禁 CLI:非受保护分支本地跑 lint/typecheck + 完整单测门禁(小改动判定/单测差异/增量覆盖率),失败即拒绝推送

Readme

jenkins-node-quality-gate

用于统一 Node.js 项目质量门禁的 Jenkins Global Trusted Pipeline Library

它将 Git diff 基线、小改动豁免、tests/unit 单测差异、本次变更覆盖率和服务整体覆盖率收敛在此仓库;业务 Jenkinsfile 只保留可见的 Stage 外壳和项目事实配置。

当前版本已在 Jenkins 通过 Shared Library 加载烟雾验证;业务项目接入前仍应执行其自身 canary。

固定规范

以下规则由公共库固定,业务项目不能降低或覆盖:

| 项目 | 规则 | | --- | --- | | 启用分支 | 默认仅标准化后的 test 分支;受控 canary 例外见下文 | | 差异基线 | 以 GIT_PREVIOUS_SUCCESSFUL_COMMIT 为基线;因分支回退/改写不再是 HEAD 祖先时退回到二者共同祖先(merge-base)做超集 diff(只多检、不漏检);首次构建(指针确实缺失)进入 bootstrap 模式跳过本次增量门禁并建立基线;无效、无共同祖先或 checkout 过浅时仍阻断 | | 生产源码 | sourcePaths 内的 .js / .jsx / .ts / .tsx,默认排除 .d.ts | | 单测目录 | 固定为 tests/unit/**/* | | 小改动豁免 | 非空白生产变更不超过 5 行、2 个文件,且没有新增、删除、重命名、复制、二进制或未知状态 | | 本次变更覆盖率 | lines ≥ 90%、statements ≥ 90%、functions ≥ 90%、branches ≥ 80%,不达标阻断 | | 服务整体覆盖率 | 全部可单测生产源码纳入统计;未加载源码应由 runner 的完整采集配置按 0% 纳入;仅展示趋势,不阻断 |

公共库在 initialize() 阶段一次解析并冻结基线完整 SHA;小改动、单测差异和增量覆盖率均使用同一 SHA。当上一次成功构建因分支回退/改写不再是 HEAD 祖先时,冻结的是它与 HEAD 的共同祖先(merge-base),对 共同祖先..HEAD 做 diff——这是真实增量的超集,只会多检不会漏检,从而在历史回退时不至于死锁。但仍不会缩小范围或回退到 HEAD^

首次构建(bootstrap):当 GIT_PREVIOUS_SUCCESSFUL_COMMIT 确实缺失(全新 Job、构建历史被清空,或该 Job 首次跑门禁)时,公共库不再 fail-closed,而是进入 bootstrap 模式——本次跳过增量门禁(小改动/单测差异/单元测试与覆盖率 stage 均跳过),让构建正常走完 Build/Push/Deploy;成功后 git 插件会记录本次 commit,之后的构建从 checkout 返回值取到 GIT_PREVIOUS_SUCCESSFUL_COMMIT 即恢复正常强制。注意:pipeline 的 checkout 步骤不会把该变量自动导出到全局 env,业务 Jenkinsfile 必须在 Checkout 阶段接住返回值 env.GIT_PREVIOUS_SUCCESSFUL_COMMIT = scmVars.GIT_PREVIOUS_SUCCESSFUL_COMMIT ?: ''(见 examples/),否则每次构建都会被当作首次构建。这是一个受控的一次性口子:仅每个 Job 的第一次成功构建(及任何清空历史后的第一次)不受增量门禁保护。基线与 HEAD 无共同祖先,或 Jenkins shallow checkout 无法取得相关 commit 时,仍然失败而不是猜测基线。

受控 QA canary

公共库只对已登记的 canaryId 开放临时 QA 验证;业务仓库不能指定任意分支、阈值或测试目录。当前唯一登记项是:

canaryId: 'positive-order-service-qa'

它仅在有效目标分支为 qa 时启用。有效目标分支统一按 CHANGE_TARGETBRANCH_NAMEGIT_BRANCH 解析:因此目标为 QA 的 PR 与 QA 分支直接构建均可验证,普通项目的 QA 构建仍不会启用。公共库会将目标分支传给内部 Shell/Node 脚本,QA 与 test 的 V2 覆盖率基线严格隔离。

Jenkins 全局配置

Manage Jenkins → System → Global Trusted Pipeline Libraries 新增:

| 字段 | 建议值 | | --- | --- | | Name | node-quality-gate | | Retrieval method | Modern SCM | | SCM | Git:https://git.8848top.com/QATeam/jenkins-node-quality-gate.git | | Credentials | Jenkins 中配置的 Gitea 只读凭据 | | Default version | 发布后的不可变 tag,例如 v1.0.0 | | Load implicitly | 关闭 | | Allow default version to be overridden | 正式环境关闭 | | Include library changes | 开启 |

该库需要设为 Trusted:它会读取 Jenkins 历史构建变量以计算覆盖率趋势,并通过 libraryResource 物化公共脚本。不要在 Jenkins 后台复制粘贴业务质量脚本。

业务项目接入

业务 Jenkinsfile 顶部显式加载库:

@Library('node-quality-gate') _

在 Jenkinsfile 中声明项目事实配置。不要提供分支、阈值、小改动阈值或测试目录:

def qualityPolicy = [
  sourcePaths: ['src/pos'],
  coverageExcludePatterns: [
    'src/pos/vendors/**', // 不采集 coverage,也不计入服务整体覆盖率基线
  ],
  diffCoverageExcludePatterns: [
    'src/pos/api/app.ts', // 仍采集并计入服务基线;变更时豁免单测差异与增量覆盖率门禁
  ],
  testRunner: 'jest', // 或 'vitest'
  testCommand: 'pnpm exec jest',
  nodeToolName: 'v20', // 可省略,默认 v20;必须已在 Jenkins 配置
  installCommand: 'pnpm install --prefer-offline --ignore-scripts',
  buildCommand: 'pnpm run build',
]

保留下面四个 Stage,便于在 Jenkins Stage View 定位失败点:

stage('V2 小改动判定') {
  when { expression { nodeQualityGate.isEnabled(qualityPolicy) } }
  steps { script { nodeQualityGate.evaluateSmallChange(qualityPolicy) } }
}
stage('V2 依赖安装与构建') {
  when { expression { nodeQualityGate.shouldRun(qualityPolicy) } }
  steps { script { nodeQualityGate.installAndBuild(qualityPolicy) } }
}
stage('单测差异检查') {
  when { expression { nodeQualityGate.shouldRun(qualityPolicy) } }
  steps { script { nodeQualityGate.requireTestDiff(qualityPolicy) } }
}
stage('单元测试与覆盖率') {
  when { expression { nodeQualityGate.shouldRun(qualityPolicy) } }
  steps { script { nodeQualityGate.runTestsAndCoverage(qualityPolicy) } }
}

Docker Build/Push/Deploy、项目专有通知(例如飞书)与其他发布逻辑继续留在业务仓库。

配置字段

| 字段 | 必填 | 说明 | | --- | --- | --- | | sourcePaths | 是 | 非空、仓库相对源码目录列表;不可重复或互为父子目录 | | coverageExcludePatterns | 否 | sourcePaths 内的正向仓库相对 glob 列表;从 runner coverage 采集和服务整体覆盖率基线排除,仅用于确实不应承担覆盖率责任的代码 | | diffCoverageExcludePatterns | 否 | sourcePaths 内的正向仓库相对 glob 列表;仅豁免命中文件变更的单测差异与增量覆盖率门禁,仍采集且计入服务整体覆盖率基线;仅用于经评审确认的生成代码或不可测边界适配层 | | testRunner | 是 | jestvitest | | testCommand | 是 | 测试 runner 基础命令;不得自行包含 coverage、reporter、output 参数 | | nodeToolName | 否 | Jenkins NodeJS Tool 名称;默认 v20 | | installCommand | 是 | 业务项目安装依赖命令 | | buildCommand | 是 | 业务项目构建或类型检查命令 | | canaryId | 否 | 仅可使用公共库登记的受控 canary 标识;当前仅 positive-order-service-qa |

Jest 与 Vitest 产物约定

公共库负责追加 CI、JSON 测试报告、coverage、完整源码采集、临时结果目录和排除项。coverageExcludePatterns 会传给 Jest/Vitest 并改变 coverage-final.json 与服务整体覆盖率口径;diffCoverageExcludePatterns 不会传给 runner,只影响变更文件的单测差异与增量覆盖率门禁范围。

  • Jest:必须能产出 <temporary coverage directory>/coverage-final.json
  • Vitest:项目必须安装与当前 Vitest 版本匹配的 coverage provider(@vitest/coverage-v8@vitest/coverage-istanbul);公共库请求 JSON coverage reporter,并要求最终产物为 Istanbul 结构的 coverage-final.json
  • 任一 runner 未生成测试 JSON 或 coverage-final.json 都会失败;公共库不会在 CI 临时安装 runner/provider。
  • 项目测试配置必须能扫描 tests/unit。若现有项目使用别的目录,应先迁移测试目录后接入。

Vitest provider 与版本可能影响 JSON 文件名和 coverage 映射;接入每类前端项目时,先在 canary Job 验证所用版本能生成公共库要求的 coverage-final.json

覆盖率趋势(V2)

每个成功构建保存:

NODE_SERVICE_COVERAGE_BASELINE_V2=schema|scope|test|average|commit

scope 基于排序后的 sourcePathscoverageExcludePatterns 和固定后缀生成;diffCoverageExcludePatterns 不影响服务整体覆盖率口径,因此不参与 scope。仅当 schema、scope 和分支一致时才比较趋势。旧项目的 V1 基线不参与比较;首次 V2 成功构建显示 📊—

公共库回填以下变量,供业务项目既有通知逻辑消费:

  • UNIT_TEST_SUMMARY
  • DIFF_COVERAGE_SUMMARY
  • DIFF_COVERAGE_FAILURE_REASONS:覆盖率门禁失败原因的单行 JSON 数组
  • DIFF_COVERAGE_FILES:实际参与本次增量覆盖率统计的文件单行 JSON 数组
  • DIFF_COVERAGE_UNCOLLECTED_CHANGED_FILES:本次变更但未进入 coverage 采集的文件单行 JSON 数组
  • COVERAGE_BASELINE_SUMMARY
  • GIT_DIFF_BASELINE_SHA:本次实际使用的完整上一次成功构建 commit SHA
  • GIT_DIFF_BASELINE_SOURCE:固定为 GIT_PREVIOUS_SUCCESSFUL_COMMIT
  • GIT_DIFF_BASELINE_SUMMARY:供通知展示的摘要,例如 0fee923b(上一次成功构建)
  • NODE_SERVICE_COVERAGE_BASELINE_V2

DIFF_COVERAGE_UNCOLLECTED_CHANGED_FILES 非空时,表示相应变更源码文件在本次生成的 coverage-final.json 中没有匹配记录。这可能来自覆盖率采集范围、忽略规则、路径匹配、runner/provider 配置或测试未加载该模块;该清单不能单独证明缺少单元测试文件。命中 diffCoverageExcludePatterns 的变更文件不会出现在该清单或 DIFF_COVERAGE_FILES 中,因此这两个字段不代表所有源码变更。

本地验证

该仓库不依赖额外 npm 包,使用 Node 内建断言和临时 Git fixture:

node test/quality-gate.test.js
bash -n resources/quality-gate/check-unit-test-diff.sh
node --check resources/quality-gate/check-diff-coverage.js
node --check resources/quality-gate/quality-result-utils.js

覆盖的场景包括:覆盖率阈值、参与增量覆盖率统计的文件与未采集变更文件诊断、差异排除文件的增量门禁与单测差异豁免、差异排除不影响服务基线和小改动判定、Istanbul 行覆盖与 statement 覆盖差异、无可执行变更、Jest/Vitest(含 todo)摘要、覆盖率失败结果的字段解析、上次成功构建基线、小改动、全量新增文件取消豁免、测试重命名携带内容修改、缺失测试变更、边界超限和仅空白变更。

发布与回滚建议

  1. 先发布不可变候选 tag(例如 v1.0.0-rc.1)。
  2. 选择一个 Jest 后端项目和一个 Vitest 前端项目,在 test canary/影子 Job 与旧门禁并行比对。
  3. 确认差异范围、小改动判定、测试结果和增量覆盖率一致;服务整体覆盖率因口径升级应只建立 V2 新基线,不与旧值直接比较。
  4. 发布不可变正式 tag(例如 v1.0.0),再将 Jenkins 默认版本切换到该 tag。
  5. 异常时在 Jenkins 后台回退到上一个稳定 tag;不要覆盖或移动已发布 tag。