// Packaging validation for supported GNU/Linux systems. // // Note: To work on this script without having to push a commit each // time, use the jenkins-cli command (see: // https://wiki.savoirfairelinux.com/wiki/Jenkins.jami.net#Usage_CLI_de_Jenkins). // // Requirements: // 1. gerrit-trigger plugin // 2. ws-cleanup plugin // Configuration globals. def SUBMODULES = ['daemon', 'lrc', 'client-gnome', 'client-qt'] def TARGETS = [:] def SSH_PRIVATE_KEY = '/var/lib/jenkins/.ssh/gplpriv' def REMOTE_HOST = env.SSH_HOST_DL_RING_CX def REMOTE_BASE_DIR = '/srv/repository/ring' def RING_PUBLIC_KEY_FINGERPRINT = 'A295D773307D25A33AE72F2F64CD5FA175348F84' def SNAPCRAFT_KEY = '/var/lib/jenkins/.snap/key' properties( [ [ $class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', numToKeepStr: '30'] ], pipelineTriggers([ [ $class: 'GerritTrigger', gerritProjects: [ [ $class: "GerritProject", pattern: "ring-project", branches: [ [$class: "Branch", pattern: "master"] ] ] ], triggerOnEvents: [ [ $class: "PluginPatchsetCreatedEvent", excludeDrafts: true, excludeTrivialRebase: true, excludeNoCodeChange: true ], [ $class: "PluginCommentAddedContainsEvent", commentAddedCommentContains: '!build' ] ] ] ]) ] ) pipeline { agent { label 'guix' } parameters { string(name: 'GERRIT_REFSPEC', defaultValue: 'refs/heads/master', description: 'The Gerrit refspec to fetch.') booleanParam(name: 'WITH_MANUAL_SUBMODULES', defaultValue: false, description: 'Checkout the ' + SUBMODULES.join(', ') + ' submodules at their Git-recorded commit. When left ' + 'unticked (the default), checkout the submodules at ' + 'their latest commit from their main remote branch.') booleanParam(name: 'BUILD_ARM', defaultValue: false, description: 'Whether to build ARM packages.') booleanParam(name: 'DEPLOY', defaultValue: false, description: 'Whether and where to deploy packages.') choice(name: 'CHANNEL', choices: 'internal\nnightly\nstable', description: 'The repository channel to deploy to. ' + 'Defaults to "internal".') string(name: 'PACKAGING_TARGETS', defaultValue: '', description: 'A whitespace-separated list of packaging ' + 'targets, e.g. "package-debian_10 package-snap". ' + 'When left unspecified, all the packaging targets are built.') } environment { TARBALLS = '/opt/ring-contrib' // set the cache directory } options { ansiColor('xterm') } stages { stage('Check configuration') { when { not { expression { fileExists TARBALLS } } } steps { error "The ${TARBALLS} directory does not exist. \ See https://wiki.savoirfairelinux.com/wiki/Jenkins.jami.net#Configuration" } } stage('Fetch submodules') { steps { echo 'Initializing submodules ' + SUBMODULES.join(', ') + (params.WITH_MANUAL_SUBMODULES ? '.' : ' to their latest commit.') sh 'git submodule update --init --recursive' + (params.WITH_MANUAL_SUBMODULES ? ' ' : ' --remote ') + SUBMODULES.join(' ') } } stage('Generate release tarball') { steps { // Note: sourcing .bashrc is necessary to setup the // environment variables used by Guix. sh '''#!/usr/bin/env bash test -f $HOME/.bashrc && . $HOME/.bashrc make portable-release-tarball .tarball-version ''' stash(includes: '*.tar.gz, .tarball-version', name: 'release-tarball') } } stage('Build packages') { environment { DISABLE_CONTRIB_DOWNLOADS = 'TRUE' // The following password is used to register with the // RHEL subscription-manager tool, required to build on RHEL. PASS = credentials('developers-redhat-com') } steps { script { def targetsText = params.PACKAGING_TARGETS.trim() if (!targetsText) { targetsText = sh(script: 'make -s list-package-targets', returnStdout: true).trim() } TARGETS = targetsText.split(/\s/) if (!params.BUILD_ARM) { TARGETS = TARGETS.findAll { !(it =~ /_(armhf|arm64)$/) } } def stages = [:] TARGETS.each { target -> // Note: The stage calls are wrapped in closures, to // delay their execution. stages[target] = { stage(target) { // Offload builds to different agents. node('linux-builder') { cleanWs() unstash 'release-tarball' catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { sh """ tar xf *.tar.gz --strip-components=1 make ${target} """ stash(includes: 'packages/**', name: target) } } } } } parallel stages } } } stage('Sign & deploy packages') { agent { label 'ring-buildmachine-02.mtl.sfl' } when { expression { params.DEPLOY } } steps { script { TARGETS.each { target -> try { unstash target } catch (err) { echo "Failed to unstash ${target}, skipping..." return } def distribution = target - ~/^package-/ echo "Deploying packages for ${distribution}..." sh """scripts/deploy-packages.sh \ --distribution=${distribution} \ --keyid="${RING_PUBLIC_KEY_FINGERPRINT}" \ --snapcraft-login="${SNAPCRAFT_KEY}" \ --remote-ssh-identity-file="${SSH_PRIVATE_KEY}" \ --remote-repository-location="${REMOTE_HOST}:${REMOTE_BASE_DIR}/${params.CHANNEL}" \ --remote-manual-download-location="${REMOTE_HOST}:${REMOTE_BASE_DIR}/manual-${params.CHANNEL}" """ } } } } } }