2017-08-03 15:18:55 -07:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
2017-11-29 12:47:04 +02:00
|
|
|
set -eu -o pipefail
|
|
|
|
|
|
2017-08-03 15:18:55 -07:00
|
|
|
readonly PROJECT_NAME="angular-payload-size"
|
2018-04-11 16:01:53 -07:00
|
|
|
NODE_MODULES_BIN=$PROJECT_ROOT/node_modules/.bin/
|
2017-08-03 15:18:55 -07:00
|
|
|
|
2018-10-25 13:50:32 +03:00
|
|
|
# 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=$1$2.gz
|
|
|
|
|
local size=-1
|
|
|
|
|
|
|
|
|
|
gzip -c -$compLevel "$filePath" >> "$compPath"
|
|
|
|
|
size=$(stat -c%s "$compPath")
|
|
|
|
|
rm "$compPath"
|
|
|
|
|
|
|
|
|
|
echo $size
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-03 15:18:55 -07:00
|
|
|
# Calculate the size of target file uncompressed size, gzip7 size, gzip9 size
|
|
|
|
|
# Write to global variable $payloadData, $filename
|
|
|
|
|
calculateSize() {
|
|
|
|
|
label=$(echo "$filename" | sed "s/.*\///" | sed "s/\..*//")
|
|
|
|
|
|
2019-10-11 15:29:23 +03:00
|
|
|
rawSize=$(stat -c%s "$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, "
|
2017-08-03 15:18:55 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-29 12:47:04 +02:00
|
|
|
# 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.
|
2017-08-03 15:18:55 -07:00
|
|
|
checkSize() {
|
2017-11-18 12:26:33 -08:00
|
|
|
name="$1"
|
|
|
|
|
limitFile="$2"
|
2018-10-17 19:19:15 +03:00
|
|
|
|
|
|
|
|
# In non-PR builds, `CI_BRANCH` is the branch being built (e.g. `pull/12345`), not the targeted branch.
|
|
|
|
|
# Thus, PRs will fall back to using the size limits for `master`.
|
|
|
|
|
node ${PROJECT_ROOT}/scripts/ci/payload-size.js $limitFile $name $CI_BRANCH $CI_COMMIT
|
2017-08-03 15:18:55 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-29 12:47:04 +02:00
|
|
|
# Write timestamp to global variable `$payloadData`.
|
2017-08-03 15:18:55 -07:00
|
|
|
addTimestamp() {
|
|
|
|
|
# Add Timestamp
|
|
|
|
|
timestamp=$(date +%s)
|
|
|
|
|
payloadData="$payloadData\"timestamp\": $timestamp, "
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-07 18:48:51 +03:00
|
|
|
# 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\", "
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-08 12:41:24 +01:00
|
|
|
# Write the commit message for the current CI commit range to global variable `$payloadData`.
|
2018-10-18 15:43:58 +03:00
|
|
|
# $1: string - The commit range for this build (in `<SHA-1>...<SHA-2>` format).
|
2017-08-03 15:18:55 -07:00
|
|
|
addMessage() {
|
2018-10-18 15:43:58 +03:00
|
|
|
commitRange="$1"
|
|
|
|
|
|
2017-08-24 12:49:58 -07:00
|
|
|
# Grab the set of SHAs for the message. This can fail when you force push or do initial build
|
2018-10-17 19:19:15 +03:00
|
|
|
# because $CI_COMMIT_RANGE may contain the previous SHA which will not be in the
|
2017-08-24 12:49:58 -07:00
|
|
|
# force push or commit, hence we default to last commit.
|
2018-10-18 15:43:58 +03:00
|
|
|
message=$(git log --oneline $commitRange -- || git log --oneline -n1)
|
2017-09-13 17:21:20 +03:00
|
|
|
message=$(echo $message | sed 's/\\/\\\\/g' | sed 's/"/\\"/g')
|
2018-10-18 15:43:58 +03:00
|
|
|
payloadData="$payloadData\"message\": \"$message\", "
|
2017-08-03 15:18:55 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-29 12:47:04 +02:00
|
|
|
# Add change source: `application`, `dependencies`, or `application+dependencies`
|
|
|
|
|
# Read from global variable `$parentDir`.
|
|
|
|
|
# Update the change source in global variable `$payloadData`.
|
2018-10-18 15:43:58 +03:00
|
|
|
# $1: string - The commit range for this build (in `<SHA-1>...<SHA-2>` format).
|
|
|
|
|
addChangeType() {
|
|
|
|
|
commitRange="$1"
|
|
|
|
|
|
2017-08-03 15:18:55 -07:00
|
|
|
yarnChanged=false
|
2018-10-18 15:43:58 +03:00
|
|
|
allChangedFiles=$(git diff --name-only $commitRange $parentDir | wc -l)
|
|
|
|
|
allChangedFileNames=$(git diff --name-only $commitRange $parentDir)
|
2017-08-03 15:18:55 -07:00
|
|
|
|
|
|
|
|
if [[ $allChangedFileNames == *"yarn.lock"* ]]; then
|
|
|
|
|
yarnChanged=true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [[ $allChangedFiles -eq 1 ]] && [[ "$yarnChanged" = true ]]; then
|
|
|
|
|
# only yarn.lock changed
|
|
|
|
|
change='dependencies'
|
|
|
|
|
elif [[ $allChangedFiles -gt 1 ]] && [[ "$yarnChanged" = true ]]; then
|
|
|
|
|
change='application+dependencies'
|
|
|
|
|
elif [[ $allChangedFiles -gt 0 ]]; then
|
|
|
|
|
change='application'
|
|
|
|
|
else
|
ci: always track and check payload size data for angular.io (#33987)
As part of the `payload-size` npm script in `aio/package.json` (which is
run on CI), the sizes of the angular.io app bundles are checked to
ensure they do not exceed certain limits and are also uploaded to
Firebase to be available for later analysis. The uploaded data include
the type of the changes (dependencies only, application only, or both).
The type of changes is inferred by looking at the files that have
changed inside the `aio/` directory.
When the `payload-size.sh` script was first introduced, the only files
that could affect bundle sizes were inside the `aio/` directory.
Therefore, the script would skip uploading the data and checking the
sizes if no changes were detected inside the `aio/` directory.
However, this assumption stopped being valid over time. For example:
- We started tracking/checking bundle sizes when building the angular.io
app with the locally built Angular packages (which live outside the
`aio/` directory.
- Due to CircleCI limitations, the `CI_COMMIT_RANGE` environment
variable (which is used for determining what files have been affected)
stopped reflecting the whole commit range of the build and only
included the last commit instead.
Based on the above, there were many cases were size data would not be
uploaded to Firebase, even when they may have been affected (because the
affecting changes were outside `aio/` - e.g. in framework packages).
This makes it harder to analyze size regressions, because important
data-points are missing.
Even worse, in these cases, the sizes were not even checked against the
specified limits, thus making it possible for size regressions to go
unnoticed (unless caught by other similar tests).
This commit fixes the `scripts/ci/payload-size.sh` script to always
track and check payload sizes for angular.io bundles.
NOTE: This change will result in more data being recorded (i.e.
recording data when it is not possible for the bundle sizes to
have been affected by the changes). This is still preferable to
failing to record and/or check when sizes could have been
affected.
PR Close #33987
2019-11-22 13:03:37 +02:00
|
|
|
# Nothing changed inside $parentDir (but size may still be affected; e.g. when using the locally
|
|
|
|
|
# built packages)
|
|
|
|
|
change='other'
|
2017-08-03 15:18:55 -07:00
|
|
|
fi
|
|
|
|
|
payloadData="$payloadData\"change\": \"$change\", "
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-18 15:43:58 +03:00
|
|
|
# Convert the current `payloadData` value to a JSON string.
|
|
|
|
|
# (Basically remove trailing `,` and wrap in `{...}`.)
|
|
|
|
|
payloadToJson() {
|
|
|
|
|
echo "{$(sed -r 's|, *$||' <<< $payloadData)}"
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-29 12:47:04 +02:00
|
|
|
# Upload data to firebase database if it's commit, print out data for pull requests.
|
|
|
|
|
# $1: string - The name in database.
|
2017-08-03 15:18:55 -07:00
|
|
|
uploadData() {
|
|
|
|
|
name="$1"
|
2017-11-03 15:20:09 -07:00
|
|
|
|
2018-10-17 19:19:15 +03:00
|
|
|
readonly safeBranchName=$(echo $CI_BRANCH | sed -e 's/\./_/g')
|
2018-10-18 15:43:58 +03:00
|
|
|
readonly dbPath=/payload/$name/$safeBranchName/$CI_COMMIT
|
|
|
|
|
readonly jsonPayload=$(payloadToJson)
|
2017-08-03 15:18:55 -07:00
|
|
|
|
2018-10-18 15:43:58 +03:00
|
|
|
# WARNING: CI_SECRET_PAYLOAD_FIREBASE_TOKEN should NOT be printed.
|
|
|
|
|
set +x
|
|
|
|
|
$NODE_MODULES_BIN/firebase database:update --data "$jsonPayload" --project $PROJECT_NAME --confirm --token "$CI_SECRET_PAYLOAD_FIREBASE_TOKEN" $dbPath
|
2017-08-03 15:18:55 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-29 12:47:04 +02:00
|
|
|
# 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: true | false - Whether to record the type of changes.
|
|
|
|
|
# $5: [string] - The payload size limit file. Only necessary if `$3` is `true`.
|
2017-08-03 15:18:55 -07:00
|
|
|
trackPayloadSize() {
|
|
|
|
|
name="$1"
|
|
|
|
|
path="$2"
|
|
|
|
|
checkSize="$3"
|
2018-10-18 15:43:58 +03:00
|
|
|
trackChangeType="$4"
|
2017-11-29 12:47:04 +02:00
|
|
|
limitFile="${5:-}"
|
2017-08-03 15:18:55 -07:00
|
|
|
|
|
|
|
|
payloadData=""
|
2017-11-29 12:47:04 +02:00
|
|
|
|
2018-10-18 15:43:58 +03:00
|
|
|
# Calculate the file sizes.
|
2017-08-03 15:18:55 -07:00
|
|
|
for filename in $path; do
|
|
|
|
|
calculateSize
|
|
|
|
|
done
|
2018-10-18 15:43:58 +03:00
|
|
|
|
|
|
|
|
# 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.
|
2019-06-19 19:05:54 +03:00
|
|
|
if [[ "$CI_PULL_REQUEST" == "false" ]]; then
|
|
|
|
|
if [[ $trackChangeType = true ]]; then
|
|
|
|
|
addChangeType $CI_COMMIT_RANGE
|
|
|
|
|
fi
|
|
|
|
|
addTimestamp
|
2019-09-07 18:48:51 +03:00
|
|
|
addBuildUrl $CI_BUILD_URL
|
2019-06-19 19:05:54 +03:00
|
|
|
addMessage $CI_COMMIT_RANGE
|
|
|
|
|
uploadData $name
|
|
|
|
|
fi
|
2018-10-18 15:43:58 +03:00
|
|
|
|
|
|
|
|
# Check the file sizes against the specified limits.
|
2017-11-18 12:26:33 -08:00
|
|
|
if [[ $checkSize = true ]]; then
|
2017-11-29 12:47:04 +02:00
|
|
|
checkSize $name $limitFile
|
2017-08-03 15:18:55 -07:00
|
|
|
fi
|
|
|
|
|
}
|