feat(bazel): Bazel workspace schematics (#26971)
This commit creates a schematics for Bazel workspace. PR Close #26971
This commit is contained in:
20
packages/bazel/src/schematics/BUILD.bazel
Normal file
20
packages/bazel/src/schematics/BUILD.bazel
Normal file
@ -0,0 +1,20 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
filegroup(
|
||||
name = "package_assets",
|
||||
srcs = [
|
||||
"collection.json",
|
||||
],
|
||||
visibility = ["//packages/bazel:__subpackages__"],
|
||||
)
|
||||
|
||||
load("//tools:defaults.bzl", "jasmine_node_test", "ts_library")
|
||||
|
||||
jasmine_node_test(
|
||||
name = "test",
|
||||
bootstrap = ["angular/tools/testing/init_node_spec.js"],
|
||||
deps = [
|
||||
"//packages/bazel/src/schematics/bazel-workspace:test",
|
||||
"//tools/testing:node",
|
||||
],
|
||||
)
|
32
packages/bazel/src/schematics/README.md
Normal file
32
packages/bazel/src/schematics/README.md
Normal file
@ -0,0 +1,32 @@
|
||||
# Schematics for Bazel
|
||||
|
||||
## Development notes
|
||||
|
||||
To test any local changes, run
|
||||
|
||||
```shell
|
||||
bazel build //packages/bazel:npm_package
|
||||
```
|
||||
|
||||
then `cd` to the npm package in the `dist` folder and run `yarn link`.
|
||||
Next run `yarn link` again in the directory where the `ng` command is invoked.
|
||||
Make sure the `ng` command is local, and not the global installation.
|
||||
|
||||
## Generate .d.ts file from JSON schema
|
||||
|
||||
The script to generate `.d.ts` file is located in the
|
||||
[Angular CLI](https://github.com/angular/angular-cli) repo. Make sure
|
||||
the CLI repository is checked out on your local machine.
|
||||
|
||||
Then, in the CLI repository, run the following command
|
||||
|
||||
```shell
|
||||
bazel run //tools:quicktype_runner -- \
|
||||
~/Documents/GitHub/angular/packages/bazel/src/schematics/ng-new/schema.json \
|
||||
~/Documents/GitHub/angular/packages/bazel/src/schematics/ng-new/schema.d.ts
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
1. Make the `ts_json_schema` rule re-usable and portable.
|
||||
2. Add comments in BUILD files. See discussion [here](https://github.com/angular/angular/pull/26971#discussion_r231325683).
|
34
packages/bazel/src/schematics/bazel-workspace/BUILD.bazel
Normal file
34
packages/bazel/src/schematics/bazel-workspace/BUILD.bazel
Normal file
@ -0,0 +1,34 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//tools:defaults.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "bazel-workspace",
|
||||
srcs = [
|
||||
"index.ts",
|
||||
"schema.d.ts",
|
||||
],
|
||||
data = glob(["files/**/*"]) + [
|
||||
"schema.json",
|
||||
],
|
||||
deps = [
|
||||
"@ngdeps//@angular-devkit/core",
|
||||
"@ngdeps//@angular-devkit/schematics",
|
||||
"@ngdeps//@schematics/angular",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "test",
|
||||
testonly = True,
|
||||
srcs = [
|
||||
"index_spec.ts",
|
||||
],
|
||||
data = [
|
||||
"//packages/bazel/src/schematics:package_assets",
|
||||
],
|
||||
deps = [
|
||||
":bazel-workspace",
|
||||
"@ngdeps//@angular-devkit/schematics",
|
||||
],
|
||||
)
|
@ -0,0 +1,7 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
# This export allows targets in other packages to reference files that live
|
||||
# in this package.
|
||||
exports_files([
|
||||
"tsconfig.json",
|
||||
])
|
@ -0,0 +1,76 @@
|
||||
# WARNING: This file is generated and it's not meant to be edited.
|
||||
# Before making any changes, please read Bazel documentation.
|
||||
# https://docs.bazel.build/versions/master/be/workspace.html
|
||||
# The WORKSPACE file tells Bazel that this directory is a "workspace", which is like a project root.
|
||||
# The content of this file specifies all the external dependencies Bazel needs to perform a build.
|
||||
|
||||
####################################
|
||||
# ESModule imports (and TypeScript imports) can be absolute starting with the workspace name.
|
||||
# The name of the workspace should match the npm package where we publish, so that these
|
||||
# imports also make sense when referencing the published package.
|
||||
workspace(name = "<%= utils.underscore(name) %>")
|
||||
|
||||
# The @angular repo contains rule for building Angular applications
|
||||
# Provides "build_bazel_rules_typescript"
|
||||
ANGULAR_VERSION = "<%= ANGULAR_VERSION %>"
|
||||
http_archive(
|
||||
name = "angular",
|
||||
url = "https://github.com/angular/angular/archive/%s.zip" % ANGULAR_VERSION,
|
||||
strip_prefix = "angular-%s" % ANGULAR_VERSION,
|
||||
)
|
||||
|
||||
# RxJS
|
||||
RXJS_VERSION = "<%= RXJS_VERSION %>"
|
||||
http_archive(
|
||||
name = "rxjs",
|
||||
url = "https://registry.yarnpkg.com/rxjs/-/rxjs-%s.tgz" % RXJS_VERSION,
|
||||
strip_prefix = "package/src",
|
||||
)
|
||||
|
||||
# Rules for compiling sass
|
||||
RULES_SASS_VERSION = "<%= RULES_SASS_VERSION %>"
|
||||
http_archive(
|
||||
name = "io_bazel_rules_sass",
|
||||
url = "https://github.com/bazelbuild/rules_sass/archive/%s.zip" % RULES_SASS_VERSION,
|
||||
strip_prefix = "rules_sass-%s" % RULES_SASS_VERSION,
|
||||
)
|
||||
|
||||
####################################
|
||||
# Load and install our dependencies downloaded above.
|
||||
|
||||
load("@angular//packages/bazel:package.bzl", "rules_angular_dependencies")
|
||||
rules_angular_dependencies()
|
||||
|
||||
load("@build_bazel_rules_typescript//:package.bzl", "rules_typescript_dependencies")
|
||||
rules_typescript_dependencies()
|
||||
# build_bazel_rules_nodejs is loaded transitively through rules_typescript_dependencies.
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories", "yarn_install")
|
||||
# 0.18.0 is needed for .bazelignore
|
||||
check_bazel_version("0.18.0")
|
||||
node_repositories()
|
||||
yarn_install(
|
||||
name = "npm",
|
||||
package_json = "//:package.json",
|
||||
yarn_lock = "//:yarn.lock",
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||
go_rules_dependencies()
|
||||
go_register_toolchains()
|
||||
|
||||
load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories")
|
||||
web_test_repositories()
|
||||
browser_repositories(
|
||||
chromium = True,
|
||||
firefox = True,
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace", "check_rules_typescript_version")
|
||||
ts_setup_workspace()
|
||||
|
||||
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
||||
sass_repositories()
|
||||
|
||||
load("@angular//:index.bzl", "ng_setup_workspace")
|
||||
ng_setup_workspace()
|
@ -0,0 +1,2 @@
|
||||
dist
|
||||
node_modules
|
@ -0,0 +1,19 @@
|
||||
# Make TypeScript and Angular compilation fast, by keeping a few copies of the
|
||||
# compiler running as daemons, and cache SourceFile AST's to reduce parse time.
|
||||
build --strategy=TypeScriptCompile=worker
|
||||
build --strategy=AngularTemplateCompile=worker
|
||||
|
||||
# Don't create bazel-* symlinks in the WORKSPACE directory, except `bazel-out`,
|
||||
# which is mandatory.
|
||||
# These require .gitignore and may scare users.
|
||||
# Also, it's a workaround for https://github.com/bazelbuild/rules_typescript/issues/12
|
||||
# which affects the common case of having `tsconfig.json` in the WORKSPACE directory.
|
||||
#
|
||||
# Instead, the output will appear in `dist/bin`. You'll need to ignore the
|
||||
# `bazel-out` directory that is created in the workspace root.
|
||||
build --symlink_prefix=dist/
|
||||
|
||||
test --test_output=errors
|
||||
|
||||
# Use the Angular 6 compiler
|
||||
build --define=compile=legacy
|
@ -0,0 +1,46 @@
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
load("@angular//:index.bzl", "protractor_web_test_suite")
|
||||
|
||||
ts_library(
|
||||
name = "e2e_lib",
|
||||
testonly = 1,
|
||||
srcs = glob(["src/**/*.ts"]),
|
||||
tsconfig = ":tsconfig.e2e.json",
|
||||
deps = [
|
||||
"@npm//@types/jasmine",
|
||||
"@npm//@types/jasminewd2",
|
||||
"@npm//@types/node",
|
||||
"@npm//jasmine",
|
||||
"@npm//protractor",
|
||||
]
|
||||
)
|
||||
|
||||
protractor_web_test_suite(
|
||||
name = "prodserver_test",
|
||||
data = [
|
||||
"@angular//packages/bazel/src/protractor/utils",
|
||||
"@npm//protractor",
|
||||
],
|
||||
on_prepare = ":protractor.on-prepare.js",
|
||||
server = "//src:prodserver",
|
||||
deps = [":e2e_lib"],
|
||||
)
|
||||
|
||||
protractor_web_test_suite(
|
||||
name = "devserver_test",
|
||||
data = [
|
||||
"@angular//packages/bazel/src/protractor/utils",
|
||||
"@npm//protractor",
|
||||
],
|
||||
on_prepare = ":protractor.on-prepare.js",
|
||||
server = "//src:devserver",
|
||||
deps = [":e2e_lib"],
|
||||
)
|
||||
|
||||
# Default target in this package is to run the e2e tests on the devserver.
|
||||
# This is a faster round-trip but doesn't exercise production optimizations like
|
||||
# code-splitting and lazy loading.
|
||||
alias(
|
||||
name = "e2e",
|
||||
actual = "devserver_test",
|
||||
)
|
@ -0,0 +1,23 @@
|
||||
// The function exported from this file is used by the protractor_web_test_suite.
|
||||
// It is passed to the `onPrepare` configuration setting in protractor and executed
|
||||
// before running tests.
|
||||
//
|
||||
// If the function returns a promise, as it does here, protractor will wait
|
||||
// for the promise to resolve before running tests.
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = function(config) {
|
||||
// In this example, `@angular/bazel/protractor-utils` is used to run
|
||||
// the server. protractorUtils.runServer() runs the server on a randomly
|
||||
// selected port (given a port flag to pass to the server as an argument).
|
||||
// The port used is returned in serverSpec and the protractor serverUrl
|
||||
// is the configured.
|
||||
const portFlag = config.server.endsWith('prodserver') ? '-p' : '-port';
|
||||
return protractorUtils.runServer(config.workspace, config.server, portFlag, [])
|
||||
.then(serverSpec => {
|
||||
const serverUrl = `http://localhost:${serverSpec.port}`;
|
||||
protractor.browser.baseUrl = serverUrl;
|
||||
});
|
||||
};
|
@ -0,0 +1,90 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@angular//:index.bzl", "ng_module")
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library", "ts_web_test_suite")
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "rollup_bundle", "history_server")
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_devserver")
|
||||
|
||||
ng_module(
|
||||
name = "src",
|
||||
srcs = glob(["**/*.ts"], exclude = ["**/*.spec.ts", "test.ts"]),
|
||||
assets = glob([
|
||||
"**/*.css",
|
||||
"**/*.html",
|
||||
]),
|
||||
deps = [
|
||||
"@angular//packages/core",
|
||||
"@angular//packages/platform-browser",
|
||||
"@npm//@types",
|
||||
],
|
||||
)
|
||||
|
||||
rollup_bundle(
|
||||
name = "bundle",
|
||||
entry_point = "src/main",
|
||||
deps = ["//src"],
|
||||
)
|
||||
|
||||
# Needed because the prodserver only loads static files that appear under this
|
||||
# package.
|
||||
genrule(
|
||||
name = "zonejs",
|
||||
srcs = ["@npm//node_modules/zone.js:dist/zone.min.js"],
|
||||
outs = ["zone.min.js"],
|
||||
cmd = "cp $< $@",
|
||||
)
|
||||
|
||||
history_server(
|
||||
name = "prodserver",
|
||||
data = [
|
||||
"index.html",
|
||||
":bundle",
|
||||
":zonejs",
|
||||
],
|
||||
)
|
||||
|
||||
ts_devserver(
|
||||
name = "devserver",
|
||||
port = 4200,
|
||||
additional_root_paths = [
|
||||
"npm/node_modules/zone.js/dist",
|
||||
"npm/node_modules/tslib",
|
||||
],
|
||||
entry_module = "<%= name %>/src/main",
|
||||
serving_path = "/bundle.min.js",
|
||||
static_files = [
|
||||
"@npm//node_modules/zone.js:dist/zone.min.js",
|
||||
"@npm//node_modules/tslib:tslib.js",
|
||||
"index.html",
|
||||
],
|
||||
deps = [":src"],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "test_lib",
|
||||
testonly = 1,
|
||||
srcs = glob(["**/*.spec.ts"]),
|
||||
deps = [
|
||||
":src",
|
||||
"@angular//packages/core/testing",
|
||||
"@angular//packages/platform-browser-dynamic/testing",
|
||||
"@npm//@types",
|
||||
],
|
||||
)
|
||||
|
||||
ts_web_test_suite(
|
||||
name = "test",
|
||||
srcs = ["@npm//node_modules/tslib:tslib.js"],
|
||||
# do not sort
|
||||
bootstrap = [
|
||||
"@npm//node_modules/zone.js:dist/zone-testing-bundle.js",
|
||||
"@npm//node_modules/reflect-metadata:Reflect.js",
|
||||
],
|
||||
browsers = [
|
||||
"@io_bazel_rules_webtesting//browsers:chromium-local",
|
||||
],
|
||||
deps = [
|
||||
":test_lib",
|
||||
"@npm//karma-jasmine",
|
||||
],
|
||||
)
|
47
packages/bazel/src/schematics/bazel-workspace/index.ts
Normal file
47
packages/bazel/src/schematics/bazel-workspace/index.ts
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*
|
||||
* @fileoverview Schematics for bazel-workspace
|
||||
*/
|
||||
|
||||
import {strings} from '@angular-devkit/core';
|
||||
import {Rule, SchematicContext, SchematicsException, Tree, apply, applyTemplates, mergeWith, move, url} from '@angular-devkit/schematics';
|
||||
import {getWorkspace} from '@schematics/angular/utility/config';
|
||||
import {validateProjectName} from '@schematics/angular/utility/validation';
|
||||
|
||||
import {Schema as BazelWorkspaceOptions} from './schema';
|
||||
|
||||
export default function(options: BazelWorkspaceOptions): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
if (!options.name) {
|
||||
throw new SchematicsException(`Invalid options, "name" is required.`);
|
||||
}
|
||||
validateProjectName(options.name);
|
||||
let newProjectRoot = '';
|
||||
try {
|
||||
const workspace = getWorkspace(host);
|
||||
newProjectRoot = workspace.newProjectRoot || '';
|
||||
} catch {
|
||||
}
|
||||
const appDir = `${newProjectRoot}/${options.name}`;
|
||||
|
||||
const workspaceVersions = {
|
||||
'ANGULAR_VERSION': '7.0.2',
|
||||
'RULES_SASS_VERSION': '1.14.1',
|
||||
'RXJS_VERSION': '6.3.3',
|
||||
};
|
||||
|
||||
return mergeWith(apply(url('./files'), [
|
||||
applyTemplates({
|
||||
utils: strings,
|
||||
...options,
|
||||
'dot': '.', ...workspaceVersions,
|
||||
}),
|
||||
move(appDir),
|
||||
]));
|
||||
};
|
||||
}
|
47
packages/bazel/src/schematics/bazel-workspace/index_spec.ts
Normal file
47
packages/bazel/src/schematics/bazel-workspace/index_spec.ts
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {SchematicTestRunner} from '@angular-devkit/schematics/testing';
|
||||
|
||||
describe('Bazel-workspace Schematic', () => {
|
||||
const schematicRunner =
|
||||
new SchematicTestRunner('@angular/bazel', require.resolve('../collection.json'), );
|
||||
const defaultOptions = {
|
||||
name: 'demo',
|
||||
};
|
||||
|
||||
it('should generate Bazel workspace files', () => {
|
||||
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');
|
||||
});
|
||||
|
||||
describe('WORKSPACE', () => {
|
||||
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(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(content).toContain('workspace(name = "demo_project"');
|
||||
});
|
||||
});
|
||||
});
|
13
packages/bazel/src/schematics/bazel-workspace/schema.d.ts
vendored
Normal file
13
packages/bazel/src/schematics/bazel-workspace/schema.d.ts
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED. TO UPDATE THIS FILE YOU NEED TO CHANGE
|
||||
// THE CORRESPONDING JSON SCHEMA FILE. See README.md.
|
||||
|
||||
// tslint:disable:no-global-tslint-disable
|
||||
// tslint:disable
|
||||
|
||||
export interface Schema {
|
||||
/**
|
||||
* The name of the project.
|
||||
*/
|
||||
name: string;
|
||||
}
|
20
packages/bazel/src/schematics/bazel-workspace/schema.json
Normal file
20
packages/bazel/src/schematics/bazel-workspace/schema.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"id": "SchematicsAngularBazelWorkspace",
|
||||
"title": "Angular Bazel Workspace Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The name of the project.",
|
||||
"type": "string",
|
||||
"format": "html-selector",
|
||||
"$default": {
|
||||
"$source": "argv",
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name"
|
||||
]
|
||||
}
|
12
packages/bazel/src/schematics/collection.json
Normal file
12
packages/bazel/src/schematics/collection.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "@angular/bazel",
|
||||
"version": "0.1",
|
||||
"schematics": {
|
||||
"bazel-workspace": {
|
||||
"factory": "./bazel-workspace",
|
||||
"schema": "./bazel-workspace/schema.json",
|
||||
"description": "Setup Bazel workspace",
|
||||
"hidden": true
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user