From 463e2872a64c4dcc558e30aba4a78d579fe951e5 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Fri, 5 Jan 2018 10:53:55 -0800 Subject: [PATCH] build: upgrade Bazel to 0.9.0 (#21335) Also install the skylark linter for .bzl files. PR Close #21335 --- .circleci/config.yml | 11 ++- WORKSPACE | 10 ++- package.json | 5 +- packages/bazel/index.bzl | 5 +- packages/bazel/src/ng_module.bzl | 105 ++++++++++++++++-------- packages/bazel/src/rules_typescript.bzl | 32 ++++++-- scripts/ci/env.sh | 2 +- 7 files changed, 121 insertions(+), 49 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0c08ea1b8b..04da8cc0d8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,8 +12,8 @@ ## IMPORTANT # If you change the `docker_image` version, also change the `cache_key` suffix and the version of # `com_github_bazelbuild_buildtools` in the `/WORKSPACE` file. -var_1: &docker_image angular/ngcontainer:0.0.8 -var_2: &cache_key angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.0.8 +var_1: &docker_image angular/ngcontainer:0.1.0 +var_2: &cache_key angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.1.0 # Settings common to each job anchor_1: &job_defaults @@ -38,7 +38,10 @@ jobs: # Then we don't need any exclude pattern to avoid checking those files - run: 'buildifier -mode=check $(find . -type f \( -name BUILD.bazel -or -name BUILD \)) || (echo "BUILD files not formatted. Please run ''yarn buildifier''" ; exit 1)' - + # Run the skylark linter to check our Bazel rules + - run: 'find . -type f -name "*.bzl" | + xargs java -jar /usr/local/bin/Skylint_deploy.jar || + (echo -e "\n.bzl files have lint errors. Please run ''yarn skylint''"; exit 1)' - restore_cache: key: *cache_key @@ -53,7 +56,7 @@ jobs: <<: *post_checkout - restore_cache: key: *cache_key - + - run: bazel info release - run: bazel run @yarn//:yarn # Use bazel query so that we explicitly ask for all buildable targets to be built as well diff --git a/WORKSPACE b/WORKSPACE index c40e30c0ea..c40194f91c 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -10,7 +10,7 @@ git_repository( load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories") -check_bazel_version("0.8.1") +check_bazel_version("0.9.0") node_repositories(package_json = ["//:package.json"]) git_repository( @@ -54,3 +54,11 @@ load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_too go_rules_dependencies() go_register_toolchains() + +# Fetching the Bazel source code allows us to compile the Skylark linter +http_archive( + name = "io_bazel", + url = "https://github.com/bazelbuild/bazel/archive/9755c72b48866ed034bd28aa033e9abd27431b1e.zip", + strip_prefix = "bazel-9755c72b48866ed034bd28aa033e9abd27431b1e", + sha256 = "5b8443fc3481b5fcd9e7f348e1dd93c1397f78b223623c39eb56494c55f41962", +) diff --git a/package.json b/package.json index ac98e29121..174434fc6c 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,10 @@ "url": "https://github.com/angular/angular.git" }, "scripts": { - "buildifier": "bazel build @com_github_bazelbuild_buildtools//buildifier && find . -type f \\( -name BUILD -or -name BUILD.bazel \\) ! -path \"*/node_modules/*\" | xargs $(bazel info bazel-bin)/external/com_github_bazelbuild_buildtools/buildifier/buildifier", + "preskylint": "bazel build --noshow_progress @io_bazel//src/tools/skylark/java/com/google/devtools/skylark/skylint:Skylint", + "skylint": "find . -type f -name \"*.bzl\" ! -path \"*/node_modules/*\" ! -path \"./dist/*\" | xargs $(bazel info bazel-bin)/external/io_bazel/src/tools/skylark/java/com/google/devtools/skylark/skylint/Skylint", + "prebuildifier": "bazel build --noshow_progress @com_github_bazelbuild_buildtools//buildifier", + "buildifier": "find . -type f \\( -name BUILD -or -name BUILD.bazel \\) ! -path \"*/node_modules/*\" | xargs $(bazel info bazel-bin)/external/com_github_bazelbuild_buildtools/buildifier/buildifier", "preinstall": "node -e \"if(process.env.npm_execpath.indexOf('yarn') === -1) throw new Error('Please use Yarn instead of NPM to install dependencies. See: https://yarnpkg.com/lang/en/docs/install/')\"", "postinstall": "yarn update-webdriver", "update-webdriver": "webdriver-manager update --gecko false $CHROMEDRIVER_VERSION_ARG", diff --git a/packages/bazel/index.bzl b/packages/bazel/index.bzl index 5db3236407..3934c35bcd 100644 --- a/packages/bazel/index.bzl +++ b/packages/bazel/index.bzl @@ -3,7 +3,10 @@ # 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 """ Public API surface is re-exported here. + Users should not load files under "/src" """ -load("//src:ng_module.bzl", "ng_module") +load("//src:ng_module.bzl", _ng_module = "ng_module") + +ng_module = _ng_module diff --git a/packages/bazel/src/ng_module.bzl b/packages/bazel/src/ng_module.bzl index c90f0eeb7e..11042e0ace 100644 --- a/packages/bazel/src/ng_module.bzl +++ b/packages/bazel/src/ng_module.bzl @@ -2,6 +2,8 @@ # # 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 +"""Implementation of the ng_module rule. +""" load(":rules_typescript.bzl", "tsc_wrapped_tsconfig", @@ -10,20 +12,17 @@ load(":rules_typescript.bzl", "compile_ts", "DEPS_ASPECTS", "ts_providers_dict_to_struct", - "json_marshal", ) # Calculate the expected output of the template compiler for every source in # in the library. Most of these will be produced as empty files but it is # unknown, without parsing, which will be empty. -def _expected_outs(ctx, label): +def _expected_outs(ctx): devmode_js_files = [] closure_js_files = [] declaration_files = [] summary_files = [] - codegen_inputs = ctx.files.srcs - for src in ctx.files.srcs + ctx.files.assets: if src.short_path.endswith(".ts") and not src.short_path.endswith(".d.ts"): basename = src.short_path[len(ctx.label.package) + 1:-len(".ts")] @@ -42,6 +41,9 @@ def _expected_outs(ctx, label): ] summaries = [] + else: + continue + closure_js = [f.replace(".js", ".closure.js") for f in devmode_js] declarations = [f.replace(".js", ".d.ts") for f in devmode_js] @@ -61,7 +63,7 @@ def _expected_outs(ctx, label): ) def _ngc_tsconfig(ctx, files, srcs, **kwargs): - outs = _expected_outs(ctx, ctx.label) + outs = _expected_outs(ctx) if "devmode_manifest" in kwargs: expected_outs = outs.devmode_js + outs.declarations + outs.summaries else: @@ -79,7 +81,7 @@ def _ngc_tsconfig(ctx, files, srcs, **kwargs): }) def _collect_summaries_aspect_impl(target, ctx): - results = target.angular.summaries if hasattr(target, "angular") else depset() + results = depset(target.angular.summaries if hasattr(target, "angular") else []) # If we are visiting empty-srcs ts_library, this is a re-export srcs = ctx.rule.attr.srcs if hasattr(ctx.rule.attr, "srcs") else [] @@ -88,7 +90,7 @@ def _collect_summaries_aspect_impl(target, ctx): if not srcs: for dep in ctx.rule.attr.deps: if (hasattr(dep, "angular")): - results += dep.angular.summaries + results = depset(dep.angular.summaries, transitive = [results]) return struct(collect_summaries_aspect_result = results) @@ -104,10 +106,29 @@ _EXTRA_NODE_OPTIONS_FLAGS = [ ] def ngc_compile_action(ctx, label, inputs, outputs, messages_out, config_file_path, - locale=None, i18n_args=[]): + locale=None, i18n_args=[]): + """Helper function to create the ngc action. + + This is exposed for google3 to wire up i18n replay rules, and is not intended + as part of the public API. + + Args: + ctx: skylark context + label: the label of the ng_module being compiled + inputs: passed to the ngc action's inputs + outputs: passed to the ngc action's outputs + messages_out: produced xmb files + config_file_path: path to the tsconfig file + locale: i18n locale, or None + i18n_args: additional command-line arguments to ngc + + Returns: + the parameters of the compilation which will be used to replay the ngc action for i18N. + """ + mnemonic = "AngularTemplateCompile" progress_message = "Compiling Angular templates (ngc) %s" % label - supports_workers = "0" + if locale: mnemonic = "AngularI18NMerging" supports_workers = "0" @@ -152,8 +173,6 @@ def ngc_compile_action(ctx, label, inputs, outputs, messages_out, config_file_pa progress_message = "Extracting Angular 2 messages (ng_xi18n)", mnemonic = "Angular2MessageExtractor") - # Return the parameters of the compilation which will be used to replay the - # ngc action for i18N. if not locale and not ctx.attr.no_i18n: return struct( label = label, @@ -162,46 +181,68 @@ def ngc_compile_action(ctx, label, inputs, outputs, messages_out, config_file_pa outputs = outputs, ) + return None + def _compile_action(ctx, inputs, outputs, messages_out, config_file_path): - summaries = depset() - for dep in ctx.attr.deps: - if hasattr(dep, "collect_summaries_aspect_result"): - summaries += dep.collect_summaries_aspect_result - - action_inputs = inputs + summaries.to_list() + ctx.files.assets - # print("ASSETS", [a.path for a in ctx.files.assets]) - # print("INPUTS", ctx.label, [o.path for o in summaries if o.path.find("core/src") > 0]) + # Give the Angular compiler all the user-listed assets + file_inputs = list(ctx.files.assets) + # The compiler only needs to see TypeScript sources from the npm dependencies, + # but may need to look at package.json and ngsummary.json files as well. if hasattr(ctx.attr, "node_modules"): - action_inputs += [f for f in ctx.files.node_modules - if f.path.endswith(".ts") or f.path.endswith(".json")] + file_inputs += [f for f in ctx.files.node_modules + if f.path.endswith(".ts") or f.path.endswith(".json")] + + # If the user supplies a tsconfig.json file, the Angular compiler needs to read it if hasattr(ctx.attr, "tsconfig") and ctx.file.tsconfig: - action_inputs += [ctx.file.tsconfig] + file_inputs.append(ctx.file.tsconfig) + + # Collect the inputs and summary files from our deps + action_inputs = depset(file_inputs, + transitive = [inputs] + [dep.collect_summaries_aspect_result for dep in ctx.attr.deps + if hasattr(dep, "collect_summaries_aspect_result")]) return ngc_compile_action(ctx, ctx.label, action_inputs, outputs, messages_out, config_file_path) def _prodmode_compile_action(ctx, inputs, outputs, config_file_path): - outs = _expected_outs(ctx, ctx.label) + outs = _expected_outs(ctx) return _compile_action(ctx, inputs, outputs + outs.closure_js, outs.i18n_messages, config_file_path) def _devmode_compile_action(ctx, inputs, outputs, config_file_path): - outs = _expected_outs(ctx, ctx.label) + outs = _expected_outs(ctx) _compile_action(ctx, inputs, outputs + outs.devmode_js + outs.declarations + outs.summaries, None, config_file_path) +def _ts_expected_outs(ctx, label): + # rules_typescript expects a function with two arguments, but our + # implementation doesn't use the label + _ignored = [label] + return _expected_outs(ctx) + def ng_module_impl(ctx, ts_compile_actions): + """Implementation function for the ng_module rule. + + This is exposed so that google3 can have its own entry point that re-uses this + and is not meant as a public API. + + Args: + ctx: the skylark rule context + ts_compile_actions: generates all the actions to run an ngc compilation + + Returns: + the result of the ng_module rule as a dict, suitable for + conversion by ts_providers_dict_to_struct + """ + providers = ts_compile_actions( ctx, is_library=True, compile_action=_prodmode_compile_action, devmode_compile_action=_devmode_compile_action, tsc_wrapped_tsconfig=_ngc_tsconfig, - outputs = _expected_outs) + outputs = _ts_expected_outs) - #addl_declarations = [_expected_outs(ctx)] - #providers["typescript"]["declarations"] += addl_declarations - #providers["typescript"]["transitive_declarations"] += addl_declarations - outs = _expected_outs(ctx, ctx.label) + outs = _expected_outs(ctx) providers["angular"] = { - "summaries": _expected_outs(ctx, ctx.label).summaries + "summaries": _expected_outs(ctx).summaries } providers["ngc_messages"] = outs.i18n_messages @@ -240,7 +281,7 @@ NG_MODULE_ATTRIBUTES = { ng_module = rule( implementation = _ng_module_impl, - attrs = COMMON_ATTRIBUTES + NG_MODULE_ATTRIBUTES + { + attrs = dict(dict(COMMON_ATTRIBUTES, **NG_MODULE_ATTRIBUTES), **{ "tsconfig": attr.label(allow_files = True, single_file = True), # @// is special syntax for the "main" repository @@ -249,6 +290,6 @@ ng_module = rule( "node_modules": attr.label( default = Label("@//:node_modules") ), - }, + }), outputs = COMMON_OUTPUTS, ) diff --git a/packages/bazel/src/rules_typescript.bzl b/packages/bazel/src/rules_typescript.bzl index 99fff5cca4..5c30db7469 100644 --- a/packages/bazel/src/rules_typescript.bzl +++ b/packages/bazel/src/rules_typescript.bzl @@ -1,12 +1,26 @@ -# Allows different paths for these imports in google3 -load("@build_bazel_rules_typescript//internal:build_defs.bzl", "tsc_wrapped_tsconfig") +"""Allows different paths for these imports in google3. +""" -load("@build_bazel_rules_typescript//internal:common/compilation.bzl", - "COMMON_ATTRIBUTES", - "COMMON_OUTPUTS", - "compile_ts", - "DEPS_ASPECTS", - "ts_providers_dict_to_struct", +load("@build_bazel_rules_typescript//internal:build_defs.bzl", + _tsc_wrapped_tsconfig = "tsc_wrapped_tsconfig", ) -load("@build_bazel_rules_typescript//internal:common/json_marshal.bzl", "json_marshal") +load("@build_bazel_rules_typescript//internal:common/compilation.bzl", + _COMMON_ATTRIBUTES = "COMMON_ATTRIBUTES", + _COMMON_OUTPUTS = "COMMON_OUTPUTS", + _compile_ts = "compile_ts", + _DEPS_ASPECTS = "DEPS_ASPECTS", + _ts_providers_dict_to_struct = "ts_providers_dict_to_struct", +) + +load("@build_bazel_rules_typescript//internal:common/json_marshal.bzl", + _json_marshal = "json_marshal", +) + +tsc_wrapped_tsconfig = _tsc_wrapped_tsconfig +COMMON_ATTRIBUTES = _COMMON_ATTRIBUTES +COMMON_OUTPUTS = _COMMON_OUTPUTS +compile_ts = _compile_ts +DEPS_ASPECTS = _DEPS_ASPECTS +ts_providers_dict_to_struct = _ts_providers_dict_to_struct +json_marshal = _json_marshal diff --git a/scripts/ci/env.sh b/scripts/ci/env.sh index 8b862cad64..8949570e89 100755 --- a/scripts/ci/env.sh +++ b/scripts/ci/env.sh @@ -40,7 +40,7 @@ setEnvVar YARN_VERSION 1.0.2 # Revision 494239 (which was part of Chrome 62.0.3186.0) is the last version that does not cause flakes. (Latest revision checked: 508578) setEnvVar CHROMIUM_VERSION 494239 # Chrome 62 linux stable, see https://www.chromium.org/developers/calendar setEnvVar CHROMEDRIVER_VERSION_ARG "--versions.chrome 2.33" -setEnvVar BAZEL_VERSION 0.8.1 +setEnvVar BAZEL_VERSION 0.9.0 setEnvVar SAUCE_CONNECT_VERSION 4.4.9 setEnvVar ANGULAR_CLI_VERSION 1.6.3 setEnvVar PROJECT_ROOT $(cd ${thisDir}/../..; pwd)