Files
OmniRoute/tests/unit/gen-contributors.test.ts
Diego Rodrigues de Sa e Souza a8d1e7bf78 chore(release): pipeline hardening — test-masking pre-flight gate + contributors/uncovered helpers (#5926)
* chore(ci): add test-masking PR-context gate to release-green pre-flight

Reproduce check:test-masking (vs origin/main) inside validate-release-green so
non-allowlisted net-assert reductions surface in the local pre-flight instead of
in a ~40-min CI layer on the release PR. run() now merges a per-gate opts.env so
GITHUB_BASE_REF reaches the child. HARD gate; skipped under --quick.

Context: v3.8.43 release cost 3 CI round-trips for PR-context gates (test-masking,
file-size, pr-evidence) that check:release-green did not reproduce locally.

* chore(release): add contributors generator + uncovered-commit reconciliation helpers

- scripts/release/gen-contributors.mjs: reproducible `### 🙌 Contributors` table for a
  CHANGELOG version (parenthetical-group parser → accurate per-PR attribution, noise-handle
  denylist). v3.8.43 shipped without the section (a real miss) because it was hand-built.
  npm run release:contributors <version> [--inject].
- scripts/release/list-uncovered-commits.mjs: lists commits since the last tag with no
  CHANGELOG bullet (v3.8.43 had 123/176 uncovered at reconciliation start). Advisory,
  maintainer-side. npm run release:uncovered.
- 20 unit tests (parenthetical attribution, noise exclusion, idempotent injection, coverage window).

* chore(quality): absorb web-cookie-providers-new file-size drift from #5928 (base-red on release/v3.8.44)
2026-07-02 14:27:31 -03:00

111 lines
4.0 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
const mod = await import("../../scripts/release/gen-contributors.mjs");
const {
extractVersionSection,
parseContributors,
renderContributors,
injectContributors,
NOISE_HANDLES,
} = mod;
const FIXTURE = `# Changelog
## [Unreleased]
---
## [3.9.0] — 2026-08-01
### ✨ New Features
- **feat(a):** thing one. ([#100](https://github.com/x/y/pull/100) — thanks @alice)
- **feat(b):** uses \`@toon-format/toon\` and \`@dnd-kit\`. ([#101](https://github.com/x/y/pull/101) — thanks @bob)
### 🔧 Bug Fixes
- **fix(c):** direct commit fix. (thanks @carol)
- **fix(d):** extracted. Extracted from [#102](https://github.com/x/y/pull/102) by [@dave](https://github.com/dave).
### 📝 Maintenance
- **refactor(rollup):** god-file split ([#200](https://github.com/x/y/pull/200), [#201](https://github.com/x/y/pull/201) — thanks @erin); editorconfig ([#202](https://github.com/x/y/pull/202) — thanks @frank). — thanks @diegosouzapw
---
## [3.8.99] — 2026-07-31
### 🔧 Bug Fixes
- **fix(z):** other version, must not leak. ([#999](https://github.com/x/y/pull/999) — thanks @zoe)
---
`;
test("extractVersionSection returns only the target version body (not the next section)", () => {
const sec = extractVersionSection(FIXTURE, "3.9.0");
assert.ok(sec.includes("thing one"), "includes 3.9.0 content");
assert.ok(!sec.includes("must not leak"), "excludes 3.8.99 content");
assert.ok(!sec.includes("#999"), "does not bleed into next version");
});
test("parseContributors credits per parenthetical group, not a flat scan", () => {
const agg = parseContributors(extractVersionSection(FIXTURE, "3.9.0"));
// rollup: erin gets 200+201, frank gets 202 — NOT both getting all three
assert.deepEqual(
[...agg.get("erin")].sort((a, b) => a - b),
[200, 201]
);
assert.deepEqual([...agg.get("frank")], [202]);
// simple bullets
assert.deepEqual([...agg.get("alice")], [100]);
// direct-commit credit with no PR ref
assert.ok(agg.has("carol") && agg.get("carol").size === 0);
// "Extracted from #N by @X"
assert.deepEqual([...agg.get("dave")], [102]);
});
test("noise handles and the maintainer are excluded from the contributor map", () => {
const agg = parseContributors(extractVersionSection(FIXTURE, "3.9.0"));
assert.ok(!agg.has("toon-format"), "package scope is not a contributor");
assert.ok(!agg.has("dnd-kit"), "package scope is not a contributor");
assert.ok(!agg.has("diegosouzapw"), "maintainer is rendered separately, not in the map");
assert.ok(NOISE_HANDLES.has("toon-format"));
});
test("renderContributors emits an alphabetical table with maintainer last", () => {
const agg = parseContributors(extractVersionSection(FIXTURE, "3.9.0"));
const table = renderContributors("3.9.0", agg);
assert.ok(table.startsWith("### 🙌 Contributors"));
const rows = table.split("\n").filter((l) => l.startsWith("| [@"));
const handles = rows.map((r) => r.match(/@([A-Za-z0-9_-]+)/)[1]);
assert.equal(handles[handles.length - 1], "diegosouzapw", "maintainer is last");
const external = handles.slice(0, -1);
assert.deepEqual(
external,
[...external].sort((a, b) => a.localeCompare(b)),
"external sorted"
);
assert.ok(table.includes("| [@carol](https://github.com/carol) | direct commit / report |"));
});
test("injectContributors inserts before the closing --- and is idempotent", () => {
const once = injectContributors(
FIXTURE,
"3.9.0",
renderContributors("3.9.0", parseContributors(extractVersionSection(FIXTURE, "3.9.0")))
);
assert.ok(once.includes("### 🙌 Contributors"), "section injected");
// 3.8.99 untouched
assert.ok(once.includes("must not leak"));
// idempotent: injecting again does not duplicate
const twice = injectContributors(
once,
"3.9.0",
renderContributors("3.9.0", parseContributors(extractVersionSection(once, "3.9.0")))
);
const count = (twice.match(/### 🙌 Contributors/g) || []).length;
assert.equal(count, 1, "no duplicate Contributors section on re-run");
});