Skip to content

Add support for npm publish --dry-run #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 23, 2020
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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ You can set any or all of the following input parameters:
|`registry` |string |no |https://registry.npmjs.org/ |The NPM registry URL to use
|`package` |string |no |./package.json |The path of your package.json file
|`check-version` |boolean |no |true |Only publish to NPM if the version number in `package.json` differs from the latest on NPM
|`dry-run` |boolean |no |false |Run NPM publish with the `--dry-run` flag to prevent publication.



Expand Down Expand Up @@ -194,6 +195,8 @@ options:

--help, -h Show help

--dry-run Pass the `--dry-run` flag to NPM

package_path The absolute or relative path of the NPM package to publish.
Can be a directory path, or the path of a package.json file.
Defaults to the current directory.
Expand Down
5 changes: 5 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ inputs:
required: false
default: "true"

dry-run:
description: If true, run with the --dry-run flag
required: false
default: "false"

outputs:
type:
description: The type of version change that occurred ("none", "major", "minor", "patch", etc.)
Expand Down
6 changes: 5 additions & 1 deletion src/action/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,19 @@ async function main(): Promise<void> {
registry: getInput("registry", { required: true }),
package: getInput("package", { required: true }),
checkVersion: getInput("check-version", { required: true }).toLowerCase() === "true",
dryRun: getInput("dry-run").toLowerCase() === "true",
debug: debugHandler,
};

// Puglish to NPM
// Publish to NPM
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for fixing my typos. 🤦‍♂️

let results = await npmPublish(options);

if (results.type === "none") {
console.log(`\n📦 ${results.package} v${results.version} is already published to NPM`);
}
else if (results.dryRun) {
console.log(`\n📦 ${results.package} v${results.version} successfully built but not published to NPM`);
}
else {
console.log(`\n📦 Successfully published ${results.package} v${results.version} to NPM`);
}
Expand Down
3 changes: 3 additions & 0 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ export async function main(args: string[]): Promise<void> {
if (results.type === "none") {
console.log(`\n📦 ${results.package} v${results.version} is already published to NPM`);
}
else if (results.dryRun) {
console.log(`\n📦 ${results.package} v${results.version} successfully built but not published to NPM`);
}
else {
console.log(`\n📦 Successfully published ${results.package} v${results.version} to NPM`);
}
Expand Down
2 changes: 2 additions & 0 deletions src/cli/parse-args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export function parseArgs(argv: string[]): ParsedArgs {
{ name: "quiet", alias: "q", type: Boolean },
{ name: "version", alias: "v", type: Boolean },
{ name: "help", alias: "h", type: Boolean },
{ name: "dry-run", type: Boolean, defaultOption: false }
],
{ argv }
);
Expand All @@ -49,6 +50,7 @@ export function parseArgs(argv: string[]): ParsedArgs {
package: args.package as string,
debug: args.debug ? console.debug : undefined,
quiet: args.quiet as boolean,
dryRun: args["dry-run"] as boolean
}
};

Expand Down
2 changes: 2 additions & 0 deletions src/normalize-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface NormalizedOptions {
registry: URL;
package: string;
checkVersion: boolean;
dryRun: boolean;
quiet: boolean;
debug: Debug;
}
Expand All @@ -26,6 +27,7 @@ export function normalizeOptions(options: Options): NormalizedOptions {
registry: registryURL || new URL("https://registry.npmjs.org/"),
package: options.package || "package.json",
checkVersion: options.checkVersion === undefined ? true : Boolean(options.checkVersion),
dryRun: options.dryRun || false,
quiet: options.quiet || false,
debug: options.debug || (() => undefined),
};
Expand Down
1 change: 1 addition & 0 deletions src/npm-publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export async function npmPublish(opts: Options = {}): Promise<Results> {
type: diff || "none",
version: manifest.version.raw,
oldVersion: publishedVersion.raw,
dryRun: options.dryRun
};

options.debug("OUTPUT:", results);
Expand Down
6 changes: 4 additions & 2 deletions src/npm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const npm = {

options.debug(`Running command: npm view ${name} version`);

// Run NPM to get the latest published versiono of the package
// Run NPM to get the latest published version of the package
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for fixing my typos. 🤦‍♂️

let { stdout } = await ezSpawn.async("npm", ["view", name, "version"], { env });
let version = stdout.trim();

Expand Down Expand Up @@ -60,8 +60,10 @@ export const npm = {

options.debug("Running command: npm publish", { stdio, cwd, env });

let command = options.dryRun ? ["publish", "--dry-run"] : ["publish"];

// Run NPM to publish the package
await ezSpawn.async("npm", ["publish"], { cwd, stdio, env });
await ezSpawn.async("npm", command, { cwd, stdio, env });
}
catch (error) {
throw ono(error, `Unable to publish ${name} v${version} to NPM.`);
Expand Down
9 changes: 9 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ export interface Options {
*/
checkVersion?: boolean;

/**
* If true, run npm publish with the --dry-run flag
* so that the package is not published. Used for
* testing workflows.
*
* Defaults to `false`
*/
dryRun?: boolean;

/**
* Suppress console output from NPM and npm-publish.
*
Expand Down
7 changes: 6 additions & 1 deletion src/results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ReleaseType } from "semver";
export { ReleaseType };

/**
* Results of the `publish
* Results of the publish
*/
export interface Results {
/**
Expand All @@ -25,4 +25,9 @@ export interface Results {
* The version number that was previously published to NPM
*/
oldVersion: string;

/**
* Whether this was a dry run (not published to NPM)
*/
dryRun: boolean;
}
45 changes: 45 additions & 0 deletions test/specs/action/success.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,4 +265,49 @@ describe("GitHub Action - success tests", () => {
npm.assert.ran(4);
});

it("should not publish a package if dryRun is true", () => {
files.create([
{ path: "workspace/package.json", contents: { name: "my-lib", version: "1.1.0" }},
{ path: "home/.npmrc", contents: "This is my NPM config.\nThere are many like it,\nbut this one is mine." },
]);

npm.mock({
args: ["config", "get", "userconfig"],
stdout: `${paths.npmrc}${EOL}`,
});

npm.mock({
args: ["view", "my-lib", "version"],
stdout: `1.0.0${EOL}`,
});

npm.mock({
args: ["config", "get", "userconfig"],
stdout: `${paths.npmrc}${EOL}`,
});

npm.mock({
args: ["publish", "--dry-run"],
env: { INPUT_TOKEN: "my-secret-token" },
stdout: `my-lib 1.1.0${EOL}`,
});

let cli = exec.action({
env: {
INPUT_TOKEN: "my-secret-token",
"INPUT_DRY-RUN": "true"
}
});

expect(cli).to.have.stderr("");
expect(cli).stdout.to.include("::set-output name=type::minor");
expect(cli).stdout.to.include("::set-output name=version::1.1.0");
expect(cli).stdout.to.include("::set-output name=old-version::1.0.0");
expect(cli).stdout.to.include("my-lib 1.1.0");
expect(cli).stdout.to.include("📦 my-lib v1.1.0 successfully built but not published to NPM");
expect(cli).to.have.exitCode(0);

npm.assert.ran(4);
});

});
8 changes: 8 additions & 0 deletions test/specs/cli/args.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,12 @@ describe("CLI - argument tests", () => {
npm.assert.ran(0);
});
});


describe("npm-publish --dry-run", () => {
it("should call npm publish with the --dry-run flag", () => {
let cli = exec.cli("--dry-run");
expect(cli.args).to.include("--dry-run");
});
});
});
34 changes: 34 additions & 0 deletions test/specs/cli/success.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,4 +266,38 @@ describe("CLI - success tests", () => {
npm.assert.ran(4);
});

it("should not publish the package if publish is called with --dry-run", () => {
files.create([
{ path: "workspace/package.json", contents: { name: "my-lib", version: "1.1.0" }},
]);

npm.mock({
args: ["config", "get", "userconfig"],
stdout: `${paths.npmrc}${EOL}`,
});

npm.mock({
args: ["view", "my-lib", "version"],
stdout: `1.0.0${EOL}`,
});

npm.mock({
args: ["config", "get", "userconfig"],
stdout: `${paths.npmrc}${EOL}`,
});

npm.mock({
args: ["publish", "--dry-run"],
stdout: `my-lib 1.1.0${EOL}`,
});

let cli = exec.cli("--dry-run");

expect(cli).to.have.stderr("");
expect(cli).stdout.to.include("my-lib 1.1.0");
expect(cli).stdout.to.include("📦 my-lib v1.1.0 successfully built but not published to NPM");
expect(cli).to.have.exitCode(0);

npm.assert.ran(4);
});
});
65 changes: 59 additions & 6 deletions test/specs/lib/success.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ describe("NPM package - success tests", () => {
type: "major",
package: "my-lib",
version: "2.0.0",
oldVersion: "1.0.0"
oldVersion: "1.0.0",
dryRun: false
});

files.assert.contents("home/.npmrc",
Expand Down Expand Up @@ -83,7 +84,8 @@ describe("NPM package - success tests", () => {
type: "none",
package: "my-lib",
version: "1.0.0",
oldVersion: "1.0.0"
oldVersion: "1.0.0",
dryRun: false
});

files.assert.contents("home/.npmrc",
Expand Down Expand Up @@ -129,7 +131,8 @@ describe("NPM package - success tests", () => {
type: "prerelease",
package: "my-lib",
version: "1.0.0-beta.1",
oldVersion: "1.0.0"
oldVersion: "1.0.0",
dryRun: false
});

files.assert.contents("home/.npmrc",
Expand Down Expand Up @@ -172,7 +175,8 @@ describe("NPM package - success tests", () => {
type: "minor",
package: "my-lib",
version: "1.1.0",
oldVersion: "1.0.0"
oldVersion: "1.0.0",
dryRun: false
});

files.assert.contents("home/.npmrc",
Expand Down Expand Up @@ -231,7 +235,8 @@ describe("NPM package - success tests", () => {
type: "patch",
package: "my-lib",
version: "1.0.1",
oldVersion: "1.0.0"
oldVersion: "1.0.0",
dryRun: false
});

files.assert.contents("home/.npmrc",
Expand Down Expand Up @@ -284,7 +289,55 @@ describe("NPM package - success tests", () => {
type: "prerelease",
package: "my-lib",
version: "1.0.0-beta",
oldVersion: "1.0.0"
oldVersion: "1.0.0",
dryRun: false
});

files.assert.contents("home/.npmrc",
`//registry.npmjs.org/:_authToken=\${INPUT_TOKEN}${EOL}` +
`registry=https://registry.npmjs.org/${EOL}`
);

npm.assert.ran(4);
});

it("results.dryRun should be true when called with --dry-run", async () => {
files.create([
{ path: "workspace/package.json", contents: { name: "my-lib", version: "1.1.0" }},
]);

npm.mock({
args: ["config", "get", "userconfig"],
stdout: `${paths.npmrc}${EOL}`,
});

npm.mock({
args: ["view", "my-lib", "version"],
stdout: `1.0.0${EOL}`,
});

npm.mock({
args: ["config", "get", "userconfig"],
stdout: `${paths.npmrc}${EOL}`,
});

npm.mock({
args: ["publish", "--dry-run"],
stdout: `my-lib 1.1.0${EOL}`,
});

let results = await npmPublish({
quiet: true,
package: "package.json",
dryRun: true
});

expect(results).to.deep.equal({
type: "minor",
package: "my-lib",
version: "1.1.0",
oldVersion: "1.0.0",
dryRun: true
});

files.assert.contents("home/.npmrc",
Expand Down