fuel-mirror/perestroika/build-functions.sh

298 lines
11 KiB
Bash

#!/bin/bash
[ -z "$GERRIT_USER" ] && GERRIT_USER='openstack-ci-jenkins'
[ -z "$GERRIT_HOST" ] && GERRIT_HOST=$gerrit_host
[ -z "$GERRIT_PORT" ] && GERRIT_PORT=$gerrit_port
[ -z "$GERRIT_PORT" ] && GERRIT_PORT=29418
[ -z "$GERRIT_SCHEME" ] && GERRIT_SCHEME="ssh"
URL="${GERRIT_SCHEME}://${GERRIT_USER}@${GERRIT_HOST}:${GERRIT_PORT}"
GITDATA=${HOME}/gitdata/$GERRIT_HOST
METADATA=${HOME}/repometadata
PKG_DIR=${HOME}/built_packages
EXCLUDES='--exclude-vcs'
WRKDIR=`pwd`
MYOUTDIR=${WRKDIR}/wrk-build
BUILDDIR=${MYOUTDIR}/src-to-build
rm -rf $BUILDDIR
mkdir -p $BUILDDIR
[ ! -d "$PKG_DIR" ] && mkdir -p $PKG_DIR
[ -f "${WRKDIR}/buildlog.txt" ] && rm -f ${WRKDIR}/buildlog.txt
error () {
echo
echo -e "ERROR: $*"
echo
exit 1
}
info () {
echo
echo -e "INFO: $*"
echo
}
job_lock() {
local LOCKFILE=$1
local TIMEOUT=600
shift
fd=15
eval "exec $fd>$LOCKFILE"
if [ "$1" = "set" ]; then
flock --timeout $TIMEOUT -x $fd
elif [ "$1" = "unset" ]; then
flock -u $fd
fi
}
request_is_merged () {
local REF=$1
local CHANGENUMBER=`echo $REF | cut -d '/' -f4`
local result=1
local status=`ssh ${GERRIT_USER}@${GERRIT_HOST} -p $GERRIT_PORT gerrit query --format=TEXT $CHANGENUMBER | egrep -o " +status:.*" | awk -F': ' '{print $2}'`
[ "$status" == "MERGED" ] && local result=0
return $result
}
set_default_params () {
[ -z "$PROJECT_NAME" ] && error "Project name is not defined! Exiting!"
[ -z "$PROJECT_VERSION" ] && error "Project version is not defined! Exiting!"
[ "$IS_HOTFIX" == "true" -a "$IS_UPDATES" == "false" ] && error "ERROR: Hotfix update before release"
if [ -n "$GERRIT_PROJECT" ]; then
if [ -z "$GERRIT_CHANGE_STATUS" ] ; then
# Detect change status
GERRIT_CHANGE_STATUS="NEW"
if [ -n "$GERRIT_REFSPEC" ]; then
request_is_merged $GERRIT_REFSPEC && GERRIT_CHANGE_STATUS="MERGED"
else
# Support ref-updated gerrit event
GERRIT_CHANGE_STATUS="REF_UPDATED"
GERRIT_BRANCH=$GERRIT_REFNAME
fi
fi
if [ -n "$GERRIT_CHANGE_COMMIT_MESSAGE" ] ; then
local GERRIT_MEGGASE="`echo $GERRIT_CHANGE_COMMIT_MESSAGE | base64 -d || :`"
fi
if [ "$GERRIT_CHANGE_STATUS" == "NEW" ] ; then
REQUEST_NUM="CR-$GERRIT_CHANGE_NUMBER"
local _LP_BUG=`echo "$GERRIT_TOPIC" | egrep -o "group/[0-9]+" | cut -d'/' -f2`
#[ -z "$_LP_BUG" ] && _LP_BUG=`echo "$GERRIT_MEGGASE" | egrep -i -o "(closes|partial|related)-bug: ?#?[0-9]+" | sort -u | head -1 | awk -F'[: #]' '{print $NF}'`
[ -n "$_LP_BUG" ] && LP_BUG="LP-$_LP_BUG"
if [ -n "${CUSTOM_REPO_ID}" ] ; then
unset LP_BUG
REQUEST_NUM=${CUSTOM_REPO_ID}
fi
fi
# Detect packagename
PACKAGENAME=${GERRIT_PROJECT##*/}
[ "${PACKAGENAME##*-}" == "build" ] && PACKAGENAME=${PACKAGENAME%-*}
SRC_PROJECT=${SRC_PROJECT_PATH}/$PACKAGENAME
[ "$IS_OPENSTACK" == "true" ] && SPEC_PROJECT=${SPEC_PROJECT_PATH}/${PACKAGENAME}${SPEC_PROJECT_SUFFIX}
case $GERRIT_PROJECT in
"$SRC_PROJECT" ) SOURCE_REFSPEC=$GERRIT_REFSPEC ;;
"$SPEC_PROJECT" ) SPEC_REFSPEC=$GERRIT_REFSPEC ;;
esac
SOURCE_BRANCH=$GERRIT_BRANCH
[ "$IS_OPENSTACK" == "true" ] && SPEC_BRANCH=$GERRIT_BRANCH
fi
[ -z "$PACKAGENAME" ] && error "Package name is not defined! Exiting!"
[ -z "$SOURCE_BRANCH" ] && error "Source branch is not defined! Exiting!"
[ "$IS_OPENSTACK" == "true" ] && [ -z "$SPEC_BRANCH" ] && SPEC_BRANCH=$SOURCE_BRANCH
[ "$IS_OPENSTACK" == "true" ] && SPEC_PROJECT=${SPEC_PROJECT_PATH}/${PACKAGENAME}${SPEC_PROJECT_SUFFIX}
SRC_PROJECT=${SRC_PROJECT_PATH}/$PACKAGENAME
}
fetch_upstream () {
# find corresponding requests
if [ -n "$SPEC_PROJECT" -a "${GERRIT_TOPIC%/*}" = "spec" ] ; then
local CORR_GERRIT_PROJECT=$SRC_PROJECT
[ "$GERRIT_PROJECT" == "$SRC_PROJECT" ] && CORR_GERRIT_PROJECT=$SPEC_PROJECT
local search_string="topic:${GERRIT_TOPIC} branch:${GERRIT_BRANCH} project:${CORR_GERRIT_PROJECT} -status:abandoned"
local CORR_CHANGE=`ssh -p $GERRIT_PORT ${GERRIT_USER}@$GERRIT_HOST gerrit query --current-patch-set \'${search_string}\'`
local CORR_CHANGE_REFSPEC="`echo \"${CORR_CHANGE}\" | grep 'ref:' | awk '{print $NF}'`"
local CORR_CHANGE_NUMBER=`echo $CORR_CHANGE_REFSPEC | cut -d'/' -f4`
local CORR_PATCHSET_NUMBER=`echo $CORR_CHANGE_REFSPEC | cut -d'/' -f5`
local CORR_CHANGE_URL=`echo "${CORR_CHANGE}" | grep 'url:' | awk '{print $NF}'`
local CORR_CHANGE_STATUS=`echo "${CORR_CHANGE}" | grep 'status:' | awk '{print $NF}'`
local corr_ref_count=`echo "$CORR_CHANGE_REFSPEC" | wc -l`
[ $corr_ref_count -gt 1 ] && error "ERROR: Multiple corresponding changes found!"
if [ -n "$CORR_CHANGE_NUMBER" ] ; then
# Provide corresponding change to vote script
cat > ${WRKDIR}/corr.setenvfile <<-EOL
CORR_CHANGE_NUMBER=$CORR_CHANGE_NUMBER
CORR_PATCHSET_NUMBER=$CORR_PATCHSET_NUMBER
CORR_CHANGE_URL=$CORR_CHANGE_URL
CORR_CHANGE_REFSPEC=$CORR_CHANGE_REFSPEC
EOL
fi
# Do not perform build stage if corresponding CR is not merged
if [ -n "${CORR_CHANGE_STATUS}" ] && [ "$GERRIT_CHANGE_STATUS" == "MERGED" ] && [ "$CORR_CHANGE_STATUS" != "MERGED" ] ; then
echo "SKIPPED=1" >> ${WRKDIR}/corr.setenvfile
error "Skipping build due to unmerged status of corresponding change ${CORR_CHANGE_URL}"
fi
fi
# Do not clone projects every time. It makes gerrit sad. Cache it!
for prj in $SRC_PROJECT $SPEC_PROJECT; do
# Update code base cache
[ -d ${GITDATA} ] || mkdir -p ${GITDATA}
if [ ! -d ${GITDATA}/$prj ]; then
info "Cache for $prj doesn't exist. Cloning to ${HOME}/gitdata/$prj"
mkdir -p ${GITDATA}/$prj
# Lock cache directory
job_lock ${GITDATA}/${prj}.lock set
pushd ${GITDATA} &>/dev/null
info "Cloning sources from $URL/$prj.git ..."
git clone "$URL/$prj.git" "$prj"
popd &>/dev/null
else
# Lock cache directory
job_lock ${GITDATA}/${prj}.lock set
info "Updating cache for $prj"
pushd ${GITDATA}/$prj &>/dev/null
info "Fetching sources from $URL/$prj.git ..."
# Replace git remote user
local remote=`git remote -v | head -1 | awk '{print $2}' | sed "s|//.*@|//${GERRIT_USER}@|"`
git remote rm origin
git remote add origin $remote
# Update gitdata
git fetch --all
popd &>/dev/null
fi
if [ "$prj" == "$SRC_PROJECT" ]; then
local _DIRSUFFIX=src
local _BRANCH=$SOURCE_BRANCH
[ -n "$SOURCE_REFSPEC" ] && local _REFSPEC=$SOURCE_REFSPEC
fi
if [ "$prj" == "$SPEC_PROJECT" ]; then
local _DIRSUFFIX=spec
local _BRANCH=$SPEC_BRANCH
[ -n "$SPEC_REFSPEC" ] && local _REFSPEC=$SPEC_REFSPEC
fi
[ -e "${MYOUTDIR}/${PACKAGENAME}-${_DIRSUFFIX}" ] && rm -rf "${MYOUTDIR}/${PACKAGENAME}-${_DIRSUFFIX}"
info "Getting $_DIRSUFFIX from $URL/$prj.git ..."
cp -R ${GITDATA}/${prj} ${MYOUTDIR}/${PACKAGENAME}-${_DIRSUFFIX}
# Unlock cache directory
job_lock ${GITDATA}/${prj}.lock unset
pushd ${MYOUTDIR}/${PACKAGENAME}-${_DIRSUFFIX} &>/dev/null
switch_to_revision $_BRANCH
# Get code from HEAD if change is merged
[ "$GERRIT_CHANGE_STATUS" == "MERGED" ] && unset _REFSPEC
# If _REFSPEC specified switch to it
if [ -n "$_REFSPEC" ] ; then
switch_to_changeset $prj $_REFSPEC
else
[ "$prj" == "${CORR_GERRIT_PROJECT}" ] && [ -n "${CORR_CHANGE_REFSPEC}" ] && switch_to_changeset $prj $CORR_CHANGE_REFSPEC
fi
popd &>/dev/null
case $_DIRSUFFIX in
src) gitshasrc=$gitsha
;;
spec) gitshaspec=$gitsha
;;
*) error "Unknown project type"
;;
esac
unset _DIRSUFFIX
unset _BRANCH
unset _REFSPEC
done
}
switch_to_revision () {
info "Switching to branch $*"
if ! git checkout $*; then
error "$* not accessible by default clone/fetch"
else
git reset --hard origin/$*
gitsha=`git log -1 --pretty="%h"`
fi
}
switch_to_changeset () {
info "Switching to changeset $2"
git fetch "$URL/$1.git" $2
git checkout FETCH_HEAD
gitsha=`git log -1 --pretty="%h"`
}
get_last_commit_info () {
if [ -n "$1" ] ; then
pushd $1 &>/dev/null
message="$(git log -n 1 --pretty=format:%B)"
author=$(git log -n 1 --pretty=format:%an)
email=$(git log -n 1 --pretty=format:%ae)
cdate=$(git log -n 1 --pretty=format:%ad | cut -d' ' -f1-3,5)
commitsha=$(git log -n 1 --pretty=format:%h)
lastgitlog=$(git log --pretty="%h|%ae|%an|%s" -n 10)
popd &>/dev/null
fi
}
get_extra_revision () {
local type=$1
local _srcpath=$2
[ -n "$3" ] && local release_tag=$3
case "$type" in
security)
local _prefix="0."
unset _suffix
;;
hotfix)
unset _prefix
local _suffix=".0"
;;
esac
# hotfix branch name for openstack projects should be like
# "{stable_branch_name}-hotfix-<id>"
# security branch name for openstack projects should be like
# "{stable_branch_name}-security-<id>"
# Get parent branch
local _parent_branch=$(echo "$SOURCE_BRANCH" | sed -r "s|-${type}-.*$||")
[ $(git -C "$_srcpath" branch -a | fgrep -c "origin/$_parent_branch") -eq 0 ] && error "Can't find parent source branch"
# Get common ancestor
local _merge_base=$(git -C "$_srcpath" merge-base "origin/$_parent_branch" "origin/$SOURCE_BRANCH")
# Calculate ancestor revision
if [ -n "$release_tag" ] ; then
local _base_rev=$(git -C "$_srcpath" rev-list --no-merges "$release_tag".."$_merge_base" | wc -l)
else
local _base_rev=$(git -C "$_srcpath" rev-list --no-merges "$_merge_base" | wc -l)
fi
# Calculate delta revision
local _delta_rev=$(( $_rev - $_base_rev ))
local _rev=${_base_rev}.${_prefix}${_delta_rev}${_suffix}
echo "$_rev"
}
fill_buildresult () {
#$status $time $PACKAGENAME $pkgtype
local status=$1
local time=$2
local packagename=$3
local pkgtype=$4
local xmlfilename=${WRKDIR}/buildresult.xml
local failcnt=0
local buildstat="Succeeded"
[ "$status" != "0" ] && failcnt=1 && buildstat="Failed"
echo "<testsuite name=\"Package build\" tests=\"Package build\" errors=\"0\" failures=\"$failcnt\" skip=\"0\">" > $xmlfilename
echo -n "<testcase classname=\"$pkgtype\" name=\"$packagename\" time=\"0\"" >> $xmlfilename
if [ "$failcnt" == "0" ] ; then
echo "/>" >> $xmlfilename
else
echo ">" >> $xmlfilename
echo "<failure type=\"Failure\" message=\"$buildstat\">" >> $xmlfilename
if [ -f "${WRKDIR}/buildlog.txt" ] ; then
cat ${WRKDIR}/buildlog.txt | sed -n '/^dpkg: error/,/^Package installation failed/p' | egrep -v '^Get|Selecting|Unpacking|Preparing' >> $xmlfilename || :
cat ${WRKDIR}/buildlog.txt | sed -n '/^The following information may help to resolve the situation/,/^Package installation failed/p' >> $xmlfilename || :
cat ${WRKDIR}/buildlog.txt | grep -B 20 '^dpkg-buildpackage: error' >> $xmlfilename || :
cat ${WRKDIR}/buildlog.txt | grep -B 20 '^EXCEPTION:' >> $xmlfilename || :
fi
if [ -f "${WRKDIR}/rootlog.txt" ] ; then
cat ${WRKDIR}/rootlog.txt | sed -n '/No Package found/,/Exception/p' >> $xmlfilename || :
cat ${WRKDIR}/rootlog.txt | sed -n '/Error: /,/You could try using --skip-broken to work around the problem/p' >> $xmlfilename || :
fi
echo "</failure>" >> $xmlfilename
echo "</testcase>" >> $xmlfilename
fi
echo "</testsuite>" >> $xmlfilename
}