Skip to content

Commit

Permalink
fix(core): support dry-run on nx release publish (#19228)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesHenry authored Sep 20, 2023
1 parent 584cb19 commit 6b16230
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 8 deletions.
4 changes: 4 additions & 0 deletions docs/generated/packages/js/executors/release-publish.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
"tag": {
"type": "string",
"description": "The distribution tag to apply to the published package."
},
"dryRun": {
"type": "boolean",
"description": "Whether to run the command without actually publishing the package to the registry."
}
},
"required": [],
Expand Down
113 changes: 109 additions & 4 deletions e2e/release/src/release.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,9 @@ describe('nx release', () => {
).length
).toEqual(1);

// publish to custom registry (not e2e registry), and a custom dist tag of "next"
const publishOutput2 = runCLI(
`release publish --registry=${customRegistryUrl} --tag=next`
);
// Perform an initial dry-run of the publish to the custom registry (not e2e registry), and a custom dist tag of "next"
const publishToNext = `release publish --registry=${customRegistryUrl} --tag=next`;
const publishOutput2 = runCLI(`${publishToNext} --dry-run`);
expect(publishOutput2).toMatchInlineSnapshot(`
> NX Running target nx-release-publish for 3 projects:
Expand All @@ -291,6 +290,111 @@ describe('nx release', () => {
With additional flags:
--registry=${customRegistryUrl}
--tag=next
--dryRun=true
> nx run {project-name}:nx-release-publish
📦 @proj/{project-name}@1000.0.0-next.0
=== Tarball Contents ===
XXB index.js
XXXB package.json
XXB project.json
=== Tarball Details ===
name: @proj/{project-name}
version: 1000.0.0-next.0
filename: proj-{project-name}-1000.0.0-next.0.tgz
package size: XXXB
unpacked size: XXXB
shasum: {SHASUM}
integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
total files: 3
Would publish to ${customRegistryUrl} with tag "next", but [dry-run] was set
> nx run {project-name}:nx-release-publish
📦 @proj/{project-name}@1000.0.0-next.0
=== Tarball Contents ===
XXB index.js
XXXB package.json
XXB project.json
=== Tarball Details ===
name: @proj/{project-name}
version: 1000.0.0-next.0
filename: proj-{project-name}-1000.0.0-next.0.tgz
package size: XXXB
unpacked size: XXXB
shasum: {SHASUM}
integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
total files: 3
Would publish to ${customRegistryUrl} with tag "next", but [dry-run] was set
> nx run {project-name}:nx-release-publish
📦 @proj/{project-name}@1000.0.0-next.0
=== Tarball Contents ===
XXB index.js
XXXB package.json
XXB project.json
=== Tarball Details ===
name: @proj/{project-name}
version: 1000.0.0-next.0
filename: proj-{project-name}-1000.0.0-next.0.tgz
package size: XXXB
unpacked size: XXXB
shasum: {SHASUM}
integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
total files: 3
Would publish to ${customRegistryUrl} with tag "next", but [dry-run] was set
> NX Successfully ran target nx-release-publish for 3 projects
`);

// Versions are still unpublished on the next tag in the custom registry, because it was only a dry-run
expect(() =>
execSync(
`npm view @proj/${pkg1}@next version --registry=${customRegistryUrl}`
)
).toThrowError(/npm ERR! code E404/);
expect(() =>
execSync(
`npm view @proj/${pkg2}@next version --registry=${customRegistryUrl}`
)
).toThrowError(/npm ERR! code E404/);
expect(() =>
execSync(
`npm view @proj/${pkg3}@next version --registry=${customRegistryUrl}`
)
).toThrowError(/npm ERR! code E404/);

// Actually publish to the custom registry (not e2e registry), and a custom dist tag of "next"
const publishOutput3 = runCLI(publishToNext);
expect(publishOutput3).toMatchInlineSnapshot(`
> NX Running target nx-release-publish for 3 projects:
- {project-name}
- {project-name}
- {project-name}
With additional flags:
--registry=${customRegistryUrl}
--tag=next
Expand Down Expand Up @@ -365,6 +469,7 @@ describe('nx release', () => {
`);

// The versions now exist on the next tag in the custom registry
expect(
execSync(
`npm view @proj/${pkg1}@next version --registry=${customRegistryUrl}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { execSync } from 'child_process';
import { env as appendLocalEnv } from 'npm-run-path';
import { logTar } from './log-tar';
import { PublishExecutorSchema } from './schema';
import chalk = require('chalk');

const LARGE_BUFFER = 1024 * 1000000;

Expand Down Expand Up @@ -40,6 +41,10 @@ export default async function runExecutor(
npmPublishCommandSegments.push(`--tag=${options.tag}`);
}

if (options.dryRun) {
npmPublishCommandSegments.push(`--dry-run`);
}

// Resolve values using the `npm config` command so that things like environment variables and `publishConfig`s are accounted for
const registry =
options.registry ?? execSync(`npm config get registry`).toString().trim();
Expand All @@ -59,7 +64,15 @@ export default async function runExecutor(
const normalizedStdoutData = stdoutData[context.projectName!] ?? stdoutData;
logTar(normalizedStdoutData);

console.log(`Published to ${registry} with tag "${tag}"`);
if (options.dryRun) {
console.log(
`Would publish to ${registry} with tag "${tag}", but ${chalk.keyword(
'orange'
)('[dry-run]')} was set`
);
} else {
console.log(`Published to ${registry} with tag "${tag}"`);
}

return {
success: true,
Expand Down
1 change: 1 addition & 0 deletions packages/js/src/executors/release-publish/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export interface PublishExecutorSchema {
packageRoot?: string;
registry?: string;
tag?: string;
dryRun?: boolean;
}
4 changes: 4 additions & 0 deletions packages/js/src/executors/release-publish/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
"tag": {
"type": "string",
"description": "The distribution tag to apply to the published package."
},
"dryRun": {
"type": "boolean",
"description": "Whether to run the command without actually publishing the package to the registry."
}
},
"required": []
Expand Down
16 changes: 13 additions & 3 deletions packages/nx/src/command-line/release/publish.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { readNxJson } from '../../config/nx-json';
import { NxJsonConfiguration, readNxJson } from '../../config/nx-json';
import {
ProjectGraph,
ProjectGraphProjectNode,
} from '../../config/project-graph';
import { NxJsonConfiguration, output } from '../../devkit-exports';
import { createProjectGraphAsync } from '../../project-graph/project-graph';
import { runCommand } from '../../tasks-runner/run-command';
import {
createOverrides,
readGraphFileFromGraphArg,
} from '../../utils/command-line-utils';
import { findMatchingProjects } from '../../utils/find-matching-projects';
import { logger } from '../../utils/logger';
import { output } from '../../utils/output';
import { generateGraph } from '../graph/graph';
import { PublishOptions } from './command-object';
import { createNxReleaseConfig } from './config/config';
import {
Expand All @@ -19,7 +21,6 @@ import {
createReleaseGroups,
handleCreateReleaseGroupsError,
} from './config/create-release-groups';
import { generateGraph } from '../graph/graph';

export async function publishHandler(
args: PublishOptions & { __overrides_unparsed__: string[] }
Expand Down Expand Up @@ -151,6 +152,12 @@ export async function publishHandler(
);
}

if (args.dryRun) {
logger.warn(
`\nNOTE: The "dryRun" flag means no projects were actually published.`
);
}

process.exit(0);
}

Expand All @@ -172,6 +179,9 @@ async function runPublishOnProjects(
if (args.tag) {
overrides.tag = args.tag;
}
if (args.dryRun) {
overrides.dryRun = args.dryRun;
}

if (args.verbose) {
process.env.NX_VERBOSE_LOGGING = 'true';
Expand Down

0 comments on commit 6b16230

Please sign in to comment.