#!/bin/bash # # make-and-check-size - wrapper around 'make' that also checks binary growth # # This script is intended to be run via 'git rebase -x', in a form such as: # # context_dir=$(mktemp -d --tmpdir make-size-check.XXXXXXX) # git rebase ${GIT_BASE_BRANCH}^ -x "hack/make-and-check-size $context_dir" # rm -rf $context_dir # # (Carefully note the '^' next to GIT_BASE_BRANCH!) # # A 'git rebase -x' has long been a part of our usual CI; it guarantees # that each commit (whether in a single- or multi-commit PR) can be # compiled individually. # # By adding the '^' to GIT_BASE_BRANCH we establish a baseline and store # the binary sizes of each file (podman, podman-remote) prior to our PR. # # context_dir is a temporary directory used to store the original sizes # of each binary file under bin/ # # *IMPORTANT NOTE*: this script will leave the git checkout in a funky state! # (because we rebase onto a nonterminal commit). I believe this is OK, since # this script is only invoked in CI from runner.sh and only in a scratch VM. # Running this in a development environment would yield unpredictable results # anyway, by rebasing onto origin/main by default and by leaving an aborted # rebase on failure. # ME=$(basename $0) ############################################################################### # BEGIN end-user-customizable settings # Maximum allowable size, in bytes MAX_BIN_GROWTH=$((50 * 1024)) # Github label which allows overriding this check OVERRIDE_LABEL=bloat_approved # END end-user-customizable settings ############################################################################### # # Helper function: queries github for labels on this PR # function bloat_approved() { # Argument is the actual size increase in this build. # FIXME: 2022-03-21: this is not actually used atm, but Ed hopes some day # to implement a more robust size-override mechanism, such as by # requiring a MAX_BIN_GROWTH=nnn statement in github comments. local actual_growth="$1" if [[ -z "$CIRRUS_PR" ]]; then echo "$ME: cannot query github: \$CIRRUS_PR is undefined" >&2 return 1 fi if [[ -z "$CIRRUS_REPO_CLONE_TOKEN" ]]; then echo "$ME: cannot query github: \$CIRRUS_REPO_CLONE_TOKEN is undefined" >&2 return 1 fi query="{ \"query\": \"query { repository(owner: \\\"containers\\\", name: \\\"podman\\\") { pullRequest(number: $CIRRUS_PR) { labels(first: 100) { nodes { name } } } } }\" }" result=$(curl -s -H "Authorization: bearer $CIRRUS_REPO_CLONE_TOKEN" -H "Accept: application/vnd.github.antiope-preview+json" -H "Content-Type: application/json" -X POST --data @- https://api.github.com/graphql <<<"$query") labels=$(jq -r '.data.repository.pullRequest.labels.nodes[].name' <<<"$result") grep -q -w "$OVERRIDE_LABEL" <<<"$labels" } # ACTUAL CODE BEGINS HERE set -e # Must be invoked with one argument, an existing context directory context_dir=${1?Missing CONTEXT-DIR argument} if [[ ! -d $context_dir ]]; then echo "$ME: directory '$context_dir' does not exist" exit 1 fi # This is the original (and primary) purpose of this check: if 'make' fails, # there is no point in continuing. Show at least the commit title since # the ID may not match anything human recognisable. echo echo "Building: $(git log -n 1 --no-show-signature --oneline)" make # Determine size of each built file. # - If this is our first time through, preserve that size in a tmpfile # - On all subsequent runs, compare built size to initial size for bin in bin/*;do size=$(stat -c %s $bin) saved_size_file=$context_dir/$(basename $bin) if [[ -e $saved_size_file ]]; then # Not the first time through: compare to original size size_orig=$(< $saved_size_file) delta_size=$(( size - size_orig )) printf "%-20s size=%9d delta=%6d\n" $bin $size $delta_size if [[ $delta_size -gt $MAX_BIN_GROWTH ]]; then separator=$(printf "%.0s*" {1..75}) # row of stars, for highlight echo "$separator" echo "* $bin grew by $delta_size bytes; max allowed is $MAX_BIN_GROWTH." echo "*" if bloat_approved $delta_size; then echo "* Continuing due to '$OVERRIDE_LABEL' label" echo "*" echo "$separator" else echo "* Please investigate, and fix if possible." echo "*" echo "* A repo admin can override by setting the $OVERRIDE_LABEL label" echo "$separator" exit 1 fi fi else # First time through: preserve original file size echo $size >$saved_size_file printf "%-20s size=%9d\n" $bin $size fi done