diff options
author | Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org> | 2019-03-12 11:12:48 +0000 |
---|---|---|
committer | Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org> | 2019-03-14 10:49:23 +0000 |
commit | e53831da288d46eb2288f7251dcc8092d6088ef1 (patch) | |
tree | 122f9a7af2d611c7bfc6d7a520be4cdb3ec38820 | |
parent | 51e051a167baa7c572647432c3aa03222f783010 (diff) |
tcwg_kernel-bisect.sh: Add support for regression cache
Change-Id: I4d88a4ed947c2bd6f23f216957dc1a141a29cf5b
-rwxr-xr-x | tcwg_kernel-bisect.sh | 128 |
1 files changed, 108 insertions, 20 deletions
diff --git a/tcwg_kernel-bisect.sh b/tcwg_kernel-bisect.sh index 06aeaadc..468b4bc6 100755 --- a/tcwg_kernel-bisect.sh +++ b/tcwg_kernel-bisect.sh @@ -187,21 +187,110 @@ ln -f -s "build-$bad_rev.sh" "$artifacts/manifests/build-bad.sh" git bisect start $bad_rev $baseline_rev 2>&1 | tee $artifacts/bisect.log -# "git bisect run" can fail (exit with non-zero) in a number of cases: -# - on trivial bisects (e.g., between HEAD^ and HEAD), -# - when merge-base between baseline and bad is worse than baseline, -# - something else? -# In all these cases we want to reset baseline to HEAD, so that we catch -# most of the commits that introduced change in the result metric. -git bisect run $artifacts/test.sh 2>&1 | tee -a $artifacts/bisect.log & -res=0 && wait $! || res=$? +if ! git bisect log > /dev/null; then + # Bisect ended before it could start: $bad_rev^ == $baseline_rev + first_bad=$bad_rev + last_good=$baseline_rev +else + first_bad="" + last_good="" +fi -if [ x"$res" = x"0" ]; then - first_bad=$(cat .git/BISECT_RUN | head -n 1 | grep "is the first bad commit" | cut -d" " -f 1) - assert [ x"$first_bad" != x"" ] +# Clone interesting-commits.git repo, which contains a list of SHA1s +# that might cut down bisection time. Mostly, these are first_bad and +# last_good commits. +interesting_commits_rev=${interesting_commits_rev-${rr[ci_project]}} +clone_or_update_repo ../interesting-commits $interesting_commits_rev https://git-us.linaro.org/toolchain/ci/interesting-commits.git auto $interesting_commits_rev +cat <<EOF | manifest_out +declare -g interesting_commits_rev=$interesting_commits_rev +EOF + +# Add revisions in $@ to interesting-commits and push the repo. +# Ignore failures (since this is cache handling). +push_interesting_commits () +{ + ( + set -euf -o pipefail + + local sha1 + + for sha1 in "$@"; do + if ! grep -q "$sha1" ../interesting-commits/$current_project; then + echo "$sha1" >> ../interesting-commits/$current_project + fi + done + + git -C ../interesting-commits add . + git -C ../interesting-commits commit -m "Add commits from $BUILD_URL: + +$@" & + local res=0 && wait $! || res=$? + + if [ x"$res" = x"0" ]; then + git_init_linaro_local_remote ../interesting-commits baseline false + git_push ../interesting-commits baseline ${rr[ci_project]} + fi + ) || true +} + +# Print first_bad revision (if detected) +get_first_bad () +{ + ( + set -euf -o pipefail + + if [ x"$first_bad" != x"" ]; then + echo "$first_bad" + return + fi + + git bisect log | tail -n1 | grep "^# first bad commit:" \ + | sed -e "s/^# first bad commit: \[\([0-9a-f]*\)\].*/\1/" + ) +} + +# Try to reduce bisection range by testing regressions (and their parents) +# identified in other configurations. +sha1="" +touch ../interesting-commits/$current_project +while [ x"$(get_first_bad </dev/null)" = x"" ] && read sha1; do + ( + set -euf -o pipefail + + # Skip $bad_rev and $baseline_rev, these were already tested. + if [ x"$sha1" = x"$bad_rev" -o x"$sha1" = x"$baseline_rev" ]; then + continue + fi + # Skip revisions outside of bisection range. + if ! git merge-base --is-ancestor $baseline_rev $sha1 \ + || ! git merge-base --is-ancestor $sha1 $bad_rev; then + continue + fi + + git checkout --detach $sha1 + $artifacts/test.sh & + res=0 && wait $! || res=$? + if [ x"$res" = x"0" ]; then + git bisect good + else + git bisect bad + fi + ) </dev/null +done < ../interesting-commits/$current_project + +if [ x"$(get_first_bad)" = x"" ]; then + git bisect run $artifacts/test.sh 2>&1 | tee -a $artifacts/bisect.log & + res=0 && wait $! || res=$? + if [ x"$res" = x"0" ]; then + assert [ x"$(get_first_bad)" != x"" ] + fi +fi + +first_bad=$(get_first_bad) +if [ x"$first_bad" != x"" ]; then res=0 - for last_good in $(git rev-parse $first_bad^@); do + for last_good in $last_good $(git rev-parse $first_bad^@); do # It seems that git-bisect assumes parent commit as "good" on # the basis of one of its children being "good". Therefore we # can have a situation when we have parent P with children C1 and C2, @@ -234,21 +323,20 @@ EOF echo > $artifacts/jenkins/mail-recipients.txt touch $artifacts/jenkins/build-name sed -i -e "s/\$/-last_good-bad/" $artifacts/jenkins/build-name + push_interesting_commits $last_good trap "" EXIT exit 0 fi + push_interesting_commits $first_bad $last_good echo $first_bad > $artifacts/first-bad else + # When "git bisect run" fails, e.g., due to merge-base of $baseline_rev and + # $bad_rev is worse than $baseline_rev, we want to reset baseline to HEAD, + # so that we catch most of the commits that introduced change in the result + # metric. first_bad=$(git rev-parse HEAD) - if ! [ -f .git/BISECT_LOG ]; then - # It seems this was a trivial bisect with $bad_rev^ == $baseline_rev. - first_bad=$bad_rev - last_good=$(git rev-parse $first_bad^) - assert [ x"$last_good" = x"$baseline_rev" ] - - echo $first_bad > $artifacts/first-bad - fi + push_interesting_commits $first_bad fi cd .. |