fix(nx): validate target and configuration in @nrwl/tao/run and provide better errors
This commit is contained in:
parent
fa675f1194
commit
58353a6be8
@ -1,16 +1,16 @@
|
|||||||
import { packagesWeCareAbout } from '@nrwl/workspace/src/command-line/report';
|
import { packagesWeCareAbout } from '@nrwl/workspace/src/command-line/report';
|
||||||
import { ensureProject, forEachCli, runCLI } from './utils';
|
import { ensureProject, forEachCli, runCommand } from './utils';
|
||||||
|
|
||||||
const testTimeout = 120000;
|
const testTimeout = 120000;
|
||||||
|
|
||||||
forEachCli('nx', () => {
|
forEachCli(() => {
|
||||||
describe('report', () => {
|
describe('report', () => {
|
||||||
it(
|
it(
|
||||||
`should report package versions`,
|
`should report package versions`,
|
||||||
async () => {
|
async () => {
|
||||||
ensureProject();
|
ensureProject();
|
||||||
|
|
||||||
const reportOutput = runCLI('report');
|
const reportOutput = runCommand('npm run nx report');
|
||||||
|
|
||||||
packagesWeCareAbout.forEach(p => {
|
packagesWeCareAbout.forEach(p => {
|
||||||
expect(reportOutput).toContain(p);
|
expect(reportOutput).toContain(p);
|
||||||
@ -20,15 +20,3 @@ forEachCli('nx', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
forEachCli('angular', () => {
|
|
||||||
describe('report', () => {
|
|
||||||
it(
|
|
||||||
`shouldn't do anything at all`,
|
|
||||||
async () => {
|
|
||||||
// report is an Nx only command
|
|
||||||
},
|
|
||||||
testTimeout
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@ -49,12 +49,18 @@ export async function invokeCommand(
|
|||||||
case 'help':
|
case 'help':
|
||||||
case '--help':
|
case '--help':
|
||||||
return (await import('./src/commands/help')).help();
|
return (await import('./src/commands/help')).help();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
const projectName = commandArgs[0] ? commandArgs[0] : '';
|
const projectNameIncluded =
|
||||||
|
commandArgs[0] && !commandArgs[0].startsWith('-');
|
||||||
|
const projectName = projectNameIncluded ? commandArgs[0] : '';
|
||||||
// this is to make `tao test mylib` same as `tao run mylib:test`
|
// this is to make `tao test mylib` same as `tao run mylib:test`
|
||||||
return (await import('./src/commands/run')).run(
|
return (await import('./src/commands/run')).run(
|
||||||
root,
|
root,
|
||||||
[`${projectName}:${command}`, ...commandArgs.slice(1)],
|
[
|
||||||
|
`${projectName}:${command}`,
|
||||||
|
...(projectNameIncluded ? commandArgs.slice(1) : commandArgs)
|
||||||
|
],
|
||||||
isVerbose
|
isVerbose
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,8 @@ import {
|
|||||||
json,
|
json,
|
||||||
logging,
|
logging,
|
||||||
normalize,
|
normalize,
|
||||||
schema
|
schema,
|
||||||
|
terminal
|
||||||
} from '@angular-devkit/core';
|
} from '@angular-devkit/core';
|
||||||
import { NodeJsSyncHost } from '@angular-devkit/core/node';
|
import { NodeJsSyncHost } from '@angular-devkit/core/node';
|
||||||
import { getLogger } from '../shared/logger';
|
import { getLogger } from '../shared/logger';
|
||||||
@ -34,7 +35,8 @@ function throwInvalidInvocation() {
|
|||||||
|
|
||||||
function parseRunOpts(
|
function parseRunOpts(
|
||||||
args: string[],
|
args: string[],
|
||||||
defaultProjectName: string | null
|
defaultProjectName: string | null,
|
||||||
|
logger: logging.Logger
|
||||||
): RunOptions {
|
): RunOptions {
|
||||||
const runOptions = convertToCamelCase(
|
const runOptions = convertToCamelCase(
|
||||||
minimist(args, {
|
minimist(args, {
|
||||||
@ -47,7 +49,14 @@ function parseRunOpts(
|
|||||||
throwInvalidInvocation();
|
throwInvalidInvocation();
|
||||||
}
|
}
|
||||||
let [project, target, configuration] = runOptions._[0].split(':');
|
let [project, target, configuration] = runOptions._[0].split(':');
|
||||||
if (!project && defaultProjectName) project = defaultProjectName;
|
if (!project && defaultProjectName) {
|
||||||
|
logger.debug(
|
||||||
|
`No project name specified. Using default project : ${terminal.bold(
|
||||||
|
defaultProjectName
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
project = defaultProjectName;
|
||||||
|
}
|
||||||
if (!project || !target) {
|
if (!project || !target) {
|
||||||
throwInvalidInvocation();
|
throwInvalidInvocation();
|
||||||
}
|
}
|
||||||
@ -82,6 +91,45 @@ function printRunHelp(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function validateTargetAndConfiguration(
|
||||||
|
workspace: experimental.workspace.Workspace,
|
||||||
|
opts: RunOptions
|
||||||
|
) {
|
||||||
|
const targets = workspace.getProjectTargets(opts.project);
|
||||||
|
|
||||||
|
const target = targets[opts.target];
|
||||||
|
if (!target) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not find target "${opts.target}" in the ${
|
||||||
|
opts.project
|
||||||
|
} project. Valid targets are: ${terminal.bold(
|
||||||
|
Object.keys(targets).join(', ')
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not all targets have configurations
|
||||||
|
// and an undefined configuration is valid
|
||||||
|
if (opts.configuration) {
|
||||||
|
if (target.configurations) {
|
||||||
|
const configuration = target.configurations[opts.configuration];
|
||||||
|
if (!configuration) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not find configuration "${opts.configuration}" in ${
|
||||||
|
opts.project
|
||||||
|
}:${opts.target}. Valid configurations are: ${Object.keys(
|
||||||
|
target.configurations
|
||||||
|
).join(', ')}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
`No configurations are defined for ${opts.project}:${opts.target}, so "${opts.configuration}" is invalid.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function run(root: string, args: string[], isVerbose: boolean) {
|
export async function run(root: string, args: string[], isVerbose: boolean) {
|
||||||
const logger = getLogger(isVerbose);
|
const logger = getLogger(isVerbose);
|
||||||
|
|
||||||
@ -93,7 +141,9 @@ export async function run(root: string, args: string[], isVerbose: boolean) {
|
|||||||
)
|
)
|
||||||
.loadWorkspaceFromHost('workspace.json' as any)
|
.loadWorkspaceFromHost('workspace.json' as any)
|
||||||
.toPromise();
|
.toPromise();
|
||||||
const opts = parseRunOpts(args, workspace.getDefaultProjectName());
|
|
||||||
|
const opts = parseRunOpts(args, workspace.getDefaultProjectName(), logger);
|
||||||
|
validateTargetAndConfiguration(workspace, opts);
|
||||||
|
|
||||||
const registry = new json.schema.CoreSchemaRegistry();
|
const registry = new json.schema.CoreSchemaRegistry();
|
||||||
registry.addPostTransform(schema.transforms.addUndefinedDefaults);
|
registry.addPostTransform(schema.transforms.addUndefinedDefaults);
|
||||||
@ -111,23 +161,24 @@ export async function run(root: string, args: string[], isVerbose: boolean) {
|
|||||||
const flattenedSchema = await registry
|
const flattenedSchema = await registry
|
||||||
.flatten(builderDesc.optionSchema! as json.JsonObject)
|
.flatten(builderDesc.optionSchema! as json.JsonObject)
|
||||||
.toPromise();
|
.toPromise();
|
||||||
|
|
||||||
if (opts.help) {
|
if (opts.help) {
|
||||||
printRunHelp(opts, flattenedSchema as any, logger);
|
printRunHelp(opts, flattenedSchema as any, logger);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
|
||||||
const runOptions = coerceTypes(opts.runOptions, flattenedSchema as any);
|
|
||||||
const run = await architect.scheduleTarget(
|
|
||||||
{
|
|
||||||
project: opts.project,
|
|
||||||
target: opts.target,
|
|
||||||
configuration: opts.configuration
|
|
||||||
},
|
|
||||||
runOptions,
|
|
||||||
{ logger }
|
|
||||||
);
|
|
||||||
const result = await run.output.toPromise();
|
|
||||||
await run.stop();
|
|
||||||
return result.success ? 0 : 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const runOptions = coerceTypes(opts.runOptions, flattenedSchema as any);
|
||||||
|
const run = await architect.scheduleTarget(
|
||||||
|
{
|
||||||
|
project: opts.project,
|
||||||
|
target: opts.target,
|
||||||
|
configuration: opts.configuration
|
||||||
|
},
|
||||||
|
runOptions,
|
||||||
|
{ logger }
|
||||||
|
);
|
||||||
|
const result = await run.output.toPromise();
|
||||||
|
await run.stop();
|
||||||
|
return result.success ? 0 : 1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user