Files
copilotkit__copilotkit/scripts/__tests__/validate-integration-pins.test.ts
Martha Schumann a274ce2023 chore(examples/integrations): scope to ADK only per review
Reverts the 14 other framework bumps and 2 lockfile regens. Each
framework needs per-framework QA against 1.56.4 before being shipped
in a sweep — too risky for the demo timeline to bump them all at once.

The validator now uses an explicit ENFORCED allowlist (currently just
adk) with an inline comment documenting the scope decision. Other
integrations get added to ENFORCED as QA clears each framework. The
structural fix (release-please automation that bumps integrations in
lockstep on each release) is tracked in CPK-7534.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 12:00:27 -07:00

202 lines
5.9 KiB
TypeScript

import { afterEach, describe, expect, it } from "vitest";
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import {
validatePins,
formatViolations,
} from "../validate-integration-pins.js";
function makePkg(deps: Record<string, string>): string {
return JSON.stringify({ name: "fixture", dependencies: deps });
}
function setupFixture(
integrations: Record<string, Record<string, string>>,
): string {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "validate-pins-"));
for (const [name, deps] of Object.entries(integrations)) {
const dir = path.join(root, name);
fs.mkdirSync(dir);
fs.writeFileSync(path.join(dir, "package.json"), makePkg(deps));
}
return root;
}
describe("validatePins", () => {
let fixtureDir: string;
afterEach(() => {
if (fixtureDir) fs.rmSync(fixtureDir, { recursive: true, force: true });
});
const ENFORCED = new Set(["adk"]);
it("returns no violations when every enforced integration matches the expected version", () => {
fixtureDir = setupFixture({
adk: { "@copilotkit/react-core": "1.56.4" },
});
const violations = validatePins({
expectedVersion: "1.56.4",
integrationsDir: fixtureDir,
enforced: ENFORCED,
});
expect(violations).toEqual([]);
});
it("flags stale exact-pinned versions in enforced integrations", () => {
fixtureDir = setupFixture({
adk: { "@copilotkit/react-core": "1.55.2" },
});
const violations = validatePins({
expectedVersion: "1.56.4",
integrationsDir: fixtureDir,
enforced: ENFORCED,
});
expect(violations).toHaveLength(1);
expect(violations[0].reason).toBe("stale");
});
it("flags floating dist-tag pins like 'latest' and 'next'", () => {
fixtureDir = setupFixture({
adk: { "@copilotkit/react-core": "latest" },
});
const violations = validatePins({
expectedVersion: "1.56.4",
integrationsDir: fixtureDir,
enforced: ENFORCED,
});
expect(violations).toHaveLength(1);
expect(violations[0].reason).toBe("floating-tag");
});
it("ignores integrations not on the allowlist (the 14 others left for QA)", () => {
fixtureDir = setupFixture({
adk: { "@copilotkit/react-core": "1.56.4" },
mastra: { "@copilotkit/react-core": "1.55.2" },
"mcp-apps": { "@copilotkit/runtime": "1.52.1" },
"a2a-middleware": { "@copilotkit/react-core": "latest" },
});
const violations = validatePins({
expectedVersion: "1.56.4",
integrationsDir: fixtureDir,
enforced: ENFORCED,
});
expect(violations).toEqual([]);
});
it("ignores intentional pre-release pins (e.g. ag-ui pre-release tags)", () => {
fixtureDir = setupFixture({
adk: {
"@copilotkit/react-core": "0.0.0-mme-ag-ui-0-0-46-20260227141603",
},
});
const violations = validatePins({
expectedVersion: "1.56.4",
integrationsDir: fixtureDir,
enforced: ENFORCED,
});
expect(violations).toEqual([]);
});
it("ignores non-@copilotkit dependencies entirely", () => {
fixtureDir = setupFixture({
adk: {
"@copilotkit/react-core": "1.56.4",
next: "16.1.1",
"@ag-ui/client": "0.0.52",
},
});
const violations = validatePins({
expectedVersion: "1.56.4",
integrationsDir: fixtureDir,
enforced: ENFORCED,
});
expect(violations).toEqual([]);
});
it("checks devDependencies too", () => {
fixtureDir = fs.mkdtempSync(path.join(os.tmpdir(), "validate-pins-dev-"));
const dir = path.join(fixtureDir, "adk");
fs.mkdirSync(dir);
fs.writeFileSync(
path.join(dir, "package.json"),
JSON.stringify({
name: "adk",
devDependencies: { "@copilotkit/react-core": "1.55.2" },
}),
);
const violations = validatePins({
expectedVersion: "1.56.4",
integrationsDir: fixtureDir,
enforced: ENFORCED,
});
expect(violations).toHaveLength(1);
expect(violations[0].dep).toBe("@copilotkit/react-core");
});
it("skips integrations without a package.json", () => {
fixtureDir = fs.mkdtempSync(path.join(os.tmpdir(), "validate-pins-skip-"));
fs.mkdirSync(path.join(fixtureDir, "adk"));
const violations = validatePins({
expectedVersion: "1.56.4",
integrationsDir: fixtureDir,
enforced: ENFORCED,
});
expect(violations).toEqual([]);
});
});
describe("formatViolations", () => {
it("returns an empty string when there are no violations", () => {
expect(formatViolations([], "1.56.4")).toBe("");
});
it("formats violations with reason, dep, and expected version", () => {
const out = formatViolations(
[
{
integration: "adk",
dep: "@copilotkit/react-core",
pinned: "1.55.2",
reason: "stale",
},
{
integration: "a2a-middleware",
dep: "@copilotkit/runtime",
pinned: "latest",
reason: "floating-tag",
},
],
"1.56.4",
);
expect(out).toContain("Found 2 stale pin(s)");
expect(out).toContain("[stale] adk: @copilotkit/react-core@1.55.2");
expect(out).toContain(
"[floating-tag] a2a-middleware: @copilotkit/runtime@latest",
);
expect(out).toContain("expected 1.56.4");
});
});
describe("live tree", () => {
it("examples/integrations/* @copilotkit pins match the monorepo release version", () => {
const repoRoot = path.resolve(__dirname, "..", "..");
const reactCorePkg = JSON.parse(
fs.readFileSync(
path.join(repoRoot, "packages", "react-core", "package.json"),
"utf8",
),
);
const expectedVersion = reactCorePkg.version;
const violations = validatePins({
expectedVersion,
integrationsDir: path.join(repoRoot, "examples", "integrations"),
});
if (violations.length > 0) {
console.error(formatViolations(violations, expectedVersion));
}
expect(violations).toEqual([]);
});
});