Files

135 lines
4.7 KiB
TypeScript

import assert from "node:assert/strict"
import { test } from "node:test"
import {
encodeName,
ensureLinked,
ensureTag,
isPublished,
publishBody,
} from "../scripts/release.ts"
import { buildEntry, bumpMinor, insertEntry, latestVersion } from "../scripts/version.ts"
const CHANGELOG = `# Changelog
## [Unreleased]
## [1.4.0] - 2026-09-01
### Changed
- Upstream sync: mattpocock/skills \`aaaaaaaaa\` -> \`bbbbbbbbb\`.
## [0.1.0] - 2026-08-01
`
test("latestVersion finds the first release heading", () => {
assert.equal(latestVersion(CHANGELOG), "1.4.0")
assert.throws(() => latestVersion("# empty\n"), /no release heading/)
})
test("bumpMinor: minor bump, prerelease untouched", () => {
assert.equal(bumpMinor("1.4.0"), "1.5.0")
assert.equal(bumpMinor("0.1.0"), "0.2.0")
assert.equal(bumpMinor("1.5.0-rc.1"), "1.5.0-rc.1")
})
test("buildEntry: minor bump + upstream diff lines; null when commit already released", () => {
const entry = buildEntry({
changelog: CHANGELOG,
fromCommit: "bbbbbbbbb123",
toCommit: "ccccccccc456",
toVersion: "1.4.0",
date: "2026-10-15",
diff: { added: ["engineering/new"], removed: [], changed: ["engineering/tdd"] },
})
assert.equal(entry?.version, "1.5.0")
assert.match(entry!.body, /^## \[1\.5\.0\] - 2026-10-15/)
assert.match(entry!.body, /`bbbbbbbbb` -> `ccccccccc`/)
assert.match(entry!.body, /added: engineering\/new/)
assert.match(entry!.body, /changed: engineering\/tdd/)
const again = buildEntry({
changelog: CHANGELOG + entry!.body,
fromCommit: "b",
toCommit: "ccccccccc456",
toVersion: "1.4.0",
date: "2026-10-15",
diff: { added: [], removed: [], changed: [] },
})
assert.equal(again, null, "idempotent for an already-released upstream commit")
})
test("insertEntry places the new version under Unreleased", () => {
const entry = { version: "1.5.0", date: "2026-10-15", body: "## [1.5.0] - 2026-10-15" }
const out = insertEntry(CHANGELOG, entry)
assert.match(out, /## \[Unreleased\]\n\n## \[1\.5\.0\] - 2026-10-15\n\n## \[1\.4\.0\]/)
assert.throws(() => insertEntry("# nothing\n", entry), /no `## \[Unreleased\]` heading/)
})
test("publish helpers: name encoding, published check, body hashes", () => {
assert.equal(encodeName("@haylan/opencode-pocock"), "@haylan%2Fopencode-pocock")
assert.equal(isPublished({ versions: { "1.0.0": {} } }, "1.0.0"), true)
assert.equal(isPublished({ versions: {} }, "1.0.0"), false)
assert.equal(isPublished({}, "1.0.0"), false)
const body = publishBody(
{ name: "@haylan/opencode-pocock", version: "1.0.0" },
Buffer.from("tar"),
) as {
"dist-tags": Record<string, string>
versions: Record<string, { dist: { shasum: string; integrity: string } }>
_attachments: Record<string, { data: string; length: number }>
}
assert.equal(body["dist-tags"].latest, "1.0.0")
assert.equal(body.versions["1.0.0"].dist.shasum.length, 40)
assert.match(body.versions["1.0.0"].dist.integrity, /^sha512-/)
const att = body._attachments["@haylan/opencode-pocock-1.0.0.tgz"]
assert.equal(att.data, Buffer.from("tar").toString("base64"))
assert.equal(att.length, 3)
})
test("ensureTag: creates on 404, no-ops when it exists, fails loudly otherwise", async () => {
const base = "https://gitea.test/api/v1"
const creating = {
base,
headers: {},
fetchFn: (async (_url: string | URL | Request, init?: RequestInit) => {
if ((init?.method ?? "GET") === "GET") return new Response(null, { status: 404 })
return new Response(null, { status: 201 })
}) as typeof fetch,
}
assert.equal(await ensureTag(creating, "o/r", "1.0.0", "sha123"), "created")
const exists = {
base,
headers: {},
fetchFn: (async () => new Response(null, { status: 200 })) as typeof fetch,
}
assert.equal(await ensureTag(exists, "o/r", "1.0.0", "sha123"), "exists")
const broken = {
base,
headers: {},
fetchFn: (async () => new Response("boom", { status: 500 })) as typeof fetch,
}
await assert.rejects(() => ensureTag(broken, "o/r", "1.0.0", "sha123"), /tag lookup failed: 500/)
})
test("ensureLinked: links once, then reports already linked", async () => {
let linked = false
const fetchFn = (async (url: string | URL | Request, init?: RequestInit) => {
const method = init?.method ?? "GET"
if (method === "GET") {
return Response.json(linked ? { repository: { id: 1 } } : {}, { status: 200 })
}
linked = true
return new Response(null, { status: 204 })
}) as typeof fetch
const api = { base: "https://gitea.test/api/v1", headers: {}, fetchFn }
assert.equal(await ensureLinked(api, "haylan", "@haylan/opencode-pocock", "0.2.0", "r"), "linked")
assert.equal(
await ensureLinked(api, "haylan", "@haylan/opencode-pocock", "0.2.0", "r"),
"already linked",
)
})