#!/bin/bash -l # SPDX-License-Identifier: EPL-1.0 ############################################################################## # Copyright (c) 2017 The Linux Foundation and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-v10.html ############################################################################## # This script parses the console log to discover which project has caused a # build failure and notify the project as appropriate. echo "---> notify-build-failure.sh" NEWLINE=$'\n' RELEASE_EMAIL="release@lists.opendaylight.org" ARCHIVES_DIR="$JENKINS_HOSTNAME/$JOB_NAME/$BUILD_NUMBER" CONSOLE_LOG="/tmp/autorelease-build.log" STREAM=${JOB_NAME#*-*e-} ERROR_LOG="$WORKSPACE/archives/error.log.gz" wget -nv -O "$CONSOLE_LOG" "${BUILD_URL}consoleText" # TODO: This section is still required since some of the projects use # description. Remove this section when the reactor info is more consistant. # extract failing project from reactor information REACTOR_INFO=$(awk '/Reactor Summary:/ { flag=1 } flag { if ( sub(/^\[(INFO)\]/,"") && sub(/FAILURE \[.*/,"") ) { gsub(/[[:space:]]*::[[:space:]]*/,"::") gsub(/^[[:space:]]+|[[:space:]]+$|[.]/,"") print } } /Final Memory:/ { flag=0 }' $CONSOLE_LOG) # check for project format if [[ ${REACTOR_INFO} =~ .*::*.*::*. ]]; then # extract project and artifactId from full format # Ex: REACTOR_INFO="ODL::sfc::odl-sfc-pot-netconf-renderer 072 " is broken down into # NAME="ODL", PROJECT_="sfc" and NAME="odl-sfc-pot-netconf-renderer" ODL=$(echo "${REACTOR_INFO}" | awk -F'::' '{ gsub(/^[ \t]+|[ \t]+[0-9]+[ \t]+$|[ \t]+$/, "", $1); print $1}') PROJECT_=$(echo "${REACTOR_INFO}" | awk -F'::' '{ gsub(/^[ \t]+|[ \t]+[0-9]+[ \t]+$|[ \t]+$/, "", $2); print $2}') NAME=$(echo "${REACTOR_INFO}" | awk -F'::' '{ gsub(/^[ \t]+|[ \t]+[0-9]+[ \t]+$|[ \t]+$/, "", $3); print $3}') else # set project from partial format ODL="" PROJECT_="" NAME=$(echo "${REACTOR_INFO}" | awk '{ gsub(/^[ \t]+|[ \t]+$/, ""); print }') fi # determine ARTIFACT_ID for project mailing list ARTIFACT_ID=$(awk -F: '/\[ERROR\].*mvn -rf :/ { print $2}' $CONSOLE_LOG) # determine project mailing list using xpaths # if project.groupId: # project.groupId is set and is not inherited # else if project.parent.groupId: # project.groupId is not set but IS inherited from project.parent.groupId # else # exclude project mailing list if [ -n "$ARTIFACT_ID" ]; then grouplist=() while IFS="" read -r p; do GROUP=$(xmlstarlet sel\ -N "x=http://maven.apache.org/POM/4.0.0"\ -t -m "/x:project[x:artifactId='$ARTIFACT_ID']"\ --if "/x:project/x:groupId"\ -v "/x:project/x:groupId"\ --elif "/x:project/x:parent/x:groupId"\ -v "/x:project/x:parent/x:groupId"\ --else -o ""\ "$p" 2>/dev/null) if [ -n "${GROUP}" ]; then # shellcheck disable=SC2207 grouplist+=($(echo "${GROUP}" | awk -F'.' '{ print $3 }')) fi done < <(find . -name "pom.xml") if [ "${#grouplist[@]}" -eq 1 ]; then PROJECT="${grouplist[0]}" elif [ "${#grouplist[@]}" -gt 1 ]; then GROUPLIST="NOTE: The artifactId: $ARTIFACT_ID matches multiple groups: ${grouplist[*]}" else echo "Unable to determine project.groupId using xpaths" fi else echo "Unable to determine failed ARTIFACT_ID. Build likely successful or bug in this script." exit 0 fi # Construct email subject & body PROJECT_STRING=${PROJECT:+" from $PROJECT"} SUBJECT="[release] Autorelease $STREAM failed to build $ARTIFACT_ID$PROJECT_STRING" # shellcheck disable=SC2034 ATTACHMENT_INCLUDE="Attached is a snippet of the error message related to the failure that we were able to automatically parse as well as console logs." # shellcheck disable=SC2034 ATTACHMENT_EXCLUDE="Unable to attach error message snippet related to the failure since this exceeds the mail server attachment size limit. Please refer ${ERROR_LOG##*/} in archives directory." ATTACHMENT=ATTACHMENT_INCLUDE # default behaviour BODY="Attention ${PROJECT:-"OpenDaylight"}-devs, Autorelease $STREAM failed to build $ARTIFACT_ID$PROJECT_STRING in build $BUILD_NUMBER. \${!ATTACHMENT} ${PROJECT:+${NEWLINE}${GROUPLIST}} Console Logs: https://s3-logs.opendaylight.org/logs/$SILO/$ARCHIVES_DIR Jenkins Build: $BUILD_URL Please review and provide an ETA on when a fix will be available. Thanks, ODL releng/autorelease team " # check if remote staging is complete successfully BUILD_STATUS=$(awk '/\[INFO\] Remote staging finished/{flag=1;next}/Total time:/{flag=0}flag' $CONSOLE_LOG \ | grep '\] BUILD' | awk '{print $3}') # shellcheck disable=SC2235 if ([ -n "${NAME}" ] || [ -n "${ARTIFACT_ID}" ]) && [[ "${BUILD_STATUS}" != "SUCCESS" ]]; then # project search pattern should handle both scenarios # 1. Full format: ODL :: $PROJECT :: $ARTIFACT_ID # 2. Partial format: Building $ARTIFACT_ID sed -e "/\[INFO\] Building \(${NAME} \|${ARTIFACT_ID} \|${ODL} :: ${PROJECT_} :: ${NAME} \)/,/Reactor Summary:/!d;//d" \ $CONSOLE_LOG | gzip > "$ERROR_LOG" if [ -n "${PROJECT}" ]; then RELEASE_EMAIL="${RELEASE_EMAIL}, ${PROJECT}-dev@lists.opendaylight.org" fi file_size=$(du -k "$ERROR_LOG" | cut -f1) # Only send emails in production (releng), not testing (sandbox) if [ "${SILO}" == "releng" ]; then if [[ "$file_size" -gt 100 ]]; then # shellcheck disable=SC2034 ATTACHMENT=ATTACHMENT_EXCLUDE eval echo \""${BODY}"\" | mail \ -r "Jenkins " \ -s "${SUBJECT}" "${RELEASE_EMAIL}" else eval echo \""${BODY}"\" | mail -a "$ERROR_LOG" \ -r "Jenkins " \ -s "${SUBJECT}" "${RELEASE_EMAIL}" fi elif [ "${SILO}" == "sandbox" ]; then echo "Running in sandbox, not actually sending notification emails" echo "Subject: ${SUBJECT}" eval echo \""Body: ${BODY}"\" else echo "Not sure how to notify in \"${SILO}\" Jenkins silo" fi fi rm $CONSOLE_LOG