modified version of jenkins debian glue (https://github.com/mika/jenkins-debian-glue) for devuan
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

369 lines
12 KiB

#!/bin/sh
set -x
set -u
checks_and_defaults() {
if [ -r /etc/jenkins/debian_glue ] ; then
. /etc/jenkins/debian_glue
fi
if [ -z "${JOB_NAME:-}" ] ; then
echo "No JOB_NAME defined, please run it in jenkins." >&2
exit 1
fi
if [ -z "${architecture:-}" ] ; then
echo "*** No architecture defined. Consider running it with matrix configuration. ***"
architecture="$(dpkg-architecture -qDEB_HOST_ARCH)"
echo "*** Falling back to default, using host architecture ${architecture}. ***"
fi
if [ -z "${REPOSITORY:-}" ] ; then
REPOSITORY='/srv/repository'
fi
}
# make sure we don't leave files for next run
bailout() {
# if [ -n "${sources:-}" ] && [ "${sources:-}" != "unset" ] ; then
# echo "*** Removing sources file. ***"
# rm -f "${sources}/"*
# fi
echo "*** Getting rid of files in $WORKSPACE/binaries/ to avoid problems in next run. ***"
rm -f "$WORKSPACE"/binaries/*
[ -n "${1:-}" ] && EXIT="${1}" || EXIT=0
[ -n "${2:-}" ] && echo "$2" >&2
exit $EXIT
}
identify_package_name() {
PACKAGE=${JOB_NAME%-binaries*}
BINARY_PACKAGE=${PACKAGE%-test*}
if [ -z "${PACKAGE:-}" ] ; then
bailout 1 "Error: could not identify Debian package name based on job name ${JOB_NAME:-}."
else
echo "*** Building binary package $BINARY_PACKAGE ***"
fi
}
build_info() {
if [ -n "${REPOS:-}" ] ; then
echo "*** Using supplied repository name $REPOS ***"
else
REPOS="${JOB_NAME%-binaries*}"
if [ -z "${distribution:-}" ]; then
echo "*** No repository supplied, using repository name $REPOS ***"
else
REPOS="${REPOS}-${distribution}"
echo "*** No repository supplied but distribution has been set, using repository name $REPOS ***"
fi
fi
}
identify_sourcefile() {
if [ -n "${sources:-}" ]; then
sourcefile=$(echo "${sources}/"*.dsc)
if [ "$sourcefile" = 'sources/*.dsc' ] ; then
bailout 1 "Error: no sourcefile (*.dsc) found. Exiting."
fi
case "$sourcefile" in
*\ *) bailout 1 "Error: Found multiple source files (*.dsc)."
;;
esac
p="$(basename $sourcefile .dsc)"
newest_version="${p#*_}"
else
sources="unset"
echo "*** Identifying newest package version ***"
newest_version="0"
for file in "${HUDSON_HOME}/userContent/${PACKAGE}-source/"*.dsc ; do
SOURCE_PACKAGE="$(awk '/^Source: / {print $2}' $file)"
p="$(basename $file .dsc)"
if [ "$p" = '*' ] ; then
bailout 1 "Error: No source package found (forgot to deploy via source job?)"
fi
cur_version="${p#*_}"
if dpkg --compare-versions "${cur_version}" gt "${newest_version}" ; then
newest_version="${cur_version}"
else
base_version="${cur_version}"
fi
done
echo "*** Found package version $newest_version ***"
sourcefile="${HUDSON_HOME}/userContent/${PACKAGE}-source/${SOURCE_PACKAGE}"_*"${newest_version}".dsc
#archtype="$(awk '/^Architecture/ {print $2}' ${HUDSON_HOME}/userContent/${PACKAGE}-source/${SOURCE_PACKAGE}_*${newest_version}.dsc)"
fi
echo "*** Using $sourcefile (version: ${newest_version}) [sources: $sources]"
}
dist_and_arch_settings() {
if [ -z "${distribution:-}" ]; then
echo "*** No distribution set, using sid for base.cow if it does not exist yet. ***"
COWBUILDER_DIST="sid"
else
echo "*** Using cowbuilder base for distribution ${distribution} ***"
DIST="-${distribution}"
COWBUILDER_DIST="${distribution}"
fi
if [ -z "${architecture:-}" ] || [ "${architecture:-}" = "all" ] ; then
echo "*** No architecture set or architecture set to 'all', using system arch for cowbuilder ***"
ARCH="$(dpkg-architecture -qDEB_HOST_ARCH)"
BASE="/var/cache/pbuilder/base${DIST:-}.cow"
else
echo "*** Using cowbuilder base for architecture ${architecture} ***"
ARCH="${architecture}"
BASE="/var/cache/pbuilder/base${DIST:-}-${architecture}.cow"
fi
}
cowbuilder_init() {
if [ ! -d "${BASE}" ]; then
echo "*** Creating cowbuilder base $BASE for arch $ARCH and distribution $COWBUILDER_DIST ***"
sudo cowbuilder --create --basepath "${BASE}" --distribution "${COWBUILDER_DIST}" \
--debootstrapopts --arch --debootstrapopts "$ARCH"
[ $? -eq 0 ] || bailout 1 "Error: Failed to create cowbuilder base ${BASE}."
else
echo "*** Updating cowbuilder cow base ***"
sudo cowbuilder --update --basepath "${BASE}"
[ $? -eq 0 ] || bailout 1 "Error: Failed to update cowbuilder base ${BASE}."
fi
}
identify_build_type() {
# -b -> binary-only build, no source files are to be built and/or distributed
DEBBUILDOPTS="-b" # default
SKIP_ARCH_BUILD=false # default
if [ "${architecture:-}" = "all" ] ; then
echo "*** \$architecture is set to 'all', skipping further identify_build_type checks. ***"
echo "*** Consider setting \$architecture to amd64, i386,... instead. ***"
return 0
fi
if [ -z "${MAIN_ARCHITECTURE:-}" ] ; then
if [ "$(dpkg-architecture -qDEB_HOST_ARCH)" = "${architecture:-}" ] ; then
echo "*** MAIN_ARCHITECTURE is unset. ***"
echo "*** Host architecture matches \$architecture, using default ${DEBBUILDOPTS} buildoption ***"
return 0
fi
else
if [ "${MAIN_ARCHITECTURE:-}" = "${architecture:-}" ] ;then
echo "*** MAIN_ARCHITECTURE matches architecture [${architecture}], using default ${DEBBUILDOPTS} buildoption ***"
return 0
else
echo "*** MAIN_ARCHITECTURE does not match ${architecture:-}, continuing with identify_build_type ***"
fi
fi
local TMPDIR=$(mktemp -d)
cd "$TMPDIR"
for file in ${HUDSON_HOME}/userContent/${PACKAGE}-source/${SOURCE_PACKAGE}_*.tar.* ; do
if tar atf "$file" 2>/dev/null | grep -q debian/control ; then
# might be source/debian/control - so let's identify the path to debian/control
local control_file=$(tar atf "$file" 2>/dev/null | grep 'debian/control$')
tar axf "$file" "$control_file" || bailout 1 "Error while looking at debian/control in source archive."
fi
done
if grep -q '^Architecture: all' "$control_file" ; then
if grep -q '^Architecture: any' "$control_file" ; then
echo "*** Package provides arch 'all' + 'any', enabling -B buildoption for this architecture. ***"
# -B -> binary-only build, limited to architecture dependent packages
DEBBUILDOPTS="-B"
else
# only "Architecture: all", so no arch specific packages since
# we aren't building for $MAIN_ARCHITECTURE
SKIP_ARCH_BUILD=true
fi
fi
rm -rf "${TMPDIR}"
}
cowbuilder_run() {
echo "*** cowbuilder build phase for arch $architecture ***"
mkdir -p "$WORKSPACE"/binaries/
# make sure we build arch specific packages only when necessary
identify_build_type
if $SKIP_ARCH_BUILD ; then
bailout 0 "Nothing to do, architecture all binary packages only for non-primary architecture."
fi
case "$architecture" in
i386)
linux32 sudo cowbuilder --buildresult "$WORKSPACE"/binaries/ \
--build $sourcefile \
--basepath $BASE --debbuildopts "$DEBBUILDOPTS"
[ $? -eq 0 ] || bailout 1 "Error: Failed to build with cowbuilder."
;;
amd64|all)
sudo cowbuilder --buildresult "$WORKSPACE"/binaries/ \
--build $sourcefile \
--basepath $BASE --debbuildopts "$DEBBUILDOPTS"
[ $? -eq 0 ] || bailout 1 "Error: Failed to build with cowbuilder."
;;
*)
bailout 1 "Error: Unsupported architecture: $architecture"
;;
esac
}
remove_packages() {
echo "*** Removing previous versions from repository ***"
for p in $(dcmd "${WORKSPACE}/binaries/"*"${newest_version}_${ARCH}.changes") ; do
file="$(basename $p)"
binpackage="${file%%_*}"
binary_list="${binary_list:-} ${binpackage}"
# note: "removesrc" would remove foreign arch files (of different builds)
echo "*** Removing existing package ${binpackage} from repository ${REPOS} ***"
sudo reprepro -v -b "${REPOSITORY}" --waitforlock 1000 remove "${REPOS}" "${binpackage}"
done
}
remove_missing_binary_packages() {
for p in $(sudo reprepro -v -b "${REPOSITORY}" --waitforlock 1000 listmatched "${REPOS}" '*' | awk '{print $2}' | sort -u); do
echo "$binary_list" | grep -q "$p" || missing_packages="${missing_packages:-} $p"
done
if echo "${missing_packages:-}" | grep -q '[a-z0-9]' ; then
echo "*** Binary package(s) found, missing in build version: ${missing_packages:-} ***"
for p in $missing_packages ; do
echo "*** Removing $p from $REPOS to avoid out-of-date data ***"
sudo reprepro -v -b "${REPOSITORY}" --waitforlock 1000 remove "${REPOS}" "${p}"
done
fi
}
reprepro_wrapper() {
if ! [ -d "$REPOSITORY" ] ; then
bailout 1 "Error: repository ${REPOSITORY} does not exist."
fi
remove_packages
remove_missing_binary_packages
archall=false
case $architecture in
all) archall=true
architecture='*' # support as file expansion in reprepro cmdline
;;
esac
echo "*** Including binary packages in repository $REPOS ***"
sudo reprepro -v -b "${REPOSITORY}" --waitforlock 1000 --ignore=wrongdistribution \
include "${REPOS}" "${WORKSPACE}/binaries/"*"${newest_version}"_${architecture}.changes
[ $? -eq 0 ] || bailout 1 "Error: Failed to include binary package in $REPOS repository."
# include the source package only in *one* architecture, being amd64
if [ "$architecture" = "amd64" ] || $archall ; then
echo "*** Including source package in repository $REPOS ***"
RC=0
if ! sudo reprepro -v -b "${REPOSITORY}" --waitforlock 1000 --ignore=wrongdistribution \
includedsc "${REPOS}" ${sourcefile} ; then
RC=1
# iff section/priority is empty then reprepro will complain
# about "No section and no priority for" and error out in the
# cmdline above, therefore we retry with -S and -P being set
sudo reprepro -v -S unstable -P extra -b "${REPOSITORY}" --waitforlock 1000 \
--ignore=wrongdistribution \
includedsc "${REPOS}" ${sourcefile}
RC=$?
fi
[ $RC -eq 0 ] || bailout 1 "Error: Failed to include source package in $REPOS repository."
fi
}
trunk_release() {
# setting TRUNK_RELEASE=true enables release-trunk repository,
# to always get a copy of the package(s) to a central place
if [ -n "${TRUNK_RELEASE:-}" ] ; then
generate-reprepro-codename "$TRUNK_RELEASE"
sudo reprepro -v -b "${REPOSITORY}" --waitforlock 1000 --ignore=wrongdistribution copymatched "$TRUNK_RELEASE" "$REPOS" '*'
[ $? -eq 0 ] || bailout 1 "Error: Failed to copy packages from ${REPOS} to ${TRUNK_RELEASE}."
fi
}
release_repos() {
echo "*** Environment variable 'release' is set, running through release steps. ***"
sudo mkdir -p "${REPOSITORY}/incoming/${release}"
sudo mkdir -p "${REPOSITORY}/conf"
sudo chown -R "$(id -un)" "${REPOSITORY}/conf"
sudo chown -R "$(id -un)" "${REPOSITORY}/incoming/${release}"
cp "${WORKSPACE}/binaries/"* "${REPOSITORY}/incoming/${release}/"
[ $? -eq 0 ] || bailout 1 "Error: Failed to copy binary packages to release directory."
REPOSITORY=$REPOSITORY generate-reprepro-codename "${release}"
if ! grep -q "^Name: $release$" "${REPOSITORY}/conf/incoming" 2>/dev/null ; then
cat >> "${REPOSITORY}/conf/incoming" << EOF
Name: $release
IncomingDir: incoming/$release
TempDir: tmp
LogDir: log
MorgueDir: ${REPOSITORY}/morgue
Allow: unstable>$release
Cleanup: unused_files on_deny on_error
EOF
fi
sudo reprepro -v -b "${REPOSITORY}" processincoming "${release}"
local RC=$?
echo "*** Gettind rid of *.tar.* and *.dsc files in incoming directory to avoid data leakage. ***"
rm -f ${REPOSITORY}/incoming/$release/*.tar.*
rm -f ${REPOSITORY}/incoming/$release/*.dsc
if [ $RC -ne 0 ] ; then
bailout 1 "Error: Failed to execute processincoming for release ${release}."
fi
}
deploy_to_releases() {
if [ "${REMOTE_REPOS:-}" = "true" ] ; then
echo "*** Config variable 'REMOTE_REPOS' is set, ignoring request to use local repository. ***"
elif [ -n "${release:-}" ] && [ "$release" != "none" ] && [ "$release" != "trunk" ] ; then
release_repos
else
reprepro_wrapper
trunk_release
fi
}
# make them available for the Jenkin's 'Archiving artifacts'
binaries_to_workspace() {
echo "*** Moving binaries files to workspace. ***"
mv "${WORKSPACE}/binaries/"* "${WORKSPACE}/"
}
# main execution
trap bailout 1 2 3 3 6 9 14 15
checks_and_defaults
identify_package_name
build_info
identify_sourcefile
dist_and_arch_settings
cowbuilder_init
cowbuilder_run
deploy_to_releases
binaries_to_workspace
bailout 0