feat(bazel): update the build to use the new architect api (#29720)

With this change the builder has been updated to use the latest architect API and make it compatable with the latest CLI

Fixes https://github.com/angular/angular-cli/issues/14082

PR Close #29720
This commit is contained in:
Alan Agius
2019-04-05 08:39:23 +02:00
committed by Igor Minar
parent e38115536f
commit 902a53a4f6
10 changed files with 124 additions and 160 deletions

View File

@ -8,10 +8,10 @@
/// <reference types='node'/>
import {Path, basename, dirname, getSystemPath, join} from '@angular-devkit/core';
import {resolve} from '@angular-devkit/core/node';
import {Path, dirname, getSystemPath, join, normalize} from '@angular-devkit/core';
import {Host} from '@angular-devkit/core/src/virtual-fs/host';
import {spawn} from 'child_process';
import * as path from 'path';
export type Executable = 'bazel' | 'ibazel';
export type Command = 'build' | 'test' | 'run' | 'coverage' | 'query';
@ -20,9 +20,9 @@ export type Command = 'build' | 'test' | 'run' | 'coverage' | 'query';
* Spawn the Bazel process. Trap SINGINT to make sure Bazel process is killed.
*/
export function runBazel(
projectDir: Path, binary: Path, command: Command, workspaceTarget: string, flags: string[]) {
projectDir: Path, binary: string, command: Command, workspaceTarget: string, flags: string[]) {
return new Promise((resolve, reject) => {
const buildProcess = spawn(getSystemPath(binary), [command, workspaceTarget, ...flags], {
const buildProcess = spawn(process.argv[0], [binary, command, workspaceTarget, ...flags], {
cwd: getSystemPath(projectDir),
stdio: 'inherit',
shell: false,
@ -39,7 +39,7 @@ export function runBazel(
if (code === 0) {
resolve();
} else {
reject(new Error(`${basename(binary)} failed with code ${code}.`));
reject(new Error(`${binary} failed with code ${code}.`));
}
});
});
@ -49,11 +49,13 @@ export function runBazel(
* Resolves the path to `@bazel/bazel` or `@bazel/ibazel`.
*/
export function checkInstallation(name: Executable, projectDir: Path): string {
const packageName = `@bazel/${name}`;
const packageName = `@bazel/${name}/package.json`;
try {
return resolve(packageName, {
basedir: projectDir,
const bazelPath = require.resolve(packageName, {
paths: [getSystemPath(projectDir)],
});
return path.dirname(bazelPath);
} catch (error) {
if (error.code === 'MODULE_NOT_FOUND') {
throw new Error(
@ -69,11 +71,11 @@ export function checkInstallation(name: Executable, projectDir: Path): string {
* Returns the absolute path to the template directory in `@angular/bazel`.
*/
export async function getTemplateDir(host: Host, root: Path): Promise<Path> {
const packageJson = resolve('@angular/bazel', {
basedir: root,
resolvePackageJson: true,
const packageJson = require.resolve('@angular/bazel/package.json', {
paths: [getSystemPath(root)],
});
const packageDir = dirname(packageJson as Path);
const packageDir = dirname(normalize(packageJson));
const templateDir = join(packageDir, 'src', 'builders', 'files');
if (!await host.isDirectory(templateDir).toPromise()) {
throw new Error('Could not find Bazel template directory in "@angular/bazel".');

View File

@ -1,7 +1,7 @@
{
"builders": {
"build": {
"class": "./index",
"implementation": "./index",
"schema": "./schema.json",
"description": "Executes Bazel on a target."
}

View File

@ -137,5 +137,6 @@ ts_web_test_suite(
deps = [
":rxjs_umd_modules",
":test_lib",
"@npm//karma-jasmine",
],
)

View File

@ -8,25 +8,24 @@
* @fileoverview Bazel builder
*/
import {BuildEvent, Builder, BuilderConfiguration, BuilderContext} from '@angular-devkit/architect';
import {Path} from '@angular-devkit/core';
import {Observable, from} from 'rxjs';
import {BuilderContext, BuilderOutput, createBuilder,} from '@angular-devkit/architect/src/index2';
import {JsonObject, normalize} from '@angular-devkit/core';
import {checkInstallation, copyBazelFiles, deleteBazelFiles, getTemplateDir, runBazel} from './bazel';
import {Schema} from './schema';
import {NodeJsSyncHost} from '@angular-devkit/core/node';
class BazelBuilder implements Builder<Schema> {
constructor(private context: BuilderContext) {}
async function _bazelBuilder(options: JsonObject & Schema, context: BuilderContext, ):
Promise<BuilderOutput> {
const root = normalize(context.workspaceRoot);
const {logger} = context;
const {bazelCommand, leaveBazelFilesOnDisk, targetLabel, watch} = options;
const executable = watch ? 'ibazel' : 'bazel';
const binary = checkInstallation(executable, root);
run(config: BuilderConfiguration<Partial<Schema>>): Observable<BuildEvent> {
const {host, logger, workspace} = this.context;
const root: Path = workspace.root;
const {bazelCommand, leaveBazelFilesOnDisk, targetLabel, watch} = config.options as Schema;
const executable = watch ? 'ibazel' : 'bazel';
const binary = checkInstallation(executable, root) as Path;
return from(Promise.resolve().then(async() => {
const host = new NodeJsSyncHost();
const templateDir = await getTemplateDir(host, root);
const bazelFiles = await copyBazelFiles(host, root, templateDir);
try {
const flags: string[] = [];
await runBazel(root, binary, bazelCommand, targetLabel, flags);
@ -39,8 +38,6 @@ class BazelBuilder implements Builder<Schema> {
await deleteBazelFiles(host, bazelFiles); // this will never throw
}
}
}));
}
}
}
export default BazelBuilder;
export default createBuilder(_bazelBuilder);