diff --git a/.ng-dev/format.mts b/.ng-dev/format.mts index 44b4bd23236..8b6e8b48ee1 100644 --- a/.ng-dev/format.mts +++ b/.ng-dev/format.mts @@ -9,7 +9,7 @@ export const format: FormatConfig = { '**/*.{yaml,yml}', '**/*.{js,ts,mjs,mts,cjs,cts,tsx}', 'devtools/**/*.{js,ts,mjs,mts,cjs,cts,html,scss}', - + 'integration/**/size.json', // Do not format d.ts files as they are generated '!**/*.d.ts', // Both third_party and .yarn are directories containing copied code which should diff --git a/.pullapprove.yml b/.pullapprove.yml index 0ba644df90e..a526de98d54 100644 --- a/.pullapprove.yml +++ b/.pullapprove.yml @@ -415,7 +415,7 @@ groups: - *no-groups-above-this-rejected - > contains_any_globs(files, [ - 'goldens/size-tracking/**/{*,.*}' + 'integration/**/size.json' ]) reviewers: users: diff --git a/BUILD.bazel b/BUILD.bazel index 5f5866dd621..a51a13a9391 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -11,9 +11,6 @@ exports_files([ "karma-js.conf.js", "browser-providers.conf.js", YARN_PATH, - "scripts/ci/bazel-payload-size.sh", - "scripts/ci/payload-size.sh", - "scripts/ci/payload-size.js", "package.json", "angular.json", ]) diff --git a/WORKSPACE b/WORKSPACE index d9e321bbe67..ba2cc2e3c78 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -271,7 +271,7 @@ yarn_install( git_repository( name = "devinfra", - commit = "6f54d143077baef582d70873722166fdc040066c", + commit = "ae6afbc8c8cd972146d1ac062ccd93b9e6587986", remote = "https://github.com/angular/dev-infra.git", ) diff --git a/goldens/BUILD.bazel b/goldens/BUILD.bazel index a841e8a70d9..3b328302653 100644 --- a/goldens/BUILD.bazel +++ b/goldens/BUILD.bazel @@ -1,9 +1,5 @@ package(default_visibility = ["//visibility:public"]) -exports_files([ - "size-tracking/integration-payloads.json", -]) - filegroup( name = "public-api", srcs = glob([ diff --git a/goldens/size-tracking/integration-payloads.json b/goldens/size-tracking/integration-payloads.json deleted file mode 100644 index bc50befed5b..00000000000 --- a/goldens/size-tracking/integration-payloads.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "cli-hello-world": { - "uncompressed": { - "main": 137461, - "polyfills": 34579 - } - }, - "cli-hello-world-ivy-i18n": { - "uncompressed": { - "main": 135813, - "polyfills": 35883 - } - }, - "cli-hello-world-lazy": { - "uncompressed": { - "main": 108611, - "polyfills": 34169, - "lazy.routes": 361 - } - }, - "forms": { - "uncompressed": { - "main": 181773, - "polyfills": 33772 - } - }, - "animations": { - "uncompressed": { - "main": 143167, - "polyfills": 34023, - "open-close.component": 1190 - } - }, - "animations-async": { - "uncompressed": { - "main": 86540, - "polyfills": 33782, - "browser": 63949, - "open-close.component": 1218 - } - }, - "standalone-bootstrap": { - "uncompressed": { - "main": 94769, - "polyfills": 33802 - } - }, - "defer": { - "uncompressed": { - "main": 12709, - "polyfills": 33807, - "defer.component": 345 - } - }, - "platform-server-hydration/browser": { - "uncompressed": { - "main": 221976, - "polyfills": 34544, - "event-dispatch-contract.min": 476 - } - } -} diff --git a/integration/cli-hello-world-ivy-i18n/BUILD.bazel b/integration/cli-hello-world-ivy-i18n/BUILD.bazel index f7c03388c9a..45298ffe014 100644 --- a/integration/cli-hello-world-ivy-i18n/BUILD.bazel +++ b/integration/cli-hello-world-ivy-i18n/BUILD.bazel @@ -3,5 +3,4 @@ load("//integration:index.bzl", "ng_integration_test") ng_integration_test( name = "test", setup_chromium = True, - track_payload_size = "cli-hello-world-ivy-i18n", ) diff --git a/integration/cli-hello-world-ivy-i18n/size.json b/integration/cli-hello-world-ivy-i18n/size.json new file mode 100644 index 00000000000..7edb4e7db0f --- /dev/null +++ b/integration/cli-hello-world-ivy-i18n/size.json @@ -0,0 +1,4 @@ +{ + "dist/main.js": 135813, + "dist/polyfills.js": 35883 +} diff --git a/integration/cli-hello-world-lazy/BUILD.bazel b/integration/cli-hello-world-lazy/BUILD.bazel index a10856ecd9b..33afcf1a1b0 100644 --- a/integration/cli-hello-world-lazy/BUILD.bazel +++ b/integration/cli-hello-world-lazy/BUILD.bazel @@ -2,5 +2,4 @@ load("//integration:index.bzl", "ng_integration_test") ng_integration_test( name = "test", - track_payload_size = "cli-hello-world-lazy", ) diff --git a/integration/cli-hello-world-lazy/README.md b/integration/cli-hello-world-lazy/README.md index 9778a30bb21..3856d5bfaee 100644 --- a/integration/cli-hello-world-lazy/README.md +++ b/integration/cli-hello-world-lazy/README.md @@ -2,4 +2,4 @@ This test checks bundle sizes when there is a lazy module. It also checks if the `ngDevMode` global variable and string references in `packages/core/src/util/ng_dev_mode.ts` are correctly removed. -This test contains a lazy route to ensure `ngDevMode` removal happens even across chunks, and a payload size check in `/goldens/size-tracking/integration-payloads.json` to ensure extra code is not retained accidentally. +This test contains a lazy route to ensure `ngDevMode` removal happens even across chunks, and a payload size check to ensure extra code is not retained accidentally. diff --git a/integration/cli-hello-world-lazy/size.json b/integration/cli-hello-world-lazy/size.json new file mode 100644 index 00000000000..17ca95e3d74 --- /dev/null +++ b/integration/cli-hello-world-lazy/size.json @@ -0,0 +1,5 @@ +{ + "dist/main.js": 108611, + "dist/polyfills.js": 34169, + "dist/lazy.routes-[hash].js": 361 +} diff --git a/integration/cli-hello-world/BUILD.bazel b/integration/cli-hello-world/BUILD.bazel index 560d8d2ddcc..33afcf1a1b0 100644 --- a/integration/cli-hello-world/BUILD.bazel +++ b/integration/cli-hello-world/BUILD.bazel @@ -2,5 +2,4 @@ load("//integration:index.bzl", "ng_integration_test") ng_integration_test( name = "test", - track_payload_size = "cli-hello-world", ) diff --git a/integration/cli-hello-world/size.json b/integration/cli-hello-world/size.json new file mode 100644 index 00000000000..ccc50b7f3f0 --- /dev/null +++ b/integration/cli-hello-world/size.json @@ -0,0 +1,4 @@ +{ + "dist/main.js": 137461, + "dist/polyfills.js": 34579 +} diff --git a/integration/defer/BUILD.bazel b/integration/defer/BUILD.bazel index 3589fb5fe7f..33afcf1a1b0 100644 --- a/integration/defer/BUILD.bazel +++ b/integration/defer/BUILD.bazel @@ -2,5 +2,4 @@ load("//integration:index.bzl", "ng_integration_test") ng_integration_test( name = "test", - track_payload_size = "defer", ) diff --git a/integration/defer/size.json b/integration/defer/size.json new file mode 100644 index 00000000000..39ca4fb91c3 --- /dev/null +++ b/integration/defer/size.json @@ -0,0 +1,5 @@ +{ + "dist/main.js": 12709, + "dist/polyfills.js": 33807, + "dist/defer.component-[hash].js": 345 +} diff --git a/integration/index.bzl b/integration/index.bzl index 04b9328b538..3fa378db70b 100644 --- a/integration/index.bzl +++ b/integration/index.bzl @@ -14,8 +14,6 @@ def _ng_integration_test(name, setup_chromium = False, **kwargs): pinned_npm_packages = kwargs.pop("pinned_npm_packages", []) toolchains = kwargs.pop("toolchains", []) environment = kwargs.pop("environment", {}) - track_payload_size = kwargs.pop("track_payload_size", None) - track_payload_paths = kwargs.pop("track_payload_paths", [""]) data = kwargs.pop("data", []) if setup_chromium: @@ -33,23 +31,6 @@ def _ng_integration_test(name, setup_chromium = False, **kwargs): "yarn test", ]) - if track_payload_size: - commands += [ - "yarn build", - ] - for path in track_payload_paths: - commands += [ - # TODO: Replace the track payload-size script with a RBE and Windows-compatible script. - "$(rootpath //:scripts/ci/bazel-payload-size.sh) {bundle}{path} 'dist{path}/*.js' true ${runfiles}/angular/$(rootpath //goldens:size-tracking/integration-payloads.json)".format(bundle = track_payload_size, path = path, runfiles = "${RUNFILES}"), - ] - - data += [ - "//goldens:size-tracking/integration-payloads.json", - "//:scripts/ci/bazel-payload-size.sh", - "//:scripts/ci/payload-size.sh", - "//:scripts/ci/payload-size.js", - ] - # Complete list of npm packages to override in the test's package.json file mapped to # tgz archive to use for the replacement. This is the full list for all integration # tests. Any given integration does not need to use all of these packages. diff --git a/integration/legacy-animations-async/BUILD.bazel b/integration/legacy-animations-async/BUILD.bazel index 947c6dd22fd..33afcf1a1b0 100644 --- a/integration/legacy-animations-async/BUILD.bazel +++ b/integration/legacy-animations-async/BUILD.bazel @@ -2,5 +2,4 @@ load("//integration:index.bzl", "ng_integration_test") ng_integration_test( name = "test", - track_payload_size = "animations-async", ) diff --git a/integration/legacy-animations-async/size.json b/integration/legacy-animations-async/size.json new file mode 100644 index 00000000000..33647f9fe6e --- /dev/null +++ b/integration/legacy-animations-async/size.json @@ -0,0 +1,6 @@ +{ + "dist/main.js": 86540, + "dist/polyfills.js": 33782, + "dist/browser-[hash].js": 63949, + "dist/open-close.component-[hash].js": 1218 +} diff --git a/integration/legacy-animations/BUILD.bazel b/integration/legacy-animations/BUILD.bazel index 6edac7e14ee..33afcf1a1b0 100644 --- a/integration/legacy-animations/BUILD.bazel +++ b/integration/legacy-animations/BUILD.bazel @@ -2,5 +2,4 @@ load("//integration:index.bzl", "ng_integration_test") ng_integration_test( name = "test", - track_payload_size = "animations", ) diff --git a/integration/legacy-animations/size.json b/integration/legacy-animations/size.json new file mode 100644 index 00000000000..c9f4a8bd888 --- /dev/null +++ b/integration/legacy-animations/size.json @@ -0,0 +1,5 @@ +{ + "dist/main.js": 143167, + "dist/polyfills.js": 34023, + "dist/open-close.component-[hash].js": 1190 +} diff --git a/integration/platform-server-hydration/BUILD.bazel b/integration/platform-server-hydration/BUILD.bazel index cc9f6a80433..45298ffe014 100644 --- a/integration/platform-server-hydration/BUILD.bazel +++ b/integration/platform-server-hydration/BUILD.bazel @@ -3,8 +3,4 @@ load("//integration:index.bzl", "ng_integration_test") ng_integration_test( name = "test", setup_chromium = True, - track_payload_paths = [ - "/browser", - ], - track_payload_size = "platform-server-hydration", ) diff --git a/integration/platform-server-hydration/size.json b/integration/platform-server-hydration/size.json new file mode 100644 index 00000000000..5c28d4a6b3d --- /dev/null +++ b/integration/platform-server-hydration/size.json @@ -0,0 +1,5 @@ +{ + "dist/browser/main-[hash].js": 221976, + "dist/browser/polyfills-[hash].js": 34544, + "dist/browser/event-dispatch-contract.min.js": 476 +} diff --git a/integration/standalone-bootstrap/BUILD.bazel b/integration/standalone-bootstrap/BUILD.bazel index 10c3d816d44..33afcf1a1b0 100644 --- a/integration/standalone-bootstrap/BUILD.bazel +++ b/integration/standalone-bootstrap/BUILD.bazel @@ -2,5 +2,4 @@ load("//integration:index.bzl", "ng_integration_test") ng_integration_test( name = "test", - track_payload_size = "standalone-bootstrap", ) diff --git a/integration/standalone-bootstrap/size.json b/integration/standalone-bootstrap/size.json new file mode 100644 index 00000000000..2e05f6219ec --- /dev/null +++ b/integration/standalone-bootstrap/size.json @@ -0,0 +1,4 @@ +{ + "dist/main.js": 94769, + "dist/polyfills.js": 33802 +} diff --git a/scripts/ci/bazel-payload-size.sh b/scripts/ci/bazel-payload-size.sh deleted file mode 100755 index cfff626dbf2..00000000000 --- a/scripts/ci/bazel-payload-size.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -set -eu -o pipefail - -# Source optional CI environment variables which are sandboxed out -# of the environment when running integration tests under Bazel -readonly bazelVarEnv="/tmp/bazel-ci-env.sh" -if [[ -f "$bazelVarEnv" ]]; then - source $bazelVarEnv -fi - -# If running locally, at a minimum set PROJECT_ROOT -if [[ -z "${PROJECT_ROOT:-}" ]]; then - PROJECT_ROOT=$(cd $(dirname $0)/../..; pwd) -fi - -# Bazel payload size tracking should always be treated as if this runs as part of -# a pull request. i.e. the results are not uploaded. This is necessary as Bazel test -# targets do not necessarily run for every commit, and cached results might originate -# from RBE-built pull requests. We will overhaut size-tracking anyway.. -export CI_PULL_REQUEST="true" - -source ${PROJECT_ROOT}/scripts/ci/payload-size.sh -trackPayloadSize "$@" diff --git a/scripts/ci/payload-size.js b/scripts/ci/payload-size.js deleted file mode 100644 index 27c711d8e1b..00000000000 --- a/scripts/ci/payload-size.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -'use strict'; - -// Imports -const fs = require('fs'); -const path = require('path'); - -// Get limit file, project name and commit SHA from command line arguments. -const [, , limitFile, project, commit] = process.argv; - -const THRESHOLD_BYTES = 5000; -const THRESHOLD_PERCENT = 5; - -// Load sizes. -const currentSizes = JSON.parse(fs.readFileSync('/tmp/current.log', 'utf8')); -const allLimitSizes = JSON.parse(fs.readFileSync(limitFile, 'utf8')); -const limitSizes = allLimitSizes[project]; -if (!limitSizes) { - throw new Error(`ERROR: Project '${project}' is missing from limit file ${limitFile}.`); -} - -// Check current sizes against limits. -let failed = false; -const successMessages = []; -const failureMessages = []; -for (const compressionType in limitSizes) { - if (typeof limitSizes[compressionType] === 'object') { - const limitPerFile = limitSizes[compressionType]; - - for (const filename in limitPerFile) { - const expectedSize = limitPerFile[filename]; - const actualSize = currentSizes[`${compressionType}/${filename}`]; - - if (actualSize === undefined) { - failed = true; - // An expected compression type/file combination is missing. Maybe the file was renamed or - // removed. Report it as an error, so the user updates the corresponding limit file. - console.error( - `ERROR: Commit ${commit} ${compressionType} ${filename} measurement is missing. ` + - 'Maybe the file was renamed or removed.', - ); - } else { - const absoluteSizeDiff = Math.abs(actualSize - expectedSize); - // If size diff is larger than THRESHOLD_BYTES or THRESHOLD_PERCENT... - if ( - absoluteSizeDiff > THRESHOLD_BYTES || - absoluteSizeDiff > (expectedSize * THRESHOLD_PERCENT) / 100 - ) { - failed = true; - // We must also catch when the size is significantly lower than the payload limit, so - // we are forced to update the expected payload number when the payload size reduces. - // Otherwise, we won't be able to catch future regressions that happen to be below - // the artificially inflated limit. - const operator = actualSize > expectedSize ? 'exceeded' : 'fell below'; - - failureMessages.push( - `FAIL: Commit ${commit} ${compressionType} ${filename} ${operator} expected size by ${THRESHOLD_BYTES} bytes or >${THRESHOLD_PERCENT}% ` + - `(expected: ${expectedSize}, actual: ${actualSize}).`, - ); - } else { - successMessages.push( - `SUCCESS: Commit ${commit} ${compressionType} ${filename} did NOT cross size threshold of ${THRESHOLD_BYTES} bytes or >${THRESHOLD_PERCENT} ` + - `(expected: ${expectedSize}, actual: ${actualSize}).`, - ); - } - } - } - } -} - -// Group failure messages separately from success messages so they are easier to find. -successMessages.concat(failureMessages).forEach((message) => console.error(message)); - -if (failed) { - const projectRoot = path.resolve(__dirname, '../..'); - const limitFileRelPath = path.relative(projectRoot, limitFile); - console.info( - `If this is a desired change, please update the size limits in file '${limitFileRelPath}'.`, - ); - process.exit(1); -} else { - console.info( - `Payload size check passed. All diffs are less than ${THRESHOLD_PERCENT}% or ${THRESHOLD_BYTES} bytes.`, - ); -} diff --git a/scripts/ci/payload-size.sh b/scripts/ci/payload-size.sh deleted file mode 100644 index 3be07c70aaa..00000000000 --- a/scripts/ci/payload-size.sh +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env bash - -set -eu -o pipefail - -# statc makes `stat -c` work on both Linux & OSX -function statc () { - case $(uname) in - Darwin*) format='-f%z' ;; - *) format='-c%s' ;; - esac - - stat ${format} $@ -} - -# sedr makes `sed -r` work on both Linux & OSX -function sedr () { - case $(uname) in - Darwin*) flag='-E' ;; - *) flag='-r' ;; - esac - - sed ${flag} "$@" -} - -readonly PROJECT_NAME="angular-payload-size" -NODE_MODULES_BIN=$PROJECT_ROOT/node_modules/.bin/ - -# Get the gzip size of a file with the specified compression level. -# $1: string - The file path. -# $2: number - The level of compression. -getGzipSize() { - local filePath=$1 - local compLevel=$2 - local compPath="$(mktemp).gz" - local size=-1 - - gzip -c -$compLevel "$filePath" >> "$compPath" - size=$(statc "$compPath") - rm "$compPath" - - echo $size -} - -# Calculate the size of target file uncompressed size, gzip7 size, gzip9 size -# Write to global variable $payloadData, $filename -calculateSize() { - # Remove .js and -T74CPV26.js from the filename - label=$(echo "$filename" | sed "s/\(-[A-Z0-9]\{8\}\)\?\.js//" | sed "s/.*\///") - rawSize=$(statc $filename) - gzip7Size=$(getGzipSize "$filename" 7) - gzip9Size=$(getGzipSize "$filename" 9) - - # Log the sizes (for information/debugging purposes). - printf "Size: %6d (gzip7: %6d, gzip9: %6d) %s\n" $rawSize $gzip7Size $gzip9Size $label - - payloadData="$payloadData\"uncompressed/$label\": $rawSize, " - payloadData="$payloadData\"gzip7/$label\": $gzip7Size, " - payloadData="$payloadData\"gzip9/$label\": $gzip9Size, " -} - -# Check whether the file size is under limit. -# Exit with an error if limit is exceeded. -# $1: string - The name in database. -# $2: string - The payload size limit file. -checkSize() { - name="$1" - limitFile="$2" - - # PRs and non-PR pushes will always test against the size-limits of the current revision. - node ${PROJECT_ROOT}/scripts/ci/payload-size.js $limitFile $name ${CI_COMMIT:-} -} - -# Write timestamp to global variable `$payloadData`. -addTimestamp() { - # Add Timestamp - timestamp=$(date +%s) - payloadData="$payloadData\"timestamp\": $timestamp, " -} - -# Write the current CI build URL to global variable `$payloadData`. -# This allows mapping the data stored in the database to the CI build job that generated it, which -# might contain more info/context. -# $1: string - The CI build URL. -addBuildUrl() { - buildUrl="$1" - payloadData="$payloadData\"buildUrl\": \"$buildUrl\", " -} - -# Write the commit message for the specified CI commit to global variable `$payloadData`. -# $1: string - The commit SHA for this build (in `` format). -addMessage() { - message="${1}" - message=$(echo $message | sed 's/\r//g' | sed 's/\\/\\\\/g' | sed 's/"/\\"/g') - payloadData="$payloadData\"message\": \"$message\", " -} - -# Convert the current `payloadData` value to a JSON string. -# (Basically remove trailing `,` and wrap in `{...}`.) -payloadToJson() { - echo "{$(sedr 's|, *$||' <<< $payloadData)}" -} - -# Upload data to firebase database if it's commit, print out data for pull requests. -# $1: string - The name in database. -uploadData() { - name="$1" - - readonly safeBranchName=$(echo $CI_BRANCH | sed -e 's/\./_/g') - readonly dbPath=/payload/$name/$safeBranchName/$CI_COMMIT - readonly jsonPayload=$(payloadToJson) - - # WARNING: CI_SECRET_PAYLOAD_FIREBASE_TOKEN should NOT be printed. - set +x - $NODE_MODULES_BIN/firebase database:update --data "$jsonPayload" --project $PROJECT_NAME --force --token "$CI_SECRET_PAYLOAD_FIREBASE_TOKEN" $dbPath -} - -# Track payload size. -# $1: string - The name in database. -# $2: string - The file path. -# $3: true | false - Whether to check the payload size and fail the test if it exceeds limit. -# $4: [string] - The payload size limit file. Only necessary if `$3` is `true`. -trackPayloadSize() { - name="$1" - path="$2" - checkSize="$3" - limitFile="${4:-}" - - payloadData="" - - # Calculate the file sizes. - echo "Calculating sizes for files in '$path'..." - for filename in $path; do - calculateSize - done - - # Save the file sizes to be retrieved from `payload-size.js`. - echo "$(payloadToJson)" > /tmp/current.log - - # If this is a non-PR build, upload the data to firebase. - if [[ "${CI_PULL_REQUEST:-}" == "false" ]]; then - echo "Uploading data for '$name'..." - addTimestamp - addBuildUrl $CI_BUILD_URL - addMessage $CI_COMMIT - uploadData $name - else - echo "Skipped uploading data for '$name', because this is a pull request." - fi - - # Check the file sizes against the specified limits. - if [[ $checkSize = true ]]; then - echo "Verifying sizes against '$limitFile'..." - checkSize $name $limitFile - else - echo "Skipped verifying sizes (checkSize: false)." - fi -}