#!/bin/bash
# Copyright 2022 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#######################################################################
# See go/clank-autoroll#androidx-bisect for instructions.
#######################################################################
function abort() {
echo "$1" >&2
# 255 will abort the bisect. 125 marks commit as "unknown".
exit ${2-255}
}
if [[ -z "$PERF_BENCHMARK" || -z "$PERF_BOT" || -z "$PERF_STORY" || -z "$PERF_METRIC" ]]; then
abort 'Example Usage:
PERF_BENCHMARK="startup.mobile" \
PERF_BOT="android-pixel4-perf" \
PERF_STORY="cct_coldish_bbc" \
PERF_METRIC="messageloop_start_time" $0 "$@"
fi
# Determine Chromium src path based on script location.
CHROMIUM_SRC="$(dirname $0)/../.."
# Determine Android src path based on current directory (git bisect must be run from it).
# Allow running from superproject root, or from within frameworks/support.
if [[ -d frameworks/support ]]; then
SUPERPROJECT_DIR="$(pwd)"
elif [[ -d ../../frameworks/support ]]; then
SUPERPROJECT_DIR="$(pwd)/../.."
else
abort "Expected to have been run from androidx checkout."
fi
FRAMEWORKS_SUPPORT_DIR="$SUPERPROJECT_DIR/frameworks/support"
set -x
set -o pipefail
cd "$CHROMIUM_SRC"
# Sanity checks:
pinpoint auth-info >/dev/null || abort "First run: pinpoint auth-login"
cipd auth-info >/dev/null || abort "First run: cipd auth-login"
# Needed for androidx sync.
gcertstatus -check_ssh=false || abort "First run: gcert"
# Allow //third_party/androidx/cipd.yaml to be listed.
local changes=$(git status --porcelain | grep -v cipd.yaml)
[[ -n "$changes" ]] && abort "git status reports changes present."
# Ensure we're on a non-main branch.
git_branch=$(git rev-parse --abbrev-ref HEAD)
[[ "$git_branch" = HEAD ]] && abort "Need to be on a branch"
[[ "$git_branch" = main ]] && abort "Need to be on a non-main branch"
# Use the most recent non-local commit as the diffbase.
git_base_rev=$(git merge-base origin/main HEAD)
cd "$SUPERPROJECT_DIR"
git submodule update --recursive --init || abort "AndroidX sync Failed"
cd "$FRAMEWORKS_SUPPORT_DIR"
# Creates a local maven repo in: out/dist/repository. Aborts bisect upon failure.
SNAPSHOT=true ./gradlew createArchive || abort "AndroidX Build Failed" 125
cd $CHROMIUM_SRC
third_party/androidx/fetch_all_androidx.py \
--local-repo "$SUPERPROJECT_DIR/out/dist/repository" || abort "fetch_all_androidx.py failure"
super_rev=$(git -C "$SUPERPROJECT_DIR" rev-parse HEAD)
support_rev=$(git -C "$FRAMEWORKS_SUPPORT_DIR" rev-parse HEAD)
cipd_output=$(cipd create -pkg-def third_party/androidx/cipd.yaml \
-tag super_rev:$super_rev \
-tag support_rev:$support_rev | grep Instance:) || abort "cipd failure"
# E.g.: Instance: experimental/google.com/agrieve/androidx:3iiAIwUqY5nB5O9ArpioN...
cipd_output=${cipd_output#*Instance: }
cipd_package=${cipd_output%:*} # Strip after colon.
cipd_package_escaped=${cipd_package//\//\\/}
cipd_instance=${cipd_output#*:} # Strip before colon.
# This needs to be run only once per package, but it's simpler to run it every time.
cipd acl-edit "$cipd_package" -reader group:all || abort "cipd acl failure"
# gclient setdep does not allow changing CIPD package, so perl it is.
perl -0777 -i -pe "s/(.*src\/third_party\/androidx.*?packages.*?package': ')(.*?)('.*?version': ')(.*?)('.*)/\${1}${cipd_package_escaped}\${3}${cipd_instance}\$5/s" DEPS
git add DEPS || abort "git add failed"
git commit -m "androidx bisect super_rev=${super_rev::9} support_rev=${support_rev::9}"
EDITOR=true git cl upload --bypass-hooks --bypass-watchlists --no-autocc --message "androidx bisect review" \
--title "super_rev=${super_rev::9} support_rev=${support_rev::9}" || abort "Upload CL failed"
review_number=$(git cl issue | grep -P --only-matching '(?<=Issue number: )(\d+)') || abort "parsing issue failed"
review_url="https://chromium-review.googlesource.com/c/chromium/src/+/$review_number"
# Returns non-zero if metric changed or if command fails.
pinpoint_job=$(pinpoint experiment-telemetry-start \
-base-commit $git_base_rev -exp-commit $git_base_rev \
-benchmark $PERF_BENCHMARK -cfg $PERF_BOT \
-story $PERF_STORY -measurement $PERF_METRIC \
-check-experiment -wait -quiet \
-exp-patch-url "$review_url" \
| tee /dev/stderr \
| grep -P --only-matching '(?<=/job/)\S+')
# E.g.: Pinpoint job scheduled: https://pinpoint-dot-chromeperf.appspot.com/job/13af94f2ea0000
retcode=$?
if [[ -z "$pinpoint_job" ]]; then
abort "Failed to parse pinpoint job"
fi
# E.g.: state: SUCCEEDED
if ! pinpoint get-job -name $pinpoint_job | grep -q "state.*SUCCEEDED"; then
abort "Pinpoint did not finish successfully."
fi
# Expect a significant difference for good changes.
if [[ $retcode = 0 ]]; then
exit 1
fi
exit 0