b5eda603a2
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
164 lines
5.2 KiB
Bash
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
|
|
}
|