[Qa-jenkins-scm] [jenkins.debian.net] 01/01: reproducible fedora: first shot at building rpm based distros.
Holger Levsen
holger at moszumanska.debian.org
Fri Dec 11 16:29:08 UTC 2015
This is an automated email from the git hooks/post-receive script.
holger pushed a commit to branch master
in repository jenkins.debian.net.
commit 84a77401e9d1f78e290caa1f3aa82bd3fdf64f0d
Author: Holger Levsen <holger at layer-acht.org>
Date: Fri Dec 11 17:28:44 2015 +0100
reproducible fedora: first shot at building rpm based distros.
---
TODO | 11 +-
bin/jenkins_node_wrapper.sh | 2 +
bin/reproducible_build_rpm.sh | 228 ++++++++++++++++++++++++++++++++++++++++++
bin/reproducible_common.sh | 3 +
job-cfg/reproducible.yaml | 11 ++
5 files changed, 251 insertions(+), 4 deletions(-)
diff --git a/TODO b/TODO
index 80f708b..4b1d4f5 100644
--- a/TODO
+++ b/TODO
@@ -282,12 +282,15 @@ This is about Debian, below are more todo entries for other projects…
==== reproducible Fedora
* build script
-** call the script reproducible_rpms.sh as it can also build OpenSuSE packages
-** then use yumdownloader to download rpms: 'yumdownloader --source sudo'
-** use mock to build: 'mock -r fedora-23-x86_64 --resultdir=. sudo-1.8.14p3-1.fc23.src.rpm'
+** how to get a list of packages?
+** no variations introduced yet:
+*** use '-j$NUM_CPU' and 'NEW_NUM_CPU=$(echo $NUM_CPU-1|bc)'
+*** modify TZ, LANG, LC_ALL, umask
+* other bits:
+** use modified rpmbuild package
* hosts/pb-build3/etc/yum/repos.d/* is really not sooo good but works…
-* how to get a list of packages?
* build rawhide instead of fedora-23?
+** when adding rawhide make sure this is not needed: 'yumdownloader --enablerepo=fedora-23-src --source sudo'
* more notes:
** http://blog.packagecloud.io/eng/2015/05/11/building-rpm-packages-with-mock/
diff --git a/bin/jenkins_node_wrapper.sh b/bin/jenkins_node_wrapper.sh
index 22aa3e6..ccd1645 100755
--- a/bin/jenkins_node_wrapper.sh
+++ b/bin/jenkins_node_wrapper.sh
@@ -109,6 +109,8 @@ elif [[ "$*" =~ reproducible_setup_mock_fedora23_x86_64 ]] ; then
exec /srv/jenkins/bin/reproducible_setup_mock.sh fedora-23 x86_64 ; croak "Exec failed";
elif [ "$1" = "/srv/jenkins/bin/reproducible_build_archlinux_pkg.sh" ] && ( [ "$2" = "1" ] || [ "$2" = "2" ] ) ; then
exec /srv/jenkins/bin/reproducible_build_archlinux_pkg.sh "$2" "$3" "$4" "$5" ; croak "Exec failed";
+elif [ "$1" = "/srv/jenkins/bin/reproducible_build_rpm.sh" ] && ( [ "$2" = "1" ] || [ "$2" = "2" ] ) ; then
+ exec /srv/jenkins/bin/reproducible_build_rpm.sh "$2" "$3" "$4" "$5" "$6" ; croak "Exec failed";
elif [ "$*" = "some_jenkins_job_name" ] ; then
exec echo run any commands here ; croak "Exec failed";
fi
diff --git a/bin/reproducible_build_rpm.sh b/bin/reproducible_build_rpm.sh
new file mode 100755
index 0000000..37c74e6
--- /dev/null
+++ b/bin/reproducible_build_rpm.sh
@@ -0,0 +1,228 @@
+#!/bin/bash
+
+# Copyright 2015 Holger Levsen <holger at layer-acht.org>
+# released under the GPLv=2
+
+DEBUG=false
+. /srv/jenkins/bin/common-functions.sh
+common_init "$@"
+
+# common code
+. /srv/jenkins/bin/reproducible_common.sh
+
+set -e
+
+cleanup_all() {
+ cd
+ # delete makepkg build dir
+ if [ ! -z $SRCPACKAGE ] && [ -d /tmp/$SRCPACKAGE-$(basename $TMPDIR) ] ; then
+ rm -r /tmp/$SRCPACKAGE-$(basename $TMPDIR)
+ fi
+ # delete main work dir (only on master)
+ if [ "$MODE" = "master" ] ; then
+ rm $TMPDIR -r
+ echo "$(date -u) - $TMPDIR deleted."
+ fi
+ rm -f $DUMMY > /dev/null || true
+}
+
+handle_remote_error() {
+ MESSAGE="${BUILD_URL}console got remote error $1"
+ echo "$(date -u ) - $MESSAGE" | tee -a /var/log/jenkins/reproducible-remote-error.log
+ echo "Sleeping 5m before aborting the job."
+ sleep 5m
+ exec /srv/jenkins/bin/abort.sh
+ exit 0
+}
+
+
+download_package() {
+ echo "$(date -u ) - downloading ${SRCPACKAGE} for $RELEASE now."
+ yumdownloader --source ${SRCPACKAGE}
+ SRC_RPM="$(ls $SRCPACKAGE*.src.rpm)"
+}
+
+choose_package() {
+ echo "$(date -u ) - choosing package to be build."
+ local MIN_AGE=6
+ for PKG in sudo ; do
+ # build package if it has never build or at least $MIN_AGE days ago
+ if [ ! -d $BASE/rpm/$RELEASE/$ARCH/$PKG ] || [ ! -z $(find $BASE/rpm/$RELEASE/$ARCH/ -name $PKG -mtime +$MIN_AGE) ] ; then
+ SRCPACKAGE=$PKG
+ echo "$(date -u ) - building package $PKG from '$RELEASE' on '$ARCH' now..."
+ # very simple locking…
+ mkdir -p $BASE/rpm/$RELEASE/$ARCH/$PKG
+ touch $BASE/rpm/$RELEASE/$ARCH/$PKG
+ # break out of the loop and then out of this function too,
+ # to build this package…
+ break
+ fi
+ done
+ done
+ if [ -z $SRCPACKAGE ] ; then
+ echo "$(date -u ) - no package found to be build, sleeping 6h."
+ for i in $(seq 1 12) ; do
+ sleep 30m
+ echo "$(date -u ) - still sleeping..."
+ done
+ echo "$(date -u ) - exiting cleanly now."
+ exit 0
+ fi
+}
+
+first_build() {
+ echo "============================================================================="
+ echo "Building for $RELEASE ($ARCH) on $(hostname -f) now."
+ echo "Source package: ${SRCPACKAGE}"
+ echo "Date: $(date -u)"
+ echo "============================================================================="
+ set -x
+ download_package
+ local BUILDDIR="/tmp/$SRCPACKAGE-$(basename $TMPDIR)"
+ local LOG=$TMPDIR/b1/$SRCPACKAGE/build1.log
+ # nicely run mock with a timeout of 4h
+ timeout -k 4.1h 4h /usr/bin/ionice -c 3 /usr/bin/nice \
+ mock -r $RELEASE-$ARCH --resultdir=. $SRC_RPM 2>&1 | tee -a $LOG
+ PRESULT=${PIPESTATUS[0]}
+ if [ $PRESULT -eq 124 ] ; then
+ echo "$(date -u) - mock was killed by timeout after 4h." | tee -a $LOG
+ fi
+ if ! "$DEBUG" ; then set +x ; fi
+}
+
+second_build() {
+ echo "============================================================================="
+ echo "Re-Building for $RELEASE ($ARCH) on $(hostname -f) now."
+ echo "Source package: ${SRCPACKAGE}"
+ echo "Date: $(date -u)"
+ echo "============================================================================="
+ set -x
+ download_package
+ local BUILDDIR="/tmp/$SRCPACKAGE-$(basename $TMPDIR)"
+ local LOG=$TMPDIR/b2/$SRCPACKAGE/build2.log
+ # NEW_NUM_CPU=$(echo $NUM_CPU-1|bc)
+ # nicely run mock with a timeout of 4h
+ timeout -k 4.1h 4h /usr/bin/ionice -c 3 /usr/bin/nice \
+ mock -r $RELEASE-$ARCH --resultdir=. $SRC_RPM 2>&1 | tee -a $LOG
+ PRESULT=${PIPESTATUS[0]}
+ if [ $PRESULT -eq 124 ] ; then
+ echo "$(date -u) - mock was killed by timeout after 4h." | tee -a $LOG
+ fi
+ if ! "$DEBUG" ; then set +x ; fi
+}
+
+remote_build() {
+ local BUILDNR=$1
+ local NODE=$RPM_BUILD_NODE
+ local FQDN=$NODE.debian.net
+ local PORT=22
+ set +e
+ ssh -p $PORT $FQDN /bin/true
+ RESULT=$?
+ # abort job if host is down
+ if [ $RESULT -ne 0 ] ; then
+ SLEEPTIME=$(echo "$BUILDNR*$BUILDNR*5"|bc)
+ echo "$(date -u) - $NODE seems to be down, sleeping ${SLEEPTIME}min before aborting this job."
+ sleep ${SLEEPTIME}m
+ exec /srv/jenkins/bin/abort.sh
+ fi
+ ssh -p $PORT $FQDN /srv/jenkins/bin/reproducible_build_rpm.sh $BUILDNR $RELEASE $ARCH ${SRCPACKAGE} ${TMPDIR}
+ RESULT=$?
+ if [ $RESULT -ne 0 ] ; then
+ ssh -p $PORT $FQDN "rm -r $TMPDIR" || true
+ handle_remote_error "with exit code $RESULT from $NODE for build #$BUILDNR for ${SRCPACKAGE} from $RELEASE ($ARCH)"
+ fi
+ rsync -e "ssh -p $PORT" -r $FQDN:$TMPDIR/b$BUILDNR $TMPDIR/
+ RESULT=$?
+ if [ $RESULT -ne 0 ] ; then
+ echo "$(date -u ) - rsync from $NODE failed, sleeping 2m before re-trying..."
+ sleep 2m
+ rsync -e "ssh -p $PORT" -r $FQDN:$TMPDIR/b$BUILDNR $TMPDIR/
+ RESULT=$?
+ if [ $RESULT -ne 0 ] ; then
+ handle_remote_error "when rsyncing remote build #$BUILDNR results from $NODE"
+ fi
+ fi
+ ls -R $TMPDIR
+ ssh -p $PORT $FQDN "rm -r $TMPDIR"
+ set -e
+}
+
+#
+# below is what controls the world
+#
+
+TMPDIR=$(mktemp --tmpdir=/srv/reproducible-results -d) # where everything actually happens
+trap cleanup_all INT TERM EXIT
+cd $TMPDIR
+
+DATE=$(date -u +'%Y-%m-%d %H:%M')
+START=$(date +'%s')
+BUILDER="${JOB_NAME#reproducible_builder_}/${BUILD_ID}"
+DUMMY=$(mktemp -t rpm-dummy-XXXXXXXX)
+
+#
+# determine mode
+#
+if [ "$1" = "1" ] || [ "$1" = "2" ] ; then
+ MODE="$1"
+ RELEASE="$2"
+ ARCH="$3"
+ SRCPACKAGE="$4"
+ TMPDIR="$5"
+ [ -d $TMPDIR ] || mkdir -p $TMPDIR
+ cd $TMPDIR
+ mkdir -p b$MODE/$SRCPACKAGE
+ if [ "$MODE" = "1" ] ; then
+ first_build
+ else
+ second_build
+ fi
+ # preserve results and delete build directory
+ mv -v /tmp/$SRCPACKAGE-$(basename $TMPDIR)/$SRCPACKAGE/*.pkg.tar.xz $TMPDIR/b$MODE/$SRCPACKAGE/ || ls /tmp/$SRCPACKAGE-$(basename $TMPDIR)/$SRCPACKAGE/
+ rm -r /tmp/$SRCPACKAGE-$(basename $TMPDIR)/
+ echo "$(date -u) - build #$MODE for $SRCPACKAGE on $HOSTNAME done."
+ exit 0
+fi
+MODE="master"
+
+#
+# main - only used in master-mode
+#
+delay_start # randomize start times
+# first, we need to choose a packagey…
+RELEASE="$1"
+ARCH="$2"
+SRCPACKAGE="" # package name
+SRC_RPM="" # src rpm file name
+choose_package
+# build package twice
+mkdir b1 b2
+remote_build 1
+# only do the 2nd build if the 1st produced results
+if [ ! -z "$(ls $TMPDIR/b1/$SRCPACKAGE/*.rpm 2>/dev/null|| true)" ] ; then
+ remote_build 2
+ # run diffoscope on the results
+ TIMEOUT="30m"
+ DIFFOSCOPE="$(schroot --directory /tmp -c source:jenkins-reproducible-${DBDSUITE}-diffoscope diffoscope -- --version 2>&1)"
+ echo "$(date -u) - Running $DIFFOSCOPE now..."
+ cd $TMPDIR/b1/$SRCPACKAGE
+ for ARTIFACT in *.rpm ; do
+ [ -f $ARTIFACT ] || continue
+ call_diffoscope $SRCPACKAGE $ARTIFACT
+ # publish page
+ if [ -f $TMPDIR/$SRCPACKAGE/$ARTIFACT.html ] ; then
+ cp $TMPDIR/$SRCPACKAGE/$ARTIFACT.html $BASE/rpm/$RELEASE/$ARCH/$SRCPACKAGE/
+ fi
+ done
+fi
+# publish logs
+cd $TMPDIR/b1/$SRCPACKAGE
+cp build1.log $BASE/rpm/$RELEASE/$ARCH/$SRCPACKAGE/
+[ ! -f $TMPDIR/b2/$SRCPACKAGE/build2.log ] || cp $TMPDIR/b2/$SRCPACKAGE/build2.log $BASE/rpm/$RELEASE/$ARCH/$SRCPACKAGE/
+echo "$(date -u) - $REPRODUCIBLE_URL/rpm/$RELEASE/$ARCH/$SRCPACKAGE/ updated."
+
+cd
+cleanup_all
+trap - INT TERM EXIT
+
diff --git a/bin/reproducible_common.sh b/bin/reproducible_common.sh
index a6e4a15..43349a3 100755
--- a/bin/reproducible_common.sh
+++ b/bin/reproducible_common.sh
@@ -56,6 +56,9 @@ USERTAGS="toolchain infrastructure timestamps fileordering buildpath username ho
ARCHLINUX_BUILD_NODE=profitbricks-build3-amd64
ARCHLINUX_REPOS="core extra"
+# common settings for testing rpm based distros
+RPM_BUILD_NODE=profitbricks-build3-amd64
+
# number of cores to be used
NUM_CPU=$(grep -c '^processor' /proc/cpuinfo)
diff --git a/job-cfg/reproducible.yaml b/job-cfg/reproducible.yaml
index e7ed8b0..b59602d 100644
--- a/job-cfg/reproducible.yaml
+++ b/job-cfg/reproducible.yaml
@@ -774,6 +774,10 @@
name: '{name}_builder_archlinux_2'
- job-template:
+ defaults: reproducible_builder_trigger
+ name: '{name}_builder_fedora23_x86_64_1'
+
+- job-template:
defaults: reproducible
name: '{name}_html_archlinux'
@@ -1555,6 +1559,13 @@
my_shell: '/srv/jenkins/bin/reproducible_build_archlinux_pkg.sh'
my_recipients: 'qa-jenkins-scm at lists.alioth.debian.org'
my_node: ''
+ - '{name}_builder_fedora23_x86_64_1':
+ my_description: 'Try to reproducibly build a Fedora 23 package.'
+ my_timed: '* * * * *'
+ my_trigger: ''
+ my_shell: '/srv/jenkins/bin/reproducible_build_rpm.sh fedora23 x86_64'
+ my_recipients: 'qa-jenkins-scm at lists.alioth.debian.org'
+ my_node: ''
- '{name}_html_archlinux':
my_description: 'Build a simple webpage for Arch Linux reproducibility tests'
my_timed: ''
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/qa/jenkins.debian.net.git
More information about the Qa-jenkins-scm
mailing list