#!/bin/bash if [ -z ${JENKINS_DEBIAN_GLUE_QUIET:-} ]; then set -x fi set -e set -u if [ -r /etc/jenkins/debian_glue ] ; then . /etc/jenkins/debian_glue fi [ -n "${DEBEMAIL:-}" ] || DEBEMAIL="jenkins-debian-glue Autobuilder " export DEBEMAIL [ -n "${SOURCE_DIRECTORY:-}" ] || SOURCE_DIRECTORY='source' # where checkout of sources resides if [ ! -d "${SOURCE_DIRECTORY}" ] ; then echo "Please run the script in the jenkins workspace." >&2 echo 'NOTE: Make sure that "Source Code Management -> Git -> Additional Behaviours -> Check out to a sub-directory" is set to "source"' >&2 exit 1 fi if [ -z "${BUILD_NUMBER:-}" ] ; then echo "No BUILD_NUMBER defined, please run it in jenkins." >&2 exit 1 fi if [ -z "${GIT_COMMIT:-}" ] ; then echo "No GIT_COMMIT defined, please run it with git-plugin in jenkins. ">&2 exit 1 fi # since git-buildpackage >=0.6.24 only the gbp command is available if [ -x "$(which gbp)" ] ; then GBP_DCH="gbp dch" GBP_BUILDPACKAGE="gbp buildpackage" else GBP_DCH="git-dch" GBP_BUILDPACKAGE="git-buildpackage" fi JENKINS_DEBIAN_GLUE_VERSION=$(dpkg --list jenkins-debian-glue 2>/dev/null | awk '/^ii/ {print $3}') if [ -n "${JENKINS_DEBIAN_GLUE_VERSION:-}" ] ; then echo "*** Running jenkins-debian-glue version $JENKINS_DEBIAN_GLUE_VERSION ***" fi if [ -n "${DIST:-}" -a -z "${KEEP_SOURCE_CHANGES:-}" ]; then echo "*** Warning: DIST is set but KEEP_SOURCE_CHANGES is not, this doesn't make sense. ***" echo "*** Please consider setting KEEP_SOURCE_CHANGES=true when setting DIST. ***" if ! ${GBP_DCH} --help 2>&1 | grep -q -- --distribution ; then echo "Error: ${GBP_DCH} doesn't support the --distribution option. Upgrade git-buildpackage to version 0.6.7 or newer." >&2 exit 1 fi fi gbp_opts() { # support overriding git-buildpackage options if [ -n "${GBP_OPTS:-}" ] ; then echo "Found environment variable GBP_OPTS, set to ${GBP_OPTS}" else GBP_OPTS=" -nc --git-force-create --git-ignore-new --git-ignore-branch -S -us -uc --git-verbose --git-builder=/bin/true --git-cleaner=/bin/true --git-export-dir= " echo "Using git-buildpackage default options provided by jenkins-debian-glue" fi } version_information() { # required for dpkg-parsechangelog if ! [ -r debian/changelog ] ; then echo "Error: debian/changelog could not be read. Is this really a Debian package?" >&2 return 1 fi # retrieve and adjust information ORIG_VERSION=$(dpkg-parsechangelog --count 1 | awk '/^Version/ {print $2}') DISTRIBUTION=$(dpkg-parsechangelog --count 1 | awk '/^Distribution/ {print $2}') APPLY_VERSION_WORKAROUND=false if [ "${USE_ORIG_VERSION:-}" = "true" ] ; then echo "*** USE_ORIG_VERSION is set to 'true', keeping original version [${ORIG_VERSION}] from changelog ***" VERSION_STRING="${ORIG_VERSION}" else # we want to get a version string like # $ORIG_VERSION+0~$TIMESTAMP.$BUILD_NUMBER~1.$GIT_ID # so the version is always increasing over time, no matter what INCREASED_VERSION=$(increase-version-number $ORIG_VERSION) if [ -n "${TIMESTAMP_FORMAT:-}" ] ; then echo "*** Using custom timestamp format as specified by TIMESTAMP_FORMAT ***" TIMESTAMP="$(date -u +"$TIMESTAMP_FORMAT")" else TIMESTAMP="$(date -u +%Y%m%d%H%M%S)" fi BUILD_VERSION="${TIMESTAMP}.${BUILD_NUMBER}" # git-dch appends something like ~1.gbp5f433e then # we do NOT raise the version number, if we detect an unreleased version, # otherwise the released version would be older than our snapshot builds if [ "$DISTRIBUTION" = "UNRELEASED" ] && dpkg --compare-versions "$ORIG_VERSION" lt "$INCREASED_VERSION" ; then echo "*** Not increasing version number as distribution is set to UNRELEASED ***" INCREASED_VERSION="$ORIG_VERSION" if [ "${UNRELEASED_APPEND_COMMIT:-}" = "true" ]; then # However, as we will use plain 'dch' for this, we still want to have # the (short) GIT commit id inside the version... echo "*** UNRELEASED_APPEND_COMMIT is set to 'true', manually appending GIT commit to version number ***" BUILD_VERSION="${BUILD_VERSION}~${GIT_COMMIT:0:7}" fi APPLY_VERSION_WORKAROUND=true fi VERSION_STRING="${INCREASED_VERSION}~${BUILD_VERSION}" fi if [ -n "${distribution:-}" ] ; then echo "Distribution variable found. Adding distribution specific version." VERSION_STRING="${VERSION_STRING}+${distribution//-/_}" fi echo "*** Version string set to $VERSION_STRING ***" } # support overriding git-dch options dch_opts() { if [ -n "${DCH_OPTS:-}" ] ; then echo "Found environment variable DCH_OPTS, set to ${DCH_OPTS}" else DCH_OPTS="-S --multimaint-merge --ignore-branch" echo "Using default ${GBP_DCH} options (${DCH_OPTS})" fi DCH_COMBINED_OPTS="${DCH_OPTS}" # support overriding extra options for git-dch if [ -n "${DCH_EXTRA_OPTS:-}" ] ; then echo "Found environment variable DCH_EXTRA_OPTS, set to ${DCH_EXTRA_OPTS}" else DCH_EXTRA_OPTS="--new-version=${VERSION_STRING}" if [ -n "${DIST:-}" ]; then DCH_EXTRA_OPTS="${DCH_EXTRA_OPTS} --distribution ${DIST} --force-distribution" fi echo "Using extra ${GBP_DCH} options (${DCH_EXTRA_OPTS})" fi DCH_COMBINED_OPTS="${DCH_COMBINED_OPTS} ${DCH_EXTRA_OPTS}" if [ -n "${DCH_LOG_RESTRICTION:-}" ] ; then echo "Found environment variable DCH_LOG_RESTRICTION, set to ${DCH_LOG_RESTRICTION}" DCH_COMBINED_OPTS="${DCH_COMBINED_OPTS} ${DCH_LOG_RESTRICTION}" fi } # support overrides from gbp.conf gbp_conf() { if [ "${IGNORE_GBP_CONF:-}" = "true" ] ; then echo "Skipping gbp_conf execution as requested via IGNORE_GBP_CONF ***" return 0 fi # List of config files in order gbp_conf_files=( /etc/git-buildpackage/gbp.conf ~/.gbp.conf .gbp.conf debian/gbp.conf .git/gbp.conf ) # Defaults UPSTREAM_BRANCH="upstream" DEBIAN_BRANCH="debian" PRISTINE_TAR="false" for gbp_conf_file in "${gbp_conf_files[@]}"; do if [ -f ${gbp_conf_file} ]; then local value; value=$(git config --file ${gbp_conf_file} --get DEFAULT.upstream-branch 2>&- || true) if [ -n "${value:-}" ]; then UPSTREAM_BRANCH=${value} fi value=$(git config --file ${gbp_conf_file} --get DEFAULT.debian-branch 2>&- || true) if [ -n "${value:-}" ]; then DEBIAN_BRANCH=${value} fi value=$(git config --file ${gbp_conf_file} --bool --get DEFAULT.pristine-tar 2>&- || true) if [ -n "${value:-}" ]; then PRISTINE_TAR=${value} fi fi done } create_local_branch() { [ -n "${1:-}" ] || return 1 local BRANCH="$1" if git branch -a | grep -q "remotes/origin/${BRANCH}"'$' ; then git branch -D "${BRANCH}" || true git branch "${BRANCH}" "remotes/origin/${BRANCH}" else echo "NOTE: branch $BRANCH does not exist, ignoring request to checkout therefore." fi } git_dch_auto() { if $APPLY_VERSION_WORKAROUND ; then echo "Applying version workaround workaround" dch -b --distribution=UNRELEASED --newversion=$VERSION_STRING -- \ "SNAPSHOT autobuild for unreleased $ORIG_VERSION via jenkins-debian-glue." else ${GBP_DCH} --auto $DCH_COMBINED_OPTS ${DCH_CHANGELOG_FILE:-} fi } identify_latest_change() { # debian/changelog might be a symlink (e.g. because debian points to # pkg/debian), so make sure we don't access a non-existing file # by calling readlink git checkout -- $(readlink -f debian/changelog) local OLD_VERSION=$(dpkg-parsechangelog | awk '/^Version: / {print $2}') local last_tag=$(git describe $(git rev-list --tags='[^u]*' --max-count=1 HEAD)) local last_merge=$(git describe $(git rev-list --all --merges --max-count=1 HEAD)) local since=${last_tag} if [ -n "$last_merge" ] ; then local merge_date=$(git log ${last_merge} --pretty="format:%at" -1) local tag_date=$(git log ${last_tag} --pretty="format:%at" -1) if [ ${merge_date} -gt ${tag_date} ] ; then local since=${last_merge} fi fi echo "Latest tag [${last_tag:-}] / merge [${last_merge:-}] seems to be $since" ${GBP_DCH} -s "${since}" $DCH_COMBINED_OPTS ${DCH_CHANGELOG_FILE:-} local NEW_VERSION=$(dpkg-parsechangelog | awk '/^Version: / {print $2}') if dpkg --compare-versions "$NEW_VERSION" lt "$OLD_VERSION" ; then echo "Calculated version is older than last release, falling back to auto mode." # debian/changelog might be a symlink (e.g. because debian points to # pkg/debian), so make sure we don't access a non-existing file # by calling readlink git checkout -- $(readlink -f debian/changelog) git_dch_auto fi } branch_checkout() { # git-dch and git-buildpackage refuse to operate on a single git # commit, so instead create a temporary branch to work on random_branch="jenkins-debian-glue-buildbranch$RANDOM" if [ "${SKIP_BRANCH_AND_TAG_HANDLING:-}" = "true" ] ; then echo "*** Skipping branch/tag handling as requested via SKIP_BRANCH_AND_TAG_HANDLING ***" echo "Making sure that random_branch $random_branch does not exist" git branch -D "$random_branch" || true echo "Checking out branch $random_branch based on git commit $GIT_COMMIT" git checkout -b "$random_branch" "$GIT_COMMIT" elif [ -n "${GERRIT_PATCHSET_REVISION:-}" ] ; then echo "*** We seem to be building for Gerrit ***" echo "Making sure that random_branch $random_branch does not exist" git branch -D "$random_branch" || true echo "*** Fetching Gerrit patchsets/commits from ${GIT_URL} ***" git fetch --tags --progress ${GIT_URL} +refs/changes/*:refs/remotes/origin/* echo "Checking out branch $random_branch based on Gerrit patchset revision ${GERRIT_PATCHSET_REVISION} ***" git checkout -b "$random_branch" "$GERRIT_PATCHSET_REVISION" elif [ -n "${tag:-}" ] && [ "${tag:-}" != "none" ] ; then echo "Making sure that random_branch $random_branch does not exist" git branch -D "$random_branch" || true echo "Checking out branch $random_branch based on tag $tag" git checkout -b "$random_branch" "$tag" elif [ -n "${branch:-}" ] ; then # prepend "origin" when checking out a branch, otherwise we might be # checking out a branch which doesn't exist locally yet, failing with: # | fatal: git checkout: updating paths is incompatible with switching branches. # | Did you intend to checkout '$BRANCH' which can not be resolved as commit? local checkout_branch case "$branch" in # rewrite refs/heads/FOO to refs/remotes/origin/FOO, otherwise it fails; # the refs/heads/FOO is something e.g. github pushes through its API refs/heads/*) checkout_branch="${branch/refs\/heads/refs/remotes/origin}" ;; # keep as it is when receiving origin/* already origin/*) checkout_branch="$branch" ;; # prepend "origin/" otherwise *) checkout_branch="origin/${branch}" ;; esac echo "Making sure that random_branch $random_branch does not exist" git branch -D "$random_branch" || true echo "Checking out branch $random_branch based on branch $checkout_branch" git checkout -b "$random_branch" "$checkout_branch" else echo "Making sure that random_branch $random_branch does not exist" git branch -D "$random_branch" || true echo "Checking out branch $random_branch based on commit $GIT_COMMIT" git checkout -b "$random_branch" "$GIT_COMMIT" fi } changelog_generation() { # Allow skipping of changelog creation, e.g. to build a branch as-is if [ "${SKIP_DCH:-}" = "true" ] ; then echo "*** SKIP_DCH is set, not modifying debian/changelog therefore ***" else if [ -n "${tag:-}" ] && [ "${tag:-}" != "none" ] ; then echo "Tag parameter found (and not set to 'none'), not touching the changelog." elif [ "${1:-}" = "identify" ] ; then echo "Trying to identify latest tag / merge..." if ! git describe $(git rev-list --tags='[^u]*' --max-count=1 HEAD) >/dev/null ; then echo "Failed to identify latest change, falling back to auto mode." git_dch_auto else identify_latest_change fi elif [ -r debian/gbp.conf ] ; then echo "Found debian/gbp.conf, using ${GBP_DCH} with auto mode." git_dch_auto else echo "Using ${GBP_DCH} with auto mode." git_dch_auto fi # get rid of "UNRELEASED" distribution header, only # necessary if the debian/changelog was modified if [ -z "${tag:-}" ]; then local debchange_opts if [ -n "${DIST:-}" ]; then debchange_opts="--distribution ${DIST} --force-distribution" fi debchange --release ${debchange_opts:-} "" fi fi } git_cleanup() { if [ -n "${SKIP_GIT_CLEANUP:-}" ] ; then echo "*** Skipping git_cleanup as requested via SKIP_GIT_CLEANUP ***" return 0 fi echo "*** Cleaning git repository to make sure there are no modified files ***" echo "*** Note: You can skip this step by setting SKIP_GIT_CLEANUP=true ***" git clean -fxd git reset --hard HEAD } quilt_cleanup() { if [ -n "${SKIP_QUILT_CLEANUP:-}" ] ; then echo "*** Skipping quilt_cleanup as requested via SKIP_QUILT_CLEANUP ***" return 0 fi echo "*** Unapplying all possibly applied quilt patches and removing quilt directory ***" echo "*** Note: You can skip this step by setting SKIP_QUILT_CLEANUP=true ***" quilt pop -a || true rm -rf .pc } identify_source_build_opts() { # unset by default DBP_OPTS="" if [ -r "debian/source/format" ] && ! grep -q '^1\.0' debian/source/format ; then echo "*** Found dpkg source format != 1.0, nothing to do ****" return 0 fi if [ -r "debian/source/options" ] ; then if ! grep -q '^[[:space:]]*tar-ignore' "debian/source/options" ; then echo "*** Enabling '-I' option as tar-ignore option not present in debian/source/options ***" DBP_OPTS+=" -I" fi # note: we shouldn't match on 'extend-diff-ignore' if ! grep -q '^[[:space:]]*diff-ignore' "debian/source/options" ; then echo "*** Enabling '-i' option as diff-ignore option not present in debian/source/options ***" DBP_OPTS+=" -i" fi else echo "*** Enabling '-i -I' options as building for dpkg source format 1.0 ***" DBP_OPTS="-i -I" fi } source_format_opts() { if ! [ -f "debian/source/format" ] ; then echo '*** WARNING: Source format is not specified in debian/source/format! ***' return 0 fi local SRC_FORMAT="$(cat debian/source/format)" case "$SRC_FORMAT" in '3.0 (quilt)') echo "*** Source format detected as 3.0 (quilt) ***"; DBP_EXTRA_OPTS="${DBP_EXTRA_OPTS:-} --source-option=--unapply-patches" ;; '3.0 (git)') echo "*** Source format detected as 3.0 (git) ***" PRISTINE_TAR=false SKIP_QUILT_CLEANUP=true IGNORE_GIT_BUILDPACKAGE=true ;; '3.0 (native)') echo "*** Source format detected as 3.0 (native) ***" ;; '3.0') echo "*** Source format detected as 3.0 ***" ;; '1.0') echo "*** Source format detected as 1.0 ***" SKIP_QUILT_CLEANUP=true ;; *) echo "*** WARNING: invalid or unknown source format: ${SRC_FORMAT} ***" ;; esac } # main execution echo "*** source package build phase ***" rm -f ./* || true if [ -n "${PRE_SOURCE_HOOK:-}" ] ; then echo "*** Found environment variable PRE_SOURCE_HOOK, set to ${PRE_SOURCE_HOOK:-} ***" sh ${PRE_SOURCE_HOOK:-} fi cd "$SOURCE_DIRECTORY" git_cleanup source_format_opts identify_source_build_opts # Only if we are using git-buildpackage... if [ "${IGNORE_GIT_BUILDPACKAGE:-}" != "true" ] ; then # gbp.conf handling gbp_conf # make sure common branches are available for git-buildpackage create_local_branch ${UPSTREAM_BRANCH} create_local_branch ${DEBIAN_BRANCH} if [ ${PRISTINE_TAR} = 'true' ]; then create_local_branch pristine-tar fi fi # check out the according branch/tag with help of $random_branch branch_checkout if [ -n "${PRE_DCH_HOOK:-}" ] ; then echo "*** Found environment variable PRE_DCH_HOOK, set to ${PRE_DCH_HOOK:-} ***" sh ${PRE_DCH_HOOK:-} fi # retrieve version information *after* checking out the according branch/tag, # otherwise version number might result in something different than expected version_information # handling of debian/changelog dch_opts changelog_generation # prepare orig.tar.gz using pristine-tar, but without actually building the source package if [ "${IGNORE_GIT_BUILDPACKAGE:-}" = "true" ] ; then echo "Skipping git-buildpackage execution as requested via IGNORE_GIT_BUILDPACKAGE ***" else gbp_opts # set $GBP_OPTS ${GBP_BUILDPACKAGE} ${GBP_OPTS:-} fi quilt_cleanup # build source package, run before switching back to previous branch # to get the actual requested version dpkg-buildpackage -uc -us -nc -d -S ${DBP_OPTS:-} ${DBP_EXTRA_OPTS:-} if [ -n "${KEY_ID:-}" ] ; then echo "*** Found environment variable KEY_ID, set to ${KEY_ID:-}, signing source package ***" if ! [ -x "$(which debsign)" ] ; then echo "Error: debsign not available, please make sure the devscripts package is installed." >&2 exit 1 fi debsign -k"${KEY_ID:-}" ../*_source.changes fi if [ -n "${KEEP_SOURCE_CHANGES:-}" ]; then echo "*** Not removing ../*_source.changes because KEEP_SOURCE_CHANGES is set ***" else echo "*** Removing ../*_source.changes because KEEP_SOURCE_CHANGES is not set ***" # get rid of the *_source.changes files generated by dpkg-buildpackage, # to avoid failures in a later stage when copying *all* files around rm -f ../*_source.changes fi # revert to original debian/changelog to avoid merge conflicts git checkout -- $(readlink -f debian/changelog) # switch back to previous "branch" before removing the tmp branch if ! git checkout -f "${GIT_BRANCH}"; then # we were probably detached git checkout -f "${GIT_COMMIT}" fi git branch -D "$random_branch" # vim:foldmethod=marker ts=2 ft=sh ai expandtab sw=2