Files
software-mansion__argent/scripts/sync-next-dist-tag.test.mjs
T
Ignacy Łątka 10ecc9e53d fix(release): auto-sync the npm 'next' dist-tag to the highest published version (#357)
Auto-sync the npm `next` dist-tag to the highest published version (prerelease or stable) so it stops drifting behind `latest`.

- New dependency-free `scripts/sync-next-dist-tag.mjs` (SemVer comparator verified against the `semver` lib in `scripts/sync-next-dist-tag.test.mjs`).
- Runs as a post-publish step in `publish.yml` and `publish-next.yml` (with `continue-on-error` so a transient registry blip never fails an already-successful release), plus a manual `Sync 'next' dist-tag` workflow with a dry-run toggle.
- Only ever advances `next` (never regresses it) to survive a stale post-publish packument read.
- Package-name arg parsing rejects flag/blank tokens so the scoped `@swmansion/argent` default reliably wins.
2026-06-24 12:29:45 +02:00

83 lines
2.8 KiB
JavaScript

/**
* Proves the dependency-free SemVer comparator in sync-next-dist-tag.mjs orders
* versions identically to the `semver` library. `semver` is a dev/transitive
* dependency used only by this test — the script itself stays dependency-free.
*
* Run: node --test scripts/sync-next-dist-tag.test.mjs
*/
import { test } from "node:test";
import assert from "node:assert/strict";
import semver from "semver";
import { compareSemver, shouldAdvanceTag } from "./sync-next-dist-tag.mjs";
// Real published history of @swmansion/argent plus tricky prerelease cases that
// exercise every branch of SemVer precedence (numeric-vs-alphanumeric ids,
// field-count tiebreak, prerelease-vs-release, build metadata).
const VERSIONS = [
"0.5.1",
"0.5.2",
"0.5.3",
"0.6.0-next.1",
"0.6.0-next.2",
"0.6.0-next.10",
"0.6.0",
"0.6.1",
"0.7.0-next.4",
"0.7.0-alpha.1",
"0.7.0-beta",
"0.7.0-rc.1",
"0.7.0",
"0.7.1",
"0.8.0",
"1.0.0-next.0",
"1.0.0+build.5",
"1.0.0",
"0.11.0",
];
test("compareSemver agrees with semver.compare for every pair", () => {
for (const a of VERSIONS) {
for (const b of VERSIONS) {
assert.equal(
Math.sign(compareSemver(a, b)),
semver.compare(a, b),
`mismatch comparing ${a} vs ${b}`
);
}
}
});
test("max-by-compareSemver equals max-by-semver", () => {
const mineMax = VERSIONS.slice().sort((x, y) => compareSemver(y, x))[0];
const semverMax = VERSIONS.slice().sort(semver.rcompare)[0];
assert.equal(mineMax, semverMax);
});
test("prerelease ranks below its release; numeric id below alphanumeric", () => {
assert.ok(compareSemver("1.0.0-next.0", "1.0.0") < 0);
assert.ok(compareSemver("1.0.0-next.0", "1.0.0-next.alpha") < 0);
assert.ok(compareSemver("0.6.0-next.2", "0.6.0-next.10") < 0); // numeric, not lexical
});
test("shouldAdvanceTag only advances, never regresses 'next'", () => {
// Self-heal: drifted `next` advances to the true max (the bug this fixes).
assert.equal(shouldAdvanceTag("0.11.0", "0.7.0-next.4"), true);
assert.equal(shouldAdvanceTag("0.7.0-next.6", "0.7.0-next.4"), true);
// Unset or unparseable current => set it.
assert.equal(shouldAdvanceTag("0.11.0", undefined), true);
assert.equal(shouldAdvanceTag("0.11.0", null), true);
assert.equal(shouldAdvanceTag("0.11.0", "not-a-version"), true);
// Idempotent: already at the max => no-op.
assert.equal(shouldAdvanceTag("0.11.0", "0.11.0"), false);
assert.equal(shouldAdvanceTag("0.12.0-next.0", "0.12.0-next.0"), false);
// Regression guard: a stale packument can compute a `max` older than the
// just-tagged prerelease `next` already points at — must NOT move backward.
assert.equal(shouldAdvanceTag("0.11.0", "0.12.0-next.0"), false);
assert.equal(shouldAdvanceTag("0.7.0-next.4", "0.11.0"), false);
});