fix(bazel): Bazel-workspace schematics should run in ScopedTree (#28349)
Users should be able to add Bazel workspace to an existing project.
The current approach assumes that the schematics is working on the same
tree as that of ng-new, which includes the top-level directory. Instead,
the schematic should work on the tree rooted at `appRoot` to enable
Bazel files to be added to existing project.
This change uses the newly implemented ScopedTree
a0ac4b0e3d
to achieve this.
NOTE: The version of `@angular-devkit/schematics` that is installed is
used to run the `@angular/bazel` schematic. Even if a different version
is used in the schematic itself, it has no effect.
Therefore, the *latest* Angular CLI should be used to generate the
files. As of this commit, the latest version is @angular/cli@7.3.0-rc.0
PR Close #28349
This commit is contained in:
parent
aed48e00d2
commit
260ac20e92
@ -34,7 +34,7 @@
|
||||
"@angular-devkit/architect": "^0.10.6",
|
||||
"@angular-devkit/build-optimizer": "^0.12.2",
|
||||
"@angular-devkit/core": "^7.0.4",
|
||||
"@angular-devkit/schematics": "^7.0.4",
|
||||
"@angular-devkit/schematics": "^7.3.0-rc.0",
|
||||
"@bazel/karma": "~0.22.1",
|
||||
"@bazel/typescript": "~0.22.1",
|
||||
"@schematics/angular": "^7.0.4",
|
||||
|
@ -14,7 +14,7 @@
|
||||
"dependencies": {
|
||||
"@angular-devkit/architect": "^0.10.6",
|
||||
"@angular-devkit/core": "^7.0.4",
|
||||
"@angular-devkit/schematics": "^7.0.4",
|
||||
"@angular-devkit/schematics": "^7.3.0-rc.0",
|
||||
"@bazel/typescript": "^0.22.1",
|
||||
"@schematics/angular": "^7.0.4",
|
||||
"@types/node": "6.0.84",
|
||||
|
@ -21,21 +21,15 @@ import {Schema as BazelWorkspaceOptions} from './schema';
|
||||
* Look for package.json file for package with `packageName` in node_modules and
|
||||
* extract its version.
|
||||
*/
|
||||
function findVersion(projectName: string, packageName: string, host: Tree): string|null {
|
||||
// Need to look in multiple locations because we could be working in a subtree.
|
||||
const candidates = [
|
||||
`node_modules/${packageName}/package.json`,
|
||||
`${projectName}/node_modules/${packageName}/package.json`,
|
||||
];
|
||||
for (const candidate of candidates) {
|
||||
if (host.exists(candidate)) {
|
||||
try {
|
||||
const packageJson = JSON.parse(host.read(candidate).toString());
|
||||
if (packageJson.name === packageName && packageJson.version) {
|
||||
return packageJson.version;
|
||||
}
|
||||
} catch {
|
||||
function findVersion(packageName: string, host: Tree): string|null {
|
||||
const candidate = `node_modules/${packageName}/package.json`;
|
||||
if (host.exists(candidate)) {
|
||||
try {
|
||||
const packageJson = JSON.parse(host.read(candidate).toString());
|
||||
if (packageJson.name === packageName && packageJson.version) {
|
||||
return packageJson.version;
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -72,23 +66,17 @@ function hasSassStylesheet(host: Tree) {
|
||||
|
||||
export default function(options: BazelWorkspaceOptions): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
if (!options.name) {
|
||||
throw new SchematicsException(`Invalid options, "name" is required.`);
|
||||
const name = options.name || getWorkspace(host).defaultProject;
|
||||
if (!name) {
|
||||
throw new Error('Please provide a name for Bazel workspace');
|
||||
}
|
||||
validateProjectName(options.name);
|
||||
let newProjectRoot = '';
|
||||
try {
|
||||
const workspace = getWorkspace(host);
|
||||
newProjectRoot = workspace.newProjectRoot || '';
|
||||
} catch {
|
||||
}
|
||||
const appDir = `${newProjectRoot}/${options.name}`;
|
||||
validateProjectName(name);
|
||||
|
||||
// If the project already has some deps installed, Bazel should use existing
|
||||
// versions.
|
||||
const existingVersions = {
|
||||
Angular: findVersion(options.name, '@angular/core', host),
|
||||
RxJs: findVersion(options.name, 'rxjs', host),
|
||||
Angular: findVersion('@angular/core', host),
|
||||
RxJs: findVersion('rxjs', host),
|
||||
};
|
||||
|
||||
Object.keys(existingVersions).forEach((name: 'Angular' | 'RxJs') => {
|
||||
@ -110,12 +98,11 @@ export default function(options: BazelWorkspaceOptions): Rule {
|
||||
return mergeWith(apply(url('./files'), [
|
||||
applyTemplates({
|
||||
utils: strings,
|
||||
...options,
|
||||
name,
|
||||
'dot': '.', ...workspaceVersions,
|
||||
routing: hasRoutingModule(host),
|
||||
sass: hasSassStylesheet(host),
|
||||
}),
|
||||
move(appDir),
|
||||
]));
|
||||
};
|
||||
}
|
||||
|
@ -21,24 +21,24 @@ describe('Bazel-workspace Schematic', () => {
|
||||
const options = {...defaultOptions};
|
||||
const host = schematicRunner.runSchematic('bazel-workspace', options);
|
||||
const files = host.files;
|
||||
expect(files).toContain('/demo/.bazelignore');
|
||||
expect(files).toContain('/demo/.bazelrc');
|
||||
expect(files).toContain('/demo/BUILD.bazel');
|
||||
expect(files).toContain('/demo/src/BUILD.bazel');
|
||||
expect(files).toContain('/demo/WORKSPACE');
|
||||
expect(files).toContain('/demo/yarn.lock');
|
||||
expect(files).toContain('/.bazelignore');
|
||||
expect(files).toContain('/.bazelrc');
|
||||
expect(files).toContain('/BUILD.bazel');
|
||||
expect(files).toContain('/src/BUILD.bazel');
|
||||
expect(files).toContain('/WORKSPACE');
|
||||
expect(files).toContain('/yarn.lock');
|
||||
});
|
||||
|
||||
it('should find existing Angular version', () => {
|
||||
let host = new UnitTestTree(new HostTree);
|
||||
host.create('/demo/node_modules/@angular/core/package.json', JSON.stringify({
|
||||
host.create('/node_modules/@angular/core/package.json', JSON.stringify({
|
||||
name: '@angular/core',
|
||||
version: '6.6.6',
|
||||
}));
|
||||
const options = {...defaultOptions};
|
||||
host = schematicRunner.runSchematic('bazel-workspace', options, host);
|
||||
expect(host.files).toContain('/demo/WORKSPACE');
|
||||
const workspace = host.readContent('/demo/WORKSPACE');
|
||||
expect(host.files).toContain('/WORKSPACE');
|
||||
const workspace = host.readContent('/WORKSPACE');
|
||||
expect(workspace).toMatch('ANGULAR_VERSION = "6.6.6"');
|
||||
});
|
||||
|
||||
@ -46,19 +46,19 @@ describe('Bazel-workspace Schematic', () => {
|
||||
const options = {...defaultOptions, name: 'demo-app'};
|
||||
const host = schematicRunner.runSchematic('bazel-workspace', options);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/demo-app/src/BUILD.bazel');
|
||||
const content = host.readContent('/demo-app/src/BUILD.bazel');
|
||||
expect(files).toContain('/src/BUILD.bazel');
|
||||
const content = host.readContent('/src/BUILD.bazel');
|
||||
expect(content).toContain('entry_module = "demo_app/src/main.dev"');
|
||||
});
|
||||
|
||||
it('should add router if project contains routing module', () => {
|
||||
let host = new UnitTestTree(new HostTree);
|
||||
host.create('/demo/src/app/app-routing.module.ts', '');
|
||||
expect(host.files).toContain('/demo/src/app/app-routing.module.ts');
|
||||
host.create('/src/app/app-routing.module.ts', '');
|
||||
expect(host.files).toContain('/src/app/app-routing.module.ts');
|
||||
const options = {...defaultOptions};
|
||||
host = schematicRunner.runSchematic('bazel-workspace', options, host);
|
||||
expect(host.files).toContain('/demo/src/BUILD.bazel');
|
||||
const content = host.readContent('/demo/src/BUILD.bazel');
|
||||
expect(host.files).toContain('/src/BUILD.bazel');
|
||||
const content = host.readContent('/src/BUILD.bazel');
|
||||
expect(content).toContain('@angular//packages/router');
|
||||
});
|
||||
|
||||
@ -66,16 +66,16 @@ describe('Bazel-workspace Schematic', () => {
|
||||
it('should contain project name', () => {
|
||||
const options = {...defaultOptions};
|
||||
const host = schematicRunner.runSchematic('bazel-workspace', options);
|
||||
expect(host.files).toContain('/demo/WORKSPACE');
|
||||
const content = host.readContent('/demo/WORKSPACE');
|
||||
expect(host.files).toContain('/WORKSPACE');
|
||||
const content = host.readContent('/WORKSPACE');
|
||||
expect(content).toContain('workspace(name = "demo")');
|
||||
});
|
||||
|
||||
it('should convert dashes in name to underscore', () => {
|
||||
const options = {...defaultOptions, name: 'demo-project'};
|
||||
const host = schematicRunner.runSchematic('bazel-workspace', options);
|
||||
expect(host.files).toContain('/demo-project/WORKSPACE');
|
||||
const content = host.readContent('/demo-project/WORKSPACE');
|
||||
expect(host.files).toContain('/WORKSPACE');
|
||||
const content = host.readContent('/WORKSPACE');
|
||||
expect(content).toContain('workspace(name = "demo_project"');
|
||||
});
|
||||
});
|
||||
@ -83,35 +83,35 @@ describe('Bazel-workspace Schematic', () => {
|
||||
describe('SASS', () => {
|
||||
let host = new UnitTestTree(new HostTree);
|
||||
beforeAll(() => {
|
||||
host.create('/demo/src/app/app.component.scss', '');
|
||||
expect(host.files).toContain('/demo/src/app/app.component.scss');
|
||||
host.create('/src/app/app.component.scss', '');
|
||||
expect(host.files).toContain('/src/app/app.component.scss');
|
||||
const options = {...defaultOptions};
|
||||
host = schematicRunner.runSchematic('bazel-workspace', options, host);
|
||||
expect(host.files).toContain('/demo/WORKSPACE');
|
||||
expect(host.files).toContain('/demo/src/BUILD.bazel');
|
||||
expect(host.files).toContain('/WORKSPACE');
|
||||
expect(host.files).toContain('/src/BUILD.bazel');
|
||||
});
|
||||
|
||||
it('should download rules_sass in WORKSPACE', () => {
|
||||
const content = host.readContent('/demo/WORKSPACE');
|
||||
const content = host.readContent('/WORKSPACE');
|
||||
expect(content).toContain('RULES_SASS_VERSION');
|
||||
expect(content).toContain('io_bazel_rules_sass');
|
||||
});
|
||||
|
||||
it('should load sass_repositories in WORKSPACE', () => {
|
||||
const content = host.readContent('/demo/WORKSPACE');
|
||||
const content = host.readContent('/WORKSPACE');
|
||||
expect(content).toContain(
|
||||
'load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")');
|
||||
expect(content).toContain('sass_repositories()');
|
||||
});
|
||||
|
||||
it('should add sass_binary rules in src/BUILD', () => {
|
||||
const content = host.readContent('/demo/src/BUILD.bazel');
|
||||
const content = host.readContent('/src/BUILD.bazel');
|
||||
expect(content).toContain('load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")');
|
||||
expect(content).toMatch(/sass_binary\((.*\n)+\)/);
|
||||
});
|
||||
|
||||
it('should add SASS targets to assets of ng_module in src/BUILD', () => {
|
||||
const content = host.readContent('/demo/src/BUILD.bazel');
|
||||
const content = host.readContent('/src/BUILD.bazel');
|
||||
expect(content).toContain(`
|
||||
assets = glob([
|
||||
"**/*.css",
|
||||
|
@ -9,5 +9,5 @@ export interface Schema {
|
||||
/**
|
||||
* The name of the project.
|
||||
*/
|
||||
name: string;
|
||||
name?: string;
|
||||
}
|
||||
|
@ -15,6 +15,5 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name"
|
||||
]
|
||||
}
|
||||
|
@ -208,7 +208,9 @@ export default function(options: Schema): Rule {
|
||||
}),
|
||||
addDevDependenciesToPackageJson(options),
|
||||
addDevAndProdMainForAot(options),
|
||||
schematic('bazel-workspace', options),
|
||||
schematic('bazel-workspace', options, {
|
||||
scope: options.name,
|
||||
}),
|
||||
overwriteGitignore(options),
|
||||
updateWorkspaceFileToUseBazelBuilder(options),
|
||||
]);
|
||||
|
@ -32,7 +32,18 @@
|
||||
rxjs "6.3.3"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/schematics@7.1.2", "@angular-devkit/schematics@^7.0.4":
|
||||
"@angular-devkit/core@7.3.0-rc.0":
|
||||
version "7.3.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.3.0-rc.0.tgz#e555a08d85259855ff1946f4268936a1aadd38f1"
|
||||
integrity sha512-0vHuw1gIMh79tI+gRxCMn89U1DnjmBnqybVktaf9YXi9xshxd+nnFb31v7n1tJQVQiQNzGxk3hviFnkzxLZipw==
|
||||
dependencies:
|
||||
ajv "6.7.0"
|
||||
chokidar "2.0.4"
|
||||
fast-json-stable-stringify "2.0.0"
|
||||
rxjs "6.3.3"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/schematics@7.1.2":
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.1.2.tgz#847639044417d044bf1bc87f64508a0c3f99fae2"
|
||||
integrity sha512-NFhHLYWf9gpGQm0s19lq+nAw3CZ0udBpoBLzCm8Crlmu6+7aAXgw7Fv5P4ukWJ/e1m7NDGVids+B6kBGXaY6Ig==
|
||||
@ -40,6 +51,14 @@
|
||||
"@angular-devkit/core" "7.1.2"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@angular-devkit/schematics@^7.3.0-rc.0":
|
||||
version "7.3.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.3.0-rc.0.tgz#9f1e1f6942da36b12c81241398ed6ca8b2e65875"
|
||||
integrity sha512-noqcQIOvah2G126DTFKY5Kiga8UwI9cKzyhQdNlf+8hAZpnWwTURItQ5xuMJg/XfRQLUSg9gWS2h1cI9AD7mxQ==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "7.3.0-rc.0"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@bazel/typescript@^0.22.1":
|
||||
version "0.22.1"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/typescript/-/typescript-0.22.1.tgz#b52c00e8560019e2f9d273d45c04785e0ec9d9bd"
|
||||
@ -79,6 +98,16 @@ ajv@6.5.3:
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ajv@6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.7.0.tgz#e3ce7bb372d6577bb1839f1dfdfcbf5ad2948d96"
|
||||
integrity sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==
|
||||
dependencies:
|
||||
fast-deep-equal "^2.0.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-regex@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||
|
@ -61,7 +61,7 @@
|
||||
rxjs "6.3.3"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/schematics@7.0.5", "@angular-devkit/schematics@^7.0.4":
|
||||
"@angular-devkit/schematics@7.0.5":
|
||||
version "7.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.0.5.tgz#527bf0af5352172e92c5473a33bc07af44c77796"
|
||||
integrity sha512-mWtPfBtObXXw5IWnMuOXBLn/Bv2lPxdmSqrCX9chTmxLXlFuv5e6HkzJfuF4BxjRUMaA+OW1qhnsHRJSI+p6sQ==
|
||||
@ -69,7 +69,7 @@
|
||||
"@angular-devkit/core" "7.0.5"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@angular-devkit/schematics@7.3.0-rc.0":
|
||||
"@angular-devkit/schematics@7.3.0-rc.0", "@angular-devkit/schematics@^7.3.0-rc.0":
|
||||
version "7.3.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.3.0-rc.0.tgz#9f1e1f6942da36b12c81241398ed6ca8b2e65875"
|
||||
integrity sha512-noqcQIOvah2G126DTFKY5Kiga8UwI9cKzyhQdNlf+8hAZpnWwTURItQ5xuMJg/XfRQLUSg9gWS2h1cI9AD7mxQ==
|
||||
|
Loading…
x
Reference in New Issue
Block a user