#!/bin/bash set -euf -o pipefail scripts=$(dirname $0) # shellcheck source=jenkins-helpers.sh . $scripts/jenkins-helpers.sh convert_args_to_variables "$@" shift "$SHIFT_CONVERTED_ARGS" obligatory_variables \ artifacts BUILD_URL ci_project ci_config current_project \ first_bad last_good summary declare \ artifacts BUILD_URL ci_project ci_config current_project \ first_bad last_good summary dryrun="${dryrun-false}" icommits="interesting-commits" verbose="${verbose-true}" if $verbose; then set -x fi if $dryrun; then dryrun="echo DRYRUN: " else dryrun="" fi prepare_interesting_commits () { ( set -euf -o pipefail # Clone interesting-commits.git repo, which contains a regression # summaries for SHA1s. These are the "first_bad" commits. clone_or_update_repo $icommits master \ https://git-us.linaro.org/toolchain/ci/interesting-commits.git \ auto master git_init_linaro_local_remote $icommits baseline false ) } # Update interesting-commit's entry for a given commit # $1: component # $2: sha1 of first_bad commit # $3: sha1 of last_good commit # # Interesting-commits store regression history in the following hierarchy: # 1. At the top level we have COMPONENT directories. # 2. At the 2nd level we have SHA1 directories. # 2a. We also have "git describe" symlinks to SHA1 directories for convenience. # 3. At the 3rd level we have CI_PROJECT directories. # 4. At the 4th level we have CI_CONFIG directories, and ... # 4a. ... status.txt, which contains status of changes from SHA1 across all # CI_CONFIGs in CI_PROJECT. # 5. At the 5th level we have per-build files last_good, summary.txt, etc. update_interesting_entry () { ( set -euf -o pipefail local component="$1" local first_bad="$2" local last_good="$3" local subdir subdir=$(interesting_subdir "$component" "$first_bad") local describe describe=$(describe_sha1 "$component" "$first_bad" false) if ! [ -d $icommits/$subdir ] && [ x"$describe" != x"" ]; then local d d=$(dirname "$describe") mkdir -p $icommits/$component/$d local symlink="" while [ x"$d" != x"." ]; do symlink="../$symlink" d=$(dirname "$d") done symlink="${symlink}sha1/$first_bad" ln -s $symlink $icommits/$component/$describe git -C $icommits add $component/$describe fi # shellcheck disable=SC2154 subdir=$(interesting_subdir "$component" "$first_bad" \ "$ci_project" "$ci_config") mkdir -p "$icommits/$subdir" echo "$BUILD_URL" > "$icommits/$subdir/build_url" echo "$last_good" > "$icommits/$subdir/last_good" git -C "$icommits" add "$subdir/build_url" "$subdir/last_good" cp $summary "$icommits/$subdir/summary.txt" git -C "$icommits" add "$subdir/summary.txt" local status="$subdir/../status.txt" if [ x"$describe" = x"" ]; then describe=$(describe_sha1 "$component" "$first_bad" true) fi cat > $icommits/$status <> $icommits/$status git -C "$icommits" add "$status" ) } update_interesting_commits () { ( set -euf -o pipefail # Reset to master branch git -C $icommits remote update -p git -C $icommits reset -q --hard refs/remotes/baseline/master local isubdir isubdir=$(interesting_subdir "$current_project" "$first_bad" \ "$ci_project") local reported_before=false if [ -d "$icommits/$isubdir/$ci_config" ]; then reported_before=true fi # We have successfully identified a bad commit with a good parent! # Add $first_bad to interesting commits. update_interesting_entry "$current_project" "$first_bad" "$last_good" # Commit and push git -C $icommits commit -m "Add entry $first_bad from ${BUILD_URL-$(pwd)}" $dryrun git -C $icommits push baseline HEAD:refs/heads/master if $reported_before; then # This is a re-occurring problem (usually, in linux-next). # Don't spam developers. rm -f $artifacts/jira-status.txt $artifacts/mail-recipients.txt else touch $artifacts/jira-status.txt $artifacts/mail-recipients.txt fi ) } # Update mail files with status of $first_bad regression update_mail_files () { ( set -euf -o pipefail if ! [ -f $artifacts/mail-recipients.txt ]; then return fi local isubdir isubdir=$(interesting_subdir "$current_project" "$first_bad" \ "$ci_project") sed -e "/#INTERESTING_COMMIT_STATUS#/r $icommits/$isubdir/status.txt" \ -e "/#INTERESTING_COMMIT_STATUS#/d" \ < $artifacts/mail-body.draft > $artifacts/mail-body.txt cp $artifacts/mail-subject.draft $artifacts/mail-subject.txt if [ "$(ls "$icommits/$isubdir" | wc -l)" = 2 ]; then cp $artifacts/mail-recipients.draft $artifacts/mail-recipients.txt else # This is not the first entry for $first_bad in $ci_project -- # don't notify the patch author. # One line for ci_config, and one for status.txt. echo "bcc:tcwg-validation@linaro.org" \ > $artifacts/mail-recipients.txt fi ) } # Post update to Jira post_to_jira () { ( set -euf -o pipefail if ! [ -f $artifacts/jira-status.txt ]; then return fi local isubdir isubdir=$(interesting_subdir "$current_project" "$first_bad" \ "$ci_project") sed -e "/#INTERESTING_COMMIT_STATUS#/r $icommits/$isubdir/status.txt" \ -e "/#INTERESTING_COMMIT_STATUS#/d" \ < $artifacts/jira-status.draft > $artifacts/jira-status.txt if [ -f $HOME/.jipdate.yml ]; then echo y | $dryrun jipdate.py -f $artifacts/jira-status.txt fi ) } prepare_interesting_commits while true; do update_interesting_commits & if wait $!; then update_mail_files post_to_jira break fi done