| #!/usr/bin/env bash |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| if [ "${TESTPATCHDEBUG}" == "true" ] ; then |
| set -x |
| fi |
| |
| BASEDIR=$(pwd) |
| TESTPATCHDIR=${BASEDIR}/test-patch |
| TOOLSDIR=${TESTPATCHDIR}/tools |
| TEMPDIR=${TESTPATCHDIR}/tmp |
| REPORTDIR=${TESTPATCHDIR}/reports |
| SUMMARYFILE=${REPORTDIR}/TEST-SUMMARY.jira |
| SUMMARYFILETXT=${REPORTDIR}/TEST-SUMMARY.txt |
| SUMMARYFILE_FULL=${REPORTDIR}/TEST-SUMMARY-FULL.jira |
| SUMMARYFILE_FULL_TXT=${REPORTDIR}/TEST-SUMMARY-FULL.txt |
| |
| JIRAHOST="https://issues.apache.org" |
| JIRAURL="${JIRAHOST}/jira" |
| JIRAURLISSUEPREFIX="${JIRAURL}/browse/" |
| |
| JIRAUPDATE="false" |
| JIRAUSER="oozieqa" |
| JIRAPASSWORD="" |
| |
| |
| VERBOSEOPTION="" |
| JIRAISSUE="" |
| PATCHFILE="" |
| TASKSTORUN="" |
| TASKSTOSKIP="" |
| RESETSCM="false" |
| DIRTYSCM="false" |
| STDOUT="/dev/null" |
| MVNPASSTHRU="" |
| |
| ############################################################################### |
| gitOrSvn() { |
| SCM="NONE" |
| which git &> /dev/null |
| if [[ $? == 0 ]] ; then |
| git status &> /dev/null |
| if [[ $? == 0 ]] ; then |
| SCM="git" |
| fi |
| fi |
| if [ "${SCM}" == "NONE" ] ; then |
| which svn &> /dev/null |
| if [[ $? == 0 ]] ; then |
| svnOutput=`svn status 2>&1` |
| if [[ "$svnOutput" != *"is not a working copy" ]] ; then |
| SCM="svn" |
| fi |
| fi |
| fi |
| if [ "${SCM}" == "NONE" ] ; then |
| echo "The current workspace is not under Source Control (GIT or SVN)" |
| exit 1 |
| fi |
| } |
| ############################################################################### |
| prepareSCM() { |
| gitOrSvn |
| if [ "${DIRTYSCM}" != "true" ] ; then |
| if [ "${RESETSCM}" == "true" ] ; then |
| if [ "${SCM}" == "git" ] ; then |
| git reset --hard HEAD > /dev/null |
| git clean -f -d > /dev/null |
| fi |
| if [ "${SCM}" == "svn" ] ; then |
| svn revert -R . > /dev/null |
| svn status | grep "\?" | awk '{print $2}' | xargs rm -rf |
| fi |
| else |
| echo "It should not happen DIRTYSCM=false & RESETSCM=false" |
| exit 1 |
| fi |
| summary_both "Cleaning local ${SCM} workspace" |
| else |
| summary_both "WARNING: Running test-patch on a dirty local ${SCM} workspace" |
| fi |
| } |
| ############################################################################### |
| prepareTestPatchDirs() { |
| mkdir ${TESTPATCHDIR} 2> /dev/null |
| rm -rf ${REPORTDIR} 2> /dev/null |
| rm -rf ${TEMPDIR} 2> /dev/null |
| mkdir ${TOOLSDIR} 2> /dev/null |
| mkdir ${TEMPDIR} 2> /dev/null |
| mkdir ${REPORTDIR} 2> /dev/null |
| if [ ! -e "${TESTPATCHDIR}" ] ; then |
| echo "Could not create test-patch/ dir" |
| exit 1 |
| fi |
| } |
| ############################################################################### |
| updateJira() { |
| if [[ "${JIRAUPDATE}" != "" && "${JIRAISSUE}" != "" ]] ; then |
| if [[ "$JIRAPASSWORD" != "" ]] ; then |
| echo "Adding comment to JIRA" |
| |
| # Replace newlines with \n so that summary can be sent via JSON to JIRA |
| comment=$(awk '{printf "%s\\n", $0}' ${SUMMARYFILE}) |
| |
| curl -u "${JIRAUSER}:${JIRAPASSWORD}"\ |
| -H "Content-type: application/json"\ |
| -H "Accept: application/json"\ |
| -X POST\ |
| --data "{\"body\": \"${comment}\"}"\ |
| ${JIRAURL}/rest/api/2/issue/${JIRAISSUE}/comment || echo "Failed to add comment to JIRA" |
| echo |
| else |
| echo "Skipping JIRA update" |
| echo |
| fi |
| fi |
| } |
| ############################################################################### |
| cleanupAndExit() { |
| updateJira |
| echo "test-patch exit code: $1" |
| echo |
| exit $1 |
| } |
| ############################################################################### |
| printUsage() { |
| echo "Usage: $0 <OPTIONS>" |
| echo " (--jira=<JIRA ISSUE> | --patch=<PATCH PATH>)" |
| echo " (--reset-scm | --dirty-scm)" |
| echo " [--tasks=<TASK,...>]" |
| echo " [--skip-tasks=<TASK,...>]" |
| echo " [--jira-cli=<JIRA CLIENT>]" |
| echo " [--jira-user=<JIRA USER>]" |
| echo " [--jira-password=<JIRA PASSWORD>]" |
| echo " [-D<MVN PROPERTY>...]" |
| echo " [-P<MVN PROFILE>...]" |
| echo " [--list-tasks]" |
| echo " [--verbose]" |
| echo |
| } |
| ############################################################################### |
| parseArgs() { |
| for i in $* |
| do |
| case $i in |
| --jira=*) |
| JIRAISSUE=${i#*=} |
| ;; |
| --patch=*) |
| PATCHFILE=${i#*=} |
| ;; |
| --tasks=*) |
| TASKSTORUN=${i#*=} |
| ;; |
| --skip-tasks=*) |
| TASKSTOSKIP=${i#*=} |
| ;; |
| --list-tasks) |
| listTasks |
| cleanupAndExit 0 |
| ;; |
| --jira-cli=*) |
| JIRACLI=${i#*=} |
| ;; |
| --jira-user=*) |
| JIRAUSER=${i#*=} |
| ;; |
| --jira-password=*) |
| JIRAPASSWORD=${i#*=} |
| JIRAUPDATE="true" |
| ;; |
| -D*) |
| MVNPASSTHRU="${MVNPASSTHRU} $i" |
| ;; |
| -P*) |
| MVNPASSTHRU="${MVNPASSTHRU} $i" |
| ;; |
| --reset-scm) |
| RESETSCM="true" |
| ;; |
| --dirty-scm) |
| DIRTYSCM="true" |
| ;; |
| --verbose) |
| VERBOSEOPTION="--verbose" |
| STDOUT="/dev/stdout" |
| ;; |
| *) |
| echo "Invalid option" |
| echo |
| printUsage |
| exit 1 |
| ;; |
| esac |
| done |
| if [[ "${JIRAISSUE}" == "" && "${PATCHFILE}" == "" ]] ; then |
| echo "Either --jira or --patch option must be specified" |
| echo |
| printUsage |
| exit 1 |
| fi |
| if [[ "${JIRAISSUE}" != "" && "${PATCHFILE}" != "" ]] ; then |
| echo "Cannot specify --jira or --patch options together" |
| echo |
| printUsage |
| exit 1 |
| fi |
| if [[ "${RESETSCM}" == "false" && "${DIRTYSCM}" == "false" ]] ; then |
| echo "Either --reset-scm or --dirty-scm option must be specified" |
| echo |
| printUsage |
| exit 1 |
| fi |
| if [[ "${RESETSCM}" == "true" && "${DIRTYSCM}" == "true" ]] ; then |
| echo "Cannot specify --reset-scm and --dirty-scm options together" |
| echo |
| printUsage |
| exit 1 |
| fi |
| } |
| ############################################################################### |
| listTasks() { |
| echo "Available Tasks:" |
| echo "" |
| getAllTasks |
| for taskFile in ${TASKFILES} ; do |
| taskName=`bash $taskFile --taskname` |
| echo " $taskName" |
| done |
| echo |
| } |
| ############################################################################### |
| downloadPatch () { |
| PATCHFILE=${TEMPDIR}/test.patch |
| jiraPage=${TEMPDIR}/jira.txt |
| curl "${JIRAURLISSUEPREFIX}${JIRAISSUE}" > ${jiraPage} |
| if [[ `grep -c 'Patch Available' ${jiraPage}` == 0 ]] ; then |
| echo "$JIRAISSUE is not \"Patch Available\". Exiting." |
| echo |
| cleanupAndExit 1 |
| fi |
| relativePatchURL=`grep -o '"/jira/secure/attachment/[0-9]*/[^"]*' ${jiraPage} \ |
| | grep -v -e 'htm[l]*$' | sort | tail -1 \ |
| | grep -o '/jira/secure/attachment/[0-9]*/[^"]*'` |
| patchURL="${JIRAHOST}${relativePatchURL}" |
| patchNum=`echo $patchURL | grep -o '[0-9]*/' | grep -o '[0-9]*'` |
| curl ${patchURL} > ${PATCHFILE} |
| if [[ $? != 0 ]] ; then |
| echo "Could not download patch for ${JIRAISSUE} from ${patchURL}" |
| echo |
| cleanupAndExit 1 |
| fi |
| echo "JIRA ${JIRAISSUE}, patch downloaded at `date` from ${patchURL}" |
| echo |
| } |
| ############################################################################### |
| applyPatch() { |
| echo "Applying patch" >> $STDOUT |
| echo "" >> $STDOUT |
| git apply --check -v -p0 < ${PATCHFILE} | tee ${REPORTDIR}/APPLY-PATCH.txt \ |
| >> $STDOUT |
| if [[ ${PIPESTATUS[0]} == 0 ]] ; then |
| git apply -v -p0 < ${PATCHFILE} > ${REPORTDIR}/APPLY-PATCH.txt |
| if [[ $? != 0 ]] ; then |
| echo "ODD!, git apply --check -p0 passed, but patch failed to apply to head of branch" |
| echo |
| cleanupAndExit 1 |
| fi |
| else |
| git apply --check -v < ${PATCHFILE} | tee ${REPORTDIR}/APPLY-PATCH.txt \ |
| >> $STDOUT |
| if [[ ${PIPESTATUS[0]} == 0 ]] ; then |
| git apply -v < ${PATCHFILE} > ${REPORTDIR}/APPLY-PATCH.txt |
| if [[ $? != 0 ]] ; then |
| echo "ODD!, git apply --check passed, but patch failed to apply to head of branch" |
| echo |
| cleanupAndExit 1 |
| fi |
| else |
| echo "Patch failed to apply to head of branch" |
| summary_both "{color:red}-1{color} Patch failed to apply to head of branch" |
| summary_both "" |
| summary_both "----------------------------" |
| echo |
| cleanupAndExit 1 |
| fi |
| fi |
| echo "" >> $STDOUT |
| echo "Patch applied" |
| summary_both "{color:green}+1 PATCH_APPLIES{color}" |
| echo |
| } |
| ############################################################################### |
| run() { |
| task=`bash $1 --taskname` |
| if [[ "${TASKSTORUN}" == "" || "${TASKSTORUN}" =~ "${task}" ]] ; then |
| if [[ ! "${TASKSTOSKIP}" =~ "${task}" ]] ; then |
| echo " Running test-patch task ${task}" |
| outputFile="`basename $1`-$2.out" |
| $1 --op=$2 --tempdir=${TEMPDIR} --reportdir=${REPORTDIR} \ |
| --summaryfile=${SUMMARYFILE} --summaryfile-full=${SUMMARYFILE_FULL} --patchfile=${PATCHFILE} ${MVNPASSTHRU} \ |
| ${VERBOSEOPTION} | tee ${TEMPDIR}/${outputFile} >> $STDOUT |
| if [[ $? != 0 ]] ; then |
| echo " Failure, check for details ${TEMPDIR}/${outputFile}" |
| echo |
| cleanupAndExit 1 |
| fi |
| fi |
| fi |
| } |
| ############################################################################### |
| getAllTasks() { |
| TASKFILES=`ls -a bin/test\-patch\-[0-9][0-9]\-*` |
| } |
| ############################################################################### |
| prePatchRun() { |
| echo "Pre patch" |
| for taskFile in ${TASKFILES} ; do |
| run $taskFile pre |
| done |
| echo |
| } |
| ############################################################################### |
| postPatchRun() { |
| echo "Post patch" |
| for taskFile in ${TASKFILES} ; do |
| run $taskFile post |
| done |
| echo |
| } |
| ############################################################################### |
| createReports() { |
| echo "Reports" |
| for taskFile in ${TASKFILES} ; do |
| run $taskFile report |
| done |
| echo |
| } |
| ############################################################################### |
| summary_both() { |
| LINE=$1 |
| echo ${LINE} >> ${SUMMARYFILE} |
| echo ${LINE} >> ${SUMMARYFILE_FULL} |
| } |
| ############################################################################### |
| |
| echo |
| |
| parseArgs "$@" |
| |
| prepareTestPatchDirs |
| |
| echo -n "PreCommit-OOZIE-Build started" > ${SUMMARYFILE} |
| updateJira |
| echo "" > ${SUMMARYFILE} |
| echo "" > ${SUMMARYFILE_FULL} |
| |
| if [ "${PATCHFILE}" == "" ] ; then |
| echo "Testing JIRA ${JIRAISSUE}" |
| echo |
| summary_both "Testing JIRA ${JIRAISSUE}" |
| summary_both "" |
| else |
| if [ ! -e ${PATCHFILE} ] ; then |
| echo "Patch file does not exist" |
| cleanupAndExit 1 |
| fi |
| echo "Testing patch ${PATCHFILE}" |
| echo |
| summary_both "Testing patch ${PATCHFILE}" |
| summary_both "" |
| fi |
| prepareSCM |
| |
| summary_both "" |
| |
| if [ "${PATCHFILE}" == "" ] ; then |
| downloadPatch ${JIRAISSUE} |
| fi |
| |
| summary_both "----------------------------" |
| summary_both "" |
| getAllTasks |
| prePatchRun |
| applyPatch |
| postPatchRun |
| createReports |
| summary_both "" |
| summary_both "----------------------------" |
| MINUSONES=`grep -c "\}\-1" ${SUMMARYFILE}` |
| if [[ $MINUSONES == 0 ]]; then |
| summary_both "{color:green}*+1 Overall result, good!, no -1s*{color}" |
| else |
| summary_both "{color:red}*-1 Overall result, please check the reported -1(s)*{color}" |
| fi |
| summary_both "" |
| WARNINGS=`grep -c "\}WARNING" ${SUMMARYFILE}` |
| if [[ $WARNINGS != 0 ]]; then |
| summary_both "{color:red}. There is at least one warning, please check{color}" |
| fi |
| summary_both "" |
| |
| if [ ! -z "${JIRAISSUE}" ]; then |
| summary_both "The full output of the test-patch run is available at" |
| summary_both "" |
| summary_both ". ${BUILD_URL}" |
| summary_both "" |
| else |
| echo |
| echo "Refer to ${REPORTDIR} for detailed test-patch reports" |
| echo |
| fi |
| |
| cat ${SUMMARYFILE} | sed -e 's/{color}//' -e 's/{color:green}//' -e 's/{color:red}//' -e 's/{color:orange}//' -e 's/^\.//' -e 's/^\*//' -e 's/\*$//' > ${SUMMARYFILETXT} |
| cat ${SUMMARYFILETXT} |
| |
| cat ${SUMMARYFILE_FULL} | sed -e 's/{color}//' -e 's/{color:green}//' -e 's/{color:red}//' -e 's/{color:orange}//' -e 's/^\.//' -e 's/^\*//' -e 's/\*$//' > ${SUMMARYFILE_FULL_TXT} |
| |
| grep "^+1 Overall result" ${SUMMARYFILETXT} &> /dev/null |
| grep "^+1 Overall result" ${SUMMARYFILE_FULL_TXT} &> /dev/null |
| cleanupAndExit "$?" |