diff options
Diffstat (limited to 'round-robin.sh')
-rw-r--r-- | round-robin.sh | 184 |
1 files changed, 133 insertions, 51 deletions
diff --git a/round-robin.sh b/round-robin.sh index cfbfe117..b9c12e99 100644 --- a/round-robin.sh +++ b/round-robin.sh @@ -7,6 +7,11 @@ #rr[PROJECT_url] # PROJECT's git branch or SHA1 revision parsable by git rev-parse. +# A special value "baseline" means that PROJECT is not being updated +# in this build, and its baseline branch should be used. +# In a successful build "update_baseline" step will update baseline +# branches of all PROJECTs to the current values, thus setting +# a baseline for the next build. #rr[PROJECT_branch] # PROJECT's git SHA1 revision. These are mostly used in manifests. @@ -16,13 +21,6 @@ # be present in all above git repos (if ${rr[init_configuration]} is false). #rr[baseline_branch]="${rr[ci_project]}/${rr[ci_config]}" -# PROJECT that we are testing in this build. Use ${rr[current_branch]} for -# this project, and ${rr[baseline_branch]} for all other projects. -#rr[current_project]="$current_project" - -# Git branch or SHA1 revision of ${rr[current_project]} to test. -#rr[current_branch]="$current_branch" - # Run mode: bisect or non-bisect. In bisect mode we do a couple things # slightly differently (e.g., don't touch repo in clone_repo() ). #rr[mode]="$mode" @@ -40,6 +38,40 @@ # to initialize baseline branches in git repos. #rr[init_configuration]=false +# Print round-robin components that are being updated in this build +# (the ones using non-baseline branches). +print_updated_components () +{ + ( + set -euf -o pipefail + + local delim="" + local c + for c in ${rr[components]}; do + if [ x"${rr[${c}_branch]}" != x"baseline" ]; then + printf "%s%s" "$delim" "$c" + delim=${1- } + fi + done + ) +} + +# Print the single round-robin component being updated in this build. +# Print nothing if multiple components are being updated. +print_single_updated_component () +{ + ( + set -euf -o pipefail + + local -a updated_components + updated_components=($(print_updated_components)) + + if [ ${#updated_components[@]} = 1 ]; then + echo "${updated_components[0]}" + fi + ) +} + # Reset artifacts to an empty state. ${rr[top_artifacts]}/results is the most # important artifact, since it records the metric of how successful the build # is. @@ -91,24 +123,15 @@ clone_repo () fi local branch - # Select the branch to build. - # ${rr[current_branch]} specifies branch for ${rr[current_project]}, - # and everything else uses baseline branch. - if [ x"$project" = x"${rr[current_project]}" ]; then - # Use the tip of the branch tracked in the current configuration. - if [ x"${rr[current_branch]}" = x"default" ]; then - branch=${rr[${rr[current_project]}_branch]} - elif [ x"${rr[current_branch]}" = x"baseline" ]; then - branch="refs/remotes/baseline/${rr[baseline_branch]}" - else - branch=${rr[current_branch]} - fi - elif ${rr[init_configuration]-false}; then - branch="${rr[${project}_branch]}" - else + + # Resolve "baseline" branch specifier. + if [ x"${rr[${project}_branch]}" = x"baseline" ]; then branch="refs/remotes/baseline/${rr[baseline_branch]}" + else + branch="${rr[${project}_branch]}" fi + # Allow manifest override branch="${rr[${project}_rev]-$branch}" # Decide on whether to use read-only or read-write mode for @@ -116,7 +139,7 @@ clone_repo () # developers without ssh keys on Linaro git servers to reproduce builds # in --mode "baseline". local read_only="true" - if [ x"$project" = x"${rr[current_project]}" -a \ + if [ x"${rr[${project}_branch]}" != x"baseline" -a \ x"${rr[mode]}" = x"jenkins-full" ]; then read_only=false fi @@ -134,20 +157,6 @@ clone_repo () cat <<EOF | manifest_out rr[${project}_rev]=$cur_rev EOF - - if [ x"$project" = x"${rr[current_project]}" ] \ - && ! ${rr[init_configuration]-false}; then - local baseline_rev - baseline_rev=$(git_rev_parse_long $project ${rr[baseline_branch]} baseline) - # Prepare for failure. If build fails we will bisect sha1 for - # ${rr[current_branch]} and sha1 for ${rr[baseline_branch]}. - cat > ${rr[top_artifacts]}/trigger-bisect-on-failure <<EOF -current_project=${rr[current_project]} -baseline_rev=$baseline_rev -bad_rev=$cur_rev -EOF - git -C $project rev-list --count HEAD ^$baseline_rev > ${rr[top_artifacts]}/distance-to-baseline - fi ) } @@ -298,8 +307,9 @@ build_llvm () clone_repo llvm # Copy only components from the monorepo that are required for kernel build - rsync -a --del --exclude /tools/clang llvm/llvm/ llvm-src/ + rsync -a --del --exclude /tools/clang --exclude /tools/lld llvm/llvm/ llvm-src/ rsync -a --del llvm/clang/ llvm-src/tools/clang/ + rsync -a --del llvm/lld/ llvm-src/tools/lld/ # Setup ccache and ninja wrappers. rm -rf $(pwd)/bin @@ -349,6 +359,32 @@ check_regression () set -euf -o pipefail if ! ${rr[reset_baseline]} && ! no_regression_p; then + local single_component=$(print_single_updated_component) + + if [ x"$single_component" = x"" -o x"${rr[mode]}" = x"bisect" ]; then + local c + for c in $(print_updated_components); do + local c2 + for c2 in ${rr[components]}; do + if [ x"$c" = x"$c2" ]; then + echo "${c2}_branch=${rr[${c}_branch]}" + else + echo "${c2}_branch=baseline" + fi + done >> ${rr[top_artifacts]}/trigger-build-$c + done + else + local baseline_rev cur_rev + baseline_rev=$(git_rev_parse_long $single_component ${rr[baseline_branch]} baseline) + cur_rev=$(git -C $single_component rev-parse HEAD) + + cat > ${rr[top_artifacts]}/trigger-bisect <<EOF +current_project=$single_component +baseline_branch=$baseline_rev +bad_branch=$cur_rev +EOF + fi + # Fail. false fi @@ -368,42 +404,84 @@ update_baseline () # the current one, but keep entries for results that are better # (so that we have a record of pending regressions). while no_regression_p; do + prev_head="" if git -C base-artifacts rev-parse HEAD^ >/dev/null 2>&1; then - prev_head=$(git -C base-artifacts rev-parse HEAD) + # For every regression we want to keep artifacts for the first-bad + # build, so reset to the most relevant regression (marked by reset-baseline). + if [ -f base-artifacts/reset-baseline ] && ! ${rr[reset_baseline]}; then + prev_head=$(git -C base-artifacts rev-parse HEAD) + fi git -C base-artifacts reset --hard HEAD^ else # We got to the beginning of git history, so amend the current # commit. The initial state of baseline is "empty" branch, # which we treat as worst possible in no_regression_p(). amend="--amend" - prev_head="" break fi done - # For every regression we want to keep artifacts for the first-bad - # build, so discard one less than needed. if [ x"$prev_head" != x"" ]; then git -C base-artifacts reset --hard $prev_head fi - # Rsync current artifacts. + # Rsync current artifacts. Make sure to use -I rsync option since + # quite often size and timestamp on artifacts/results will be the same + # as on base-artifacts/results due to "git reset --hard HEAD^" below. + # This caused rsync's "quick check" heuristic to skip "results" file. # !!! From this point on, logs and other artifacts won't be included # in base-artifacts.git repo (though they will be uploaded to jenkins). - rsync -a --del --exclude /.git ${rr[top_artifacts]}/ base-artifacts/ + rsync -aI --del --exclude /.git ${rr[top_artifacts]}/ base-artifacts/ - local build_rev - build_rev=$(git -C ${rr[current_project]} rev-parse HEAD) + local rev_count + if [ x"$amend" = x"" ]; then + rev_count=$(git -C base-artifacts rev-list --count HEAD) + else + rev_count="0" + fi - cd base-artifacts - git add . - git commit $amend -m "${rr[current_project]}-$build_rev: $(tail -n1 ${rr[top_artifacts]}/results) + local msg_title="$rev_count" + + if ${rr[reset_baseline]}; then + # Create a marker for builds that reset baselines (these are builds + # for bisected regressions). + touch base-artifacts/reset-baseline + msg_title="$msg_title: first-bad" + else + msg_title="$msg_title: good" + fi + + local single_component + single_component=$(print_single_updated_component) + if [ x"$single_component" != x"" ]; then + local single_rev + single_rev=$(git -C $single_component rev-parse HEAD) + msg_title="$msg_title: $single_component-$single_rev" + else + msg_title="$msg_title: $(print_updated_components "-")" + fi + msg_title="$msg_title: $(tail -n1 ${rr[top_artifacts]}/results)" + + git -C base-artifacts add . + git -C base-artifacts commit $amend -m "$msg_title $(cat ${rr[top_artifacts]}/results)" + + # We saw strange behavior with base-artifacts/results not being updated + # in the rsync above. This should be fixed by "-I" rsync option, but + # keep below asserts just in case. + if [ x"$(diff -up ${rr[top_artifacts]}/results base-artifacts/results)" != x"" ] \ + || [ x"$amend" = x"" -a x"$(git -C base-artifacts diff HEAD HEAD^ -- results)" = x"" ]; then + cd base-artifacts + git status + cat results + ls -la + assert false + fi ) } -# Push to ${rr[current_project]} baseline branch and to base-artifacts repo. +# Push to baseline branches and to base-artifacts repo. push_baseline () { ( @@ -411,6 +489,10 @@ push_baseline () git_init_linaro_local_remote base-artifacts baseline false git_push base-artifacts baseline ${rr[baseline_branch]} - git_push ${rr[current_project]} baseline ${rr[baseline_branch]} + + local c + for c in $(print_updated_components); do + git_push $c baseline ${rr[baseline_branch]} + done ) } |