|
| 1 | +/** |
| 2 | + * Audit: packages/mcp/server.json stays aligned with package.json. |
| 3 | + * |
| 4 | + * The release pipeline (.github/workflows/release.yml) refuses to publish to |
| 5 | + * the MCP Registry unless server.json.version === package.json.version and |
| 6 | + * server.json.name === package.json.mcpName. That guard only runs at release |
| 7 | + * time, so a drift (e.g. bumping package.json without server.json) ships to |
| 8 | + * npm + the GitHub .mcpb and only fails the registry step — silently, after |
| 9 | + * the fact. server.json sat at 0.17.2 across the 0.17.3 / 0.18.0 / 0.18.1 |
| 10 | + * releases for exactly this reason. This test moves the check to PR time. |
| 11 | + */ |
| 12 | +import { readFileSync } from "node:fs"; |
| 13 | +import { dirname, join } from "node:path"; |
| 14 | +import { fileURLToPath } from "node:url"; |
| 15 | +import { describe, it, expect } from "vitest"; |
| 16 | + |
| 17 | +const __dirname = dirname(fileURLToPath(import.meta.url)); |
| 18 | +// packages/mcp/test/audit -> packages/mcp |
| 19 | +const MCP_DIR = join(__dirname, "..", ".."); |
| 20 | + |
| 21 | +const pkg = JSON.parse(readFileSync(join(MCP_DIR, "package.json"), "utf8")); |
| 22 | +const srv = JSON.parse(readFileSync(join(MCP_DIR, "server.json"), "utf8")); |
| 23 | + |
| 24 | +describe("audit: server.json aligns with package.json", () => { |
| 25 | + it("top-level server.json.version matches package.json.version", () => { |
| 26 | + expect(srv.version).toBe(pkg.version); |
| 27 | + }); |
| 28 | + |
| 29 | + it("server.json.name matches package.json.mcpName", () => { |
| 30 | + expect(srv.name).toBe(pkg.mcpName); |
| 31 | + }); |
| 32 | + |
| 33 | + it("every server.json packages[].version matches package.json.version", () => { |
| 34 | + const versions = (srv.packages ?? []).map((p: { version?: string }) => p.version); |
| 35 | + for (const v of versions) { |
| 36 | + expect(v).toBe(pkg.version); |
| 37 | + } |
| 38 | + }); |
| 39 | + |
| 40 | + it("the npm package entry identifies @leadbay/mcp", () => { |
| 41 | + const npmPkg = (srv.packages ?? []).find( |
| 42 | + (p: { registryType?: string }) => p.registryType === "npm" |
| 43 | + ); |
| 44 | + expect(npmPkg?.identifier).toBe(pkg.name); |
| 45 | + }); |
| 46 | + |
| 47 | + it("every @leadbay/mcp@<major.minor> npx pin tracks the current version line", () => { |
| 48 | + // Pins appear in packages[].runtimeArguments AND in env-var description |
| 49 | + // prose; scan the raw file so neither can silently lag (the registry would |
| 50 | + // otherwise install an older line — exactly the 0.17 staleness this fixes). |
| 51 | + const raw = readFileSync(join(MCP_DIR, "server.json"), "utf8"); |
| 52 | + const [major, minor] = pkg.version.split("."); |
| 53 | + const line = `${major}.${minor}`; |
| 54 | + const pins = [...raw.matchAll(/@leadbay\/mcp@(\d+\.\d+)/g)].map((m) => m[1]); |
| 55 | + expect(pins.length).toBeGreaterThan(0); |
| 56 | + for (const p of pins) expect(p).toBe(line); |
| 57 | + }); |
| 58 | +}); |
0 commit comments