Skip to content
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

feat(dry-run): always print publish results in dry run mode #185

Merged
merged 1 commit into from
Mar 22, 2024
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
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: "[email protected]", files: [] };
const npmPublishResult = {
id: "[email protected]",
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: "[email protected]",
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: "[email protected]",
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: "[email protected]",
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: "[email protected]",
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