diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa8cf10d4..c55e0ebe2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,15 +45,16 @@ jobs: - run: yarn install --immutable - run: yarn bazel test -- //... - test-macos: - timeout-minutes: 30 - runs-on: macos-latest - steps: - # Because the checkout and setup node action is contained in the dev-infra repo, we must - # checkout the repo to be able to run the action we have created. Other repos will skip - # this step. - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: ./github-actions/npm/checkout-and-setup-node - - uses: ./github-actions/bazel/setup - - run: yarn install --immutable - - run: yarn bazel test --sandbox_writable_path="$HOME/Library/Application Support" --test_tag_filters=macos --build_tests_only -- //... + # macos testing is disabled as we do not have any targets we currently test. + #test-macos: + # timeout-minutes: 30 + # runs-on: macos-latest + # steps: + # # Because the checkout and setup node action is contained in the dev-infra repo, we must + # # checkout the repo to be able to run the action we have created. Other repos will skip + # # this step. + # - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + # - uses: ./github-actions/npm/checkout-and-setup-node + # - uses: ./github-actions/bazel/setup + # - run: yarn install --immutable + # - run: yarn bazel test --sandbox_writable_path="$HOME/Library/Application Support" --test_tag_filters=macos --build_tests_only -- //... diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 023accd47..5076d10dd 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -56,15 +56,16 @@ jobs: - run: yarn install --immutable - run: yarn bazel test -- //... - test-macos: - timeout-minutes: 30 - runs-on: macos-latest - steps: - # Because the checkout and setup node action is contained in the dev-infra repo, we must - # checkout the repo to be able to run the action we have created. Other repos will skip - # this step. - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: ./github-actions/npm/checkout-and-setup-node - - uses: ./github-actions/bazel/setup - - run: yarn install --immutable - - run: yarn bazel test --sandbox_writable_path="$HOME/Library/Application Support" --test_tag_filters=macos --build_tests_only -- //... + # macos testing is disabled as we do not have any targets we currently test. + #test-macos: + # timeout-minutes: 30 + # runs-on: macos-latest + # steps: + # # Because the checkout and setup node action is contained in the dev-infra repo, we must + # # checkout the repo to be able to run the action we have created. Other repos will skip + # # this step. + # - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + # - uses: ./github-actions/npm/checkout-and-setup-node + # - uses: ./github-actions/bazel/setup + # - run: yarn install --immutable + # - run: yarn bazel test --sandbox_writable_path="$HOME/Library/Application Support" --test_tag_filters=macos --build_tests_only -- //... diff --git a/WORKSPACE b/WORKSPACE index 691a95ce5..aad8c8e94 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -2,6 +2,7 @@ workspace( name = "devinfra", ) +load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # The PKG rules are needed to build tar packages for integration tests. The builtin @@ -99,10 +100,6 @@ load("@io_bazel_rules_webtesting//web:repositories.bzl", "web_test_repositories" web_test_repositories() -load("//bazel/browsers:browser_repositories.bzl", "browser_repositories") - -browser_repositories() - load("@build_bazel_rules_nodejs//toolchains/esbuild:esbuild_repositories.bzl", "esbuild_repositories") esbuild_repositories( @@ -166,3 +163,17 @@ esbuild_register_toolchains( name = "esbuild", esbuild_version = LATEST_ESBUILD_VERSION, ) + +git_repository( + name = "rules_browsers", + commit = "56ef8007ea07cd1916429bca8bb523433b0e9cdc", + remote = "https://github.com/devversion/rules_browsers.git", +) + +load("@rules_browsers//setup:step_1.bzl", "rules_browsers_setup_1") + +rules_browsers_setup_1() + +load("@rules_browsers//setup:step_2.bzl", "rules_browsers_setup_2") + +rules_browsers_setup_2() diff --git a/bazel/BUILD.bazel b/bazel/BUILD.bazel index d8f28ff18..677b6f76f 100644 --- a/bazel/BUILD.bazel +++ b/bazel/BUILD.bazel @@ -22,14 +22,10 @@ filegroup( "extract_types.bzl", "filter_outputs.bzl", "//bazel/api-golden:files", - "//bazel/app-bundling:files", - "//bazel/browsers:files", "//bazel/constraints:files", "//bazel/esbuild:files", "//bazel/git-toolchain:files", "//bazel/http-server:files", - "//bazel/karma:files", - "//bazel/map-size-tracking:files", "//bazel/private:files", "//bazel/remote-execution:files", "//bazel/spec-bundling:files", diff --git a/bazel/app-bundling/BUILD.bazel b/bazel/app-bundling/BUILD.bazel deleted file mode 100644 index 1c27a95d1..000000000 --- a/bazel/app-bundling/BUILD.bazel +++ /dev/null @@ -1,21 +0,0 @@ -load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary") - -package(default_visibility = ["//visibility:public"]) - -exports_files([ - "terser_config.json", - "esbuild.config-tmpl.mjs", -]) - -nodejs_binary( - name = "brotli-compress", - data = ["brotli-compress.cjs"], - entry_point = ":brotli-compress.cjs", - templated_args = ["--nobazel_run_linker"], -) - -# Make source files available for distribution via pkg_npm -filegroup( - name = "files", - srcs = glob(["*"]), -) diff --git a/bazel/app-bundling/brotli-compress.cjs b/bazel/app-bundling/brotli-compress.cjs deleted file mode 100644 index e35aecaf9..000000000 --- a/bazel/app-bundling/brotli-compress.cjs +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 - */ - -const fs = require('fs'); -const {brotliCompressSync} = require('zlib'); - -function main(args) { - const output = args[0].substring('--output='.length); - const input = args[1]; - const buffer = fs.readFileSync(input); - fs.writeFileSync(output, brotliCompressSync(buffer)); -} - -if (require.main === module) { - main(process.argv.slice(2)); -} diff --git a/bazel/app-bundling/esbuild.config-tmpl.mjs b/bazel/app-bundling/esbuild.config-tmpl.mjs deleted file mode 100644 index 81e67de5c..000000000 --- a/bazel/app-bundling/esbuild.config-tmpl.mjs +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {createEsbuildAngularOptimizePlugin} from '@angular/build-tooling/shared-scripts/angular-optimization/esbuild-plugin.mjs'; -import {GLOBAL_DEFS_FOR_TERSER_WITH_AOT} from '@angular/compiler-cli/private/tooling'; -import * as path from 'path'; - -/** Root path pointing to the app bundle source entry-point file. */ -const entryPointSourceRootPath = path.normalize(`TMPL_ENTRY_POINT_ROOTPATH`); - -/** - * Root path to the bundle entry-point without extension. - * - * The extension of the bundle entry-point file is not known because the ESBuild - * rule strips the source extension (like `.ts`) and resolves the file based on - * the resolved inputs. - */ -const entryPointBasepath = entryPointSourceRootPath.replace(/\.[^.]+$/, ''); - -/** Whether the given file is considered side-effect free. */ -function isFileSideEffectFree(filePath) { - // All files except for the entry-point are considered side-effect free. We - // naively check using `includes` as a root path is quite unique regardless. - return !filePath.includes(entryPointBasepath); -} - -export default { - // Note: We prefer `.mjs` here as this is the extension used by Angular APF - // packages. - resolveExtensions: ['.mjs', '.js'], - // Based on the CLI configuration: - // https://github.com/angular/angular-cli/blame/8089c9388056b3caaf56f981848aca94f022da73/packages/angular_devkit/build_angular/src/tools/esbuild/application-code-bundle.ts#L51. - conditions: ['es2022', 'es2020', 'es2015', 'module'], - // Note: ES2015 main condition is needed for `rxjs@v6`. - mainFields: ['fesm2022', 'es2022', 'es2020', 'es2015', 'module', 'main'], - // The majority of these options match with the ones the CLI sets: - // https://github.com/angular/angular-cli/blob/0d76bf04bca6e083865972b5398a32bbe9396e14/packages/angular_devkit/build_angular/src/webpack/plugins/javascript-optimizer-worker.ts#L133. - treeShaking: true, - pure: ['forwardRef'], - legalComments: 'none', - supported: { - // We always downlevel `async/await` when bundling apps. The Angular CLI does the - // same with its ESBuild experimental builder, and with the non-esbuild pipeline - // Babel is used to downlevel async/await. See: - // https://github.com/angular/angular-cli/blob/afe9feaa45913cbebe7f22c678d693d96f38584a/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts#L111 - // https://github.com/angular/angular-cli/blob/afe9feaa45913/packages/angular_devkit/build_angular/src/builders/browser-esbuild/index.ts#L313-L318. - 'async-await': false, - }, - // ESBuild requires the `define` option to take a string-based dictionary. - define: convertObjectToStringDictionary(GLOBAL_DEFS_FOR_TERSER_WITH_AOT), - plugins: [ - await createEsbuildAngularOptimizePlugin({ - optimize: { - isSideEffectFree: isFileSideEffectFree, - }, - downlevelAsyncGeneratorsIfPresent: true, - enableLinker: { - ensureNoPartialDeclaration: false, - linkerOptions: { - linkerJitMode: false, - }, - }, - }), - ], -}; - -/** Converts an object to a string dictionary. */ -function convertObjectToStringDictionary(value) { - return Object.entries(value).reduce((result, [propName, value]) => { - result[propName] = String(value); - return result; - }, {}); -} diff --git a/bazel/app-bundling/index.bzl b/bazel/app-bundling/index.bzl deleted file mode 100644 index 31e8178db..000000000 --- a/bazel/app-bundling/index.bzl +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright Google LLC -# -# 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 - -load("@build_bazel_rules_nodejs//:index.bzl", "npm_package_bin") -load("@npm//@bazel/terser:index.bzl", "terser_minified") -load("@npm//prettier:index.bzl", "prettier") -load("//bazel:expand_template.bzl", "expand_template") -load("//bazel:filter_outputs.bzl", "filter_outputs") -load("//bazel/esbuild:index.bzl", "esbuild", "esbuild_config") - -def _create_esbuild_minify_options(debug = False): - # The minify options match with the configuration used by the CLI. The whitespace - # minification is left to Terser. More details can be found here: - # https://github.com/angular/angular-cli/blob/0d76bf04bca6e083865972b5398a32bbe9396e14/packages/angular_devkit/build_angular/src/webpack/plugins/javascript-optimizer-worker.ts#L133. - return { - "minifyIdentifiers": not debug, - "minifySyntax": True, - "minifyWhitespace": False, - } - -def app_bundle( - name, - entry_point, - visibility = None, - testonly = False, - platform = "browser", - target = "es2022", - format = "iife", - **kwargs): - """ - Bundles an Angular applications in an optimized way that closely matches - the compilation pipeline as within the Angular CLI. - - The rule produces a number of output bundles. - - JS : "%{name}.js" - JS minified : "%{name}.min.js" - JS minified (compressed) : "%{name}.min.js.br", - ---- - JS debug : "%{name}.debug.js" - JS debug minified : "%{name}.debug.min.js" - JS debug minified (beautified) : "%{name}.debug.min.beautified.js" - """ - - common_base_attributes = { - "testonly": testonly, - "visibility": visibility, - } - - expand_template( - name = "%s_config_file" % name, - output_name = "%s_config.mjs" % name, - template = "//bazel/app-bundling:esbuild.config-tmpl.mjs", - substitutions = { - "TMPL_ENTRY_POINT_ROOTPATH": "$(rootpath %s)" % entry_point, - }, - data = [entry_point], - **common_base_attributes - ) - - esbuild_config( - name = "%s_esbuild_config" % name, - config_file = ":%s_config_file" % name, - deps = [ - "@npm//@angular/compiler-cli", - "//shared-scripts/angular-optimization:js_lib", - ], - **common_base_attributes - ) - - common_esbuild_options = dict({ - "config": "%s_esbuild_config" % name, - "entry_point": entry_point, - "target": target, - "platform": platform, - "format": format, - "sourcemap": "external", - }, **common_base_attributes) - - common_terser_options = dict({ - "config_file": "//bazel/app-bundling:terser_config.json", - "sourcemap": True, - }, **common_base_attributes) - - esbuild( - name = name, - args = _create_esbuild_minify_options(False), - **dict(kwargs, **common_esbuild_options) - ) - - esbuild( - name = "%s.debug" % name, - args = _create_esbuild_minify_options(True), - **dict(kwargs, tags = ["manual"], **common_esbuild_options) - ) - - terser_minified(name = name + ".min", src = ":%s" % name, **common_terser_options) - filter_outputs(name = name + ".min.js", target = ":%s.min" % name, filters = ["%s.min.js" % name], **common_base_attributes) - filter_outputs(name = name + ".min.js.map", target = ":%s.min" % name, filters = ["%s.min.js.map" % name], **common_base_attributes) - - terser_minified(name = name + ".debug.min", src = ":%s.debug" % name, debug = True, tags = ["manual"], **common_terser_options) - filter_outputs(name = name + ".debug.min.js", target = ":%s.debug.min" % name, filters = ["%s.debug.min.js" % name], **common_base_attributes) - filter_outputs(name = name + ".debug.min.js.map", target = ":%s.debug.min" % name, filters = ["%s.debug.min.js.map" % name], **common_base_attributes) - - # For better debugging, we also run prettier on the minified debug bundle. This is - # necessary as Terser no longer has beautify/formatting functionality. - prettier( - name = name + ".debug.min.beautified", - args = ["$(execpath %s)" % (name + ".debug.min")], - # The `outs` attribute needs to be set when `stdout` is captured as an output. - outs = [], - stdout = name + ".debug.min.beautified.js", - data = [name + ".debug.min"], - tags = ["manual"], - **common_base_attributes - ) - - npm_package_bin( - name = "_%s_brotli" % name, - tool = "//bazel/app-bundling:brotli-compress", - data = [name + ".min.js"], - outs = [name + ".min.js.br"], - args = [ - "--output=$(execpath %s.min.js.br)" % name, - "$(execpath %s.min.js)" % name, - ], - **common_base_attributes - ) diff --git a/bazel/app-bundling/terser_config.json b/bazel/app-bundling/terser_config.json deleted file mode 100644 index d0af1569e..000000000 --- a/bazel/app-bundling/terser_config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "ecma": "es2020", - "compress": { - "passes": 2, - "pure_getters": true - }, - "format": { - "ascii_only": true, - "wrap_func_args": false - }, - "mangle": false -} diff --git a/bazel/app-bundling/test/BUILD.bazel b/bazel/app-bundling/test/BUILD.bazel deleted file mode 100644 index 8a6976a35..000000000 --- a/bazel/app-bundling/test/BUILD.bazel +++ /dev/null @@ -1,49 +0,0 @@ -load("@npm//@angular/bazel:index.bzl", "ng_module") -load("//bazel/app-bundling:index.bzl", "app_bundle") -load("//tools:defaults.bzl", "jasmine_node_test", "ts_library") - -ng_module( - name = "test_fixture_lib", - srcs = ["main_fixture.ts"], - tsconfig = "tsconfig.json", - deps = [ - "@npm//@angular/core", - "@npm//@angular/platform-browser", - ], -) - -app_bundle( - name = "bundle", - entry_point = "main_fixture.ts", - tags = ["some-test-tag"], - deps = [":test_fixture_lib"], -) - -ts_library( - name = "test_lib", - testonly = True, - srcs = [ - "bundle.spec.ts", - ], - deps = [ - "@npm//@bazel/runfiles", - "@npm//@types/jasmine", - "@npm//@types/jsdom", - "@npm//@types/node", - "@npm//jsdom", - ], -) - -jasmine_node_test( - name = "test", - data = [ - ":bundle.min.js", - ":bundle.min.js.map", - "@npm//jsdom", - ], - # JSDOM should not be bundled because it has workers and dynamic imports. - external = ["jsdom"], - specs = [ - ":test_lib", - ], -) diff --git a/bazel/app-bundling/test/bundle.spec.ts b/bazel/app-bundling/test/bundle.spec.ts deleted file mode 100644 index 133055bcf..000000000 --- a/bazel/app-bundling/test/bundle.spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 * as fs from 'fs'; -import {JSDOM} from 'jsdom'; -import {runInNewContext} from 'vm'; -import {runfiles} from '@bazel/runfiles'; - -/** Absolute file path to the built minified app bundle. */ -const bundleScriptPath = runfiles.resolveWorkspaceRelative('bazel/app-bundling/test/bundle.min.js'); - -const appIndexHtml = ` - - - - - -`; - -describe('app bundling', () => { - /** - * Executes the app in a virtual DOM and waits for bootstrap - * to complete. - */ - async function executeBundleWithVirtualDom() { - const code = await fs.promises.readFile(bundleScriptPath, 'utf8'); - const {window} = new JSDOM(appIndexHtml); - const document = window.document; - - runInNewContext(code, { - window, - document, - clearTimeout, - }); - - await window.bootstrapPromise; - - return {window, document}; - } - - it('should be possible to run the generated bundle', async () => { - const {document} = await executeBundleWithVirtualDom(); - - expect(document.body.innerHTML).toContain('Hello'); - expect(document.body.innerHTML).toContain('Hello', - standalone: false, -}) -class AppComponent {} - -@NgModule({ - imports: [BrowserModule], - declarations: [AppComponent], - bootstrap: [AppComponent], -}) -class AppModule {} - -enableProdMode(); - -(window as any).bootstrapPromise = platformBrowser().bootstrapModule(AppModule, { - ngZone: 'noop', -}); diff --git a/bazel/app-bundling/test/package.json b/bazel/app-bundling/test/package.json deleted file mode 100644 index 3dbc1ca59..000000000 --- a/bazel/app-bundling/test/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "module" -} diff --git a/bazel/app-bundling/test/pnpm-lock.yaml b/bazel/app-bundling/test/pnpm-lock.yaml deleted file mode 100644 index 9b60ae178..000000000 --- a/bazel/app-bundling/test/pnpm-lock.yaml +++ /dev/null @@ -1,9 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: {} diff --git a/bazel/app-bundling/test/tsconfig.json b/bazel/app-bundling/test/tsconfig.json deleted file mode 100644 index 7907f7235..000000000 --- a/bazel/app-bundling/test/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "compilerOptions": { - "experimentalDecorators": true, - "importHelpers": true - } -} diff --git a/bazel/browsers/BUILD.bazel b/bazel/browsers/BUILD.bazel deleted file mode 100644 index 6d2a350fd..000000000 --- a/bazel/browsers/BUILD.bazel +++ /dev/null @@ -1,10 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -# Make source files available for distribution via pkg_npm -filegroup( - name = "files", - srcs = glob(["*"]) + [ - "//bazel/browsers/chromium:files", - "//bazel/browsers/firefox:files", - ], -) diff --git a/bazel/browsers/README.md b/bazel/browsers/README.md deleted file mode 100644 index dc244375f..000000000 --- a/bazel/browsers/README.md +++ /dev/null @@ -1,137 +0,0 @@ -# Browser configuration and versioning for testing of Angular - -Within the Angular organization, we use Chrome and Firefox to perform most of the local testing, and rely on Sauce Labs and BrowserStack to do cross-browser testing on our CI. - -The version of Chrome used in tests within this monorepo is configured and controlled via Bazel and `puppeteer`. -We manually keep the configuration of these two tools in sync to create a consistent testing environment across unit, e2e, and integration tests. - -## Bazel - -Bazel `karma_web_test_suite` and `protractor_web_test_suite` targets will use Chromium or Firefox provisioned by `//bazel/browsers`. -The version of Chrome and Firefox are specified in the `chromium.bzl` and `firefox.bzl` files in `/bazel/browsers`. - -The process of updating the Chrome or Firefox version is not straightforward, but below are dedicated sections for each browser. - -## Updating Chromium - -1. Run `bazel run bazel/browsers/update-script find-latest-chromium-revision` - -2. Inspect the console output which looks like the following: - -``` -Release Info: https://storage.googleapis.com/chromium-find-releases-static/index.html#r885453 -Click on the link above to determine the Chromium version number. - -MAC: https://storage.googleapis.com/chromium-browser-snapshots/Mac/885453/chrome-mac.zip - 0c7ed37b2128c992d5563a5b54d2c2790ce4872d2004b298ca073c7db4cc3f58 - https://storage.googleapis.com/chromium-browser-snapshots/Mac/885453/chromedriver_mac64.zip - fc5150742c045b12ec0a138365b87be3d4216a52bf6b65c914325e941a3c8af7 - -WINDOWS: https://storage.googleapis.com/chromium-browser-snapshots/Win/885453/chrome-win.zip - 2a78bc9331a9fd7d1153e9e87cad85948853d4e37427d053dc88887ac9774a69 - https://storage.googleapis.com/chromium-browser-snapshots/Win/885453/chromedriver_win32.zip - bdde7e7aa6349dd0e6e185c07c2fdef4a8f60739eacd79ee49c175390231be20 - -LINUX: https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/885453/chrome-linux.zip - ac5d11ff66698cb29ece33f8a38de011d2384c609123f421b771aafeea87f679 - https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/885453/chromedriver_linux64.zip - aa38374059252bb7896d79ac7bb4b3ee3eca84cfa5641f432e05bba5f04c01a2 - -``` - -3. Click on the `Release Info` URL and update version number comments in the `chromium.bzl` file so - that it is easier to figure out which version of Chromium is configured. - -4. Update the `chromium` and `chromedriver` repository URLs for all platforms to use the - new URLs printed out by the tool. Also make sure to update the SHA256 checksums. The tool prints the - new checksums for convenient copy & paste. - -5. Update the dev-infra Google Cloud Storage mirror by running the following command. - You need to acquire a service key for the `dev-infra-gcs-manager` service account. - -```bash -GOOGLE_APPLICATION_CREDENTIALS= \ - bazel run bazel/browsers/update-script upload-to-mirror chromium -``` - -Update the fallback `dev-infra-mirror` URLs for your browser archives to point to the newly -uploaded files (as printed by the script to the terminal output). - -## Puppeteer - -1. Visit https://github.com/puppeteer/puppeteer/blob/master/docs/api.md to determine which version of puppeteer corresponds to the version of Chrome desired. - -2. Visit https://chromedriver.chromium.org/downloads to determine which version of ChromeDriver should be used for the version of Chrome desired. - - > NOTE: - > The version of Chrome does not necessarily correspond exactly with the version of ChromeDriver. - > For example, you might have to use ChromeDriver v87.0.4280.x to drive Chrome v87.0.4272.x. - -3. Update `scripts/puppeteer-chromedriver-versions.js` to include an entry with the new version of puppeteer as key and the new version of ChromeDriver as value (as determined in the two previous steps). - -4. Update all of the puppeteer versions throughout the repo: - - - `package.json` - - `aio/package.json` - - `aio/tools/examples/shared/package.json` - - ...and their corresponding `yarn.lock` files. - -## Firefox - -In order to update Firefox, open the `bazel/browsers/firefox/firefox.bzl` file and update the repository URLs to the desired version. -For example: - -```bzl -platform_http_file( - name = "org_mozilla_firefox_amd64", - licenses = ["reciprocal"], # MPL 2.0 - sha256 = "bde6e020556a21561e4b8d7aaecf8db7077951f179b98ca5d0305435bc6802c9", - # Firefox v78.0 - urls = ["https://ftp.mozilla.org/pub/firefox/releases/78.0/linux-x86_64/en-US/firefox-78.0.tar.bz2"], -) -``` - -1. Go to the `urls` property and update the URL by replacing all `78.0` occurrences with the version you intend to use. - Once done, do the same change for other platforms (such as `macos`). - -2. Update the `sha256` checksum of the browser archives. - You can do this by downloading the artifacts from the URLs you just updated, and then running `shasum` on those files: - - ```sh - curl -L | shasum -a 256 - ``` - -3. Go to https://firefox-source-docs.mozilla.org/testing/geckodriver/Support.html and find a version that is compatible with the version of Firefox being used. - -4. Update the `geckodriver` repository URLs to the desired version: - - ```bzl - platform_http_file( - name = "org_mozilla_geckodriver_amd64", - licenses = ["reciprocal"], # MPL 2.0 - sha256 = "d59ca434d8e41ec1e30dd7707b0c95171dd6d16056fb6db9c978449ad8b93cc0", - # Geckodriver v0.26.0 - urls = ["https://github.com/mozilla/geckodriver/releases/download/v0.26.0/geckodriver-v0.26.0-linux64.tar.gz"], - ) - ``` - - For example, replace all occurrences of `0.26.0` with the newer version. - -5. Update the `sha256` checksum of the driver archives. - You can do this by downloading the artifacts from the URLs you just updated, and then running `shasum` on those files: - - ```sh - curl -L | shasum -a 256 - ``` - -6. Update the dev-infra Google Cloud Storage mirror by running the following command. - You need to acquire a service key for the `dev-infra-gcs-manager` service account. - -```bash -GOOGLE_APPLICATION_CREDENTIALS= \ - bazel run bazel/browsers/update-script upload-to-mirror firefox -``` - -Update the fallback `dev-infra-mirror` URLs for your browser archives to point to the newly -uploaded files (as printed by the script to the terminal output). diff --git a/bazel/browsers/browser_archive_repo.bzl b/bazel/browsers/browser_archive_repo.bzl deleted file mode 100644 index 0bccf21c3..000000000 --- a/bazel/browsers/browser_archive_repo.bzl +++ /dev/null @@ -1,123 +0,0 @@ -"""Implementation of the `browser_archive` rule.""" - -def _browser_archive_impl(ctx): - urls = ctx.attr.urls - sha256 = ctx.attr.sha256 - - # If the URL resolves to a `.dmg` file, then we need to convert the file - # to a zip so that we can extract the actual binaries. We use the `convert_dmg` - # script provided by the webtesting Bazel rules. - if urls[0].endswith(".dmg"): - download_file_name = "_download_file_%s.dmg" % ctx.attr.name - result_zip_name = "_converted_file_%s.zip" % ctx.attr.name - - ctx.download(urls, download_file_name, sha256) - ctx.execute([ctx.path(Label("@io_bazel_rules_webtesting//web/internal:convert_dmg.sh")), download_file_name, result_zip_name]) - ctx.extract(result_zip_name) - - ctx.delete(result_zip_name) - ctx.delete(download_file_name) - else: - ctx.download_and_extract( - url = urls, - sha256 = sha256, - ) - - # The browser archive has been downloaded and extracted. We now generate a repository - # `BUILD.bazel` file that exposes the archive files, together with the specified - # named files using the `browser_configure` rule. - ctx.file("BUILD.bazel", content = """ -load("@devinfra//bazel/browsers:browser_configure.bzl", "browser_configure") - -licenses(%s) - -browser_configure( - name = "metadata", - files = glob(["**/*"], exclude = %s), - named_files = %s, - visibility = ["//visibility:public"], -) - -exports_files(%s) -""" % ( - str(ctx.attr.licenses), - str(ctx.attr.exclude_patterns), - str(ctx.attr.named_files), - str(ctx.attr.exports_files), - )) - -""" - Rule that can be used to download and unpack a browser archive in a dedicated Bazel - repository. Additionally, files within the archive can be denoted with an unique name - so that web tests can access browser files in a platform-agnostic way, regardless of - which `browser_archive` repository is added as dependency. - - As an example for the concept of denoting archive files with an unique name, consider a case - where a web test decides conditionally based on the current exec platform which - `browser_archive` repository is used (e.g. mac, windows or linux). The archives are different - for each platform. The test usually would need to determine the current platform, and know how - each archive is structured in order to access the browser binary within the repository. By - defining named files though, the web test could just pull a named file called `BINARY` that - always resolves to the browser binary in a platform-agnostic way. - - Note #1: This rule exists as an alternative to the `platform_http_file` concept - from `rules_webtesting` because the `platform_http_file` rule does not extract the archive - directly, but relies on later build actions to perform the unpacking. This results in less - efficient caching because build actions are invalidated more frequently (e.g. `bazel clean). - We also noticed that the extraction within RBE containers is rather unstable, and extracting - the archives as part of a Bazel repository mitigates this (as extractions happens on the host). - - Note #2: Additionally `rules_webtesting` defines a single repository for all platforms, - where only an archive for the current host platform is pulled. This breaks cross-compilation - because the wrong platform archive would be used for web tests that run in the exec platform. -""" -browser_archive = repository_rule( - implementation = _browser_archive_impl, - attrs = { - "urls": attr.string_list( - doc = "URLs used for downloading the archive. Multiple URLs can be serve as fallback.", - mandatory = True, - ), - "sha256": attr.string( - doc = "SHA256 checksum for the archive.", - mandatory = True, - ), - "licenses": attr.string_list( - mandatory = True, - allow_empty = False, - doc = """ - Licenses that apply to the archive. Will be passed to a `licenses` invocation - within the repository. https://docs.bazel.build/versions/0.24.0/be/functions.html#licenses. - """, - ), - "named_files": attr.string_dict( - doc = """ - Dictionary that maps files to unique identifiers. This is useful - if browser archives are different on different platforms and the web - tests would not want to care about archive-specific paths. e.g. targets - expect a `CHROMIUM` key to point to the Chromium browser binary. - """, - mandatory = True, - ), - "exclude_patterns": attr.string_list( - default = [], - doc = """Patterns of files which should be excluded from the browser runfiles. - - This is useful for example when files with spaces are shipped as part of the - archives of browsers. Runfiles with spaces cause issues within Bazel and if - these files are not strictly needed, they should be omitted. - """, - ), - "exports_files": attr.string_list( - default = [], - doc = """Patterns of files which should be added to exports_files. - - This is useful for example when files with spaces are shipped as part of the - archives of browsers. Instead of individual files, the top-level source directory - can be depended on which resolves the runfiles with spaces issue. NB: source - directories are not compatible with remote execution so a target that uses sources - directory inputs should be tagged "local". - """, - ), - }, -) diff --git a/bazel/browsers/browser_configure.bzl b/bazel/browsers/browser_configure.bzl deleted file mode 100644 index 5ffd3dfd6..000000000 --- a/bazel/browsers/browser_configure.bzl +++ /dev/null @@ -1,75 +0,0 @@ -load("@io_bazel_rules_webtesting//web/internal:metadata.bzl", "metadata") -load("@io_bazel_rules_webtesting//web/internal:provider.bzl", "WebTestInfo") - -NamedFilesInfo = provider( - doc = "Provider exposing the named files of an extracted browser archive.", - fields = { - "value": "Dictionary of keys and their corresponding manifest paths", - }, -) - -def _label_to_manifest_path(label): - """Converts the specified label to a manifest path""" - if label.package != "": - return "%s/%s" % (label.workspace_name, label.package) - return label.workspace_name - -def _browser_configure_impl(ctx): - """Implementation of the `browser_configure` rule.""" - named_files = {} - base_dir = _label_to_manifest_path(ctx.label) - - # Update the named files to manifest paths that can be resolved - # with Bazel runfile resolution in web tests. - for n, p in ctx.attr.named_files.items(): - named_files[n] = base_dir + "/" + p - - # Create a web test metadata file that will be provided as part of - # the `WebTestInfo` provider. - metadata.create_file( - ctx = ctx, - output = ctx.outputs.web_test_metadata, - web_test_files = [ - metadata.web_test_files(ctx = ctx, named_files = named_files), - ], - ) - - return [ - DefaultInfo(runfiles = ctx.runfiles(files = ctx.files.files)), - WebTestInfo(metadata = ctx.outputs.web_test_metadata), - NamedFilesInfo(value = ctx.attr.named_files), - ] - -""" - Rule that is used in combination with the `browser_archive` rule. It captures a set - of files which are needed for dealing with a browser. Additionally, specific files - for the browser can be denoted with an unique name so that web tests can access browser - files in a platform-agnostic way, regardless of which browser repository is selected. - - The specified browser files are exposed as runfiles of the target defined through this - rule. The unique names with their associated files are captured within a metadata file - that is exposed through a `WebTestInfo` provider. Web tests will be able to deal with - this metadata file to resolve browser files in a platform-agnostic way. - - More details on this can be found in the `browser_archive` rule. -""" -browser_configure = rule( - attrs = { - "files": attr.label_list( - mandatory = True, - allow_files = True, - doc = "List of files which are needed for the browser.", - ), - "named_files": attr.string_dict( - doc = """ - Dictionary that maps files to unique identifiers. This is useful - if browser archives are different on different platforms and the web - tests would not want to care about archive-specific paths. e.g. targets - expect a `CHROMIUM` key to point to the Chromium browser binary. - """, - mandatory = True, - ), - }, - outputs = {"web_test_metadata": "%{name}.gen.json"}, - implementation = _browser_configure_impl, -) diff --git a/bazel/browsers/browser_repositories.bzl b/bazel/browsers/browser_repositories.bzl deleted file mode 100644 index ed77e6435..000000000 --- a/bazel/browsers/browser_repositories.bzl +++ /dev/null @@ -1,15 +0,0 @@ -"""Pinned browser versions. - -This function is here to make browser repositories work with cross-platform RBE. -Unlike the `rules_webtesting` `browser_repositories`, this function defines -separate repositories for each platform. -""" - -load("//bazel/browsers/chromium:chromium.bzl", "define_chromium_repositories") -load("//bazel/browsers/firefox:firefox.bzl", "define_firefox_repositories") - -def browser_repositories(): - """Load pinned rules_webtesting browser versions.""" - - define_chromium_repositories() - define_firefox_repositories() diff --git a/bazel/browsers/browser_toolchain_alias.bzl b/bazel/browsers/browser_toolchain_alias.bzl deleted file mode 100644 index c29549331..000000000 --- a/bazel/browsers/browser_toolchain_alias.bzl +++ /dev/null @@ -1,37 +0,0 @@ -load("//bazel/browsers:browser_configure.bzl", "NamedFilesInfo") - -def _browser_toolchain_alias_impl(ctx): - template_variables = {} - - for dep in ctx.attr.deps: - base_path = dep.label.workspace_name - named_files = dep[NamedFilesInfo].value - - for key, value in named_files.items(): - # We explicitly include the workspace name in the rootpath, so we need - # follow the `..//` pattern. This matches what the - # Bazel location expansion would generate for `$(rootpath )`. - # https://docs.bazel.build/versions/main/be/make-variables.html#predefined_label_variables. - template_variables[key] = "../%s/%s" % (base_path, value) - - return [ - platform_common.TemplateVariableInfo(template_variables), - ] - -browser_toolchain_alias = rule( - doc = """ - Exposes a toolchain alias exposing the template variables for all named files - included in the browser metadata dependencies. The values of the template variables - will follow the semantics of Bazel location rootpaths. - - The variables can be consumed within Bazel make variable expansion. - """, - implementation = _browser_toolchain_alias_impl, - attrs = { - "deps": attr.label_list( - doc = """Metadata targets that provides the browser named files.""", - mandatory = True, - providers = [NamedFilesInfo, DefaultInfo], - ), - }, -) diff --git a/bazel/browsers/chromium/BUILD.bazel b/bazel/browsers/chromium/BUILD.bazel deleted file mode 100644 index 5f15ba48a..000000000 --- a/bazel/browsers/chromium/BUILD.bazel +++ /dev/null @@ -1,49 +0,0 @@ -load("@io_bazel_rules_webtesting//web:web.bzl", "browser") -load("//bazel/browsers:browser_toolchain_alias.bzl", "browser_toolchain_alias") - -package(default_visibility = ["//visibility:public"]) - -PLATFORM_METADATA = select({ - "//bazel/constraints:linux_x64": [ - "@org_chromium_chromedriver_linux_x64//:metadata", - "@org_chromium_chromium_linux_x64//:metadata", - ], - "//bazel/constraints:macos_x64": [ - "@org_chromium_chromedriver_macos_x64//:metadata", - "@org_chromium_chromium_macos_x64//:metadata", - ], - "//bazel/constraints:macos_arm64": [ - "@org_chromium_chromedriver_macos_arm64//:metadata", - "@org_chromium_chromium_macos_arm64//:metadata", - ], - "//bazel/constraints:windows_x64": [ - "@org_chromium_chromedriver_windows//:metadata", - "@org_chromium_chromium_windows//:metadata", - ], -}) - -browser( - name = "chromium", - metadata = "chromium.json", - deps = PLATFORM_METADATA + [ - "@io_bazel_rules_webtesting//go/wsl", - ], -) - -browser( - name = "chromium-for-generation", - testonly = False, - metadata = "chromium.json", - deps = PLATFORM_METADATA, -) - -browser_toolchain_alias( - name = "toolchain_alias", - deps = PLATFORM_METADATA, -) - -# Make source files available for distribution via pkg_npm -filegroup( - name = "files", - srcs = glob(["*"]), -) diff --git a/bazel/browsers/chromium/chromium.bzl b/bazel/browsers/chromium/chromium.bzl deleted file mode 100644 index a78fe5c26..000000000 --- a/bazel/browsers/chromium/chromium.bzl +++ /dev/null @@ -1,140 +0,0 @@ -load("//bazel/browsers:browser_archive_repo.bzl", "browser_archive") - -""" - Defines repositories for Chromium that can be used inside Karma unit tests - and Protractor e2e tests with Bazel. -""" - -def define_chromium_repositories(): - # To update to a newer version of Chromium see instructions in - # https://github.com/angular/dev-infra/blob/master/bazel/browsers/README.md. - - browser_archive( - name = "org_chromium_chromium_linux_x64", - licenses = ["notice"], # BSD 3-clause (maybe more?) - sha256 = "e45b0439b7f69e0e885d6cae9535a9f1e5f0c206fd619044288e9a53e8a004c7", - # 114.0.5673.0 - urls = [ - "https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/1263141/chrome-linux.zip", - "https://storage.googleapis.com/dev-infra-mirror/chromium/1263141/linux_x64/browser-bin.zip", - ], - named_files = { - "CHROMIUM": "chrome-linux/chrome", - }, - exclude_patterns = [ - # Exclude a log file that chromium writes to each run, causing remote cache misses. - "chrome-linux/chrome_debug.log", - ], - exports_files = ["chrome-linux"], - ) - - browser_archive( - name = "org_chromium_chromium_macos_x64", - licenses = ["notice"], # BSD 3-clause (maybe more?) - sha256 = "c18ba7a79fda6bc82229fd9ff685ff0d7b41ab32845b7fb989daecd8a2b10a00", - # 114.0.5673.0 - urls = [ - "https://storage.googleapis.com/chromium-browser-snapshots/Mac/1263141/chrome-mac.zip", - "https://storage.googleapis.com/dev-infra-mirror/chromium/1263141/mac_x64/browser-bin.zip", - ], - named_files = { - "CHROMIUM": "chrome-mac/Chromium.app/Contents/MacOS/Chromium", - }, - exclude_patterns = [ - # Exclude a log file that chromium writes to each run, causing remote cache misses. - "chrome-mac/Chromium.app/Contents/Frameworks/Chromium Framework.framework/Versions/*/chrome_debug.log", - ], - exports_files = ["chrome-mac"], - ) - - browser_archive( - name = "org_chromium_chromium_macos_arm64", - licenses = ["notice"], # BSD 3-clause (maybe more?) - sha256 = "2debe4e82002cd898a7573a1e132fafd2cb21a5af70c811fda50ebe9abe37d08", - # 114.0.5673.0 - urls = [ - "https://storage.googleapis.com/chromium-browser-snapshots/Mac_Arm/1263141/chrome-mac.zip", - "https://storage.googleapis.com/dev-infra-mirror/chromium/1263141/mac_arm64/browser-bin.zip", - ], - named_files = { - "CHROMIUM": "chrome-mac/Chromium.app/Contents/MacOS/Chromium", - }, - exclude_patterns = [ - # Exclude a log file that chromium writes to each run, causing remote cache misses. - "chrome-mac/Chromium.app/Contents/Frameworks/Chromium Framework.framework/Versions/*/chrome_debug.log", - ], - exports_files = ["chrome-mac"], - ) - - browser_archive( - name = "org_chromium_chromium_windows", - licenses = ["notice"], # BSD 3-clause (maybe more?) - sha256 = "05f0d21f822531ab05e1daa33fb7bf1fcec51a2b6103a3f8b2b3edf3a3cd0ce0", - # 114.0.5673.0 - urls = [ - "https://storage.googleapis.com/chromium-browser-snapshots/Win/1263141/chrome-win.zip", - "https://storage.googleapis.com/dev-infra-mirror/chromium/1263141/windows_x64/browser-bin.zip", - ], - named_files = { - "CHROMIUM": "chrome-win/chrome.exe", - }, - exclude_patterns = [ - # Exclude files with spaces to prevent errors when symlinked as runfiles (https://github.com/bazelbuild/bazel/issues/4327). - "chrome-win/First Run", - # Exclude a log file that chromium writes to each run, causing remote cache misses. - "chrome-win/debug.log", - ], - exports_files = ["chrome-win"], - ) - - browser_archive( - name = "org_chromium_chromedriver_linux_x64", - licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT - sha256 = "3bd1ed0fee4153ab78eb61109c73657a965f6eabbbba8d0895626967b068beaa", - urls = [ - "https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/1263141/chromedriver_linux64.zip", - "https://storage.googleapis.com/dev-infra-mirror/chromium/1263141/linux_x64/driver-bin.zip", - ], - named_files = { - "CHROMEDRIVER": "chromedriver_linux64/chromedriver", - }, - ) - - browser_archive( - name = "org_chromium_chromedriver_macos_x64", - licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT - sha256 = "1a08bdfb06bd395caafbbb5fe9be982edf5c3c5d07e8082b06f0cf416389a5af", - urls = [ - "https://storage.googleapis.com/chromium-browser-snapshots/Mac/1263141/chromedriver_mac64.zip", - "https://storage.googleapis.com/dev-infra-mirror/chromium/1263141/mac_x64/driver-bin.zip", - ], - named_files = { - "CHROMEDRIVER": "chromedriver_mac64/chromedriver", - }, - ) - - browser_archive( - name = "org_chromium_chromedriver_macos_arm64", - licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT - sha256 = "0548bc04cd7d3a9016002034bc30b1df18283612fe99bb7cf1811a60258d60a0", - urls = [ - "https://storage.googleapis.com/chromium-browser-snapshots/Mac_Arm/1263141/chromedriver_mac64.zip", - "https://storage.googleapis.com/dev-infra-mirror/chromium/1263141/mac_arm64/driver-bin.zip", - ], - named_files = { - "CHROMEDRIVER": "chromedriver_mac64/chromedriver", - }, - ) - - browser_archive( - name = "org_chromium_chromedriver_windows", - licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT - sha256 = "fe9dd78b5257a804bb46d81225af84da6eaa5308ce7a69a4b96d31fb31e2c834", - urls = [ - "https://storage.googleapis.com/chromium-browser-snapshots/Win/1263141/chromedriver_win32.zip", - "https://storage.googleapis.com/dev-infra-mirror/chromium/1263141/windows_x64/driver-bin.zip", - ], - named_files = { - "CHROMEDRIVER": "chromedriver_win32/chromedriver.exe", - }, - ) diff --git a/bazel/browsers/chromium/chromium.json b/bazel/browsers/chromium/chromium.json deleted file mode 100644 index b86f84e27..000000000 --- a/bazel/browsers/chromium/chromium.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "environment": "local", - "capabilities": { - "browserName": "chrome", - "goog:chromeOptions": { - "binary": "%FILE:CHROMIUM%", - "args": ["--headless", "--use-gl=swiftshader-webgl", "--no-sandbox"] - }, - "google:wslConfig": { - "binary": "%FILE:CHROMEDRIVER%", - "port": "%WSLPORT:WSL%", - "args": ["--port=%WSLPORT:WSL%"], - "status": true, - "shutdown": true - } - } -} diff --git a/bazel/browsers/firefox/BUILD.bazel b/bazel/browsers/firefox/BUILD.bazel deleted file mode 100644 index cea514a41..000000000 --- a/bazel/browsers/firefox/BUILD.bazel +++ /dev/null @@ -1,49 +0,0 @@ -load("@io_bazel_rules_webtesting//web:web.bzl", "browser") -load("//bazel/browsers:browser_toolchain_alias.bzl", "browser_toolchain_alias") - -package(default_visibility = ["//visibility:public"]) - -PLATFORM_METADATA = select({ - "//bazel/constraints:linux_x64": [ - "@org_mozilla_firefox_linux_x64//:metadata", - "@org_mozilla_geckodriver_linux_x64//:metadata", - ], - "//bazel/constraints:macos_x64": [ - # Firefox has a launcher that conditionally starts x64/arm64 - "@org_mozilla_firefox_macos//:metadata", - "@org_mozilla_geckodriver_macos_x64//:metadata", - ], - "//bazel/constraints:macos_arm64": [ - # Firefox has a launcher that conditionally starts x64/arm64 - "@org_mozilla_firefox_macos//:metadata", - "@org_mozilla_geckodriver_macos_arm64//:metadata", - ], - "//conditions:default": [], -}) - -browser( - name = "firefox", - disabled = select({ - # TODO: Consider adding support for Windows. Requires a portable version of - # Firefox. Official distribution only ships with installers. - "//bazel/constraints:windows_x64": "Firefox is not disabled on Windows but always passing", - # Note: We keep always keep others enabled. This will result in proper errors if e.g. a - # linux arm64 machine intends to run tests with Firefox but we miss binaries for the platform. - "//conditions:default": None, - }), - metadata = "firefox.json", - deps = PLATFORM_METADATA + [ - "@io_bazel_rules_webtesting//go/wsl", - ], -) - -browser_toolchain_alias( - name = "toolchain_alias", - deps = PLATFORM_METADATA, -) - -# Make source files available for distribution via pkg_npm -filegroup( - name = "files", - srcs = glob(["*"]), -) diff --git a/bazel/browsers/firefox/firefox.bzl b/bazel/browsers/firefox/firefox.bzl deleted file mode 100644 index 6b81b6310..000000000 --- a/bazel/browsers/firefox/firefox.bzl +++ /dev/null @@ -1,81 +0,0 @@ -load("//bazel/browsers:browser_archive_repo.bzl", "browser_archive") - -""" - Defines repositories for Firefox that can be used inside Karma unit tests - and Protractor e2e tests with Bazel. -""" - -def define_firefox_repositories(): - # Instructions on updating the Firefox version can be found in the `README.md` file - # next to this file. - - browser_archive( - name = "org_mozilla_firefox_linux_x64", - licenses = ["reciprocal"], # MPL 2.0 - sha256 = "0f702f7690b02953e336fac27874276d9d471c9d264dc0feb7fcc6693d63bd4b", - # Firefox v125.0.1 - urls = [ - "https://ftp.mozilla.org/pub/firefox/releases/125.0.1/linux-x86_64/en-US/firefox-125.0.1.tar.bz2", - "https://storage.googleapis.com/dev-infra-mirror/firefox/125.0.1/linux_x64/browser-bin.tar.bz2", - ], - named_files = { - "FIREFOX": "firefox/firefox", - }, - ) - - browser_archive( - # Firefox has a launcher that conditionally starts x64/arm64 - name = "org_mozilla_firefox_macos", - licenses = ["reciprocal"], # MPL 2.0 - sha256 = "3f431079d423e5397987a4120a63948217252426219f23348cb6b6bbded3acf3", - # Firefox v125.0.1 - urls = [ - "https://ftp.mozilla.org/pub/firefox/releases/125.0.1/mac/en-US/Firefox%20125.0.1.dmg", - "https://storage.googleapis.com/dev-infra-mirror/firefox/125.0.1/mac_x64/browser-bin.dmg", - ], - named_files = { - "FIREFOX": "Firefox.app/Contents/MacOS/firefox", - }, - ) - - browser_archive( - name = "org_mozilla_geckodriver_linux_x64", - licenses = ["reciprocal"], # MPL 2.0 - sha256 = "79b2e77edd02c0ec890395140d7cdc04a7ff0ec64503e62a0b74f88674ef1313", - # Geckodriver v0.34.0 - urls = [ - "https://github.com/mozilla/geckodriver/releases/download/v0.34.0/geckodriver-v0.34.0-linux64.tar.gz", - "https://storage.googleapis.com/dev-infra-mirror/firefox/125.0.1/linux_x64/driver-bin.tar.gz", - ], - named_files = { - "GECKODRIVER": "geckodriver", - }, - ) - - browser_archive( - name = "org_mozilla_geckodriver_macos_x64", - licenses = ["reciprocal"], # MPL 2.0 - sha256 = "9cec1546585b532959782c8220599aa97c1f99265bb2d75ad00cd56ef98f650c", - # Geckodriver v0.34.0 - urls = [ - "https://github.com/mozilla/geckodriver/releases/download/v0.34.0/geckodriver-v0.34.0-macos.tar.gz", - "https://storage.googleapis.com/dev-infra-mirror/firefox/125.0.1/mac_x64/driver-bin.tar.gz", - ], - named_files = { - "GECKODRIVER": "geckodriver", - }, - ) - - browser_archive( - name = "org_mozilla_geckodriver_macos_arm64", - licenses = ["reciprocal"], # MPL 2.0 - sha256 = "d33232d29d764018d83e7e4e0c25ac274b5548658c605421c4373e64ba81d904", - # Geckodriver v0.34.0 - urls = [ - "https://github.com/mozilla/geckodriver/releases/download/v0.34.0/geckodriver-v0.34.0-macos-aarch64.tar.gz", - "https://storage.googleapis.com/dev-infra-mirror/firefox/125.0.1/mac_arm64/driver-bin.tar.gz", - ], - named_files = { - "GECKODRIVER": "geckodriver", - }, - ) diff --git a/bazel/browsers/firefox/firefox.json b/bazel/browsers/firefox/firefox.json deleted file mode 100644 index 1f3f4ecda..000000000 --- a/bazel/browsers/firefox/firefox.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "environment": "local", - "capabilities": { - "browserName": "firefox", - "moz:firefoxOptions": { - "binary": "%FILE:FIREFOX%", - "args": ["--headless"] - }, - "google:wslConfig": { - "binary": "%FILE:GECKODRIVER%", - "port": "%WSLPORT:WSL%", - "args": [ - "--port=%WSLPORT:WSL%", - "--host=%WSL:HOST_IP%", - "--marionette-port=%WSLPORT:MARIONETTE%" - ], - "status": true, - "shutdown": false - } - } -} diff --git a/bazel/browsers/test/BUILD.bazel b/bazel/browsers/test/BUILD.bazel deleted file mode 100644 index a1ed8487a..000000000 --- a/bazel/browsers/test/BUILD.bazel +++ /dev/null @@ -1,31 +0,0 @@ -load("@build_bazel_rules_nodejs//:index.bzl", "js_library") -load("//bazel/karma:index.bzl", "karma_web_test_suite") -load("//bazel/spec-bundling:index.bzl", "spec_bundle") - -karma_web_test_suite( - name = "test", - browsers = [ - "//bazel/browsers/chromium:chromium", - "//bazel/browsers/firefox:firefox", - ], - tags = [ - "linux", - "macos", - ], - deps = [ - ":test_bundle", - ], -) - -js_library( - name = "test_lib", - testonly = True, - srcs = ["browser-test.spec.mjs"], -) - -spec_bundle( - name = "test_bundle", - platform = "browser", - workspace_name = "devinfra", - deps = [":test_lib"], -) diff --git a/bazel/browsers/test/browser-test.spec.mjs b/bazel/browsers/test/browser-test.spec.mjs deleted file mode 100644 index 464d08192..000000000 --- a/bazel/browsers/test/browser-test.spec.mjs +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 - */ - -describe('browser test', () => { - it('should work', () => { - expect(true).toBe(true); - }); -}); diff --git a/bazel/browsers/update-script/BUILD.bazel b/bazel/browsers/update-script/BUILD.bazel deleted file mode 100644 index 4942a0969..000000000 --- a/bazel/browsers/update-script/BUILD.bazel +++ /dev/null @@ -1,35 +0,0 @@ -load("//tools:defaults.bzl", "esbuild", "ts_library") -load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary") - -package(default_visibility = ["//visibility:private"]) - -ts_library( - name = "update_script_lib", - testonly = True, - srcs = glob(["*.ts"]), - deps = [ - "//ng-dev/utils", - "@npm//@google-cloud/storage", - "@npm//@types/node", - "@npm//@types/tmp", - "@npm//@types/yargs", - "@npm//tmp", - "@npm//yargs", - ], -) - -esbuild( - name = "cli_script", - testonly = True, - entry_point = ":index.ts", - format = "iife", - deps = [":update_script_lib"], -) - -nodejs_binary( - name = "update-script", - testonly = True, - data = [":cli_script"], - entry_point = "cli_script.js", - templated_args = ["--nobazel_run_linker"], -) diff --git a/bazel/browsers/update-script/README.md b/bazel/browsers/update-script/README.md deleted file mode 100644 index fdfd032a3..000000000 --- a/bazel/browsers/update-script/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## Update script - -This is an internal helper script for easing the updates of browsers with `bazel/browsers`. This -folder is _not_ shipped to the NPM package. diff --git a/bazel/browsers/update-script/browser-artifact.ts b/bazel/browsers/update-script/browser-artifact.ts deleted file mode 100644 index b2ce70c00..000000000 --- a/bazel/browsers/update-script/browser-artifact.ts +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {Browser} from './browser.js'; -import * as path from 'path'; - -/** Type describing possible artifact types for browser downloads. */ -export type ArtifactType = 'driver-bin' | 'browser-bin'; - -/** Set of known artifact extensions, including chained extensions for gzipped files. */ -const KNOWN_EXTENSIONS = new Set(['zip', 'tar.gz', 'tar.bz2', 'dmg']); - -/** Class describing an artifact for a browser. */ -export class BrowserArtifact { - constructor( - /** Instance of the browser this artifact exists for. */ - public browser: Browser, - /** Type of the artifact. */ - public type: ArtifactType, - /** URL for downloading the artifact. */ - public downloadUrl: string, - /** Extension of the artifact. If unspecified, derived from the download URL. */ - public extension: string = detectArtifactExtension(downloadUrl), - ) {} -} - -/** - * Gets the extension of a given artifact file, excluding the dot/period. - * - * Since artifact download URLs can use chained extensions as for - * example with `.tar.gz`, we will need to keep track of known extensions - * and start looking with the first dot/period we discover. - */ -export function detectArtifactExtension(filePath: string) { - let tmpPath: string = filePath; - let extension: string = ''; - let currentPart: string = ''; - - // Iterate from the end of the path, finding the largest possible - // extension substring, accounting for cases like `a/b.tmp/file.tar.gz`. - while ((currentPart = path.extname(tmpPath)) !== '') { - // An extension needs to be a continuous set of alphanumeric characters. This is a rather - // strict requirement as technically extensions could contain e.g. `dashes`. In our case - // this strictness is acceptable though as we don't expect such extensions and it makes - // this extension detection logic more correct. e.g. the logic would not incorrectly - // detect an extension for `firefox-97.0-linux.tar.gz` to `0-linux.tar.gz`. - if (!/^\.[a-zA-Z0-9]+$/.test(currentPart)) { - break; - } - - extension = currentPart + extension; - tmpPath = path.basename(tmpPath, currentPart); - } - - // Strip off the leading period/dot from the extension. - // If there is no extension, this string would remain empty. - extension = extension.substring(1); - - if (KNOWN_EXTENSIONS.has(extension)) { - return extension; - } - - throw new Error(`Unable to find known extension for file path: ${filePath}`); -} diff --git a/bazel/browsers/update-script/browser.ts b/bazel/browsers/update-script/browser.ts deleted file mode 100644 index d1306ad87..000000000 --- a/bazel/browsers/update-script/browser.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {BrowserArtifact, ArtifactType} from './browser-artifact.js'; -import {Platform} from './platform.js'; - -/** Interface describing a browser. */ -export interface Browser { - name: string; - revision: T; - supports(platform: Platform): boolean; - getArtifact(platform: Platform, type: ArtifactType): BrowserArtifact; -} diff --git a/bazel/browsers/update-script/chromium.ts b/bazel/browsers/update-script/chromium.ts deleted file mode 100644 index cae4feac6..000000000 --- a/bazel/browsers/update-script/chromium.ts +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {Browser} from './browser.js'; -import {ArtifactType, BrowserArtifact} from './browser-artifact.js'; -import {Platform} from './platform.js'; - -const cloudStorageArchiveUrl = - 'https://storage.googleapis.com/chromium-browser-snapshots/{platform}/{revision}/{file}'; - -const cloudStorageHeadRevisionUrl = `https://storage.googleapis.com/chromium-browser-snapshots/{platform}/LAST_CHANGE`; - -/** - * Map a platform to the platfrom key used by the Chromium snapshot buildbot. - * See: https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html. - */ -const PlatformSnapshotNameMap = { - [Platform.LINUX_X64]: 'Linux_x64', - [Platform.MAC_X64]: 'Mac', - [Platform.MAC_ARM64]: 'Mac_Arm', - [Platform.WINDOWS_X64]: 'Win', -}; - -/** Maps a browser platform to the snapshot archive file containing the browser binary. */ -const PlatformBrowserArchiveMap = { - [Platform.LINUX_X64]: 'chrome-linux.zip', - [Platform.MAC_X64]: 'chrome-mac.zip', - [Platform.MAC_ARM64]: 'chrome-mac.zip', - [Platform.WINDOWS_X64]: 'chrome-win.zip', -}; - -/** Maps a browser platform to the archive file containing the driver. */ -const PlatformDriverArchiveMap = { - [Platform.LINUX_X64]: 'chromedriver_linux64.zip', - [Platform.MAC_X64]: 'chromedriver_mac64.zip', - [Platform.MAC_ARM64]: 'chromedriver_mac64.zip', - [Platform.WINDOWS_X64]: 'chromedriver_win32.zip', -}; - -/** List of supported platforms for the Chromium binaries. */ -const supportedPlatforms = new Set([ - Platform.LINUX_X64, - Platform.MAC_X64, - Platform.MAC_ARM64, - Platform.WINDOWS_X64, -]); - -/** Class providing necessary information for the chromium browser. */ -export class Chromium implements Browser { - name = 'chromium'; - - constructor(public revision: number) {} - - supports(platform: Platform): boolean { - return supportedPlatforms.has(platform); - } - - getArtifact(platform: Platform, type: ArtifactType): BrowserArtifact { - return new BrowserArtifact(this, type, this.getDownloadUrl(platform, type)); - } - - getDownloadUrl(platform: Platform, type: ArtifactType): string { - return Chromium.getDownloadArtifactUrl(this.revision, platform, type); - } - - static getDownloadArtifactUrl(revision: number, platform: Platform, type: ArtifactType): string { - const archiveMap = type === 'driver-bin' ? PlatformDriverArchiveMap : PlatformBrowserArchiveMap; - return cloudStorageArchiveUrl - .replace('{platform}', PlatformSnapshotNameMap[platform]) - .replace('{revision}', `${revision}`) - .replace('{file}', archiveMap[platform]); - } - - static getLatestRevisionUrl(platform: Platform) { - return cloudStorageHeadRevisionUrl.replace('{platform}', PlatformSnapshotNameMap[platform]); - } -} diff --git a/bazel/browsers/update-script/find-revision-chromium.ts b/bazel/browsers/update-script/find-revision-chromium.ts deleted file mode 100644 index c80b4e57e..000000000 --- a/bazel/browsers/update-script/find-revision-chromium.ts +++ /dev/null @@ -1,188 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 - * Script that fetches the latest revision currently in the "stable" channel of Chromium. - * It then checks if build artifacts on the CDN exist for that revision. If there are missing - * build artifacts, it looks for more recent revisions, starting from the determined revision - * in the stable channel, and checks if those have build artifacts. This allows us to determine - * a Chromium revision that is as close as possible to the "stable" channel and we have CDN - * artifacts available for each supported platform. - * - * This is needed because Chromium does not build artifacts for every revision. See: - * https://github.com/puppeteer/puppeteer/issues/2567#issuecomment-393436282 - * - * Note: An explicit revision can be specified as command line argument. This allows - * for finding snapshot builds if a revision is already known. e.g. consider a case - * where a specific Chromium bug (needed for the Angular org) is fixed but is ahead - * of the current revision in the stable channel. We still may want to update Chromium - * to a revision ahead of the specified revision for which snapshot builds exist. - */ - -import {createHash} from 'crypto'; -import {Spinner} from '../../../ng-dev/utils/spinner.js'; -import {ArtifactType} from './browser-artifact.js'; -import {Chromium} from './chromium.js'; -import {Platform} from './platform.js'; - -/** - * Entry-point for the script, finding a revision which has snapshot builds for all platforms. - * If an explicit start revision has been specified, this function looks for a closest - * revision that is available for all platforms. If none has been specified, we look for - * a revision that is as close as possible to the revision in the stable release channel. - */ -export async function findLatestRevisionForAllPlatforms( - explicitStartRevision: number | undefined, -): Promise { - const availableRevision = - explicitStartRevision === undefined - ? await findClosestStableRevisionForAllPlatforms() - : await findClosestAscendingRevisionForAllPlatforms(explicitStartRevision); - - if (availableRevision === null) { - console.error('Could not find a revision for which builds are available for all platforms.'); - process.exit(1); - } - - const browser = new Chromium(availableRevision); - - console.info('Found a revision for which builds are available for all platforms.'); - console.info('Printing the URLs and archive checksums:'); - console.info(); - // Note: We cannot extract the Chromium version and commit automatically because - // this requires an actual browser resolving a manual `window.open` redirect. - console.info('Release Info:', await getReleaseInfoUrlForRevision(availableRevision)); - console.info('Click on the link above to determine the Chromium version number.'); - console.info(); - - for (const platformName of Object.keys(Platform)) { - const platform = Platform[platformName as keyof typeof Platform]; - - console.info(`${platformName}: `.padEnd(10), browser.getDownloadUrl(platform, 'browser-bin')); - console.info( - ' '.repeat(15), - await getSha256ChecksumForPlatform(browser, platform, 'browser-bin'), - ); - console.info(' '.repeat(10), browser.getDownloadUrl(platform, 'driver-bin')); - console.info( - ' '.repeat(15), - await getSha256ChecksumForPlatform(browser, platform, 'driver-bin'), - ); - console.info(); - } -} - -/** - * Finds a Chromium revision which is as close as possible to the revision currently - * in the stable release channel, and for which snapshot builds exist for all platforms. - */ -async function findClosestStableRevisionForAllPlatforms(): Promise { - const stableBaseRevision = await getStableChromiumRevision(); - - // Note: We look for revisions with snapshot builds for every platform by searching in - // ascending order because going back to older revisions would mean that we use a revision - // which might miss fixes that have landed before the determined "stable" revision has been - // released. Note that searching for a revision is ascending order is technically also not - // ideal because it may contain new regressions, or new APIs, but either way is not ideal here. - // It seems better to use a more up-to-date revision, rather than relying on code that has - // already been fixed, but we'd accidentally use it then. - return findClosestAscendingRevisionForAllPlatforms(stableBaseRevision); -} - -/** - * Finds a Chromium revision in ascending order which is as close as possible to - * the specified revision and has snapshot builds for all platforms. - */ -async function findClosestAscendingRevisionForAllPlatforms( - startRevision: number, -): Promise { - return lookForRevisionWithBuildsForAllPlatforms(startRevision, await getHeadChromiumRevision()); -} - -/** - * Looks for revision within the specified revision range for which builds exist for - * every platform. This is needed because there are no builds available for every - * revision that lands within Chromium. More details can be found here: - * https://github.com/puppeteer/puppeteer/issues/2567#issuecomment-393436282. - */ -async function lookForRevisionWithBuildsForAllPlatforms( - startRevision: number, - toRevision: number, -): Promise { - const spinner = new Spinner('Looking for revision build.'); - const increment = toRevision >= startRevision ? 1 : -1; - - for (let i = startRevision; i !== toRevision; i += increment) { - spinner.update(`Checking: r${i}`); - - const checks = await Promise.all( - Object.values(Platform).map((p) => isRevisionAvailableForPlatform(i, p)), - ); - - // If the current revision is available for all platforms, stop - // searching and return the current revision. - if (checks.every((isAvailable) => isAvailable === true)) { - spinner.complete(); - console.log(` √ Found revision: r${i}`); - return i; - } - } - spinner.complete(); - console.log(' ✘ No revision found.'); - return null; -} - -/** Checks if the specified revision is available for the given platform. */ -async function isRevisionAvailableForPlatform( - revision: number, - platform: Platform, -): Promise { - // Look for the `driver` archive as this is smaller and faster to check. - const response = await fetch(Chromium.getDownloadArtifactUrl(revision, platform, 'driver-bin')); - return response.ok && response.status === 200; -} - -/** Gets the latest revision currently in the `stable` release channel of Chromium. */ -async function getStableChromiumRevision(): Promise { - // Endpoint is maintained by the Chromium team and can be consulted for determining - // the current latest revision in stable channel. - // https://github.com/googlechromelabs/chrome-for-testing/ - const response = await fetch( - `https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json`, - ); - const revisionStr = ((await response.json()) as any).channels.Stable.revision; - return Number(revisionStr); -} - -/** Gets the Chromium release information page URL for a given revision. */ -async function getReleaseInfoUrlForRevision(revision: number): Promise { - // This is a site used and maintained by the Chromium team. - // https://chromium.googlesource.com/chromium/chromium/+/refs/heads/trunk/tools/omahaproxy.py. - return `https://storage.googleapis.com/chromium-find-releases-static/index.html#r${revision}`; -} - -/** Determines the latest Chromium revision available in the CDN. */ -async function getHeadChromiumRevision(): Promise { - const responses = await Promise.all( - Object.values(Platform).map((p) => fetch(Chromium.getLatestRevisionUrl(p))), - ); - const revisions = await Promise.all(responses.map(async (r) => Number(await r.text()))); - return Math.max(...revisions); -} - -/** Gets the SHA256 checksum for the platform archive of a given chromium instance. */ -async function getSha256ChecksumForPlatform( - browser: Chromium, - platform: Platform, - artifactType: ArtifactType, -): Promise { - const response = await fetch(browser.getDownloadUrl(platform, artifactType)); - const binaryContent = Buffer.from(await response.arrayBuffer()); - return createHash('sha256').update(binaryContent).digest('hex'); -} diff --git a/bazel/browsers/update-script/firefox.ts b/bazel/browsers/update-script/firefox.ts deleted file mode 100644 index 80e0e1219..000000000 --- a/bazel/browsers/update-script/firefox.ts +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {ArtifactType, BrowserArtifact, detectArtifactExtension} from './browser-artifact.js'; -import {Browser} from './browser.js'; -import {Platform} from './platform.js'; - -const downloadLinuxUrls = { - 'browser-bin': - 'https://ftp.mozilla.org/pub/firefox/releases/{version}/linux-x86_64/en-US/firefox-{version}.tar.bz2', - 'driver-bin': - 'https://github.com/mozilla/geckodriver/releases/download/v{version}/geckodriver-v{version}-linux64.tar.gz', -}; - -const downloadMacOsX64Urls = { - 'browser-bin': - 'https://ftp.mozilla.org/pub/firefox/releases/{version}/mac/en-US/Firefox {version}.dmg', - 'driver-bin': - 'https://github.com/mozilla/geckodriver/releases/download/v{version}/geckodriver-v{version}-macos.tar.gz', -}; - -const downloadMacOsArm64Urls = { - 'browser-bin': - 'https://ftp.mozilla.org/pub/firefox/releases/{version}/mac/en-US/Firefox {version}.dmg', - 'driver-bin': - 'https://github.com/mozilla/geckodriver/releases/download/v{version}/geckodriver-v{version}-macos-aarch64.tar.gz', -}; - -/** Class providing necessary information for the firefox browser. */ -export class Firefox implements Browser { - name = 'firefox'; - - constructor( - public revision: string, - public driverVersion: string, - ) {} - - supports(platform: Platform): boolean { - return ( - platform === Platform.LINUX_X64 || - platform === Platform.MAC_X64 || - platform === Platform.MAC_ARM64 - ); - } - - getArtifact(platform: Platform, archiveType: ArtifactType): BrowserArtifact { - const urlSet = this._getUrlSetForPlatform(platform); - const baseUrl = urlSet[archiveType]; - const downloadUrl = baseUrl.replace( - /\{version}/g, - // Depending on browser, or driver being requested, substitute the associated version. - archiveType === 'browser-bin' ? this.revision : this.driverVersion, - ); - - // Note that for the artifact extension we will consult the non-substituted base URL - // as the substituted version like `97.0.tar.bz2` would throw off the detection. - return new BrowserArtifact(this, archiveType, downloadUrl, detectArtifactExtension(baseUrl)); - } - - private _getUrlSetForPlatform(platform: Platform): Record { - switch (platform) { - case Platform.LINUX_X64: - return downloadLinuxUrls; - case Platform.MAC_X64: - return downloadMacOsX64Urls; - case Platform.MAC_ARM64: - return downloadMacOsArm64Urls; - default: - throw Error(`Unexpected platform "${platform}" without Firefox support.`); - } - } -} diff --git a/bazel/browsers/update-script/index.ts b/bazel/browsers/update-script/index.ts deleted file mode 100644 index 6b186e258..000000000 --- a/bazel/browsers/update-script/index.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {Storage} from '@google-cloud/storage'; -import yargs from 'yargs'; -import {Chromium} from './chromium.js'; -import {findLatestRevisionForAllPlatforms} from './find-revision-chromium.js'; -import {Firefox} from './firefox.js'; -import {uploadBrowserArtifactsToMirror} from './upload-mirror.js'; - -async function main() { - await yargs(process.argv.slice(2)) - .strict() - .help() - .scriptName('') - .demandCommand() - .command( - 'find-latest-chromium-revision [start-revision]', - 'Finds the latest stable revision for Chromium with artifacts available for all platforms.', - (args) => args.positional('startRevision', {type: 'number'}), - (args) => findLatestRevisionForAllPlatforms(args.startRevision), - ) - .command('upload-to-mirror', 'Upload browser binaries to the dev-infra cloud mirror', (args) => - args - .demandCommand() - .command( - 'chromium ', - 'Push Chromium artifacts', - (cArgs) => cArgs.positional('revision', {type: 'number', demandOption: true}), - (cArgs) => uploadBrowserArtifactsToMirror(new Storage(), new Chromium(cArgs.revision)), - ) - .command( - 'firefox ', - 'Push Firefox artifacts', - (fArgs) => - fArgs - .positional('browserVersion', {type: 'string', demandOption: true}) - .positional('driverVersion', {type: 'string', demandOption: true}), - (fArgs) => - uploadBrowserArtifactsToMirror( - new Storage(), - new Firefox(fArgs.browserVersion, fArgs.driverVersion), - ), - ), - ) - .parseAsync(); -} - -main().catch((e) => { - console.log(e); - process.exitCode = 1; -}); diff --git a/bazel/browsers/update-script/package.json b/bazel/browsers/update-script/package.json deleted file mode 100644 index 3dbc1ca59..000000000 --- a/bazel/browsers/update-script/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "module" -} diff --git a/bazel/browsers/update-script/platform.ts b/bazel/browsers/update-script/platform.ts deleted file mode 100644 index fd43ab44c..000000000 --- a/bazel/browsers/update-script/platform.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 - */ - -export enum Platform { - LINUX_X64 = 'linux_x64', - MAC_X64 = 'mac_x64', - MAC_ARM64 = 'mac_arm64', - WINDOWS_X64 = 'windows_x64', -} diff --git a/bazel/browsers/update-script/pnpm-lock.yaml b/bazel/browsers/update-script/pnpm-lock.yaml deleted file mode 100644 index 9b60ae178..000000000 --- a/bazel/browsers/update-script/pnpm-lock.yaml +++ /dev/null @@ -1,9 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: {} diff --git a/bazel/browsers/update-script/upload-mirror.ts b/bazel/browsers/update-script/upload-mirror.ts deleted file mode 100644 index 33d4d1cc5..000000000 --- a/bazel/browsers/update-script/upload-mirror.ts +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {Bucket, Storage, File} from '@google-cloud/storage'; -import {Browser} from './browser.js'; -import {Platform} from './platform.js'; -import {createTmpDir, downloadFileThroughStreaming} from './utils.js'; - -import * as path from 'path'; -import {BrowserArtifact} from './browser-artifact.js'; - -/** Name of the Google Cloud Storage bucket for the browser mirror. */ -const MIRROR_BUCKET_NAME = 'dev-infra-mirror'; - -/** Gets the directory in the mirror bucket for a given browser instance. */ -export function getMirrorDirectoryForBrowserInstance(browser: Browser): string { - return `${browser.name}/${browser.revision}`; -} - -/** Gets the destination file path for a given browser artifact. */ -export function getDestinationFilePath(artifact: BrowserArtifact, platform: Platform): string { - const versionMirrorDir = getMirrorDirectoryForBrowserInstance(artifact.browser); - return `${versionMirrorDir}/${platform}/${artifact.type}.${artifact.extension}`; -} - -/** - * Uploads a browser platform artifact to the browser mirror. - * - * @throws {Error} An error if the artifact already exists in the mirror. - */ -export async function uploadArtifactToMirror( - bucket: Bucket, - artifact: BrowserArtifact, - platform: Platform, - sourceFile: string, -): Promise { - const [file] = await bucket.upload(sourceFile, { - destination: getDestinationFilePath(artifact, platform), - public: true, - }); - - return file; -} - -/** - * Helper function that takes an authenticated instance of the Google Cloud Storage API - * and a browser instance. The artifacts (both driver and browser itself) will be - * downloaded and re-uploaded to the mirror bucket in the given GCP instance. - */ -export async function uploadBrowserArtifactsToMirror(storage: Storage, browser: Browser) { - const bucket = storage.bucket(MIRROR_BUCKET_NAME); - const tmpDir = await createTmpDir({template: `${browser.name}-${browser.revision}-XXXXXX`}); - const downloadTasks: Promise<{ - platform: Platform; - filePath: string; - artifact: BrowserArtifact; - }>[] = []; - - for (const platform of Object.values(Platform)) { - if (!browser.supports(platform)) { - continue; - } - - const driverArtifact = browser.getArtifact(platform, 'driver-bin'); - const browserArtifact = browser.getArtifact(platform, 'browser-bin'); - const driverTmpPath = path.join(tmpDir, `${platform}-driver.${driverArtifact.extension}`); - const browserTmpPath = path.join(tmpDir, `${platform}-browser.${browserArtifact.extension}`); - - // We use the driver artifact (which is usually much smaller) to run a quick - // sanity check upstream to ensure that the artifact does not yet exist upstream. - const testDestinationFile = getDestinationFilePath(driverArtifact, platform); - // Note that we cannot check directly for the directory to exist since GCP does - // not support this. Hence we need to run this check for the actual files instead. - if ((await bucket.file(testDestinationFile).exists())[0]) { - throw Error('Revision is already in the mirror. Remove the artifacts if you want to retry.'); - } - - downloadTasks.push( - downloadFileThroughStreaming(browserArtifact.downloadUrl, browserTmpPath) - .then(() => console.info(`✅ Downloaded: ${browser.name} - ${platform} browser.`)) - .then(() => ({ - platform, - filePath: browserTmpPath, - artifact: browserArtifact, - })), - ); - - downloadTasks.push( - downloadFileThroughStreaming(driverArtifact.downloadUrl, driverTmpPath) - .then(() => console.info(`✅ Downloaded: ${browser.name} - ${platform} driver.`)) - .then(() => ({ - platform, - filePath: driverTmpPath, - artifact: driverArtifact, - })), - ); - } - - const tasks = await Promise.all(downloadTasks); - const uploadTasks: Promise<{platform: Platform; artifact: BrowserArtifact; file: File}>[] = []; - - console.info(); - console.info('Fetched all browser artifacts. Now uploading to mirror.'); - console.info(); - - for (const {platform, filePath, artifact} of tasks) { - uploadTasks.push( - uploadArtifactToMirror(bucket, artifact, platform, filePath).then((file) => { - console.log(`✅ Uploaded: ${platform} ${artifact.type}`); - console.log(` -> ${file.publicUrl()}`); - - return {platform, file, artifact}; - }), - ); - } - - await Promise.all(uploadTasks); - - console.info(`Uploaded ${browser.name} artifacts to the Google Cloud Storage mirror.`); -} diff --git a/bazel/browsers/update-script/utils.ts b/bazel/browsers/update-script/utils.ts deleted file mode 100644 index 1ca487309..000000000 --- a/bazel/browsers/update-script/utils.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 * as fs from 'fs'; -import * as tmp from 'tmp'; -import {Readable} from 'stream'; -import {ReadableStream} from 'stream/web'; - -/** Creates a temporary directory with the given options. */ -export function createTmpDir(options: tmp.DirOptions): Promise { - return new Promise((resolve, reject) => { - tmp.dir(options, (err, name) => (err !== null ? reject(err) : resolve(name))); - }); -} - -/** - * Downloads a file and stores it at the given location. - * - * The file is downloaded asynchronously using streaming to avoid - * increasing acquired memory of the NodeJS process unnecessarily. - */ -export async function downloadFileThroughStreaming( - sourceUrl: string, - destinationPath: string, -): Promise { - return new Promise(async (resolve, reject) => { - const webStream = (await fetch(sourceUrl)).body; - - if (webStream === null) { - reject(); - return; - } - - const stream = Readable.fromWeb(webStream as ReadableStream); - const outStream = fs.createWriteStream(destinationPath); - - stream.on('error', (err) => reject(err)); - stream.on('close', () => resolve()); - stream.pipe(outStream); - }); -} diff --git a/bazel/http-server/test/BUILD.bazel b/bazel/http-server/test/BUILD.bazel index 91ae90c90..aa7112731 100644 --- a/bazel/http-server/test/BUILD.bazel +++ b/bazel/http-server/test/BUILD.bazel @@ -37,14 +37,14 @@ js_test( # Pass the chromium and chromedriver binaries as arguments to the test. # These variables are made available by the toolchain alias. args = [ - "$(CHROMIUM)", + "$(CHROME-HEADLESS-SHELL)", "$(CHROMEDRIVER)", ], data = [ ":server", ":test_lib", - "//bazel/browsers/chromium", + "@rules_browsers//src/browsers/chromium", ], entry_point = ":server-test.js", - toolchains = ["//bazel/browsers/chromium:toolchain_alias"], + toolchains = ["@rules_browsers//src/browsers/chromium:toolchain_alias"], ) diff --git a/bazel/integration/tests/angular-cli/BUILD.bazel b/bazel/integration/tests/angular-cli/BUILD.bazel index 8c3297cb0..5a625866a 100644 --- a/bazel/integration/tests/angular-cli/BUILD.bazel +++ b/bazel/integration/tests/angular-cli/BUILD.bazel @@ -11,12 +11,12 @@ integration_test( ], data = [ # Makes the chromium binaries available for the `ng test` command. - "//bazel/browsers/chromium", + "@rules_browsers//src/browsers/chromium", ], environment = { "CHROMEDRIVER_SKIP_DOWNLOAD": "true", "CHROMEDRIVER_PATH": "$(CHROMEDRIVER)", - "CHROME_BIN": "$(CHROMIUM)", + "CHROME_BIN": "$(CHROME-HEADLESS-SHELL)", }, tags = [ # This test relies on `yarn` so there needs to be internet access. @@ -26,5 +26,5 @@ integration_test( "//:yarn_classic_vendored": "yarn", "@nodejs_toolchains//:resolved_toolchain": "node", }, - toolchains = ["//bazel/browsers/chromium:toolchain_alias"], + toolchains = ["@rules_browsers//src/browsers/chromium:toolchain_alias"], ) diff --git a/bazel/integration/tests/playwright_chromium/BUILD.bazel b/bazel/integration/tests/playwright_chromium/BUILD.bazel index 910da2969..c1b350460 100644 --- a/bazel/integration/tests/playwright_chromium/BUILD.bazel +++ b/bazel/integration/tests/playwright_chromium/BUILD.bazel @@ -9,10 +9,10 @@ integration_test( ], data = [ # Makes the chromium binaries available for the `ng test` command. - "//bazel/browsers/chromium", + "@rules_browsers//src/browsers/chromium", ], environment = { - "CHROME_BIN": "$(CHROMIUM)", + "CHROME_BIN": "$(CHROME-HEADLESS-SHELL)", }, tags = [ # This test relies on `yarn` so there needs to be internet access. @@ -22,5 +22,5 @@ integration_test( "//:yarn_classic_vendored": "yarn", "@nodejs_toolchains//:resolved_toolchain": "node", }, - toolchains = ["//bazel/browsers/chromium:toolchain_alias"], + toolchains = ["@rules_browsers//src/browsers/chromium:toolchain_alias"], ) diff --git a/bazel/karma/BUILD.bazel b/bazel/karma/BUILD.bazel deleted file mode 100644 index cfaaa6e52..000000000 --- a/bazel/karma/BUILD.bazel +++ /dev/null @@ -1,9 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -exports_files(["karma-debug-config.cjs"]) - -# Make source files available for distribution via pkg_npm -filegroup( - name = "files", - srcs = glob(["*"]), -) diff --git a/bazel/karma/index.bzl b/bazel/karma/index.bzl deleted file mode 100644 index faf61967d..000000000 --- a/bazel/karma/index.bzl +++ /dev/null @@ -1,55 +0,0 @@ -load( - "@npm//@bazel/concatjs:index.bzl", - _karma_web_test = "karma_web_test", - _karma_web_test_suite = "karma_web_test_suite", -) - -# Re-export of unmodified Karma test macros/rules. -karma_web_test = _karma_web_test - -def _karma_debug_browsers_target(name, **web_test_args): - """Macro for defining a standalone karma web test target that starts Karma - without a browser, allowing for manual debugging.""" - - # Custom standalone web test that can be run to test against any browser - # that is manually connected to. - _karma_web_test( - name = "%s_bin" % name, - config_file = "@devinfra//bazel/karma:karma-debug-config.cjs", - tags = ["manual"], - **web_test_args - ) - - # Workaround for: https://github.com/bazelbuild/rules_nodejs/issues/1429 - native.sh_test( - name = name, - srcs = ["%s_bin" % name], - tags = ["manual", "requires-network", "ibazel_notify_changes"], - testonly = True, - ) - -def karma_web_test_suite(name, **kwargs): - """Wrapper for the default `karma_web_test_suite` with additional default browsers, - and a local target to ease debugging.""" - - # Set up default browsers if no explicit `browsers` have been specified. - if "browsers" not in kwargs: - kwargs["tags"] = ["native"] + kwargs.get("tags", []) - kwargs["browsers"] = [ - "//bazel/browsers/chromium:chromium", - "//bazel/browsers/firefox:firefox", - ] - - # Filter out options which are specific to "karma_web_test" targets. We cannot - # pass options like "browsers" to the debug web test target. - web_test_args = {} - for opt_name in kwargs.keys(): - if not opt_name in ["wrapped_test_tags", "browsers", "tags"]: - web_test_args[opt_name] = kwargs[opt_name] - - # Custom standalone web test that can be run to test against any - # browser that is manually connected to. - _karma_debug_browsers_target(name = "%s_debug" % name, **web_test_args) - - # Default test suite with all configured browsers. - _karma_web_test_suite(name = name, **kwargs) diff --git a/bazel/karma/karma-debug-config.cjs b/bazel/karma/karma-debug-config.cjs deleted file mode 100644 index fd3099833..000000000 --- a/bazel/karma/karma-debug-config.cjs +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Karma configuration that is used by Bazel `karma_web_test` local target which intends - * to not launch any browser, enabling manual browser debugging. - */ - -module.exports = (config) => { - const overwrites = {}; - - // By default "@bazel/concatjs" configures Chrome as browser. Since we don't want - // to launch any browser at all, we overwrite the "browsers" option. Since the - // default config tries to extend the browsers array with "Chrome", we need to - // always return a new empty array. - Object.defineProperty(overwrites, 'browsers', { - get: () => [], - set: () => {}, - enumerable: true, - }); - - // Ensures that tests start executing once browsers have been manually connected. We need - // to use "defineProperty" because the default "@bazel/concatjs" config overwrites the option. - Object.defineProperty(overwrites, 'autoWatch', { - get: () => true, - set: () => {}, - enumerable: true, - }); - - // When not running with ibazel, do not set up the `@bazel/concatjs` watcher. This one - // relies on ibazel to write to the `stdin` interface. When running without ibazel, the - // watcher will kill concatjs since there is no data written to the `stdin` interface. - if (process.env['IBAZEL_NOTIFY_CHANGES'] !== 'y') { - // We pre-define a plugins array that captures registration of Karma plugins - // and unsets the watcher definitions so that no watcher can be configured. - overwrites.plugins = new KarmaPluginArrayWithoutWatchers(); - } - - config.set(overwrites); -}; - -class KarmaPluginArrayWithoutWatchers extends Array { - // The Bazel Karma rules only register new plugins using `.push`. - push(...plugins) { - plugins.filter((p) => typeof p === 'object').forEach((p) => delete p.watcher); - - super.push(...plugins); - } -} diff --git a/bazel/map-size-tracking/BUILD.bazel b/bazel/map-size-tracking/BUILD.bazel deleted file mode 100644 index 55e1fa112..000000000 --- a/bazel/map-size-tracking/BUILD.bazel +++ /dev/null @@ -1,22 +0,0 @@ -load("//bazel:defaults.bzl", "ts_library") - -package(default_visibility = ["//visibility:public"]) - -ts_library( - name = "map-size-tracking", - srcs = glob(["**/*.ts"]), - # A tsconfig needs to be specified as otherwise `ts_library` will look for the config - # in `//:package.json` and this breaks when the BUILD file is copied to `@npm//`. - tsconfig = "//:tsconfig.json", - deps = [ - "@npm//@bazel/runfiles", - "@npm//@types/node", - "@npm//source-map", - ], -) - -# Make source files available for distribution via pkg_npm -filegroup( - name = "files", - srcs = glob(["*"]), -) diff --git a/bazel/map-size-tracking/file_size_compare.ts b/bazel/map-size-tracking/file_size_compare.ts deleted file mode 100644 index dbc559572..000000000 --- a/bazel/map-size-tracking/file_size_compare.ts +++ /dev/null @@ -1,134 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {DirectorySizeEntry, FileSizeData, getChildEntryNames} from './file_size_data.js'; - -export interface SizeDifference { - filePath?: string; - message: string; -} - -export interface Threshold { - /** - * Maximum difference percentage. Exceeding this causes a reported size - * difference. Percentage difference is helpful for small files where - * the byte threshold is not exceeded but the change is relatively large - * for the small file and should be reported. - */ - maxPercentageDiff: number; - /** - * Maximum byte difference. Exceeding this causes a reported size difference. - * The max byte threshold works good for large files where change is relatively - * small but still needs to reported as it causes an overall size regression. - */ - maxByteDiff: number; -} - -/** Compares two file size data objects and returns an array of size differences. */ -export function compareFileSizeData( - actual: FileSizeData, - expected: FileSizeData, - threshold: Threshold, -) { - return [ - ...compareSizeEntry(actual.files, expected.files, '/', threshold), - ...compareActualSizeToExpected(actual.unmapped, expected.unmapped, '', threshold), - ]; -} - -/** Compares two file size entries and returns an array of size differences. */ -function compareSizeEntry( - actual: DirectorySizeEntry | number, - expected: DirectorySizeEntry | number, - filePath: string, - threshold: Threshold, -) { - if (typeof actual !== 'number' && typeof expected !== 'number') { - return compareDirectorySizeEntry(actual, expected, filePath, threshold); - } else { - return compareActualSizeToExpected(actual, expected, filePath, threshold); - } -} - -/** - * Compares two size numbers and returns a size difference if the difference - * percentage exceeds the specified maximum percentage or the byte size - * difference exceeds the maximum byte difference. - */ -function compareActualSizeToExpected( - actualSize: number, - expectedSize: number, - filePath: string, - threshold: Threshold, -): SizeDifference[] { - const diffPercentage = getDifferencePercentage(actualSize, expectedSize); - const byteDiff = Math.abs(expectedSize - actualSize); - const diffs: SizeDifference[] = []; - if (diffPercentage > threshold.maxPercentageDiff) { - diffs.push({ - filePath: filePath, - message: - `Differs by ${diffPercentage.toFixed(2)}% from the expected size ` + - `(actual = ${actualSize}, expected = ${expectedSize})`, - }); - } - if (byteDiff > threshold.maxByteDiff) { - diffs.push({ - filePath: filePath, - message: - `Differs by ${byteDiff}B from the expected size ` + - `(actual = ${actualSize}, expected = ${expectedSize})`, - }); - } - return diffs; -} - -/** - * Compares two size directory size entries and returns an array of found size - * differences within that directory. - */ -function compareDirectorySizeEntry( - actual: DirectorySizeEntry, - expected: DirectorySizeEntry, - filePath: string, - threshold: Threshold, -): SizeDifference[] { - const diffs: SizeDifference[] = [ - ...compareActualSizeToExpected(actual.size, expected.size, filePath, threshold), - ]; - - getChildEntryNames(expected).forEach((childName) => { - if (actual[childName] === undefined) { - diffs.push({ - filePath: filePath + childName, - message: 'Expected file/directory is not included.', - }); - return; - } - - diffs.push( - ...compareSizeEntry(actual[childName], expected[childName], filePath + childName, threshold), - ); - }); - - getChildEntryNames(actual).forEach((childName) => { - if (expected[childName] === undefined) { - diffs.push({ - filePath: filePath + childName, - message: 'Unexpected file/directory included (not part of golden).', - }); - } - }); - - return diffs; -} - -/** Gets the difference of the two size values in percentage. */ -function getDifferencePercentage(actualSize: number, expectedSize: number) { - return (Math.abs(actualSize - expectedSize) / ((expectedSize + actualSize) / 2)) * 100; -} diff --git a/bazel/map-size-tracking/file_size_data.ts b/bazel/map-size-tracking/file_size_data.ts deleted file mode 100644 index 39ea12551..000000000 --- a/bazel/map-size-tracking/file_size_data.ts +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 - */ - -export interface DirectorySizeEntry { - size: number; - [filePath: string]: DirectorySizeEntry | number; -} - -export interface FileSizeData { - unmapped: number; - files: DirectorySizeEntry; -} - -/** Returns a new file size data sorted by keys in ascending alphabetical order. */ -export function sortFileSizeData({unmapped, files}: FileSizeData): FileSizeData { - return {unmapped, files: _sortDirectorySizeEntryObject(files)}; -} - -/** Gets the name of all child size entries of the specified one. */ -export function getChildEntryNames(entry: DirectorySizeEntry): string[] { - // The "size" property is reserved for the stored size value. - return Object.keys(entry).filter((key) => key !== 'size'); -} - -/** - * Returns the first size-entry that has multiple children. This is also known as - * the omitting of the common path prefix. - * */ -export function omitCommonPathPrefix(entry: DirectorySizeEntry): DirectorySizeEntry { - let current: DirectorySizeEntry = entry; - while (getChildEntryNames(current).length === 1) { - const newChild = current[getChildEntryNames(current)[0]]; - // Only omit the current node if it is a size entry. In case the new - // child is a holding a number, then this is a file and we don'twant - // to incorrectly omit the leaf file entries. - if (typeof newChild === 'number') { - break; - } - current = newChild; - } - return current; -} - -function _sortDirectorySizeEntryObject(oldObject: DirectorySizeEntry): DirectorySizeEntry { - return Object.keys(oldObject) - .sort(_sortSizeEntryKeys) - .reduce((result, key) => { - if (typeof oldObject[key] === 'number') { - result[key] = oldObject[key]; - } else { - result[key] = _sortDirectorySizeEntryObject(oldObject[key] as DirectorySizeEntry); - } - return result; - }, {} as DirectorySizeEntry); -} - -function _sortSizeEntryKeys(a: string, b: string) { - // The "size" property should always be the first item in the size entry. - // This makes it easier to inspect the size of an entry in the golden. - if (a === 'size') { - return -1; - } else if (a < b) { - return -1; - } else if (a > b) { - return 1; - } - return 0; -} diff --git a/bazel/map-size-tracking/index.bzl b/bazel/map-size-tracking/index.bzl deleted file mode 100644 index 39657b065..000000000 --- a/bazel/map-size-tracking/index.bzl +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright Google LLC -# -# 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 - -load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary", "nodejs_test") - -nodejs_args = ["--nobazel_run_linker"] - -def js_mapping_size_test( - name, - src, - source_map, - golden_file, - max_percentage_diff, - max_byte_diff, - **kwargs): - """Track the size of a given input file by inspecting the corresponding source map. - - A golden file is used to compare the current file size data against previously approved file size data - - Args: - name: Name of the test target - src: Label pointing to the script to be analyzed. - source_map: Label pointing to the JavaScript map file. - golden_file: Label pointing to the golden JSON file. - max_percentage_diff: Limit percentage difference that would result in test failures. - max_byte_diff: Limit relative byte difference that would result in test failures. - **kwargs: Additional arguments being passed to the NodeJS test target. - """ - - all_data = ["//bazel/map-size-tracking", src, source_map, golden_file] - entry_point = "//bazel/map-size-tracking:index.ts" - - nodejs_test( - name = name, - data = all_data, - entry_point = entry_point, - templated_args = nodejs_args + [ - "$(rootpath %s)" % src, - "$(rootpath %s)" % source_map, - "$(rootpath %s)" % golden_file, - "%d" % max_percentage_diff, - "%d" % max_byte_diff, - "false", - ], - **kwargs - ) - - nodejs_binary( - name = "%s.accept" % name, - testonly = True, - data = all_data, - entry_point = entry_point, - templated_args = nodejs_args + [ - "$(rootpath %s)" % src, - "$(rootpath %s)" % source_map, - "$(rootpath %s)" % golden_file, - "0", - "0", - "true", - ], - **kwargs - ) diff --git a/bazel/map-size-tracking/index.ts b/bazel/map-size-tracking/index.ts deleted file mode 100644 index 18f3ae7a8..000000000 --- a/bazel/map-size-tracking/index.ts +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {readFileSync, writeFileSync} from 'fs'; -import {runfiles} from '@bazel/runfiles'; - -import {compareFileSizeData} from './file_size_compare.js'; -import {FileSizeData} from './file_size_data.js'; -import {SizeTracker} from './size_tracker.js'; - -// TODO(ESM) This can be replaced with an actual ESM import when `ts_library` is -// guaranteed to be ESM-only and supports the `mts` extension. -const chalk = {red: (v: string) => v, green: (v: string) => v}; - -export async function main( - entryPointScriptPath: string, - sourceMapPath: string, - goldenSizeMapPath: string, - writeGolden: boolean, - maxPercentageDiff: number, - maxByteDiff: number, -): Promise { - const tracker = new SizeTracker(entryPointScriptPath, sourceMapPath); - const sizeResult = await tracker.computeSizeResult(); - - if (writeGolden) { - writeFileSync(goldenSizeMapPath, JSON.stringify(sizeResult, null, 2)); - console.error(chalk.green(`Updated golden size data in ${goldenSizeMapPath}`)); - return; - } - - const expectedSizeData = JSON.parse(readFileSync(goldenSizeMapPath, 'utf8')) as FileSizeData; - const differences = compareFileSizeData(sizeResult, expectedSizeData, { - maxByteDiff, - maxPercentageDiff, - }); - - if (!differences.length) { - return; - } - - console.error( - `Computed file size data does not match golden size data. ` + - `The following differences were found:\n`, - ); - differences.forEach(({filePath, message}) => { - const failurePrefix = filePath ? `"${filePath}": ` : ''; - console.error(chalk.red(` ${failurePrefix}${message}`)); - }); - - const bazelTargetName = process.env['TEST_TARGET']; - - console.error(`\nThe golden file can be updated with the following command:`); - console.error(` yarn bazel run ${bazelTargetName}.accept`); - - throw new Error('Actual size report does not match with golden file.'); -} - -// Invoke main. -(() => { - const [ - fileRootPath, - sourceMapRootPath, - goldenRootPath, - maxPercentageDiffArg, - maxSizeDiffArg, - writeGoldenArg, - ] = process.argv.slice(2); - - main( - runfiles.resolveWorkspaceRelative(fileRootPath), - runfiles.resolveWorkspaceRelative(sourceMapRootPath), - runfiles.resolveWorkspaceRelative(goldenRootPath), - writeGoldenArg === 'true', - parseInt(maxPercentageDiffArg), - parseInt(maxSizeDiffArg), - ).catch((e) => { - console.error(e); - process.exitCode = 1; - }); -})(); diff --git a/bazel/map-size-tracking/size_tracker.ts b/bazel/map-size-tracking/size_tracker.ts deleted file mode 100644 index fc7d5e554..000000000 --- a/bazel/map-size-tracking/size_tracker.ts +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {promises as fs} from 'fs'; -import {RawSourceMap, SourceMapConsumer} from 'source-map'; - -import { - DirectorySizeEntry, - FileSizeData, - omitCommonPathPrefix, - sortFileSizeData, -} from './file_size_data.js'; - -export class SizeTracker { - constructor( - private filePath: string, - private sourceMapPath: string, - ) {} - - /** - * Computes the file size data by analyzing the input file through - * the specified source-map. - */ - async computeSizeResult(): Promise { - const fileContent = await fs.readFile(this.filePath, 'utf8'); - const mapContent = await fs.readFile(this.sourceMapPath, 'utf8'); - const consumer = await new SourceMapConsumer(JSON.parse(mapContent) as RawSourceMap); - - const lines = fileContent.split(/(\r?\n)/); - const result: FileSizeData = { - unmapped: 0, - files: {size: 0}, - }; - - // Walk through the columns for each line in the input file and find the - // origin source-file of the given character. This allows us to inspect - // how the given input file is composed and how much each individual file - // contributes to the overall bundle file. - for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) { - const lineText = lines[lineIdx]; - for (let colIdx = 0; colIdx < lineText.length; colIdx++) { - // Note that the "originalPositionFor" line number is one-based. - let {source} = consumer.originalPositionFor({line: lineIdx + 1, column: colIdx}); - - // Increase the amount of total bytes. - result.files.size += 1; - - if (!source) { - result.unmapped += 1; - continue; - } - - const pathSegments = this._resolveMappedPath(source).split('/'); - let currentEntry = result.files; - - // Walk through each path segment and update the size entries with - // new size. This makes it possibly to create na hierarchical tree - // that matches the actual file system. - pathSegments.forEach((segmentName, index) => { - // The last segment always refers to a file and we therefore can - // store the size verbatim as property value. - if (index === pathSegments.length - 1) { - currentEntry[segmentName] = (currentEntry[segmentName] || 0) + 1; - } else { - // Append a trailing slash to the segment so that it - // is clear that this size entry represents a folder. - segmentName = `${segmentName}/`; - const newEntry = currentEntry[segmentName] || {size: 0}; - newEntry.size += 1; - currentEntry = currentEntry[segmentName] = newEntry; - } - }); - } - } - - // Omit size entries which are not needed and just bloat up the file - // size data. e.g. if all paths start with "../../", we want to omit - // this prefix to make the size data less confusing. - result.files = omitCommonPathPrefix(result.files); - - return sortFileSizeData(result); - } - - private _resolveMappedPath(filePath: string): string { - // We only want to store POSIX-like paths in order to avoid path - // separator failures when running the golden tests on Windows. - return filePath.replace(/\\/g, '/'); - } -} diff --git a/bazel/map-size-tracking/test/BUILD.bazel b/bazel/map-size-tracking/test/BUILD.bazel deleted file mode 100644 index 9bc8da0ba..000000000 --- a/bazel/map-size-tracking/test/BUILD.bazel +++ /dev/null @@ -1,35 +0,0 @@ -load("//tools:defaults.bzl", "ts_library") -load("//bazel/map-size-tracking:index.bzl", "js_mapping_size_test") -load("@npm//@bazel/jasmine:index.bzl", "jasmine_node_test") - -ts_library( - name = "test_lib", - testonly = True, - srcs = glob(["**/*_spec.ts"]), - # TODO(devversion): Remove this when `ts_library` supports `.mts` extension. - # Also switch back to the `defaults.bzl`-provided Jasmine node test macro. - devmode_module = "commonjs", - deps = [ - "//bazel/map-size-tracking", - "@npm//@types/jasmine", - "@npm//@types/node", - "@npm//source-map", - ], -) - -jasmine_node_test( - name = "test", - srcs = [ - ":test_lib", - ], - templated_args = ["--nobazel_run_linker"], -) - -js_mapping_size_test( - name = "size_test", - src = "//bazel/map-size-tracking/test/fixture-app:bundle.js", - golden_file = "size-golden.json", - max_byte_diff = 1000, - max_percentage_diff = 10, - source_map = "//bazel/map-size-tracking/test/fixture-app:bundle.js.map", -) diff --git a/bazel/map-size-tracking/test/file_size_compare_spec.ts b/bazel/map-size-tracking/test/file_size_compare_spec.ts deleted file mode 100644 index b0c784c06..000000000 --- a/bazel/map-size-tracking/test/file_size_compare_spec.ts +++ /dev/null @@ -1,134 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {compareFileSizeData} from '../file_size_compare.js'; - -describe('file size compare', () => { - it('should report if size entry differ by more than the specified max percentage diff', () => { - const diffs = compareFileSizeData( - { - unmapped: 0, - files: { - size: 50, - 'a.ts': 50, - }, - }, - { - unmapped: 0, - files: { - size: 75, - 'a.ts': 75, - }, - }, - {maxPercentageDiff: 0, maxByteDiff: 25}, - ); - - expect(diffs.length).toBe(2); - expect(diffs[0].filePath).toBe('/'); - expect(diffs[0].message).toMatch(/40.00% from the expected size/); - expect(diffs[1].filePath).toBe('/a.ts'); - expect(diffs[1].message).toMatch(/40.00% from the expected size/); - }); - - it('should report if size entry differ by more than the specified max byte diff', () => { - const diffs = compareFileSizeData( - { - unmapped: 0, - files: { - size: 1000, - 'a.ts': 1000, - }, - }, - { - unmapped: 0, - files: { - size: 1055, - 'a.ts': 1055, - }, - }, - {maxPercentageDiff: 6, maxByteDiff: 50}, - ); - - expect(diffs.length).toBe(2); - expect(diffs[0].filePath).toBe('/'); - expect(diffs[0].message).toMatch(/55B from the expected size/); - expect(diffs[1].filePath).toBe('/a.ts'); - expect(diffs[1].message).toMatch(/55B from the expected size/); - }); - - it('should report if unmapped bytes differ by more than specified threshold', () => { - const diffs = compareFileSizeData( - {unmapped: 1000, files: {size: 0}}, - {unmapped: 1055, files: {size: 0}}, - {maxPercentageDiff: 6, maxByteDiff: 50}, - ); - - expect(diffs.length).toBe(1); - expect(diffs[0].filePath).toBe(''); - expect(diffs[0].message).toMatch(/55B from the expected size/); - }); - - it('should not report if size percentage difference does not exceed threshold', () => { - const diffs = compareFileSizeData( - { - unmapped: 0, - files: { - size: 50, - 'a.ts': 50, - }, - }, - { - unmapped: 0, - files: { - size: 75, - 'a.ts': 75, - }, - }, - {maxPercentageDiff: 40, maxByteDiff: 25}, - ); - - expect(diffs.length).toBe(0); - }); - - it('should report if expected file size data misses a file size entry', () => { - const diffs = compareFileSizeData( - { - unmapped: 0, - files: { - size: 101, - 'a.ts': 100, - 'b.ts': 1, - }, - }, - {unmapped: 0, files: {size: 100, 'a.ts': 100}}, - {maxByteDiff: 10, maxPercentageDiff: 1}, - ); - - expect(diffs.length).toBe(1); - expect(diffs[0].filePath).toBe('/b.ts'); - expect(diffs[0].message).toMatch(/Unexpected file.*not part of golden./); - }); - - it('should report if actual file size data misses an expected file size entry', () => { - const diffs = compareFileSizeData( - { - unmapped: 0, - files: { - size: 100, - 'a.ts': 100, - }, - }, - {unmapped: 0, files: {size: 101, 'a.ts': 100, 'b.ts': 1}}, - {maxByteDiff: 10, maxPercentageDiff: 1}, - ); - - expect(diffs.length).toBe(1); - expect(diffs[0].filePath).toBe('/b.ts'); - expect(diffs[0].message).toMatch(/Expected file.*not included./); - }); -}); diff --git a/bazel/map-size-tracking/test/file_size_data_spec.ts b/bazel/map-size-tracking/test/file_size_data_spec.ts deleted file mode 100644 index 0e0fe64f5..000000000 --- a/bazel/map-size-tracking/test/file_size_data_spec.ts +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {FileSizeData, omitCommonPathPrefix, sortFileSizeData} from '../file_size_data.js'; - -describe('file size data', () => { - it('should be able to properly omit the common path prefix', () => { - const data: FileSizeData = { - unmapped: 0, - files: { - size: 3, - 'parent/': { - size: 3, - 'parent2/': { - size: 3, - 'a/': { - size: 3, - 'file.ts': 3, - }, - 'b/': { - size: 0, - }, - }, - }, - }, - }; - - expect(omitCommonPathPrefix(data.files)).toEqual({ - size: 3, - 'a/': { - size: 3, - 'file.ts': 3, - }, - 'b/': { - size: 0, - }, - }); - }); - - it('should be able to properly sort file size data in alphabetical order', () => { - const data: FileSizeData = { - unmapped: 0, - files: { - size: 7, - 'b/': {'c.ts': 3, 'a.ts': 3, size: 6}, - 'a/': {'nested/': {size: 1, 'a.ts': 1}, size: 1}, - }, - }; - - expect(sortFileSizeData(data)).toEqual({ - unmapped: 0, - files: { - size: 7, - 'a/': {size: 1, 'nested/': {size: 1, 'a.ts': 1}}, - 'b/': {size: 6, 'a.ts': 3, 'c.ts': 3}, - }, - }); - }); -}); diff --git a/bazel/map-size-tracking/test/fixture-app/BUILD.bazel b/bazel/map-size-tracking/test/fixture-app/BUILD.bazel deleted file mode 100644 index 697fcf699..000000000 --- a/bazel/map-size-tracking/test/fixture-app/BUILD.bazel +++ /dev/null @@ -1,23 +0,0 @@ -load("//bazel/app-bundling:index.bzl", "app_bundle") -load("//tools:defaults.bzl", "ts_library") - -package(default_visibility = ["//bazel/map-size-tracking/test:__pkg__"]) - -ts_library( - name = "fixture-app", - testonly = True, - srcs = [ - "main.ts", - "test-component.ts", - ], - deps = [ - "@npm//rxjs", - ], -) - -app_bundle( - name = "bundle", - testonly = True, - entry_point = "main.ts", - deps = [":fixture-app"], -) diff --git a/bazel/map-size-tracking/test/fixture-app/main.ts b/bazel/map-size-tracking/test/fixture-app/main.ts deleted file mode 100644 index 8ef321ef0..000000000 --- a/bazel/map-size-tracking/test/fixture-app/main.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {Observable} from 'rxjs'; -import {TestClass} from './test-component.js'; - -console.log(TestClass, Observable); diff --git a/bazel/map-size-tracking/test/fixture-app/package.json b/bazel/map-size-tracking/test/fixture-app/package.json deleted file mode 100644 index 3dbc1ca59..000000000 --- a/bazel/map-size-tracking/test/fixture-app/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "module" -} diff --git a/bazel/map-size-tracking/test/fixture-app/test-component.ts b/bazel/map-size-tracking/test/fixture-app/test-component.ts deleted file mode 100644 index 5bd8951c9..000000000 --- a/bazel/map-size-tracking/test/fixture-app/test-component.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 - */ - -export class TestClass {} diff --git a/bazel/map-size-tracking/test/size-golden.json b/bazel/map-size-tracking/test/size-golden.json deleted file mode 100644 index d50a02e25..000000000 --- a/bazel/map-size-tracking/test/size-golden.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "unmapped": 6345, - "files": { - "bazel/": { - "map-size-tracking/": { - "size": 25, - "test/": { - "fixture-app/": { - "main.ts": 5, - "size": 25, - "test-component.ts": 20 - }, - "size": 25 - } - }, - "size": 25 - }, - "node_modules/": { - "rxjs/": { - "size": 3616, - "src/": { - "internal/": { - "NotificationFactories.ts": 126, - "Observable.ts": 557, - "Subscriber.ts": 1029, - "Subscription.ts": 1026, - "config.ts": 53, - "scheduler/": { - "size": 62, - "timeoutProvider.ts": 62 - }, - "size": 3616, - "symbol/": { - "observable.ts": 16, - "size": 16 - }, - "util/": { - "UnsubscriptionError.ts": 69, - "arrRemove.ts": 93, - "createErrorClass.ts": 69, - "errorContext.ts": 180, - "identity.ts": 1, - "isFunction.ts": 75, - "noop.ts": 10, - "pipe.ts": 104, - "reportUnhandledError.ts": 146, - "size": 747 - } - }, - "size": 3616 - } - }, - "size": 3616 - }, - "size": 3641 - } -} \ No newline at end of file diff --git a/bazel/map-size-tracking/test/size_tracking_spec.ts b/bazel/map-size-tracking/test/size_tracking_spec.ts deleted file mode 100644 index 14620c5fa..000000000 --- a/bazel/map-size-tracking/test/size_tracking_spec.ts +++ /dev/null @@ -1,122 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 {writeFileSync} from 'fs'; -import {join} from 'path'; -import {SourceMapGenerator} from 'source-map'; - -import {SizeTracker} from '../size_tracker.js'; - -const testTempDir = process.env['TEST_TMPDIR']!; - -describe('size tracking', () => { - let generator: SourceMapGenerator; - - beforeEach(() => { - generator = new SourceMapGenerator(); - }); - - function writeFile(filePath: string, content: string): string { - const tmpFilePath = join(testTempDir, filePath); - writeFileSync(tmpFilePath, content); - return tmpFilePath; - } - - it('should keep track of unmapped bytes in the file', async () => { - generator.addMapping({ - generated: {line: 1, column: 1}, - original: {line: 1, column: 1}, - source: './origin-a.ts', - }); - - // A => origin-a (2 bytes), U => unmapped (1 byte) - const mapPath = writeFile('/test.map', generator.toString()); - const inputPath = writeFile('/test.js', `UAA`); - - const tracker = new SizeTracker(inputPath, mapPath); - const sizeResult = await tracker.computeSizeResult(); - - expect(sizeResult.unmapped).toBe(1); - expect(sizeResult.files).toEqual({ - size: 3, - 'origin-a.ts': 2, - }); - }); - - it('should properly combine mapped characters from same source', async () => { - generator.addMapping({ - generated: {line: 1, column: 0}, - original: {line: 1, column: 0}, - source: './origin-a.ts', - }); - - generator.addMapping({ - generated: {line: 1, column: 1}, - original: {line: 1, column: 0}, - source: './origin-b.ts', - }); - - generator.addMapping({ - generated: {line: 1, column: 2}, - original: {line: 10, column: 0}, - source: './origin-a.ts', - }); - - // A => origin-a (1 byte), B => origin-b (two bytes) - const mapPath = writeFile('/test.map', generator.toString()); - const inputPath = writeFile('/test.js', `ABB`); - - const tracker = new SizeTracker(inputPath, mapPath); - const sizeResult = await tracker.computeSizeResult(); - - expect(sizeResult.unmapped).toBe(0); - expect(sizeResult.files).toEqual({ - size: 3, - 'origin-a.ts': 2, - 'origin-b.ts': 1, - }); - }); - - it('should keep track of summed-up byte sizes for directories', async () => { - generator.addMapping({ - generated: {line: 1, column: 0}, - original: {line: 1, column: 0}, - source: '@angular/core/render3/a.ts', - }); - - generator.addMapping({ - generated: {line: 1, column: 2}, - original: {line: 1, column: 0}, - source: '@angular/core/render3/b.ts', - }); - - generator.addMapping({ - generated: {line: 1, column: 3}, - original: {line: 1, column: 0}, - source: '@angular/core/c.ts', - }); - - // A => render3/a.ts (2 bytes), B => render3/b.ts (1 byte), C => c.ts (1 byte) - const mapPath = writeFile('/test.map', generator.toString()); - const inputPath = writeFile('/test.js', `AABC`); - - const tracker = new SizeTracker(inputPath, mapPath); - const sizeResult = await tracker.computeSizeResult(); - - expect(sizeResult.unmapped).toBe(0); - expect(sizeResult.files).toEqual({ - size: 4, - 'render3/': { - size: 3, - 'a.ts': 2, - 'b.ts': 1, - }, - 'c.ts': 1, - }); - }); -}); diff --git a/ng-dev/utils/BUILD.bazel b/ng-dev/utils/BUILD.bazel index 8bbfa5a92..382c6b092 100644 --- a/ng-dev/utils/BUILD.bazel +++ b/ng-dev/utils/BUILD.bazel @@ -33,7 +33,6 @@ ts_library( visibility = [ "//.github/local-actions/branch-manager:__subpackages__", "//.github/local-actions/changelog/lib:__subpackages__", - "//bazel/browsers/update-script:__pkg__", "//github-actions/google-internal-tests:__subpackages__", "//github-actions/slash-commands/lib:__subpackages__", "//ng-dev:__subpackages__", diff --git a/package.bzl b/package.bzl index d87b12f43..aeaa6dff9 100644 --- a/package.bzl +++ b/package.bzl @@ -34,7 +34,6 @@ BZL_DEFAULTS_ALLOW_PACKAGES = [ ".github/local-actions", "", "apps", - "bazel/browsers/update-script", "bazel/api-golden", "github-actions", "ng-dev", diff --git a/tools/defaults.bzl b/tools/defaults.bzl index 02a829482..e01f02e73 100644 --- a/tools/defaults.bzl +++ b/tools/defaults.bzl @@ -1,8 +1,7 @@ -load("@npm//@bazel/concatjs:index.bzl", _ts_library = "ts_library") -load("@npm//@angular/bazel:index.bzl", _ng_module = "ng_module") load("@build_bazel_rules_nodejs//:index.bzl", _pkg_npm = "pkg_npm") -load("//tools/jasmine:jasmine.bzl", _jasmine_node_test = "jasmine_node_test") -load("//tools/karma:karma.bzl", _karma_web_test = "karma_web_test") +load("@npm//@angular/bazel:index.bzl", _ng_module = "ng_module") +load("@npm//@bazel/concatjs:index.bzl", _ts_library = "ts_library") +load("//:package.bzl", "BZL_DEFAULTS_ALLOW_PACKAGES") load( "//tools:esbuild.bzl", _esbuild = "esbuild", @@ -11,7 +10,7 @@ load( _esbuild_config = "esbuild_config", _esbuild_esm_bundle = "esbuild_esm_bundle", ) -load("//:package.bzl", "BZL_DEFAULTS_ALLOW_PACKAGES") +load("//tools/jasmine:jasmine.bzl", _jasmine_node_test = "jasmine_node_test") esbuild = _esbuild esbuild_config = _esbuild_config @@ -20,7 +19,6 @@ esbuild_checked_in = _esbuild_checked_in esbuild_cjs_bundle = _esbuild_cjs_bundle jasmine_node_test = _jasmine_node_test -karma_web_test = _karma_web_test def _assert_defaults_allowed_for_caller(): current_pkg = native.package_name() diff --git a/tools/karma/BUILD.bazel b/tools/karma/BUILD.bazel deleted file mode 100644 index 3dcbd9c0b..000000000 --- a/tools/karma/BUILD.bazel +++ /dev/null @@ -1,18 +0,0 @@ -load("//tools:defaults.bzl", "ts_library") - -ts_library( - name = "bootstrap", - testonly = True, - srcs = [ - "bootstrap.init.ts", - ], - visibility = ["//visibility:public"], - deps = [ - "@npm//@angular/compiler", - "@npm//@angular/core", - "@npm//@angular/platform-browser", - "@npm//@angular/platform-browser-dynamic", - "@npm//@types/jasmine", - "@npm//zone.js", - ], -) diff --git a/tools/karma/bootstrap.init.ts b/tools/karma/bootstrap.init.ts deleted file mode 100644 index 040ebe8fc..000000000 --- a/tools/karma/bootstrap.init.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @license - * Copyright Google LLC - * - * 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 'zone.js'; -import 'zone.js/testing'; - -import {TestBed} from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting, -} from '@angular/platform-browser-dynamic/testing'; -import {NoopAnimationsModule} from '@angular/platform-browser/animations'; - -TestBed.initTestEnvironment( - [BrowserDynamicTestingModule, NoopAnimationsModule], - platformBrowserDynamicTesting(), -); diff --git a/tools/karma/karma.bzl b/tools/karma/karma.bzl deleted file mode 100644 index 7d77ab90d..000000000 --- a/tools/karma/karma.bzl +++ /dev/null @@ -1,18 +0,0 @@ -load("//bazel/karma:index.bzl", _karma_web_test_suite = "karma_web_test_suite") -load("//bazel/spec-bundling:index.bzl", "spec_bundle") - -def karma_web_test(name, specs = [], external = [], **kwargs): - spec_bundle( - name = "%s_test_bundle" % name, - platform = "browser", - workspace_name = "devinfra", - bootstrap = ["//tools/karma:bootstrap"], - deps = specs, - external = external, - ) - - _karma_web_test_suite( - name = name, - deps = [":%s_test_bundle" % name], - **kwargs - )