Skip to content

Commit

Permalink
feat(dry-run): always print publish results in dry run
Browse files Browse the repository at this point in the history
  • Loading branch information
mcous committed Mar 22, 2024
1 parent 126874f commit c339148
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 49 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/ci-cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,21 @@ jobs:
echo "::error::Expected release type to be 'patch', got '${{ steps.action-publish.outputs.type }}'"
exit 1
- id: action-publish-dry
name: Publish a dry run
uses: ./
with:
registry: http://localhost:4873
package: ${{ steps.setup.outputs.package }}/package.json
token: ${{ steps.setup.outputs.token }}
dry-run: true

- name: Check release output
if: ${{ steps.action-publish-dry.outputs.type }}
run: |
echo "::error::Expected release type to be '', got '${{ steps.action-publish-dry.outputs.type }}'"
exit 1
deploy:
if: ${{ github.ref == 'refs/heads/main' }}
name: Publish
Expand Down
30 changes: 19 additions & 11 deletions dist/main.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions dist/main.js.map

Large diffs are not rendered by default.

27 changes: 22 additions & 5 deletions src/__tests__/format-publish-result.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ import { describe, it, expect } from "vitest";
import * as subject from "../format-publish-result.js";
import type { PackageManifest } from "../read-manifest.js";
import type { NormalizedOptions } from "../normalize-options.js";
import type { PublishResult } from "../compare-and-publish/index.js";
import type {
PublishResult,
PublishFile,
} from "../compare-and-publish/index.js";

describe("formatPublishResult", () => {
it("should say if a publish was skipped", () => {
const result = subject.formatPublishResult(
{ name: "cool-package", version: "1.2.3" } as PackageManifest,
{} as NormalizedOptions,
{ id: undefined } as PublishResult
{ dryRun: { value: false } } as NormalizedOptions,
{ id: undefined, files: [] as PublishFile[] } as PublishResult
);

expect(result).toMatch(/cool-package@1\.2\.3.+skipped/);
expect(result).toMatch(/cool-package@1\.2\.3.+already published/);
});

it("should say if a publish was a dry run", () => {
Expand All @@ -26,7 +29,21 @@ describe("formatPublishResult", () => {
} as PublishResult
);

expect(result).toMatch(/cool-package@1\.2\.3.+DRY RUN/);
expect(result).toMatch(/DRY RUN/);
});

it("should say if a dry run would have skipped", () => {
const result = subject.formatPublishResult(
{ name: "cool-package", version: "1.2.3" } as PackageManifest,
{ dryRun: { value: true } } as NormalizedOptions,
{
id: undefined,
files: [{ path: "cool-file-1", size: 1 }],
type: undefined,
} as PublishResult
);

expect(result).toMatch(/cool-package@1\.2\.3.+already published/);
});

it("should print files", () => {
Expand Down
80 changes: 65 additions & 15 deletions src/compare-and-publish/__tests__/compare-and-publish.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,31 @@ vi.mock("../compare-versions");
vi.mock("../get-arguments");

describe("compareAndPublish", () => {
const manifest = {
packageSpec: ".",
name: "fizzbuzz",
version: "1.2.3",
} as PackageManifest;

const logger = { debug: (message: string) => void message } as Logger;
const normalizedOptions = {
token: "abc123",
ignoreScripts: { value: false },
logger,
} as NormalizedOptions;
const environment: NpmCliEnvironment = { foo: "bar" };
const npmViewResult = { versions: ["0.0.1"], "dist-tags": {} };
const npmPublishResult = { id: "fizzbuzz@1.2.3", files: [] };
const npmPublishResult = {
id: "fizzbuzz@1.2.3",
files: [{ path: "package.json", size: 42 }],
};

let manifest: PackageManifest;
let normalizedOptions: NormalizedOptions;

beforeEach(() => {
manifest = {
packageSpec: ".",
name: "fizzbuzz",
version: "1.2.3",
} as PackageManifest;

normalizedOptions = {
token: "abc123",
ignoreScripts: { value: false },
dryRun: { value: false },
logger,
} as NormalizedOptions;

when(getViewArguments)
.calledWith("fizzbuzz", normalizedOptions)
.thenReturn(["fizzbuzz"]);
Expand Down Expand Up @@ -83,7 +91,24 @@ describe("compareAndPublish", () => {

expect(result).toEqual({
id: "fizzbuzz@1.2.3",
files: [],
files: [{ path: "package.json", size: 42 }],
oldVersion: "0.0.1",
type: "major",
});
});

it("should get versions, compare, and publish in dry run", async () => {
normalizedOptions.dryRun.value = true;

const result = await subject.compareAndPublish(
manifest,
normalizedOptions,
environment
);

expect(result).toEqual({
id: "fizzbuzz@1.2.3",
files: [{ path: "package.json", size: 42 }],
oldVersion: "0.0.1",
type: "major",
});
Expand Down Expand Up @@ -118,6 +143,31 @@ describe("compareAndPublish", () => {
);
});

it("should run publish if version exists but dry run", async () => {
normalizedOptions.dryRun.value = true;

when(compareVersions)
.calledWith(
"1.2.3",
{ versions: ["0.0.1"], "dist-tags": {} },
normalizedOptions
)
.thenReturn({ type: undefined, oldVersion: "0.0.1" });

const result = await subject.compareAndPublish(
manifest,
normalizedOptions,
environment
);

expect(result).toEqual({
id: undefined,
files: [{ path: "package.json", size: 42 }],
oldVersion: "0.0.1",
type: undefined,
});
});

it("should handle an E404 from npm view", async () => {
when(callNpmCli<"view">)
.calledWith("view", ["fizzbuzz"], {
Expand Down Expand Up @@ -146,7 +196,7 @@ describe("compareAndPublish", () => {

expect(result).toEqual({
id: "fizzbuzz@1.2.3",
files: [],
files: [{ path: "package.json", size: 42 }],
oldVersion: "0.0.1",
type: "major",
});
Expand Down Expand Up @@ -260,7 +310,7 @@ describe("compareAndPublish", () => {

expect(result).toEqual({
id: "fizzbuzz@1.2.3",
files: [],
files: [{ path: "package.json", size: 42 }],
oldVersion: "0.0.1",
type: "major",
});
Expand Down
10 changes: 6 additions & 4 deletions src/compare-and-publish/compare-and-publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,12 @@ export async function compareAndPublish(
throw viewCall.error;
}

const isDryRun = options.dryRun.value;
const comparison = compareVersions(version, viewCall.successData, options);
const publishCall = comparison.type
? await callNpmCli(PUBLISH, publishArguments, cliOptions)
: { successData: undefined, errorCode: undefined, error: undefined };
const publishCall =
comparison.type ?? isDryRun
? await callNpmCli(PUBLISH, publishArguments, cliOptions)
: { successData: undefined, errorCode: undefined, error: undefined };

if (publishCall.error && publishCall.errorCode !== EPUBLISHCONFLICT) {
throw publishCall.error;
Expand All @@ -71,7 +73,7 @@ export async function compareAndPublish(
const { successData: publishData } = publishCall;

return {
id: publishData?.id,
id: isDryRun && !comparison.type ? undefined : publishData?.id,
files: publishData?.files ?? [],
type: publishData ? comparison.type : undefined,
oldVersion: comparison.oldVersion,
Expand Down
5 changes: 1 addition & 4 deletions src/compare-and-publish/compare-versions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@ import semverValid from "semver/functions/valid.js";

import { STRATEGY_ALL } from "../options.js";
import type { NormalizedOptions } from "../normalize-options.js";
import type { ReleaseType } from "../results.js";
import { INITIAL, DIFFERENT, type ReleaseType } from "../results.js";
import type { NpmViewData } from "../npm/index.js";

export interface VersionComparison {
type: ReleaseType | undefined;
oldVersion: string | undefined;
}

const INITIAL = "initial";
const DIFFERENT = "different";

/**
* Compare previously published versions with the package's current version.
*
Expand Down
31 changes: 24 additions & 7 deletions src/format-publish-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import type { PublishResult } from "./compare-and-publish/index.js";
import type { PackageManifest } from "./read-manifest.js";
import type { NormalizedOptions } from "./normalize-options.js";

const DRY_RUN_BANNER =
"=== DRY RUN === DRY RUN === DRY RUN === DRY RUN === DRY RUN ===";

const CONTENTS_BANNER = "=== Contents ===";

/**
* Format publish results into a string.
*
Expand All @@ -17,15 +22,27 @@ export function formatPublishResult(
options: NormalizedOptions,
result: PublishResult
): string {
if (result.id === undefined) {
return `πŸ™…β€β™€οΈ ${manifest.name}@${manifest.version} publish skipped.`;
const lines = [];

lines.push(
result.id === undefined
? `πŸ™…β€β™€οΈ ${manifest.name}@${manifest.version} already published.`
: `πŸ“¦ ${result.id}`
);

if (result.files.length > 0) {
lines.push("", CONTENTS_BANNER);
}

for (const { path, size } of result.files) {
lines.push(`${formatSize(size)}\t${path}`);
}

return [
`πŸ“¦ ${result.id}${options.dryRun.value ? " (DRY RUN)" : ""}`,
"=== Contents ===",
...result.files.map(({ path, size }) => `${formatSize(size)}\t${path}`),
].join(os.EOL);
return (
options.dryRun.value
? [DRY_RUN_BANNER, "", ...lines, "", DRY_RUN_BANNER]
: lines
).join(os.EOL);
}

const formatSize = (size: number): string => {
Expand Down
1 change: 1 addition & 0 deletions src/results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { ReleaseType as SemverReleaseType } from "semver";

/** Release type */
export type ReleaseType = SemverReleaseType | typeof INITIAL | typeof DIFFERENT;

export const INITIAL = "initial";
export const DIFFERENT = "different";

Expand Down

0 comments on commit c339148

Please sign in to comment.