mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
Fixes #11703. **Problem:** `getNewEntries()` parsed the saved version with `split(".")`. `0.1.5-20261020.7` became `["0", "1", "5-20261020", "7"]`, `Number("5-20261020")` is `NaN`, and `|| 0` turned it into `0.1.0`. The `[0.1.1]` to `[0.1.5]` notes counted as new, were shown, and the same prerelease string was saved again, so they repeated on every fresh launch. **Fix:** read only the leading `major.minor.patch` of the saved version, the same way changelog headings are parsed. `0.1.5-20261020.7` and `0.1.5+build.3` now count as `0.1.5`. If the saved version has no `major.minor.patch` (for example `latest`), nothing is shown and the installed version is saved in its place, like on a fresh install. Before, it was read as `0.0.0` and the whole changelog was shown. Saving the installed version matters because callers only save when there are new entries, so an unreadable value would otherwise silence the changelog for good. Alternatives considered (noted in a code comment): - plain string comparison: orders `0.10.0` before `0.9.0` - `localeCompare` with `numeric: true`: works only because `0.1.5-x` happens to sort after `0.1.5`, and depends on locale collation - strict semver: orders `0.1.5-x` before `0.1.5`, so the `[0.1.5]` notes would still repeat forever Tests added in `test/changelog.test.ts` and `test/interactive-mode-extension-changelog.test.ts`. `npm run check` passes.
76 lines
3 KiB
TypeScript
76 lines
3 KiB
TypeScript
import { describe, expect, test } from "vitest";
|
|
import { type ChangelogEntry, getNewEntries, normalizeChangelogLinks } from "../src/utils/changelog.ts";
|
|
|
|
const entry: ChangelogEntry = {
|
|
major: 0,
|
|
minor: 79,
|
|
patch: 0,
|
|
content: "",
|
|
};
|
|
|
|
describe("normalizeChangelogLinks", () => {
|
|
test("rewrites package-relative changelog links to tag-pinned GitHub source links", () => {
|
|
const markdown = [
|
|
"[Project Trust](README.md#project-trust)",
|
|
"[Extensions](docs/extensions.md#project_trust)",
|
|
"[Examples](examples/extensions/)",
|
|
"[Root README](../../README.md#supply-chain-hardening)",
|
|
].join("\n");
|
|
|
|
expect(normalizeChangelogLinks(markdown, entry)).toBe(
|
|
[
|
|
"[Project Trust](https://github.com/earendil-works/pi/blob/v0.79.0/packages/coding-agent/README.md#project-trust)",
|
|
"[Extensions](https://github.com/earendil-works/pi/blob/v0.79.0/packages/coding-agent/docs/extensions.md#project_trust)",
|
|
"[Examples](https://github.com/earendil-works/pi/tree/v0.79.0/packages/coding-agent/examples/extensions/)",
|
|
"[Root README](https://github.com/earendil-works/pi/blob/v0.79.0/README.md#supply-chain-hardening)",
|
|
].join("\n"),
|
|
);
|
|
});
|
|
|
|
test("canonicalizes old repository URLs without changing external links", () => {
|
|
const markdown = [
|
|
"[#5167](https://github.com/earendil-works/pi-mono/pull/5167)",
|
|
"[#4163](https://github.com/badlogic/pi-mono/issues/4163)",
|
|
"[Agent README](https://github.com/badlogic/pi-mono/blob/main/packages/agent/README.md)",
|
|
"[External](https://example.com/docs)",
|
|
"[Local anchor](#settings)",
|
|
].join("\n");
|
|
|
|
expect(normalizeChangelogLinks(markdown, "0.79.0")).toBe(
|
|
[
|
|
"[#5167](https://github.com/earendil-works/pi/pull/5167)",
|
|
"[#4163](https://github.com/earendil-works/pi/issues/4163)",
|
|
"[Agent README](https://github.com/earendil-works/pi/blob/v0.79.0/packages/agent/README.md)",
|
|
"[External](https://example.com/docs)",
|
|
"[Local anchor](#settings)",
|
|
].join("\n"),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("getNewEntries", () => {
|
|
const entries: ChangelogEntry[] = [
|
|
{ major: 0, minor: 1, patch: 5, content: "0.1.5" },
|
|
{ major: 0, minor: 1, patch: 4, content: "0.1.4" },
|
|
];
|
|
const newContent = (lastVersion: string) => getNewEntries(entries, lastVersion)?.map((e) => e.content);
|
|
|
|
// #11703
|
|
test("ignores prerelease and build suffixes of the last seen version", () => {
|
|
expect(newContent("0.1.5-20261020.7")).toEqual([]);
|
|
expect(newContent("0.1.5+build.3")).toEqual([]);
|
|
expect(newContent("0.1.4-beta.1")).toEqual(["0.1.5"]);
|
|
});
|
|
|
|
test("compares release versions numerically", () => {
|
|
expect(newContent("0.1.5")).toEqual([]);
|
|
expect(newContent("0.1.3")).toEqual(["0.1.5", "0.1.4"]);
|
|
expect(getNewEntries([{ major: 0, minor: 10, patch: 0, content: "0.10.0" }], "0.9.0")?.length).toBe(1);
|
|
});
|
|
|
|
test("returns undefined for a last seen version without major.minor.patch", () => {
|
|
expect(newContent("latest")).toBeUndefined();
|
|
expect(newContent("0.1")).toBeUndefined();
|
|
expect(newContent("")).toBeUndefined();
|
|
});
|
|
});
|