| #!/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 |