Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion bin/publish-tagged.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import { join } from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";
import {
classifyView,
npmEnv,
parseTags,
publishArgs,
readWorkspaces,
registry,
selectPackages,
topoSort,
viewVersions,
Expand Down Expand Up @@ -121,6 +123,25 @@ describe("classifyView", () => {
});
});

describe("npmEnv", () => {
it("strips npm_config_* keys regardless of case", () => {
const cleaned = npmEnv({
npm_config_registry: "https://registry.yarnpkg.com",
NPM_CONFIG_REGISTRY: "https://registry.yarnpkg.com",
npm_config_user_agent: "yarn/1.22.0 npm/? node/v20",
PATH: "/usr/bin",
HOME: "/home/gnidan",
GITHUB_ACTIONS: "true",
});
expect(cleaned).not.toHaveProperty("npm_config_registry");
expect(cleaned).not.toHaveProperty("NPM_CONFIG_REGISTRY");
expect(cleaned).not.toHaveProperty("npm_config_user_agent");
expect(cleaned.PATH).toBe("/usr/bin");
expect(cleaned.HOME).toBe("/home/gnidan");
expect(cleaned.GITHUB_ACTIONS).toBe("true");
});
});

describe("viewVersions", () => {
it("prefixes the package name on a probe failure", () => {
const result: SpawnSyncReturns<string> = {
Expand All @@ -136,6 +157,35 @@ describe("viewVersions", () => {
/@ethdebug\/format/,
);
});

it("targets registry.npmjs.org and strips yarn's registry env", () => {
const originalRegistry = process.env.npm_config_registry;
process.env.npm_config_registry = "https://registry.yarnpkg.com";
try {
const result: SpawnSyncReturns<string> = {
pid: 1,
output: [null, "", ""],
stdout: '["0.1.0-1"]',
stderr: "",
status: 0,
signal: null,
};
vi.mocked(spawnSync).mockReturnValue(result);
viewVersions("@ethdebug/format", "0.1.0-1");
const [command, args, options] = vi.mocked(spawnSync).mock.calls[0];
expect(command).toBe("npm");
expect(args).toContain("--registry");
expect(args).toContain(registry);
const passedEnv = (options as { env?: NodeJS.ProcessEnv }).env ?? {};
expect(passedEnv).not.toHaveProperty("npm_config_registry");
} finally {
if (originalRegistry === undefined) {
delete process.env.npm_config_registry;
} else {
process.env.npm_config_registry = originalRegistry;
}
}
});
});

describe("readWorkspaces", () => {
Expand Down Expand Up @@ -196,13 +246,15 @@ describe("readWorkspaces", () => {
});

describe("publishArgs", () => {
it("tags a publish as latest", () => {
it("tags a publish as latest, on registry.npmjs.org", () => {
expect(publishArgs(false, {})).toEqual([
"publish",
"--access",
"public",
"--tag",
"latest",
"--registry",
registry,
]);
});

Expand All @@ -213,6 +265,8 @@ describe("publishArgs", () => {
"public",
"--tag",
"latest",
"--registry",
registry,
"--dry-run",
]);
});
Expand All @@ -224,11 +278,20 @@ describe("publishArgs", () => {
"public",
"--tag",
"latest",
"--registry",
registry,
"--provenance",
]);
});

it("omits --provenance outside GitHub Actions", () => {
expect(publishArgs(false, {})).not.toContain("--provenance");
});

it("always includes --registry pointing at registry.npmjs.org", () => {
expect(publishArgs(false, {})).toContain(registry);
expect(publishArgs(true, {})).toContain(registry);
expect(publishArgs(false, { GITHUB_ACTIONS: "true" })).toContain(registry);
expect(publishArgs(true, { GITHUB_ACTIONS: "true" })).toContain(registry);
});
});
34 changes: 30 additions & 4 deletions bin/publish-tagged.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
import { fileURLToPath, pathToFileURL } from "node:url";
import { checkPackList, packList } from "./packlist.js";

export const registry = "https://registry.npmjs.org";

export function npmEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
const clean: NodeJS.ProcessEnv = {};
for (const [key, value] of Object.entries(env)) {
if (!key.toLowerCase().startsWith("npm_config_")) {
clean[key] = value;
}
}
return clean;
}

export interface Workspace {
name: string;
version: string;
Expand Down Expand Up @@ -65,7 +77,7 @@
for (const tag of tags) {
const workspace = workspaces.find((w) => w.name === tag.name);
if (!workspace) {
console.warn(`${tag.name}: no such workspace, ignoring`);

Check warning on line 80 in bin/publish-tagged.ts

View workflow job for this annotation

GitHub Actions / lint-and-format

Unexpected console statement
continue;
}
if (workspace.private) {
Expand Down Expand Up @@ -135,9 +147,14 @@
}

export function viewVersions(name: string, version: string): ViewResult {
const result = spawnSync("npm", ["view", name, "versions", "--json"], {
encoding: "utf8",
});
const result = spawnSync(
"npm",
["view", name, "versions", "--json", "--registry", registry],
{
encoding: "utf8",
env: npmEnv(process.env),
},
);
try {
return classifyView(result.status ?? 1, result.stdout, version);
} catch (error) {
Expand All @@ -147,7 +164,15 @@
}

export function publishArgs(dryRun: boolean, env: NodeJS.ProcessEnv): string[] {
const args = ["publish", "--access", "public", "--tag", "latest"];
const args = [
"publish",
"--access",
"public",
"--tag",
"latest",
"--registry",
registry,
];
if (env.GITHUB_ACTIONS) {
args.push("--provenance");
}
Expand All @@ -162,6 +187,7 @@
const result = spawnSync("npm", args, {
cwd: workspace.dir,
stdio: "inherit",
env: npmEnv(process.env),
});
if (result.status !== 0) {
throw new Error(`npm publish failed for ${workspace.name}`);
Expand All @@ -177,7 +203,7 @@
}).split("\n");
const tags = parseTags(tagLines);
if (tags.length === 0) {
console.log("no @ethdebug package tags at HEAD; nothing to publish");

Check warning on line 206 in bin/publish-tagged.ts

View workflow job for this annotation

GitHub Actions / lint-and-format

Unexpected console statement
return 0;
}
const selected = topoSort(selectPackages(tags, readWorkspaces(root)));
Expand All @@ -189,7 +215,7 @@
const label = `${workspace.name}@${workspace.version}`;
failed = label;
if (viewVersions(workspace.name, workspace.version) === "published") {
console.log(`${label}: already published, skipping`);

Check warning on line 218 in bin/publish-tagged.ts

View workflow job for this annotation

GitHub Actions / lint-and-format

Unexpected console statement
skipped.push(label);
failed = undefined;
continue;
Expand All @@ -200,7 +226,7 @@
`${label}: disallowed files in tarball:\n ${bad.join("\n ")}`,
);
}
console.log(`${label}: publishing${dryRun ? " (dry run)" : ""}`);

Check warning on line 229 in bin/publish-tagged.ts

View workflow job for this annotation

GitHub Actions / lint-and-format

Unexpected console statement
publish(workspace, dryRun);
published.push(label);
failed = undefined;
Expand Down
Loading