Skip to content
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

feat: add @bazel/angular package #1048

Merged
merged 23 commits into from
Nov 8, 2021
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Builders' and Angular **major** versions **must** match.

- [Custom webpack builders](./packages/custom-webpack) (an alternative to `ng eject`) [![npm version](https://img.shields.io/npm/v/@angular-builders/custom-webpack.svg) ![npm (tag)](https://img.shields.io/npm/v/@angular-builders/custom-webpack/next.svg) ![npm](https://img.shields.io/npm/dm/@angular-builders/custom-webpack.svg)](https://www.npmjs.com/package/@angular-builders/custom-webpack)
- [Jest builder](./packages/jest) (allows running `ng test` with Jest) [![npm version](https://img.shields.io/npm/v/@angular-builders/jest.svg) ![npm (tag)](https://img.shields.io/npm/v/@angular-builders/jest/next.svg) ![npm](https://img.shields.io/npm/dm/@angular-builders/jest.svg)](https://www.npmjs.com/package/@angular-builders/jest)
- [Bazel builder](./packages/bazel) (`ng` wrapper for `Bazel` build) [![npm version](https://img.shields.io/npm/v/@angular-builders/bazel.svg) ![npm (tag)](https://img.shields.io/npm/v/@angular-builders/bazel/next.svg) ![npm](https://img.shields.io/npm/dm/@angular-builders/bazel.svg)](https://www.npmjs.com/package/@angular-builders/bazek)
- [Timestamp builder](./packages/timestamp) (an example builder from [this](https://medium.com/@justjeb/angular-cli-6-under-the-hood-builders-demystified-f0690ebcf01) article) [![npm version](https://img.shields.io/npm/v/@angular-builders/timestamp.svg) ![npm (tag)](https://img.shields.io/npm/v/@angular-builders/timestamp/next.svg) ![npm](https://img.shields.io/npm/dm/@angular-builders/timestamp.svg)](https://www.npmjs.com/package/@angular-builders/timestamp)

# Get in touch
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"packages": [
"packages/*",
"packages/*/examples/*",
"packages/timestamp/example"
"packages/*/example"
],
"command": {
"publish": {
Expand Down
15 changes: 15 additions & 0 deletions packages/bazel/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
*.iml
.idea
node_modules

## this is generated by `npm pack`
*.tgz
package

dist
src/schema.ts
*.d.ts
**/*.js
!scripts/*.js
*.js.map
example/bazel-*
33 changes: 33 additions & 0 deletions packages/bazel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Angular CLI support for Bazel

Provides an Angular CLI Builder, which can execute Bazel when triggered by `ng build`, `ng test`, etc.
See https://angular.io/guide/cli-builder for more info about Builders.

> This package is a replacement for parts of the deprecated @angular/bazel package previously maintained by the Angular team.

This builder assumes you have already created Bazel configurations (WORKSPACE and BUILD files).
There is presently no tooling to generate these automatically that's supported by either Angular team or rules_nodejs maintainers.
See the [`@bazel/create`](https://www.npmjs.com/package/@bazel/create)
package for a quickstart to creating a Bazel workspace, or look at examples in [rules_nodejs].

To use it, you would just install this package (it doesn't hook into `ng add` because it has no schematics):

```sh
$ npm install --save-dev @angular-builders/bazel
```

Then edit your `angular.json` to invoke Bazel. For example, to have `ng build` do `bazel build //:all` you would edit the `architect` block to have:

```json
"architect": {
"build": {
"builder": "@angular-builders/bazel:build",
"options": {
"targetLabel": "//:all",
"bazelCommand": "build"
}
}
}
```

[rules_nodejs]: https://github.com/bazelbuild/rules_nodejs
9 changes: 9 additions & 0 deletions packages/bazel/builders.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"builders": {
"build": {
"implementation": "./dist",
"schema": "./dist/schema.json",
"description": "Executes Bazel on a target."
}
}
}
6 changes: 6 additions & 0 deletions packages/bazel/example/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Writes "hello world" to ./bazel-bin/out
genrule(
name = "hello_world",
outs = ["out"],
cmd = "echo 'hello world' >$@",
)
Empty file.
18 changes: 18 additions & 0 deletions packages/bazel/example/angular.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"bazel-build": {
"architect": {
"build": {
"builder": "@angular-builders/bazel:build",
"options": {
"targetLabel": "//:all",
"bazelCommand": "build"
}
}
}
}
}
}
12 changes: 12 additions & 0 deletions packages/bazel/example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "bazel-example",
"version": "13.0.0",
"scripts": {
"build": "ng build"
},
"private": true,
"devDependencies": {
"@angular/cli": "^13.0.1",
"@angular-builders/bazel": "latest"
}
}
41 changes: 41 additions & 0 deletions packages/bazel/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "@angular-builders/bazel",
"description": "Run Bazel under the Angular CLI",
"license": "Apache-2.0",
"version": "13.0.0",
"repository": {
"type": "git",
"url": "https://github.com/just-jeb/angular-builders.git",
"directory": "packages/bazel"
},
"bugs": {
"url": "https://github.com/just-jeb/angular-builders/issues"
},
"keywords": [
"angular",
"bazel"
],
"builders": "./builders.json",
"main": "dist/index.js",
"files": [
"dist",
"builders.json"
],
"scripts": {
"prebuild": "yarn clean && yarn generate",
"build": "../../node_modules/.bin/tsc",
"postbuild": "yarn copy",
"clean": "../../node_modules/.bin/rimraf dist src/schema.ts",
"copy": "../../node_modules/.bin/cpy src/schema.json dist",
"generate": "../../node_modules/.bin/quicktype -s schema src/schema.json -o src/schema.ts",
"ci": "node ./scripts/ci.js"
},
"dependencies": {
"@angular-devkit/architect": ">=0.1300.0 < 0.1400.0",
"@bazel/bazelisk": "^1.4.0",
"@bazel/ibazel": "^0.13.1"
},
"devDependencies": {
"@angular-devkit/core": "^13.0.0"
}
}
24 changes: 24 additions & 0 deletions packages/bazel/scripts/ci.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const { execSync } = require('child_process');
const { readFileSync } = require('fs');
const { exit } = require('process');

runTests();

function runTests() {
process.chdir('./example');
runBuild();
compareResults();
}

function runBuild() {
execSync('yarn build');
}

function compareResults() {
const expectedOut = 'hello world\n';
const bazelOut = readFileSync('./bazel-bin/out', { encoding: 'utf-8' });
if (bazelOut !== expectedOut) {
console.log(`ERROR: Expected bazel output is ${expectedOut}, actual is ${bazelOut}`);
exit(1);
}
}
38 changes: 38 additions & 0 deletions packages/bazel/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import type { JsonObject } from '@angular-devkit/core';
import { getNativeBinary as bazeliskBin } from '@bazel/bazelisk/bazelisk';
import { getNativeBinary as ibazelBin } from '@bazel/ibazel';
import { spawn } from 'child_process';
import { Schema } from './schema';

async function _bazelBuilder(
options: JsonObject & Schema,
context: BuilderContext
): Promise<BuilderOutput> {
const { bazelCommand, targetLabel, watch } = options;
const binary = watch ? ibazelBin() : bazeliskBin();
if (typeof binary !== 'string') {
// this happens if no binary is located for the current platform
context.logger.error('No Bazel binary detected');
return { success: false };
} else {
try {
const ps = spawn(binary, [bazelCommand, targetLabel], { stdio: 'inherit' });

function shutdown() {
ps.kill('SIGTERM');
}

process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
return new Promise(resolve => {
ps.on('close', e => resolve({ success: e === 0 }));
});
} catch (err: any) {
context.logger.error(err.message);
return { success: false };
}
}
}

export default createBuilder(_bazelBuilder);
31 changes: 31 additions & 0 deletions packages/bazel/src/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"$schema": "http://json-schema.org/schema",
"title": "Bazel builder schema",
"description": "Options for Bazel Builder",
"type": "object",
"properties": {
"targetLabel": {
"type": "string",
"description": "Target to be executed under Bazel."
},
"bazelCommand": {
"type": "string",
"description": "Common commands supported by Bazel.",
"enum": [
"run",
"build",
"test"
]
},
"watch": {
"type": "boolean",
"description": "If true, watch the filesystem using ibazel.",
"default": false
}
},
"additionalProperties": false,
"required": [
"targetLabel",
"bazelCommand"
]
}
10 changes: 10 additions & 0 deletions packages/bazel/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"noImplicitAny": false
},
"files": [
"src/index.ts"
]
}
7 changes: 7 additions & 0 deletions packages/bazel/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
declare module '@bazel/bazelisk/bazelisk' {
function getNativeBinary(): Promise<number> | string;
}

declare module '@bazel/ibazel' {
function getNativeBinary(): Promise<number> | string;
}
2 changes: 1 addition & 1 deletion packages/timestamp/example/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "example",
"name": "timestamp-example",
"version": "13.0.0-beta.0",
"scripts": {
"ng": "ng",
Expand Down
7 changes: 3 additions & 4 deletions scripts/run-ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,9 @@ yarn bootstrap:examples

# Get travis's chrome version and download the appropriate webdriver-manager for protractor
CHROME_VERSION=`google-chrome --version | egrep -o '[0-9.]+' | head -1`
npx lerna exec --ignore '@angular-builders/*' -- ./node_modules/protractor/bin/webdriver-manager update --versions.chrome $CHROME_VERSION
WEBDRIVER_MANAGER_BIN=./node_modules/protractor/bin/webdriver-manager;
yarn lerna exec --ignore '@angular-builders/*' "[ -f $WEBDRIVER_MANAGER_BIN ] && $WEBDRIVER_MANAGER_BIN update --versions.chrome $CHROME_VERSION || echo \`pwd\`: No webdriver-manager found"

npx lerna run ci
yarn lerna run ci

cleanup