UNPKG

nx

Version:

The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.

186 lines (185 loc) • 9.15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.releasePublishCLIHandler = void 0; exports.createAPI = createAPI; const nx_json_1 = require("../../config/nx-json"); const file_map_utils_1 = require("../../project-graph/file-map-utils"); const project_graph_1 = require("../../project-graph/project-graph"); const run_command_1 = require("../../tasks-runner/run-command"); const command_line_utils_1 = require("../../utils/command-line-utils"); const handle_errors_1 = require("../../utils/handle-errors"); const output_1 = require("../../utils/output"); const project_graph_utils_1 = require("../../utils/project-graph-utils"); const graph_1 = require("../graph/graph"); const config_1 = require("./config/config"); const deep_merge_json_1 = require("./config/deep-merge-json"); const filter_release_groups_1 = require("./config/filter-release-groups"); const print_config_1 = require("./utils/print-config"); const workspace_root_1 = require("../../utils/workspace-root"); const tasks_execution_hooks_1 = require("../../project-graph/plugins/tasks-execution-hooks"); const releasePublishCLIHandler = (args) => (0, handle_errors_1.handleErrors)(args.verbose, async () => { const publishProjectsResult = await createAPI({})(args); // If all projects are published successfully, return 0, otherwise return 1 return Object.values(publishProjectsResult).every((result) => result.code === 0) ? 0 : 1; }); exports.releasePublishCLIHandler = releasePublishCLIHandler; function createAPI(overrideReleaseConfig) { /** * NOTE: This function is also exported for programmatic usage and forms part of the public API * of Nx. We intentionally do not wrap the implementation with handleErrors because users need * to have control over their own error handling when using the API. */ return async function releasePublish(args) { /** * When used via the CLI, the args object will contain a __overrides_unparsed__ property that is * important for invoking the relevant executor behind the scenes. * * We intentionally do not include that in the function signature, however, so as not to cause * confusing errors for programmatic consumers of this function. */ const _args = args; const projectGraph = await (0, project_graph_1.createProjectGraphAsync)({ exitOnError: true }); const nxJson = (0, nx_json_1.readNxJson)(); const userProvidedReleaseConfig = (0, deep_merge_json_1.deepMergeJson)(nxJson.release ?? {}, overrideReleaseConfig ?? {}); // Apply default configuration to any optional user configuration const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), userProvidedReleaseConfig); if (configError) { return await (0, config_1.handleNxReleaseConfigError)(configError); } // --print-config exits directly as it is not designed to be combined with any other programmatic operations if (args.printConfig) { return (0, print_config_1.printConfigAndExit)({ userProvidedReleaseConfig, nxReleaseConfig, isDebug: args.printConfig === 'debug', }); } const { error: filterError, filterLog, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, _args.projects, _args.groups); if (filterError) { output_1.output.error(filterError); process.exit(1); } if (filterLog && process.env.NX_RELEASE_INTERNAL_SUPPRESS_FILTER_LOG !== 'true') { output_1.output.note(filterLog); } /** * If the user is filtering to a subset of projects or groups, we should not run the publish task * for dependencies, because that could cause projects outset of the filtered set to be published. */ const shouldExcludeTaskDependencies = _args.projects?.length > 0 || _args.groups?.length > 0 || args.excludeTaskDependencies; let overallPublishProjectsResult = {}; if (args.projects?.length) { /** * Run publishing for all remaining release groups and filtered projects within them */ for (const releaseGroup of releaseGroups) { const publishProjectsResult = await runPublishOnProjects(_args, projectGraph, nxJson, Array.from(releaseGroupToFilteredProjects.get(releaseGroup)), { excludeTaskDependencies: shouldExcludeTaskDependencies, loadDotEnvFiles: process.env.NX_LOAD_DOT_ENV_FILES !== 'false', }); overallPublishProjectsResult = { ...overallPublishProjectsResult, ...publishProjectsResult, }; } return overallPublishProjectsResult; } /** * Run publishing for all remaining release groups */ for (const releaseGroup of releaseGroups) { const publishProjectsResult = await runPublishOnProjects(_args, projectGraph, nxJson, releaseGroup.projects, { excludeTaskDependencies: shouldExcludeTaskDependencies, loadDotEnvFiles: process.env.NX_LOAD_DOT_ENV_FILES !== 'false', }); overallPublishProjectsResult = { ...overallPublishProjectsResult, ...publishProjectsResult, }; } return overallPublishProjectsResult; }; } async function runPublishOnProjects(args, projectGraph, nxJson, projectNames, extraOptions) { const projectsToRun = projectNames.map((projectName) => projectGraph.nodes[projectName]); const overrides = (0, command_line_utils_1.createOverrides)(args.__overrides_unparsed__); if (args.registry) { overrides.registry = args.registry; } if (args.tag) { overrides.tag = args.tag; } if (args.otp) { overrides.otp = args.otp; } if (args.access) { overrides.access = args.access; } if (args.dryRun) { overrides.dryRun = args.dryRun; /** * Ensure the env var is set too, so that any and all publish executors triggered * indirectly via dependsOn can also pick up on the fact that this is a dry run. */ process.env.NX_DRY_RUN = 'true'; } if (args.firstRelease) { overrides.firstRelease = args.firstRelease; } const requiredTargetName = 'nx-release-publish'; if (args.graph) { const file = (0, command_line_utils_1.readGraphFileFromGraphArg)(args); const projectNamesWithTarget = projectsToRun .map((t) => t.name) .filter((projectName) => (0, project_graph_utils_1.projectHasTarget)(projectGraph.nodes[projectName], requiredTargetName)); await (0, graph_1.generateGraph)({ watch: true, all: false, open: true, view: 'tasks', targets: [requiredTargetName], projects: projectNamesWithTarget, file, }, projectNamesWithTarget); return {}; } const projectsWithTarget = projectsToRun.filter((project) => (0, project_graph_utils_1.projectHasTarget)(project, requiredTargetName)); if (projectsWithTarget.length === 0) { throw new Error(`Based on your config, the following projects were matched for publishing but do not have the "${requiredTargetName}" target specified:\n${[ ...projectsToRun.map((p) => `- ${p.name}`), '', `This is usually caused by not having an appropriate plugin, such as "@nx/js" installed, which will add the appropriate "${requiredTargetName}" target for you automatically.`, ].join('\n')}\n`); } await (0, tasks_execution_hooks_1.runPreTasksExecution)({ workspaceRoot: workspace_root_1.workspaceRoot, nxJsonConfiguration: nxJson, }); /** * Run the relevant nx-release-publish executor on each of the selected projects. */ const commandResults = await (0, run_command_1.runCommandForTasks)(projectsWithTarget, projectGraph, { nxJson }, { targets: [requiredTargetName], outputStyle: 'static', ...args, // It is possible for workspaces to have circular dependencies between packages and still release them to a registry nxIgnoreCycles: true, }, overrides, null, {}, extraOptions); const publishProjectsResult = {}; for (const taskData of Object.values(commandResults)) { publishProjectsResult[taskData.task.target.project] = { code: taskData.code, }; } await (0, tasks_execution_hooks_1.runPostTasksExecution)({ taskResults: commandResults, workspaceRoot: workspace_root_1.workspaceRoot, nxJsonConfiguration: nxJson, }); return publishProjectsResult; }