diff --git a/package.json b/package.json index f70c61f075c..a545b987cc1 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "@bazel/rollup": "5.4.1", "@bazel/runfiles": "5.4.1", "@bazel/terser": "5.4.1", + "@bazel/worker": "5.4.1", "@microsoft/api-extractor": "7.22.2", "@rollup/plugin-babel": "^5.3.0", "@rollup/plugin-commonjs": "^21.0.0", diff --git a/packages/bazel/package.json b/packages/bazel/package.json index cbfa8714dd7..007931c0820 100644 --- a/packages/bazel/package.json +++ b/packages/bazel/package.json @@ -30,6 +30,7 @@ "peerDependencies": { "@angular/compiler-cli": "0.0.0-PLACEHOLDER", "@bazel/concatjs": "^5.3.0", + "@bazel/worker": "^5.3.0", "@rollup/plugin-commonjs": "^21.0.0", "@rollup/plugin-node-resolve": "^13.0.4", "rollup": "^2.56.3", diff --git a/packages/bazel/src/ng_package/ng_package.bzl b/packages/bazel/src/ng_package/ng_package.bzl index 93e94de34b6..193ac4fde0f 100644 --- a/packages/bazel/src/ng_package/ng_package.bzl +++ b/packages/bazel/src/ng_package/ng_package.bzl @@ -221,7 +221,7 @@ def _run_rollup(ctx, bundle_name, rollup_config, entry_point, inputs, js_output, if stamp and ctx.version_file: other_inputs.append(ctx.version_file) ctx.actions.run( - progress_message = "ng_package: Rollup %s %s" % (bundle_name, ctx.label), + progress_message = "ng_package: Rollup %s (%s)" % (bundle_name, entry_point.short_path), mnemonic = "AngularPackageRollup", inputs = inputs.to_list() + other_inputs, outputs = [js_output, map_output], diff --git a/packages/bazel/src/types_bundle/BUILD.bazel b/packages/bazel/src/types_bundle/BUILD.bazel index 761c77abbb9..e08ad5cfecb 100644 --- a/packages/bazel/src/types_bundle/BUILD.bazel +++ b/packages/bazel/src/types_bundle/BUILD.bazel @@ -10,6 +10,7 @@ ts_library( "index.ts", ], deps = [ + "@npm//@bazel/worker", "@npm//@microsoft/api-extractor", "@npm//@types/node", ], @@ -17,11 +18,7 @@ ts_library( nodejs_binary( name = "types_bundler", - data = [ - ":lib", - "@npm//@bazel/concatjs", - "@npm//@microsoft/api-extractor", - ], + data = [":lib"], entry_point = ":index.ts", # Disable the linker and rely on patched resolution which works better on Windows # and is less prone to race conditions when targets build concurrently. diff --git a/packages/bazel/src/types_bundle/index.bzl b/packages/bazel/src/types_bundle/index.bzl index 63ad36b7c07..e52a9dd1fcd 100644 --- a/packages/bazel/src/types_bundle/index.bzl +++ b/packages/bazel/src/types_bundle/index.bzl @@ -28,12 +28,19 @@ def bundle_type_declaration( args.add(license_banner_file.path) inputs.append(license_banner_file) + # Pass arguments using a flag-file prefixed with `@`. This is + # a requirement for build action arguments in persistent workers. + # https://docs.bazel.build/versions/main/creating-workers.html#work-action-requirements. + args.use_param_file("@%s", use_always = True) + args.set_param_file_format("multiline") + ctx.actions.run( mnemonic = "BundlingTypes", inputs = depset(inputs, transitive = [types]), outputs = [output_file], executable = ctx.executable._types_bundler_bin, arguments = [args], + execution_requirements = {"supports-workers": "1"}, progress_message = "Bundling types (%s)" % entry_point.short_path, ) diff --git a/packages/bazel/src/types_bundle/index.ts b/packages/bazel/src/types_bundle/index.ts index 6703537d49e..28fbb89da74 100644 --- a/packages/bazel/src/types_bundle/index.ts +++ b/packages/bazel/src/types_bundle/index.ts @@ -9,7 +9,8 @@ /// /// -import {Extractor, ExtractorConfig, IConfigFile, IExtractorConfigPrepareOptions,} from '@microsoft/api-extractor'; +import {runAsWorker, runWorkerLoop} from '@bazel/worker'; +import {Extractor, ExtractorConfig, ExtractorMessage, IConfigFile, IExtractorConfigPrepareOptions} from '@microsoft/api-extractor'; import * as fs from 'fs'; import * as path from 'path'; @@ -55,7 +56,8 @@ export async function runMain( }; const extractorConfig = ExtractorConfig.prepare(options); - const {succeeded} = Extractor.invoke(extractorConfig); + const {succeeded} = + Extractor.invoke(extractorConfig, {messageCallback: handleApiExtractorMessage}); if (!succeeded) { throw new Error('Type bundling failed. See error above.'); @@ -89,12 +91,51 @@ function stripAmdModuleDirectiveComments(content: string): string { return content.replace(/^\/\/\/ [\r\n]+/gm, ''); } -// Entry point -const [entryPointExecpath, outputExecpath, packageJsonExecpath, licenseBannerExecpath] = - process.argv.slice(2); +/** + * Handles logging messages from API extractor. + * + * Certain info messages should be omitted and other messages should be printed + * to stderr to avoid worker protocol conflicts. + */ +function handleApiExtractorMessage(msg: ExtractorMessage): void { + msg.handled = true; -runMain({entryPointExecpath, outputExecpath, packageJsonExecpath, licenseBannerExecpath}) - .catch(e => { - console.error(e); + if (msg.messageId === 'console-compiler-version-notice' || msg.messageId === 'console-preamble') { + return; + } + + if (msg.logLevel !== 'verbose' && msg.logLevel !== 'none') { + console.error(msg.text); + } +} + +/** Runs one build using the specified build action command line arguments. */ +async function runOneBuild(args: string[]): Promise { + const [entryPointExecpath, outputExecpath, packageJsonExecpath, licenseBannerExecpath] = args; + + try { + await runMain({entryPointExecpath, outputExecpath, packageJsonExecpath, licenseBannerExecpath}); + return true; + } catch (e) { + console.error(e); + return false; + } +} + +// Entry-point. +const processArgs = process.argv.slice(2); + +if (runAsWorker(processArgs)) { + runWorkerLoop(runOneBuild); +} else { + // In non-worker mode we need to manually read the flag file and omit + // the leading `@` that is added as part of the worker requirements. + const flagFile = processArgs[0].substring(1); + const args = fs.readFileSync(flagFile, 'utf8').split('\n'); + + runOneBuild(args).then(success => { + if (!success) { process.exitCode = 1; - }); + } + }); +}