Skip to content

Support multiple configurations in commands and target strings #15819

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

Merged
merged 2 commits into from
Oct 14, 2019
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
9 changes: 7 additions & 2 deletions packages/angular/cli/models/architect-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,10 +366,15 @@ export abstract class ArchitectCommand<
} else {
project = commandOptions.project;
target = this.target;
configuration = commandOptions.configuration;
if (!configuration && commandOptions.prod) {
if (commandOptions.prod) {
// The --prod flag will always be the first configuration, available to be overwritten
// by following configurations.
configuration = 'production';
}
if (commandOptions.configuration) {
configuration =
`${configuration ? `${configuration},` : ''}${commandOptions.configuration}`;
}
}

if (!project) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,26 @@ export class WorkspaceNodeModulesArchitectHost implements ArchitectHost<NodeModu
if (targetSpec === undefined) {
return null;
}
if (
target.configuration
&& !(targetSpec['configurations'] && targetSpec['configurations'][target.configuration])
) {
throw new Error(`Configuration '${target.configuration}' is not set in the workspace.`);

let additionalOptions = {};

if (target.configuration) {
const configurations = target.configuration.split(',').map(c => c.trim());
for (const configuration of configurations) {
if (!(targetSpec['configurations'] && targetSpec['configurations'][configuration])) {
throw new Error(`Configuration '${configuration}' is not set in the workspace.`);
} else {
additionalOptions = {
...additionalOptions,
...targetSpec['configurations'][configuration],
};
}
}
}

return {
...targetSpec['options'],
...(target.configuration ? targetSpec['configurations'][target.configuration] : 0),
...additionalOptions,
};
}

Expand Down
71 changes: 71 additions & 0 deletions tests/legacy-cli/e2e/tests/build/multiple-configs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { expectFileToExist } from '../../utils/fs';
import { ng } from '../../utils/process';
import { updateJsonFile } from '../../utils/project';
import { expectToFail } from '../../utils/utils';

export default async function () {
await updateJsonFile('angular.json', workspaceJson => {
const appArchitect = workspaceJson.projects['test-project'].architect;
// These are the default options, that we'll overwrite in subsequent configs.
// extractCss defaults to false
// sourceMap defaults to true
appArchitect['options'] = {
outputPath: 'dist/latest-project',
index: 'src/index.html',
main: 'src/main.ts',
polyfills: 'src/polyfills.ts',
tsConfig: 'tsconfig.app.json',
assets: [
'src/favicon.ico',
'src/assets',
],
'styles': [
'src/styles.css',
],
'scripts': [],
};
const browserConfigs = appArchitect['build'].configurations;
browserConfigs['production'] = {
extractCss: true,
};
browserConfigs['one'] = {
assets: [],
};
browserConfigs['two'] = {
sourceMap: false,
};
browserConfigs['three'] = {
extractCss: false, // Defaults to false when not set.
};
});

// Test the base configuration.
await ng('build');
await expectFileToExist('dist/test-project/favicon.ico');
await expectFileToExist('dist/test-project/main-es2015.js.map');
await expectFileToExist('dist/test-project/styles-es2015.js');
await expectFileToExist('dist/test-project/vendor-es2015.js');
// Test that --prod extracts css.
await ng('build', '--prod');
await expectFileToExist('dist/test-project/styles.css');
// But using a config overrides prod.
await ng('build', '--prod', '--configuration=three');
await expectFileToExist('dist/test-project/styles-es2015.js');
await expectToFail(() => expectFileToExist('dist/test-project/styles.css'));
// Use two configurations.
await ng('build', '--configuration=one,two', '--vendor-chunk=false');
await expectToFail(() => expectFileToExist('dist/test-project/favicon.ico'));
await expectToFail(() => expectFileToExist('dist/test-project/main-es2015.js.map'));
// Use two configurations and two overrides, one of which overrides a config.
await ng('build', '--configuration=one,two', '--vendor-chunk=false', '--sourceMap=true');
await expectToFail(() => expectFileToExist('dist/test-project/favicon.ico'));
await expectFileToExist('dist/test-project/main-es2015.js.map');
await expectToFail(() => expectFileToExist('dist/test-project/vendor-es2015.js'));
// Use three configurations and a override, and prod at the end.
await ng('build', '--configuration=one,two,three', '--vendor-chunk=false', '--prod');
await expectToFail(() => expectFileToExist('dist/test-project/favicon.ico'));
await expectToFail(() => expectFileToExist('dist/test-project/main-es2015.js.map'));
await expectToFail(() => expectFileToExist('dist/test-project/vendor-es2015.js'));
await expectFileToExist('dist/test-project/styles-es2015.js');
await expectToFail(() => expectFileToExist('dist/test-project/styles.css'));
}