build: use bazel from node modules (#16361)

The goal of https://github.com/angular/components/commit/2ce5ffd56b70c3791331ceedeadc1f1f6daf3924 was to avoid the
use of Bazel through the `node_modules` because it adds unnecessary code overhead, slows down CI and means that
some tools need to be installed multiple times (such as `yarn`). Unfortunately when building a release with Bazel
right now, the bazel workspace status script depends on the global `node` binary. This means that we need
to bring in Node when running with the `--config=release` flag.. Since that causes inconsistent behavior
and just complicates the setup, we are using Bazel through Yarn for now. Similar to how we did it for
`angular/angular` with https://github.com/angular/angular/commit/8fc4ae51fb66d14f6dc82712a536c3842205fc6d.
This commit is contained in:
Paul Gschwendtner
2019-06-22 00:08:30 +02:00
committed by Jeremy Elbourn
parent 94c84edd58
commit 10370ef659
5 changed files with 113 additions and 121 deletions
@@ -1,5 +1,8 @@
#!/bin/bash
# The script should immediately exit if any command in the script fails.
set -e
if [[ -z "${GCP_DECRYPT_TOKEN}" ]]; then
echo "Please specify the \"GCP_DECRYPT_TOKEN\" environment variable when setting up remote " \
"execution"
@@ -8,12 +11,12 @@ fi
# Decode the GCP token that is needed to authenticate the Bazel remote execution.
openssl aes-256-cbc -d -in .circleci/gcp_token -md md5 -k ${GCP_DECRYPT_TOKEN} \
-out /home/.gcp_credentials
-out $HOME/.gcp_credentials
# Export the "GOOGLE_APPLICATION_CREDENTIALS" variable that should refer to the GCP credentials
# file. Bazel automatically picks up the credentials from that variable.
# https://github.com/bazelbuild/bazel/blob/master/third_party/grpc/include/grpc/grpc_security.h#L134-L137
echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/.gcp_credentials" >> $BASH_ENV
echo "export GOOGLE_APPLICATION_CREDENTIALS=$HOME/.gcp_credentials" >> $BASH_ENV
# Update the CircleCI Bazel configuration to always use remote execution.
echo 'build --config=remote' >> .circleci/bazel.rc
@@ -0,0 +1,58 @@
/**
* Script that sets up the Angular snapshot github builds. We set up the snapshot builds by
* overwriting the versions in the "package.json" and taking advantage of Yarn's resolutions
* feature. Yarn resolutions will be used to flatten nested Angular packages because by default
* Yarn does not flatten any dependency. See:
*
* node_modules/compiler@snapshot
* node_modules/compiler-cli@snapshot
* node_modules/compiler@7.0.1
*
* Note that we cannot just use Yarn's `--flat` option because that would mean that it tries
* to flatten **all** dependencies and could cause unexpected results. We **only** want to
* explicitly flatten out all `@angular/*` dependencies. This can be achieved with resolutions.
* Read more here: https://yarnpkg.com/lang/en/docs/package-json/#toc-resolutions
*/
const {yellow, green} = require('chalk');
const {writeFileSync} = require('fs');
const {join} = require('path');
const {tag} = require('minimist')(process.argv.slice(2), {string: ['tag']});
const projectDir = join(__dirname, '../../');
const packageJsonPath = join(projectDir, 'package.json');
const packageJson = require(packageJsonPath);
// Initialize the "resolutions" property in case it is not present in the "package.json" yet.
// See: https://yarnpkg.com/lang/en/docs/package-json/#toc-resolutions for the API.
packageJson['resolutions'] = packageJson['resolutions'] || {};
// List that contains the names of all installed Angular packages (e.g. "@angular/core")
const angularPackages = Object.keys({...packageJson.dependencies, ...packageJson.devDependencies})
.filter(packageName => packageName.startsWith('@angular/'));
const packageSuffix = tag ? ` (${tag})` : '';
console.log(green('Setting up snapshot builds for:\n'));
console.log(yellow(` ${angularPackages.map(n => `${n}${packageSuffix}`).join('\n ')}\n`));
// Setup the snapshot version for each Angular package specified in the "package.json" file.
angularPackages.forEach(packageName => {
let buildsUrl = `github:angular/${packageName.split('/')[1]}-builds${tag ? `#${tag}` : ''}`;
// Add resolutions for each package in the format "**/{PACKAGE}" so that all
// nested versions of that specific Angular package will have the same version.
packageJson.resolutions[`**/${packageName}`] = buildsUrl;
// Since the resolutions only cover the version of all nested installs, we also need
// to explicitly set the version for the package listed in the project "package.json".
packageJson.dependencies[packageName] = buildsUrl;
// In case this dependency was previously a dev dependency, just remove it because we
// re-added it as a normal dependency for simplicity.
delete packageJson.devDependencies[packageName];
});
// Write changes to the "packageJson", so that we can install the new versions afterwards.
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
console.log(green('Successfully added the "resolutions" to the "package.json".'));
@@ -1,77 +0,0 @@
"""
Script that sets up the Angular snapshot github builds. We set up the snapshot builds by
overwriting the versions in the "package.json" and taking advantage of Yarn's resolutions
feature. Yarn resolutions will be used to flatten nested Angular packages because by default
Yarn does not flatten any dependency. See:
node_modules/compiler@snapshot
node_modules/compiler-cli@snapshot
node_modules/compiler@7.0.1
Note that we cannot just use Yarn's `--flat` option because that would mean that it tries
to flatten **all** dependencies and could cause unexpected results. We **only** want to
explicitly flatten out all `@angular/*` dependencies. This can be achieved with resolutions.
Read more here: https://yarnpkg.com/lang/en/docs/package-json/#toc-resolutions
**Note** that this script has to be written in Python because the docker container which
is used for our CI does not come with NodeJS pre-installed. Since this script needs to run
before the Bazel analysis phase is started, we can only run this script only with tools that
are pre-installed in the image. Python is a pre-installed in the google/bazel official image
and therefore we use that for the "package.json" modification. Note that this script is only
running on CI and therefore there are no implications with writing this in python.
"""
import json
import os
import argparse
def collect_angular_deps(obj, result):
for item in obj:
if (item.startswith('@angular/')):
result.append(item)
project_dir = os.path.realpath(os.path.join(os.path.dirname(__file__), '../../'))
package_json_path = os.path.join(project_dir, 'package.json')
parser = argparse.ArgumentParser(description='Setup Angular snapshot packages')
parser.add_argument('--tag', required = True)
parsed_args = parser.parse_args()
with open(package_json_path, 'r') as package_json:
data = json.load(package_json)
angular_pkgs = []
collect_angular_deps(data['dependencies'], angular_pkgs)
collect_angular_deps(data['devDependencies'], angular_pkgs)
if not 'resolutions' in data:
data['resolutions'] = {}
print('Setting up snapshot builds for:')
for pkg in angular_pkgs:
new_url = "github:angular/%s-builds#%s" % (pkg.split('/')[1], parsed_args.tag)
print(" %s -> %s" % (pkg, new_url))
# Add resolutions for each package in the format "**/{PACKAGE}" so that all
# nested versions of that specific Angular package will have the same version.
data['resolutions']['**/%s' % pkg] = new_url
# Since the resolutions only cover the version of all nested installs, we also need
# to explicitly set the version for the package listed in the project "package.json".
data['dependencies'][pkg] = new_url
# In case this dependency was previously a dev dependency, just remove it because we
# re-added it as a normal dependency for simplicity.
if pkg in data['devDependencies']:
del data['devDependencies'][pkg]
new_package_json = json.dumps(data, indent = 2)
with open(package_json_path, 'w') as package_json_out:
package_json_out.write(new_package_json)
print('')
print('Successfully added the "resolutions" to the "package.json".')
print('Please run "yarn install" in the project to update the lock file.')
+1 -1
View File
@@ -24,7 +24,7 @@ docsDistPath="${projectPath}/dist/docs"
docsContentPath="${projectPath}/tmp/material2-docs-content"
# Path to the release output of the Bazel "@angular/material-examples" NPM package.
examplesPackagePath="$(bazel info bazel-bin)/src/material-examples/npm_package"
examplesPackagePath="$(yarn -s bazel info bazel-bin)/src/material-examples/npm_package"
# Git clone URL for the material2-docs-content repository.
docsContentRepoUrl="https://github.com/angular/material2-docs-content"