[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
184
scripts/resolve-mosh-bin-release.test.cjs
Normal file
184
scripts/resolve-mosh-bin-release.test.cjs
Normal file
@@ -0,0 +1,184 @@
|
||||
const test = require("node:test");
|
||||
const assert = require("node:assert/strict");
|
||||
const fs = require("node:fs");
|
||||
const os = require("node:os");
|
||||
const path = require("node:path");
|
||||
|
||||
const {
|
||||
loadReleases,
|
||||
main,
|
||||
parseRepository,
|
||||
parseNextLink,
|
||||
pickLatestMoshBinRelease,
|
||||
validateReleaseTag,
|
||||
isAtLeastMinRelease,
|
||||
MIN_TAG,
|
||||
} = require("./resolve-mosh-bin-release.cjs");
|
||||
|
||||
function makeTmp(t) {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-resolve-mosh-"));
|
||||
t.after(() => fs.rmSync(dir, { recursive: true, force: true }));
|
||||
return dir;
|
||||
}
|
||||
|
||||
test("validateReleaseTag accepts only moshcatty-* tags at min version", () => {
|
||||
assert.equal(validateReleaseTag("moshcatty-0.1.8"), "moshcatty-0.1.8");
|
||||
assert.equal(validateReleaseTag("moshcatty-0.2.0"), "moshcatty-0.2.0");
|
||||
assert.equal(validateReleaseTag("moshcatty-0.1.9-rc1"), "moshcatty-0.1.9-rc1");
|
||||
assert.equal(validateReleaseTag("moshcatty-0.1.8+build.1"), "moshcatty-0.1.8+build.1");
|
||||
assert.throws(() => validateReleaseTag("mosh-bin-1.4.0-1"), /invalid mosh binary release tag/);
|
||||
assert.throws(() => validateReleaseTag("v1.2.3"), /invalid mosh binary release tag/);
|
||||
assert.throws(() => validateReleaseTag("moshcatty-../bad"), /invalid mosh binary release tag/);
|
||||
assert.throws(() => validateReleaseTag("moshcatty-not-a-version"), /invalid mosh binary release tag/);
|
||||
assert.throws(() => validateReleaseTag("moshcatty-0.1.0"), /below minimum/);
|
||||
assert.throws(() => validateReleaseTag("moshcatty-0.1.1"), /below minimum/);
|
||||
assert.throws(() => validateReleaseTag("moshcatty-0.1.2"), /below minimum/);
|
||||
assert.throws(() => validateReleaseTag("moshcatty-0.1.3"), /below minimum/);
|
||||
assert.throws(() => validateReleaseTag("moshcatty-0.1.4"), /below minimum/);
|
||||
assert.throws(() => validateReleaseTag("moshcatty-0.1.5"), /below minimum/);
|
||||
assert.throws(() => validateReleaseTag("moshcatty-0.1.6"), /below minimum/);
|
||||
assert.throws(() => validateReleaseTag("moshcatty-0.1.7"), /below minimum/);
|
||||
assert.throws(() => validateReleaseTag("moshcatty-0.1.8-rc1"), /below minimum/);
|
||||
});
|
||||
|
||||
test("isAtLeastMinRelease enforces moshcatty-0.1.8 floor with semver prerelease rules", () => {
|
||||
assert.equal(MIN_TAG, "moshcatty-0.1.8");
|
||||
assert.equal(isAtLeastMinRelease("moshcatty-0.1.3"), false);
|
||||
assert.equal(isAtLeastMinRelease("moshcatty-0.1.4"), false);
|
||||
assert.equal(isAtLeastMinRelease("moshcatty-0.1.5"), false);
|
||||
assert.equal(isAtLeastMinRelease("moshcatty-0.1.6"), false);
|
||||
assert.equal(isAtLeastMinRelease("moshcatty-0.1.7"), false);
|
||||
// Prerelease of the floor sorts below the final floor release.
|
||||
assert.equal(isAtLeastMinRelease("moshcatty-0.1.8-rc1"), false);
|
||||
// Above the floor, prereleases are fine.
|
||||
assert.equal(isAtLeastMinRelease("moshcatty-0.1.9-rc1"), true);
|
||||
assert.equal(isAtLeastMinRelease("moshcatty-0.1.8+build.1"), true);
|
||||
assert.equal(isAtLeastMinRelease("moshcatty-not-a-version"), false);
|
||||
});
|
||||
|
||||
test("parseRepository defaults to binaricat/MoshCatty (ignores GITHUB_REPOSITORY fork owner)", () => {
|
||||
assert.deepEqual(parseRepository({}), { owner: "binaricat", repo: "MoshCatty" });
|
||||
assert.deepEqual(parseRepository({ GITHUB_REPOSITORY: "owner/project" }), {
|
||||
owner: "binaricat",
|
||||
repo: "MoshCatty",
|
||||
});
|
||||
assert.deepEqual(
|
||||
parseRepository({ GITHUB_REPOSITORY: "owner/project", MOSH_BIN_OWNER: "bin", MOSH_BIN_REPO: "binaries" }),
|
||||
{ owner: "bin", repo: "binaries" },
|
||||
);
|
||||
});
|
||||
|
||||
test("pickLatestMoshBinRelease ignores non-moshcatty and pre-0.1.8 tags", () => {
|
||||
const got = pickLatestMoshBinRelease([
|
||||
{ tag_name: "v1.0.0", published_at: "2026-03-01T00:00:00Z" },
|
||||
{ tag_name: "mosh-bin-1.4.0-2", published_at: "2026-06-01T00:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.8", draft: true, published_at: "2026-07-13T00:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.2", published_at: "2026-07-10T00:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.5", published_at: "2026-07-10T13:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.6", published_at: "2026-07-13T01:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.7", published_at: "2026-07-14T01:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.8", published_at: "2026-07-17T01:00:00Z" },
|
||||
]);
|
||||
|
||||
assert.equal(got, "moshcatty-0.1.8");
|
||||
});
|
||||
|
||||
test("parseNextLink reads the next GitHub pagination URL", () => {
|
||||
const link = [
|
||||
'<https://api.github.com/repos/owner/repo/releases?per_page=100&page=1>; rel="prev"',
|
||||
'<https://api.github.com/repos/owner/repo/releases?per_page=100&page=3>; rel="next"',
|
||||
'<https://api.github.com/repos/owner/repo/releases?per_page=100&page=9>; rel="last"',
|
||||
].join(", ");
|
||||
|
||||
assert.equal(
|
||||
parseNextLink(link),
|
||||
"https://api.github.com/repos/owner/repo/releases?per_page=100&page=3",
|
||||
);
|
||||
assert.equal(parseNextLink('<https://api.github.com/repos/owner/repo/releases?page=1>; rel="last"'), null);
|
||||
});
|
||||
|
||||
test("loadReleases follows GitHub pagination until the last page", async () => {
|
||||
const requested = [];
|
||||
const got = await loadReleases({ GITHUB_REPOSITORY: "owner/repo" }, async (url) => {
|
||||
requested.push(url);
|
||||
if (url.includes("page=2")) {
|
||||
return {
|
||||
json: [{ tag_name: "moshcatty-0.1.6", published_at: "2026-01-01T00:00:00Z" }],
|
||||
headers: {},
|
||||
};
|
||||
}
|
||||
return {
|
||||
json: [{ tag_name: "v1.0.0", published_at: "2026-01-01T00:00:00Z" }],
|
||||
headers: {
|
||||
link: '<https://api.github.com/repos/owner/repo/releases?per_page=100&page=2>; rel="next"',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
assert.deepEqual(got.map((release) => release.tag_name), ["v1.0.0", "moshcatty-0.1.6"]);
|
||||
assert.equal(requested.length, 2);
|
||||
});
|
||||
|
||||
test("loadReleases rejects pagination loops", async () => {
|
||||
await assert.rejects(
|
||||
loadReleases({ GITHUB_REPOSITORY: "owner/repo" }, async (url) => ({
|
||||
json: [],
|
||||
headers: { link: `<${url}>; rel="next"` },
|
||||
})),
|
||||
/pagination looped/,
|
||||
);
|
||||
});
|
||||
|
||||
test("main keeps an explicit MOSH_BIN_RELEASE and exports it", async (t) => {
|
||||
const githubEnv = path.join(makeTmp(t), "github-env");
|
||||
|
||||
const got = await main({
|
||||
MOSH_BIN_RELEASE: "moshcatty-0.1.8",
|
||||
GITHUB_ENV: githubEnv,
|
||||
});
|
||||
|
||||
assert.equal(got, "moshcatty-0.1.8");
|
||||
assert.equal(fs.readFileSync(githubEnv, "utf8"), "MOSH_BIN_RELEASE=moshcatty-0.1.8\n");
|
||||
});
|
||||
|
||||
test("main rejects explicit pre-0.1.8 MOSH_BIN_RELEASE", async () => {
|
||||
await assert.rejects(
|
||||
main({ MOSH_BIN_RELEASE: "moshcatty-0.1.7" }),
|
||||
/below minimum/,
|
||||
);
|
||||
});
|
||||
|
||||
test("main resolves the latest moshcatty release from the list and exports it", async (t) => {
|
||||
const githubEnv = path.join(makeTmp(t), "github-env");
|
||||
const got = await main({
|
||||
GITHUB_ENV: githubEnv,
|
||||
MOSH_BIN_RELEASES_JSON: JSON.stringify([
|
||||
{ tag_name: "moshcatty-0.1.0", published_at: "2026-01-01T00:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.2", published_at: "2026-07-10T00:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.5", published_at: "2026-07-10T13:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.6", published_at: "2026-07-13T01:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.7", published_at: "2026-07-14T01:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.8", published_at: "2026-07-17T01:00:00Z" },
|
||||
{ tag_name: "mosh-bin-1.4.0-2", published_at: "2026-08-01T00:00:00Z" },
|
||||
]),
|
||||
});
|
||||
|
||||
assert.equal(got, "moshcatty-0.1.8");
|
||||
assert.equal(fs.readFileSync(githubEnv, "utf8"), "MOSH_BIN_RELEASE=moshcatty-0.1.8\n");
|
||||
});
|
||||
|
||||
test("main fails when no usable moshcatty release exists", async () => {
|
||||
await assert.rejects(
|
||||
main({
|
||||
MOSH_BIN_RELEASES_JSON: JSON.stringify([
|
||||
{ tag_name: "v1.0.0", published_at: "2026-01-01T00:00:00Z" },
|
||||
{ tag_name: "mosh-bin-1.4.0-1", published_at: "2026-02-01T00:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.5", published_at: "2026-02-01T00:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.6", published_at: "2026-02-01T00:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.7", published_at: "2026-02-01T00:00:00Z" },
|
||||
{ tag_name: "moshcatty-0.1.8", draft: true, published_at: "2026-02-01T00:00:00Z" },
|
||||
]),
|
||||
}),
|
||||
/could not find/,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user