Jenkinsfile for Devuan unified package building
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.

288 lines
12 KiB

pipeline {
parameters {
string description: 'Source package', name: 'srcpackage', trim: true
string defaultValue: 'experimental', description: 'Target suite', name: 'codename', trim: true
/* Keep this list of architectures in sync with DSC_ARCHITECTURES and axis values below.
'default' builds the architectures defined in the source dsc file.
*/
choice(name: 'ARCH_FILTER', choices: ['default', 'i386', 'amd64', 'armel', 'armhf', 'arm64', 'ppc64el', 'all'], description: 'Limit build to this architecture')
booleanParam defaultValue: false, description: 'Binary Rebuild (binNMU)', name: 'binary_rebuild'
string defaultValue: 'Rebuild', description: 'Changelog entry for binNMU rebuild', name: 'CHANGELOG_binNMU', trim: true
}
options {
skipDefaultCheckout true
preserveStashes()
/* Successful builds are kept forever: see post{} */
buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '3')
}
agent {label 'master'}
environment {
KEY_ID = '72E3CB773315DFA2E464743D94532124541922FB'
build_name_tag = "${params.codename}${params.binary_rebuild ? '+binNMU' : ''}${env.ARCH_FILTER != 'default' ? ':'+env.ARCH_FILTER : ''}"
RMADISON_URL = 'https://api.pkginfo.devuan.org/madison'
PKGMASTER_URL = 'http://pkgmaster.devuan.org'
LC_ALL = 'C'
}
stages {
stage('SourceGit'){
when { not { expression { return params.binary_rebuild } } }
steps {
deleteDir()
buildName "${params.srcpackage} (${env.build_name_tag})"
// ircNotify notifyOnStart:true
script {
checkout(
changelog: false,
poll: false,
scm: [$class: 'GitSCM',
branches: [[name: '*/suites/$codename']],
doGenerateSubmoduleConfigurations: false,
extensions: [[$class: 'CleanBeforeCheckout'],
[$class: 'CloneOption', honorRefspec: true, noTags: false, reference: '', shallow: true],
[$class: 'RelativeTargetDirectory', relativeTargetDir: 'source']],
submoduleCfg: [],
userRemoteConfigs: [[url: "https://gitea.devuan.dev/devuan/$srcpackage"]]
]).each { k,v -> env.setProperty(k, v) }
}
dir ('source'){
script {
version = sh(script: 'dpkg-parsechangelog -S version', returnStdout: true).trim().replaceFirst(/\d+:/,'')
if (version.endsWith('+devuan1')) {
/* Reject old versioning */
echo "ERROR: Source should use new version scheme: ${version.replaceFirst(/\+devuan1$/, 'devuan1')}"
assert(false)
}
}
buildName "${params.srcpackage}_${version} (${build_name_tag})"
sh 'git checkout suites/$codename'
// ircNotify customMessage: "Version: $BUILD_DISPLAY_NAME"
// ircNotify customMessage: "Commit: $GIT_COMMIT"
/* Build orig */
sh('gbp buildpackage --git-builder=/bin/true --git-cleaner=/bin/true --git-export-dir= --git-debian-branch=suites/$codename')
sh('dpkg-buildpackage --build=source --no-pre-clean --no-check-builddeps --sign-key=${KEY_ID}')
}
stash includes: '*.gz,*.bz2,*.xz,*.dsc', name: 'source'
stash includes: '*source.changes', name: 'source_changes'
}
}
stage('SourceBinNMU'){
when { expression { return params.binary_rebuild } }
environment {
version = sh(script: "rmadison -u ${RMADISON_URL} -s ${codename} -a source ${srcpackage}|awk '{print \$3}'|sort -u|grep '\$' || ! echo 'Failed to find src:${srcpackage} in suite ${codename} for binNMU'", returnStdout: true).trim()
DSC_PATH = "${String.format('/devuan/pool/main/%1$s/%2$s/%2$s_%3$s.dsc', srcpackage.find(/^(lib)?\w/), srcpackage, version)}"
}
steps {
buildName "${params.srcpackage}_${version} (${env.build_name_tag})"
// ircNotify notifyOnStart:true
sh "dget --download-only --allow-unauthenticated ${PKGMASTER_URL}${DSC_PATH}"
/* Verify separately so the correct keyring can be specified */
sh "dscverify --keyring /usr/share/keyrings/devuan-archive-keyring.gpg ${params.srcpackage}_${version}.dsc"
stash includes: '*.gz,*.bz2,*.xz,*.dsc', name: 'source'
}
}
stage('Binary Matrix') {
environment {
DSC_ARCHITECTURES = sh(script: "awk -F: '/^Architecture: / {print \$2}' ${params.srcpackage}_*.dsc", returnStdout: true).trim().replaceFirst(/\b(linux-)?any\b/,'i386 amd64 armel armhf arm64 ppc64el')
}
matrix {
when {
allOf {
expression { env.architecture in env.DSC_ARCHITECTURES.tokenize() }
expression { params.ARCH_FILTER == env.architecture || params.ARCH_FILTER == 'default' }
/* binNMU for arch:all is not allowed. See thread https://lists.debian.org/debian-devel/2011/01/msg00444.html */
not {
expression { env.architecture == 'all' && params.binary_rebuild }
}
}
beforeAgent true
beforeOptions true
}
axes {
axis {
name 'architecture'
values 'armel', 'armhf', 'arm64', 'amd64', 'i386', 'ppc64el', 'all'
}
}
stages {
stage('Builder') {
agent {label architecture}
environment {
codename = env.codename.replaceFirst(/-.*$/, '')
distribution = "${env.codename == 'experimental' ? 'unstable' : env.codename}"
LAST_binNMU = "${params.binary_rebuild ? sh(script: "rmadison -u ${RMADISON_URL} -S ${params.srcpackage} -s ${codename} -a ${architecture}|awk '{print \$3}'|sort -u", returnStdout: true).find('(?<=\\+b)\\d+$').toString() : ''}"
ADT = 'skip'
PBUILDER_CONFIG = '/tmp/jenkins.pbuilderrc'
DEB_BUILD_ARCH = sh(script: 'dpkg-architecture -qDEB_BUILD_ARCH', returnStdout: true).trim()
DEB_HOST_ARCH = "${env.architecture == 'all' ? env.DEB_BUILD_ARCH : env.architecture}"
COW_PATH = "/var/cache/pbuilder/base-${distribution}-${DEB_HOST_ARCH}.cow"
COWBUILDER_BUILD_OPTIONS = """${
[
/* debian-installer requires network access */
"${params.srcpackage == 'debian-installer' ? '--use-network yes' : ''}",
"${env.architecture == 'all' ? '--binary-indep' : '--binary-arch' }",
"${params.binary_rebuild ? "--bin-nmu '${params.CHANGELOG_binNMU}' --bin-nmu-version \$(($LAST_binNMU+1))" : ''}",
"--buildresult .",
].join(' ')
}"""
/* Use the same lockfile as jenkins-debian-glue */
lockfile = "/var/run/lock/${distribution}-${DEB_HOST_ARCH}.update"
}
stages{
stage('Prepare'){
steps {
writeFile file: "${env.PBUILDER_CONFIG}", text: """# Jenkins arch independent builder config
MIRRORSITE=${PKGMASTER_URL}/merged
OTHERMIRROR=
COMPONENTS='main contrib non-free'
DEBOOTSTRAPOPTS=('--variant=buildd' '--keyring=/usr/share/keyrings/devuan-keyring.gpg' '--no-merged-usr')
PBUILDERSATISFYDEPENDSCMD=/usr/lib/pbuilder/pbuilder-satisfydepends-apt
EXTRAPACKAGES='eatmydata devuan-keyring'
AUTOCLEANAPTCACHE=yes
"""
sh "cat ${env.PBUILDER_CONFIG}"
sh """(flock -n 9 || exit 0;
if [ -d ${COW_PATH} ]
then
sudo cowbuilder --update --configfile ${PBUILDER_CONFIG} --override-config --distribution ${distribution} --basepath ${COW_PATH}
else
sudo DIST=${distribution} ARCH=${DEB_HOST_ARCH} cowbuilder --create --configfile ${PBUILDER_CONFIG} --architecture ${DEB_HOST_ARCH} --distribution ${distribution} --debootstrapopts --arch=${DEB_HOST_ARCH} --basepath ${COW_PATH}
fi
) 9>$lockfile"""
}
}
stage('Build'){
steps {
// ircNotify customMessage: "$BUILD_DISPLAY_NAME: started binary build for ${architecture} on ${NODE_NAME}"
deleteDir()
unstash 'source'
sh "flock --shared $lockfile sudo DIST=${distribution} ARCH=${DEB_HOST_ARCH} cowbuilder --build --configfile ${PBUILDER_CONFIG} --architecture ${DEB_HOST_ARCH} --distribution ${distribution} ${COWBUILDER_BUILD_OPTIONS} --basepath ${COW_PATH} ${params.srcpackage}_*.dsc"
stash includes: '*.deb,*.udeb,devuan-installer-images*.tar.gz,*.changes,*.buildinfo', name: "${architecture}"
}
}
stage('Autopkgtest'){
when {
allOf {
/* autopackage tests are unreliable on 32bit arm and pointless for binNMU and binary-indep
builds of Architecture: any all. */
anyOf {
expression { env.architecture in ['amd64', 'i386', 'arm64', 'ppc64el'] }
expression { env.DSC_ARCHITECTURES == 'all' }
}
not { expression { params.binary_rebuild } }
expression { 'autopkgtest' in sh(script: "awk -F: '\$1==\"Testsuite\" {print \$2}' ${params.srcpackage}_*.dsc", returnStdout: true).trim().tokenize(',') }
}
}
environment {
run_script = "${pwd()}/autopkgtest.run"
}
steps{
waitUntil{
script {
try {
unstash 'all'
return true
} catch (e) {
return !('all' in "${env.DSC_ARCHITECTURES}".tokenize())
}
}
}
writeFile file: "${env.run_script}", text: """
apt-get install --assume-yes autopkgtest newpid
newpid autopkgtest ${pwd()}/${params.srcpackage}_*.dsc ${pwd()}/*.deb -- autopkgtest-virt-null
case \$? in
2|4|6|8)
exit 0
;;
*)
exit \$?
;;
esac
"""
sh "flock --shared $lockfile sudo cowbuilder --execute --configfile ${PBUILDER_CONFIG} --basepath ${COW_PATH} --bindmount ${pwd()} -- ${run_script}"
}
}
}
post {
always {
echo ''
// ircNotify customMessage: "$BUILD_DISPLAY_NAME: finished binary build for ${architecture} on ${NODE_NAME}: ${currentBuild.currentResult}"
}
cleanup {
echo "Cleaning architecture:${env.architecture} workspace on ${env.NODE_NAME}"
deleteDir()
/* Sigh, jenkins-debian-glue:build-and-provide-package tests the presence of the lockfile,
so remove it if there are no locks */
sh "flock --nonblock --conflict-exit-code 0 $lockfile rm $lockfile"
}
}
}
stage('Sign'){
steps {
dir ("architecture=${architecture}") {
unstash "${architecture}"
sh 'debsign -k$KEY_ID *_${architecture}.changes'
}
}
}
}
}
}
stage('Lintian'){
steps{
// ircNotify customMessage: "$BUILD_DISPLAY_NAME: Running lintian"
sh "find -name '*.changes' '!' -name '*_source.changes' -o -name '*.dsc' | xargs lintian -i > lintian.txt"
}
}
stage('BinNMU'){
when { expression { return params.binary_rebuild } }
steps {
/* For binNMU empty the source stashes */
stash excludes: '**', name: 'source', allowEmpty: true
stash excludes: '**', name: 'source_changes', allowEmpty: true
}
}
stage('Deploy to DAK'){
steps{
dir ('sources') {
unstash 'source'
unstash 'source_changes'
}
/* ircNotify customMessage: "$BUILD_DISPLAY_NAME: Deploy to DAK"
sh 'ssh dak@repo.devuan.org mkdir /home/dak/jenkins/$BUILD_TAG'
sh 'scp -r * dak@repo.devuan.org:/home/dak/jenkins/$BUILD_TAG'
sh '[ $srcpackage != "debian-installer" ] || ssh dak@repo.devuan.org installer_tgz -s $codename $BUILD_TAG'
sh 'ssh dak@repo.devuan.org dak_add_pkgs -s $codename -c main $BUILD_TAG' */
archiveArtifacts artifacts: 'lintian.*,sources/**,architecture=*/**', fingerprint: true, onlyIfSuccessful: true
}
}
}
post {
always {
echo ''
// ircNotify ()
}
success {
echo 'Successful build: keeping forever'
script {
currentBuild.keepLog = true
}
}
cleanup {
echo "Cleaning workspace on ${env.NODE_NAME}"
deleteDir()
}
}
}