angular-cn/scripts/ci/payload-size.sh
George Kalpakas b5eda603a2 ci: work around CIRCLE_COMPARE_URL not being available wih CircleCI Pipelines (#32537)
The commit range that is associated with a CI build is used for a couple
of things (mostly related to payload-size tracking):
- Determine whether a size change was caused by application code or
  dependencies (or both).
- Add the messages of the commits associated with the build (and thus
  the payload-size change).

NOTE: The commit range is only used on push builds.

Previously, the commit range was computed based on the
`CIRCLE_COMPARE_URL` environment variable. With [CircleCI Pipelines][1]
enabled, `CIRCLE_COMPARE_URL` is no longer available and the commit
range cannot be reliably detected.

This commit switches `CI_COMMIT_RANGE` to only include the last commit.
This can be less accurate in some rare cases, but is true in the
majority of cases (on push builds). Additionally, it stores the CircleCI
build URL in the database along with the payload data, so the relevant
info can be retrieved when needed.

[1]: https://circleci.com/docs/2.0/build-processing

PR Close #32537
2019-09-09 12:21:44 -04:00

164 lines
5.2 KiB
Bash

#!/usr/bin/env bash
set -eu -o pipefail
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=$1$2.gz
local size=-1
gzip -c -$compLevel "$filePath" >> "$compPath"
size=$(stat -c%s "$compPath")
rm "$compPath"
echo $size
}
# 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/\..*//")
payloadData="$payloadData\"uncompressed/$label\": $(stat -c%s "$filename"), "
payloadData="$payloadData\"gzip7/$label\": $(getGzipSize "$filename" 7), "
payloadData="$payloadData\"gzip9/$label\": $(getGzipSize "$filename" 9), "
}
# 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"
# 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
}
# 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 current CI commit range to global variable `$payloadData`.
# $1: string - The commit range for this build (in `<SHA-1>...<SHA-2>` format).
addMessage() {
commitRange="$1"
# Grab the set of SHAs for the message. This can fail when you force push or do initial build
# because $CI_COMMIT_RANGE may contain the previous SHA which will not be in the
# force push or commit, hence we default to last commit.
message=$(git log --oneline $commitRange -- || git log --oneline -n1)
message=$(echo $message | sed 's/\\/\\\\/g' | sed 's/"/\\"/g')
payloadData="$payloadData\"message\": \"$message\", "
}
# Add change source: `application`, `dependencies`, or `application+dependencies`
# Read from global variable `$parentDir`.
# Update the change source in global variable `$payloadData`.
# $1: string - The commit range for this build (in `<SHA-1>...<SHA-2>` format).
addChangeType() {
commitRange="$1"
yarnChanged=false
allChangedFiles=$(git diff --name-only $commitRange $parentDir | wc -l)
allChangedFileNames=$(git diff --name-only $commitRange $parentDir)
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
# Nothing changed in aio/
exit 0
fi
payloadData="$payloadData\"change\": \"$change\", "
}
# Convert the current `payloadData` value to a JSON string.
# (Basically remove trailing `,` and wrap in `{...}`.)
payloadToJson() {
echo "{$(sed -r '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 --confirm --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: true | false - Whether to record the type of changes.
# $5: [string] - The payload size limit file. Only necessary if `$3` is `true`.
trackPayloadSize() {
name="$1"
path="$2"
checkSize="$3"
trackChangeType="$4"
limitFile="${5:-}"
payloadData=""
# Calculate the file sizes.
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
if [[ $trackChangeType = true ]]; then
addChangeType $CI_COMMIT_RANGE
fi
addTimestamp
addBuildUrl $CI_BUILD_URL
addMessage $CI_COMMIT_RANGE
uploadData $name
fi
# Check the file sizes against the specified limits.
if [[ $checkSize = true ]]; then
checkSize $name $limitFile
fi
}