Skip to content

Commit 7060d90

Browse files
kyliaukara
authored andcommittedMar 7, 2019
feat(bazel): Hide Bazel files in Bazel builder (#29110)
This commit modifies the Bazel builder to copy the Bazel WORKSPACE and BUILD.bazel files to the project root directory before invoking Bazel. This hides the Bazel files from users. PR Close #29110
1 parent 14ce8a9 commit 7060d90

File tree

12 files changed

+553
-96
lines changed

12 files changed

+553
-96
lines changed
 

‎integration/bazel-schematics/yarn.lock

+32-41
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,29 @@
1010
"@angular-devkit/core" "7.3.2"
1111
rxjs "6.3.3"
1212

13-
"@angular-devkit/architect@^0.10.6":
14-
version "0.10.7"
15-
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.10.7.tgz#c74b9f6b7f1b4261ada2d24c832328aa4c394464"
16-
integrity sha512-S49LSslNRxIflHzrIrEgK7mGQ7HzETr/FU0fyTbB0vubcmfzMoYTsgYdK7SUz583lovc+UvASoUAhPJI3e35ng==
13+
"@angular-devkit/architect@^0.13.4":
14+
version "0.13.4"
15+
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.13.4.tgz#f5db62f028e3c0971db5719be9c17a78fd8a67a2"
16+
integrity sha512-wJF8oz8MurtpFi0ik42bkI2F5gEnuOe79KHPO1i3SYfdhEp5NY8igVKZ6chB/eq4Ml50aHxas8Hh9ke12K+Pxw==
1717
dependencies:
18-
"@angular-devkit/core" "7.0.7"
18+
"@angular-devkit/core" "7.3.4"
1919
rxjs "6.3.3"
2020

21-
"@angular-devkit/core@7.0.7":
22-
version "7.0.7"
23-
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.0.7.tgz#665176ad8421adfd5f3ea0b2c4a9a432a158b1bb"
24-
integrity sha512-M8tTT9r3nUtWI3YyiyynHIQn+lQQgeKkxVZ+rdxvyvgE3U9+wn0yep5HkFLQETTuJetu9ARRRD94sD2XL3F/3A==
21+
"@angular-devkit/core@7.3.2", "@angular-devkit/core@^7.0.4":
22+
version "7.3.2"
23+
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.3.2.tgz#67ac2cfcbe47f1e457929c19ab1b04c9e061b2e2"
24+
integrity sha512-W5KjkHRNVBcZRUNJamAn52IAj9Gl1zUjPA2r75JJK7k199xOA8UZqcIukQOgM1N7rwKCWht08i4FsdcTDghMhQ==
2525
dependencies:
26-
ajv "6.5.3"
26+
ajv "6.9.1"
2727
chokidar "2.0.4"
2828
fast-json-stable-stringify "2.0.0"
2929
rxjs "6.3.3"
3030
source-map "0.7.3"
3131

32-
"@angular-devkit/core@7.3.2", "@angular-devkit/core@^7.0.4":
33-
version "7.3.2"
34-
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.3.2.tgz#67ac2cfcbe47f1e457929c19ab1b04c9e061b2e2"
35-
integrity sha512-W5KjkHRNVBcZRUNJamAn52IAj9Gl1zUjPA2r75JJK7k199xOA8UZqcIukQOgM1N7rwKCWht08i4FsdcTDghMhQ==
32+
"@angular-devkit/core@7.3.4":
33+
version "7.3.4"
34+
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.3.4.tgz#fae0521652c7430237025f117531ca3262ef8335"
35+
integrity sha512-MBfen51iOBKfK4tlg5KwmPxePsF1QoFNUMGLuvUUwPkteonrGcupX1Q7NWTpf+HA+i08mOnZGuepeuQkD12IQw==
3636
dependencies:
3737
ajv "6.9.1"
3838
chokidar "2.0.4"
@@ -51,11 +51,11 @@
5151
"@angular/bazel@file:../../dist/packages-dist/bazel":
5252
version "8.0.0-beta.6"
5353
dependencies:
54-
"@angular-devkit/architect" "^0.10.6"
54+
"@angular-devkit/architect" "^0.13.4"
5555
"@angular-devkit/core" "^7.0.4"
5656
"@angular-devkit/schematics" "^7.3.0-rc.0"
5757
"@bazel/typescript" "^0.26.0"
58-
"@microsoft/api-extractor" "^7.0.17"
58+
"@microsoft/api-extractor" "^7.0.21"
5959
"@schematics/angular" "^7.0.4"
6060
"@types/node" "6.0.84"
6161
semver "^5.6.0"
@@ -112,26 +112,27 @@
112112
source-map-support "0.5.9"
113113
tsutils "2.27.2"
114114

115-
"@microsoft/api-extractor@^7.0.17":
116-
version "7.0.18"
117-
resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.0.18.tgz#4eb931436495177dfcef8f2d8da3d084d10eebb6"
118-
integrity sha512-puQisjyoYK1A0I8DqyBoLPV9noyFUlxTE3WsjhgJw//TrmegGHYmsRlD3rnHeXcKPM1F7sd/VKJXeXC3IPTf2Q==
115+
"@microsoft/api-extractor@^7.0.21":
116+
version "7.0.22"
117+
resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.0.22.tgz#9c6eb0500168811ed14194de413ddd310622533a"
118+
integrity sha512-1mNMbmUeqtjNmS9hgrONio2uRZL2eeZk39zCKq04ReImFXnMR+fnMTQG98B+SAkFFGJuOucwke5U0bgWnrG6kw==
119119
dependencies:
120-
"@microsoft/node-core-library" "3.10.0"
120+
"@microsoft/node-core-library" "3.12.0"
121121
"@microsoft/ts-command-line" "4.2.3"
122-
"@microsoft/tsdoc" "0.12.5"
122+
"@microsoft/tsdoc" "0.12.7"
123123
"@types/node" "8.5.8"
124124
"@types/z-schema" "3.16.31"
125125
colors "~1.2.1"
126126
lodash "~4.17.5"
127127
resolve "1.8.1"
128+
source-map "~0.6.1"
128129
typescript "~3.1.6"
129130
z-schema "~3.18.3"
130131

131-
"@microsoft/node-core-library@3.10.0":
132-
version "3.10.0"
133-
resolved "https://registry.yarnpkg.com/@microsoft/node-core-library/-/node-core-library-3.10.0.tgz#70e089534d8e20f6a0f9c7a4a12a6aeafd6a1ddb"
134-
integrity sha512-1SbU+XNYAabhV9noGXHtsUVPc5ELV+oEuJQtZQoCncbOd6WAMeTgB1xFwh96hmdEXyKQyML/pnByiKocmh/nbQ==
132+
"@microsoft/node-core-library@3.12.0":
133+
version "3.12.0"
134+
resolved "https://registry.yarnpkg.com/@microsoft/node-core-library/-/node-core-library-3.12.0.tgz#f9c27b8bb6b55d60b91d4e1962f42b03b9f8f47f"
135+
integrity sha512-9T2dEXmmxZqnqcpHuIB8mTAOM/DNSi/QcAwKYDjvZvkd+PGT5lCUXjM9GL7SaR2NPa3UrWDGgFhNoqLqLfEPbw==
135136
dependencies:
136137
"@types/fs-extra" "5.0.4"
137138
"@types/jju" "~1.4.0"
@@ -152,10 +153,10 @@
152153
argparse "~1.0.9"
153154
colors "~1.2.1"
154155

155-
"@microsoft/tsdoc@0.12.5":
156-
version "0.12.5"
157-
resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.12.5.tgz#c448a38902ccb5601c1b2ef3b1a105012ef7712c"
158-
integrity sha512-xEAyvLXo4Cter/b0EMCWUZTgXOfLOPJ/Xr52WdjVclPx9eDmNTGFtZl8Pn/nqSnZsQBNcHL0eHk/YyRyyXXpiQ==
156+
"@microsoft/tsdoc@0.12.7":
157+
version "0.12.7"
158+
resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.12.7.tgz#8fb4a9f4fdf01f1469c9fc54b0ad2d36ec57c25d"
159+
integrity sha512-0bqNlQT8aR4Iq9xx/OsY579Zeqon9uTZDIuvl+XXu16TPPN2sASeKojwm366jA2MjgXd9iyTWpJM5/P1QJ4Dxg==
159160

160161
"@schematics/angular@7.3.2", "@schematics/angular@^7.0.4":
161162
version "7.3.2"
@@ -249,16 +250,6 @@ agentkeepalive@^3.4.1:
249250
dependencies:
250251
humanize-ms "^1.2.1"
251252

252-
ajv@6.5.3:
253-
version "6.5.3"
254-
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.3.tgz#71a569d189ecf4f4f321224fecb166f071dd90f9"
255-
integrity sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==
256-
dependencies:
257-
fast-deep-equal "^2.0.1"
258-
fast-json-stable-stringify "^2.0.0"
259-
json-schema-traverse "^0.4.1"
260-
uri-js "^4.2.2"
261-
262253
ajv@6.9.1:
263254
version "6.9.1"
264255
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.9.1.tgz#a4d3683d74abc5670e75f0b16520f70a20ea8dc1"
@@ -2154,7 +2145,7 @@ source-map@^0.5.6:
21542145
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
21552146
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
21562147

2157-
source-map@^0.6.0:
2148+
source-map@^0.6.0, source-map@~0.6.1:
21582149
version "0.6.1"
21592150
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
21602151
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==

‎packages/bazel/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
}
1919
},
2020
"dependencies": {
21-
"@angular-devkit/architect": "^0.10.6",
21+
"@angular-devkit/architect": "^0.13.4",
2222
"@angular-devkit/core": "^7.0.4",
2323
"@angular-devkit/schematics": "^7.3.0-rc.0",
2424
"@bazel/typescript": "^0.26.0",
@@ -42,4 +42,4 @@
4242
"ng-update": {
4343
"packageGroup": "NG_UPDATE_PACKAGE_GROUP"
4444
}
45-
}
45+
}

‎packages/bazel/src/builders/BUILD.bazel

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
load("//tools:defaults.bzl", "ts_library")
1+
load("//tools:defaults.bzl", "jasmine_node_test", "ts_library")
22

33
package(default_visibility = ["//visibility:public"])
44

@@ -19,7 +19,7 @@ ts_library(
1919
],
2020
data = [
2121
"schema.json",
22-
],
22+
] + glob(["files/**/*"]),
2323
module_name = "@angular/bazel/src/builders",
2424
deps = [
2525
"@npm//@angular-devkit/architect",
@@ -28,3 +28,24 @@ ts_library(
2828
"@npm//rxjs",
2929
],
3030
)
31+
32+
ts_library(
33+
name = "test_lib",
34+
testonly = True,
35+
srcs = [
36+
"bazel_spec.ts",
37+
],
38+
deps = [
39+
"builders",
40+
"@npm//@angular-devkit/core",
41+
],
42+
)
43+
44+
jasmine_node_test(
45+
name = "test",
46+
bootstrap = ["angular/tools/testing/init_node_spec.js"],
47+
deps = [
48+
":test_lib",
49+
"//tools/testing:node",
50+
],
51+
)

‎packages/bazel/src/builders/bazel.ts

+129-28
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,145 @@
77
*/
88

99
/// <reference types='node'/>
10-
import {spawn, spawnSync} from 'child_process';
11-
import {Observable, Subject} from 'rxjs';
10+
11+
import {Path, basename, dirname, getSystemPath, join} from '@angular-devkit/core';
12+
import {resolve} from '@angular-devkit/core/node';
13+
import {Host} from '@angular-devkit/core/src/virtual-fs/host';
14+
import {spawn} from 'child_process';
1215

1316
export type Executable = 'bazel' | 'ibazel';
1417
export type Command = 'build' | 'test' | 'run' | 'coverage' | 'query';
1518

19+
/**
20+
* Spawn the Bazel process. Trap SINGINT to make sure Bazel process is killed.
21+
*/
1622
export function runBazel(
17-
projectDir: string, executable: Executable, command: Command, workspaceTarget: string,
18-
flags: string[]): Observable<void> {
19-
const doneSubject = new Subject<void>();
20-
const bin = require.resolve(`@bazel/${executable}`);
21-
const buildProcess = spawn(bin, [command, workspaceTarget, ...flags], {
22-
cwd: projectDir,
23-
stdio: 'inherit',
24-
shell: false,
25-
});
23+
projectDir: Path, binary: Path, command: Command, workspaceTarget: string, flags: string[]) {
24+
return new Promise((resolve, reject) => {
25+
const buildProcess = spawn(getSystemPath(binary), [command, workspaceTarget, ...flags], {
26+
cwd: getSystemPath(projectDir),
27+
stdio: 'inherit',
28+
shell: false,
29+
});
2630

27-
buildProcess.once('close', (code: number) => {
28-
if (code === 0) {
29-
doneSubject.next();
30-
} else {
31-
doneSubject.error(`${executable} failed with code ${code}.`);
32-
}
33-
});
31+
process.on('SIGINT', (signal) => {
32+
if (!buildProcess.killed) {
33+
buildProcess.kill();
34+
reject(new Error(`Bazel process received ${signal}.`));
35+
}
36+
});
3437

35-
return doneSubject.asObservable();
38+
buildProcess.once('close', (code: number) => {
39+
if (code === 0) {
40+
resolve();
41+
} else {
42+
reject(new Error(`${basename(binary)} failed with code ${code}.`));
43+
}
44+
});
45+
});
3646
}
3747

38-
export function checkInstallation(executable: Executable, projectDir: string) {
39-
let bin: string;
48+
/**
49+
* Resolves the path to `@bazel/bazel` or `@bazel/ibazel`.
50+
*/
51+
export function checkInstallation(name: Executable, projectDir: Path): string {
52+
const packageName = `@bazel/${name}`;
4053
try {
41-
bin = require.resolve(`@bazel/${executable}`);
42-
} catch {
43-
return false;
54+
return resolve(packageName, {
55+
basedir: projectDir,
56+
});
57+
} catch (error) {
58+
if (error.code === 'MODULE_NOT_FOUND') {
59+
throw new Error(
60+
`Could not run ${name}. Please make sure that the ` +
61+
`"${name}" command is installed by running ` +
62+
`"npm install ${packageName}" or "yarn install ${packageName}".`);
63+
}
64+
throw error;
4465
}
45-
const child = spawnSync(bin, ['version'], {
46-
cwd: projectDir,
47-
shell: false,
66+
}
67+
68+
/**
69+
* Returns the absolute path to the template directory in `@angular/bazel`.
70+
*/
71+
export async function getTemplateDir(host: Host, root: Path): Promise<Path> {
72+
const packageJson = resolve('@angular/bazel', {
73+
basedir: root,
74+
resolvePackageJson: true,
4875
});
49-
return child.status === 0;
76+
const packageDir = dirname(packageJson as Path);
77+
const templateDir = join(packageDir, 'src', 'builders', 'files');
78+
if (!await host.isDirectory(templateDir).toPromise()) {
79+
throw new Error('Could not find Bazel template directory in "@angular/bazel".');
80+
}
81+
return templateDir;
82+
}
83+
84+
/**
85+
* Recursively list the specified 'dir' using depth-first approach. Paths
86+
* returned are relative to 'dir'.
87+
*/
88+
function listR(host: Host, dir: Path): Promise<Path[]> {
89+
async function list(dir: Path, root: Path, results: Path[]) {
90+
const paths = await host.list(dir).toPromise();
91+
for (const path of paths) {
92+
const absPath = join(dir, path);
93+
const relPath = join(root, path);
94+
if (await host.isFile(absPath).toPromise()) {
95+
results.push(relPath);
96+
} else {
97+
await list(absPath, relPath, results);
98+
}
99+
}
100+
return results;
101+
}
102+
103+
return list(dir, '' as Path, []);
104+
}
105+
106+
/**
107+
* Copy the file from 'source' to 'dest'.
108+
*/
109+
async function copyFile(host: Host, source: Path, dest: Path) {
110+
const buffer = await host.read(source).toPromise();
111+
await host.write(dest, buffer).toPromise();
112+
}
113+
114+
/**
115+
* Copy Bazel files (WORKSPACE, BUILD.bazel, etc) from the template directory to
116+
* the project `root` directory, and return the absolute paths of the files
117+
* copied, so that they can be deleted later.
118+
* Existing files in `root` will not be replaced.
119+
*/
120+
export async function copyBazelFiles(host: Host, root: Path, templateDir: Path) {
121+
const bazelFiles: Path[] = [];
122+
const templates = await listR(host, templateDir);
123+
124+
await Promise.all(templates.map(async(template) => {
125+
const name = template.replace('__dot__', '.').replace('.template', '');
126+
const source = join(templateDir, template);
127+
const dest = join(root, name);
128+
try {
129+
const exists = await host.exists(dest).toPromise();
130+
if (!exists) {
131+
await copyFile(host, source, dest);
132+
bazelFiles.push(dest);
133+
}
134+
} catch {
135+
}
136+
}));
137+
138+
return bazelFiles;
139+
}
140+
141+
/**
142+
* Delete the specified 'files' and return a promise that always resolves.
143+
*/
144+
export function deleteBazelFiles(host: Host, files: Path[]) {
145+
return Promise.all(files.map(async(file) => {
146+
try {
147+
await host.delete(file).toPromise();
148+
} catch {
149+
}
150+
}));
50151
}
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {Path} from '@angular-devkit/core';
10+
import {test} from '@angular-devkit/core/src/virtual-fs/host/test';
11+
12+
import {copyBazelFiles, deleteBazelFiles} from './bazel';
13+
14+
describe('Bazel builder', () => {
15+
it('should copy Bazel files', async() => {
16+
const host = new test.TestHost({
17+
'/files/WORKSPACE.template': '',
18+
'/files/BUILD.bazel.template': '',
19+
'/files/__dot__bazelrc.template': '',
20+
'/files/__dot__bazelignore.template': '',
21+
'/files/e2e/BUILD.bazel.template': '',
22+
'/files/src/BUILD.bazel.template': '',
23+
});
24+
const root = '/' as Path;
25+
const templateDir = '/files' as Path;
26+
await copyBazelFiles(host, root, templateDir);
27+
const {records} = host;
28+
expect(records).toContain({kind: 'write', path: '/WORKSPACE' as Path});
29+
expect(records).toContain({kind: 'write', path: '/BUILD.bazel' as Path});
30+
});
31+
32+
it('should delete Bazel files', async() => {
33+
const host = new test.TestHost({
34+
'/WORKSPACE': '',
35+
'/BUILD.bazel': '',
36+
});
37+
await deleteBazelFiles(host, ['/WORKSPACE', '/BUILD.bazel'] as Path[]);
38+
const {records} = host;
39+
expect(records).toContain({kind: 'delete', path: '/WORKSPACE' as Path});
40+
expect(records).toContain({kind: 'delete', path: '/BUILD.bazel' as Path});
41+
});
42+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
# This export allows targets in other packages to reference files that live
4+
# in this package.
5+
exports_files([
6+
"tsconfig.json",
7+
])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# WARNING: This file is generated and it's not meant to be edited.
2+
# Before making any changes, please read Bazel documentation.
3+
# https://docs.bazel.build/versions/master/be/workspace.html
4+
# The WORKSPACE file tells Bazel that this directory is a "workspace", which is like a project root.
5+
# The content of this file specifies all the external dependencies Bazel needs to perform a build.
6+
7+
####################################
8+
# ESModule imports (and TypeScript imports) can be absolute starting with the workspace name.
9+
# The name of the workspace should match the npm package where we publish, so that these
10+
# imports also make sense when referencing the published package.
11+
workspace(name = "project")
12+
13+
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
14+
15+
RULES_NODEJS_VERSION = "0.26.0"
16+
http_archive(
17+
name = "build_bazel_rules_nodejs",
18+
sha256 = "5c86b055c57e15bf32d9009a15bcd6d8e190c41b1ff2fb18037b75e0012e4e7c",
19+
url = "https://github.com/bazelbuild/rules_nodejs/releases/download/%s/rules_nodejs-%s.tar.gz" % (RULES_NODEJS_VERSION, RULES_NODEJS_VERSION),
20+
)
21+
22+
# Rules for compiling sass
23+
RULES_SASS_VERSION = "1.17.2"
24+
http_archive(
25+
name = "io_bazel_rules_sass",
26+
sha256 = "e5316ee8a09d1cbb732d3938b400836bf94dba91a27476e9e27706c4c0edae1f",
27+
url = "https://github.com/bazelbuild/rules_sass/archive/%s.zip" % RULES_SASS_VERSION,
28+
strip_prefix = "rules_sass-%s" % RULES_SASS_VERSION,
29+
)
30+
31+
####################################
32+
# Load and install our dependencies downloaded above.
33+
34+
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories", "yarn_install")
35+
check_bazel_version("0.22.0")
36+
node_repositories()
37+
yarn_install(
38+
name = "npm",
39+
data = ["//:angular-metadata.tsconfig.json"],
40+
package_json = "//:package.json",
41+
yarn_lock = "//:yarn.lock",
42+
)
43+
44+
load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
45+
install_bazel_dependencies()
46+
47+
load("@npm_bazel_karma//:package.bzl", "rules_karma_dependencies")
48+
rules_karma_dependencies()
49+
50+
load("@io_bazel_rules_webtesting//web:repositories.bzl", "web_test_repositories")
51+
web_test_repositories()
52+
53+
load("@npm_bazel_karma//:browser_repositories.bzl", "browser_repositories")
54+
browser_repositories()
55+
56+
load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace")
57+
ts_setup_workspace()
58+
59+
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
60+
sass_repositories()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dist
2+
node_modules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Make TypeScript and Angular compilation fast, by keeping a few copies of the
2+
# compiler running as daemons, and cache SourceFile AST's to reduce parse time.
3+
build --strategy=TypeScriptCompile=worker
4+
build --strategy=AngularTemplateCompile=worker
5+
6+
# Don't create bazel-* symlinks in the WORKSPACE directory, except `bazel-out`,
7+
# which is mandatory.
8+
# These require .gitignore and may scare users.
9+
# Also, it's a workaround for https://github.com/bazelbuild/rules_typescript/issues/12
10+
# which affects the common case of having `tsconfig.json` in the WORKSPACE directory.
11+
#
12+
# Instead, the output will appear in `dist/bin`. You'll need to ignore the
13+
# `bazel-out` directory that is created in the workspace root.
14+
build --symlink_prefix=dist/
15+
16+
# Turn on --incompatible_strict_action_env which was on by default
17+
# in Bazel 0.21.0 but turned off again in 0.22.0. Follow
18+
# https://github.com/bazelbuild/bazel/issues/7026 for more details.
19+
# This flag is needed to so that the bazel cache is not invalidated
20+
# when running bazel via `yarn bazel`.
21+
# See https://github.com/angular/angular/issues/27514.
22+
build --incompatible_strict_action_env
23+
run --incompatible_strict_action_env
24+
test --incompatible_strict_action_env
25+
26+
test --test_output=errors
27+
28+
# Use the Angular 6 compiler
29+
build --define=compile=legacy
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
load("@npm_bazel_typescript//:index.bzl", "ts_library")
2+
load("@npm_angular_bazel//:index.bzl", "protractor_web_test_suite")
3+
4+
ts_library(
5+
name = "e2e_lib",
6+
testonly = 1,
7+
srcs = glob(["src/**/*.ts"]),
8+
tsconfig = ":tsconfig.e2e.json",
9+
deps = [
10+
"@npm//@types/jasmine",
11+
"@npm//@types/jasminewd2",
12+
"@npm//@types/node",
13+
"@npm//jasmine",
14+
"@npm//protractor",
15+
"@npm//tslib",
16+
],
17+
data = [
18+
"//:tsconfig.json",
19+
],
20+
)
21+
22+
protractor_web_test_suite(
23+
name = "prodserver_test",
24+
data = [
25+
"@npm//@angular/bazel",
26+
"@npm//protractor",
27+
],
28+
on_prepare = ":protractor.on-prepare.js",
29+
server = "//src:prodserver",
30+
deps = [":e2e_lib"],
31+
)
32+
33+
protractor_web_test_suite(
34+
name = "devserver_test",
35+
data = [
36+
"@npm//@angular/bazel",
37+
"@npm//protractor",
38+
],
39+
on_prepare = ":protractor.on-prepare.js",
40+
server = "//src:devserver",
41+
deps = [":e2e_lib"],
42+
)
43+
44+
# Default target in this package is to run the e2e tests on the devserver.
45+
# This is a faster round-trip but doesn't exercise production optimizations like
46+
# code-splitting and lazy loading.
47+
alias(
48+
name = "e2e",
49+
actual = "devserver_test",
50+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
load("@npm_angular_bazel//:index.bzl", "ng_module")
4+
load("@npm_bazel_karma//:index.bzl", "ts_web_test_suite")
5+
load("@build_bazel_rules_nodejs//:defs.bzl", "rollup_bundle", "history_server")
6+
load("@build_bazel_rules_nodejs//internal/web_package:web_package.bzl", "web_package")
7+
load("@npm_bazel_typescript//:index.bzl", "ts_devserver", "ts_library")
8+
load("@io_bazel_rules_sass//:defs.bzl", "multi_sass_binary")
9+
10+
multi_sass_binary(
11+
name = "styles",
12+
srcs = glob(["**/*.scss"]),
13+
)
14+
15+
ng_module(
16+
name = "src",
17+
srcs = glob(
18+
include = ["**/*.ts"],
19+
exclude = [
20+
"**/*.spec.ts",
21+
"main.ts",
22+
"test.ts",
23+
"initialize_testbed.ts",
24+
],
25+
),
26+
assets = glob([
27+
"**/*.css",
28+
"**/*.html",
29+
]) + ([":styles"] if len(glob(["**/*.scss"])) else []),
30+
deps = [
31+
"@npm//@angular/core",
32+
"@npm//@angular/platform-browser",
33+
"@npm//@angular/router",
34+
"@npm//@types",
35+
"@npm//rxjs",
36+
],
37+
)
38+
39+
rollup_bundle(
40+
name = "bundle",
41+
entry_point = "src/main.prod",
42+
deps = [
43+
"//src",
44+
"@npm//rxjs",
45+
],
46+
)
47+
48+
web_package(
49+
name = "prodapp",
50+
assets = [
51+
# do not sort
52+
"@npm//node_modules/zone.js:dist/zone.min.js",
53+
":bundle.min.js",
54+
],
55+
data = [
56+
"favicon.ico",
57+
],
58+
index_html = "index.html",
59+
)
60+
61+
history_server(
62+
name = "prodserver",
63+
data = [":prodapp"],
64+
templated_args = ["src/prodapp"],
65+
)
66+
67+
filegroup(
68+
name = "rxjs_umd_modules",
69+
srcs = [
70+
# do not sort
71+
"@npm//node_modules/rxjs:bundles/rxjs.umd.js",
72+
":rxjs_shims.js",
73+
],
74+
)
75+
76+
ts_devserver(
77+
name = "devserver",
78+
port = 4200,
79+
entry_module = "project/src/main.dev",
80+
serving_path = "/bundle.min.js",
81+
scripts = [
82+
"@npm//node_modules/@angular/common:bundles/common.umd.js",
83+
"@npm//node_modules/@angular/common:bundles/common-http.umd.js",
84+
"@npm//node_modules/@angular/core:bundles/core.umd.js",
85+
"@npm//node_modules/@angular/platform-browser:bundles/platform-browser.umd.js",
86+
"@npm//node_modules/tslib:tslib.js",
87+
":rxjs_umd_modules",
88+
],
89+
static_files = [
90+
"@npm//node_modules/zone.js:dist/zone.min.js",
91+
],
92+
data = [
93+
"favicon.ico",
94+
],
95+
index_html = "index.html",
96+
deps = [":src"],
97+
)
98+
99+
ts_library(
100+
name = "test_lib",
101+
testonly = 1,
102+
srcs = glob(["**/*.spec.ts"]),
103+
deps = [
104+
":src",
105+
"@npm//@angular/core",
106+
"@npm//@types",
107+
],
108+
)
109+
110+
ts_library(
111+
name = "initialize_testbed",
112+
testonly = 1,
113+
srcs = [
114+
"initialize_testbed.ts",
115+
],
116+
deps = [
117+
"@npm//@angular/core",
118+
"@npm//@angular/platform-browser-dynamic",
119+
"@npm//@types",
120+
],
121+
)
122+
123+
ts_web_test_suite(
124+
name = "test",
125+
srcs = [
126+
"@npm//node_modules/@angular/common:bundles/common.umd.js",
127+
"@npm//node_modules/@angular/compiler:bundles/compiler.umd.js",
128+
"@npm//node_modules/@angular/compiler:bundles/compiler-testing.umd.js",
129+
"@npm//node_modules/@angular/core:bundles/core.umd.js",
130+
"@npm//node_modules/@angular/core:bundles/core-testing.umd.js",
131+
"@npm//node_modules/@angular/platform-browser:bundles/platform-browser.umd.js",
132+
"@npm//node_modules/@angular/platform-browser:bundles/platform-browser-testing.umd.js",
133+
"@npm//node_modules/@angular/platform-browser-dynamic:bundles/platform-browser-dynamic.umd.js",
134+
"@npm//node_modules/@angular/platform-browser-dynamic:bundles/platform-browser-dynamic-testing.umd.js",
135+
"@npm//node_modules/tslib:tslib.js",
136+
],
137+
runtime_deps = [
138+
":initialize_testbed",
139+
],
140+
# do not sort
141+
bootstrap = [
142+
"@npm//node_modules/zone.js:dist/zone-testing-bundle.js",
143+
"@npm//node_modules/reflect-metadata:Reflect.js",
144+
],
145+
browsers = [
146+
"@io_bazel_rules_webtesting//browsers:chromium-local",
147+
],
148+
deps = [
149+
":rxjs_umd_modules",
150+
":test_lib",
151+
"@npm//karma-jasmine",
152+
],
153+
)

‎packages/bazel/src/builders/index.ts

+24-23
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,35 @@
99
*/
1010

1111
import {BuildEvent, Builder, BuilderConfiguration, BuilderContext} from '@angular-devkit/architect';
12-
import {getSystemPath, resolve} from '@angular-devkit/core';
13-
import {Observable, of } from 'rxjs';
14-
import {catchError, map} from 'rxjs/operators';
15-
16-
import {checkInstallation, runBazel} from './bazel';
12+
import {Path} from '@angular-devkit/core';
13+
import {Observable, from} from 'rxjs';
14+
import {checkInstallation, copyBazelFiles, deleteBazelFiles, getTemplateDir, runBazel} from './bazel';
1715
import {Schema} from './schema';
1816

1917
class BazelBuilder implements Builder<Schema> {
2018
constructor(private context: BuilderContext) {}
2119

22-
run(builderConfig: BuilderConfiguration<Partial<Schema>>): Observable<BuildEvent> {
23-
const projectRoot = getSystemPath(resolve(this.context.workspace.root, builderConfig.root));
24-
const targetLabel = builderConfig.options.targetLabel;
25-
26-
const executable = builderConfig.options.watch ? 'ibazel' : 'bazel';
27-
28-
if (!checkInstallation(executable, projectRoot)) {
29-
throw new Error(
30-
`Could not run ${executable}. Please make sure that the ` +
31-
`"${executable}" command is installed by running ` +
32-
`"npm install" or "yarn install".`);
33-
}
34-
35-
// TODO: Support passing flags.
36-
return runBazel(
37-
projectRoot, executable, builderConfig.options.bazelCommand !, targetLabel !,
38-
[] /* flags */)
39-
.pipe(map(() => ({success: true})), catchError(() => of ({success: false})), );
20+
run(config: BuilderConfiguration<Partial<Schema>>): Observable<BuildEvent> {
21+
const {host, logger, workspace} = this.context;
22+
const root: Path = workspace.root;
23+
const {bazelCommand, targetLabel, watch} = config.options as Schema;
24+
const executable = watch ? 'ibazel' : 'bazel';
25+
const binary = checkInstallation(executable, root) as Path;
26+
27+
return from(Promise.resolve().then(async() => {
28+
const templateDir = await getTemplateDir(host, root);
29+
const bazelFiles = await copyBazelFiles(host, root, templateDir);
30+
try {
31+
const flags: string[] = [];
32+
await runBazel(root, binary, bazelCommand, targetLabel, flags);
33+
return {success: true};
34+
} catch (err) {
35+
logger.error(err.message);
36+
return {success: false};
37+
} finally {
38+
await deleteBazelFiles(host, bazelFiles); // this will never throw
39+
}
40+
}));
4041
}
4142
}
4243

0 commit comments

Comments
 (0)
Please sign in to comment.