mirror of
https://github.com/przeprogramowani/10x-cli.git
synced 2026-09-19 03:30:01 +08:00
261d084165
npm pack --dry-run --json consistently exceeds 30s on windows-latest runners. Since package contents are platform-independent, this test only needs to run on Ubuntu (check job). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
143 lines
4.5 KiB
TypeScript
143 lines
4.5 KiB
TypeScript
/**
|
|
* Smoke tests for the npm package tarball.
|
|
*
|
|
* Verifies the published package contains the right files, excludes
|
|
* sensitive content, and targets the correct registry.
|
|
*/
|
|
import { describe, it, expect } from "bun:test";
|
|
import { execSync } from "node:child_process";
|
|
import { readFileSync, writeFileSync, copyFileSync, appendFileSync, mkdtempSync, mkdirSync, rmSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join, resolve } from "node:path";
|
|
|
|
const ROOT = resolve(import.meta.dir, "../..");
|
|
|
|
describe("npm pack contents", () => {
|
|
it.skipIf(process.platform === "win32")("includes required files and excludes dev artifacts", () => {
|
|
const output = execSync("npm pack --dry-run --json", {
|
|
cwd: ROOT,
|
|
encoding: "utf8",
|
|
stdio: ["pipe", "pipe", "pipe"],
|
|
});
|
|
const [pack] = JSON.parse(output);
|
|
const filePaths = pack.files.map(
|
|
(f: { path: string }) => f.path,
|
|
) as string[];
|
|
|
|
// Must include
|
|
expect(filePaths.some((f: string) => f.startsWith("dist/"))).toBe(true);
|
|
expect(filePaths).toContain("package.json");
|
|
expect(filePaths).toContain("README.md");
|
|
|
|
// Must NOT include
|
|
const forbidden = ["src/", "test/", "tests/", ".env", "node_modules/"];
|
|
for (const prefix of forbidden) {
|
|
const leaked = filePaths.filter((f: string) => f.startsWith(prefix));
|
|
expect(leaked).toEqual([]);
|
|
}
|
|
|
|
// No secret-like files
|
|
const secrets = filePaths.filter((f: string) =>
|
|
/secret/i.test(f),
|
|
);
|
|
expect(secrets).toEqual([]);
|
|
}, 30_000);
|
|
});
|
|
|
|
describe("registry target", () => {
|
|
it(".npmrc resolves to registry.npmjs.org, not GitHub Packages", () => {
|
|
const npmrc = readFileSync(resolve(ROOT, ".npmrc"), "utf8");
|
|
expect(npmrc).toContain("registry=https://registry.npmjs.org/");
|
|
expect(npmrc).not.toContain("npm.pkg.github.com");
|
|
});
|
|
});
|
|
|
|
describe("auto-version script", () => {
|
|
/**
|
|
* Helper: creates a temp git repo, runs auto-version.mjs, returns
|
|
* { stdout, stderr, exitCode, packageJson }.
|
|
*/
|
|
function runAutoVersion(commits: string[]): {
|
|
stdout: string;
|
|
stderr: string;
|
|
exitCode: number;
|
|
packageJson: string;
|
|
} {
|
|
const tmpDir = mkdtempSync(join(tmpdir(), "10x-autoversion-"));
|
|
|
|
try {
|
|
// Write files via Node.js to avoid shell quoting issues on Windows.
|
|
writeFileSync(join(tmpDir, "package.json"), '{"version":"1.0.0"}');
|
|
mkdirSync(join(tmpDir, "src"), { recursive: true });
|
|
writeFileSync(join(tmpDir, "src/index.ts"), "// placeholder\n");
|
|
|
|
// Initialize repo with a v1.0.0 tag.
|
|
execSync(
|
|
[
|
|
"git init -q",
|
|
'git config user.name "test"',
|
|
'git config user.email "test@test.com"',
|
|
"git add -A",
|
|
'git commit -m "initial" -q',
|
|
"git tag v1.0.0",
|
|
].join(" && "),
|
|
{ cwd: tmpDir, stdio: "pipe" },
|
|
);
|
|
|
|
// Add commits that touch src/ so the git-diff release gate fires.
|
|
for (const msg of commits) {
|
|
appendFileSync(join(tmpDir, "src/index.ts"), "// change\n");
|
|
execSync(`git add -A && git commit -m "${msg}" -q`, {
|
|
cwd: tmpDir,
|
|
stdio: "pipe",
|
|
});
|
|
}
|
|
|
|
copyFileSync(
|
|
join(ROOT, "scripts/auto-version.mjs"),
|
|
join(tmpDir, "auto-version.mjs"),
|
|
);
|
|
|
|
const homeEnv = process.platform === "win32"
|
|
? { USERPROFILE: tmpDir }
|
|
: { HOME: tmpDir };
|
|
const proc = Bun.spawnSync(["bun", "auto-version.mjs"], {
|
|
cwd: tmpDir,
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
env: { ...process.env, ...homeEnv, NODE_PATH: `${ROOT}/node_modules` },
|
|
});
|
|
|
|
const pkgContent = (() => {
|
|
try {
|
|
return readFileSync(`${tmpDir}/package.json`, "utf8");
|
|
} catch {
|
|
return "";
|
|
}
|
|
})();
|
|
|
|
return {
|
|
stdout: proc.stdout.toString(),
|
|
stderr: proc.stderr.toString(),
|
|
exitCode: proc.exitCode,
|
|
packageJson: pkgContent,
|
|
};
|
|
} finally {
|
|
rmSync(tmpDir, { recursive: true, force: true });
|
|
}
|
|
}
|
|
|
|
it("exits with code 1 when no releasable commits exist", () => {
|
|
const result = runAutoVersion(["chore(release): v1.0.0"]);
|
|
expect(result.exitCode).toBe(1);
|
|
expect(result.stderr).toContain("No version bump needed");
|
|
});
|
|
|
|
it("bumps minor for feat: commits", () => {
|
|
const result = runAutoVersion(["feat: add new command"]);
|
|
expect(result.exitCode).toBe(0);
|
|
expect(result.packageJson).toContain('"version": "1.1.0"');
|
|
expect(result.stdout).toContain("NEW_VERSION=v1.1.0");
|
|
});
|
|
});
|