def projects = ['ahtc', 'guez'] // Maps OsVersion -> BUILD_VERSION env var consumed by rpmbuild/make_rpm_ubuntu26.py // (the script looks for lts${BUILD_VERSION}.spec; empty selects specs/lts.spec). // Ubuntu 26.04 is the target platform for Qt6 migration def spec_suffix_for_os = [ '26.04': '26.04' ] def choice_projects = ['ALL'] + projects properties([ disableConcurrentBuilds(), parameters([ choice(name: 'ProjectName', choices: choice_projects, description: 'LTS project flavor (passed as cmake -D_pname)'), string(name: 'OsVersions', defaultValue: '26.04', description: 'Comma-separated Ubuntu base versions, all built in parallel (selects build container tag and spec variant)'), string(name: 'LtsVersion', defaultValue: '1.0', description: 'LTS version (major.minor) passed to make_rpm_ubuntu26.py --version'), booleanParam(name: 'ClearWorkspace', defaultValue: false, description: 'Clear entire workspace on all nodes used for build'), booleanParam(name: 'PublishArtifactRepo', defaultValue: true, description: 'Upload produced DEB packages to the internal artifact repository') ]) ]) env.GIT_TERMINAL_PROMPT = "0" env.LTS_VERSION = "${params.LtsVersion}" env.BUILD_CONTAINER_REGISTRY = "harbor.sl.defence-elec.de" env.BUILD_CONTAINER_PREFIX = "buildcontainer" env.ARTIFACTREPO = "https://internal-repo.sl.defence-elec.de" env.BITBUCKET_URL = "https://devhub.defence-elec.de/bitbucket" // Posts the build status to Bitbucket via jenkins/jenkins_notifier.sh (REST // build-status API). A notification failure must never break the build itself. def notifyBitbucketStatus(String state) { try { withCredentials([usernamePassword(credentialsId: 'bitbucket-notifier', usernameVariable: 'CURL_USER', passwordVariable: 'CURL_PASS')]) { sh """ export CURL_CRED="\${CURL_USER}:\${CURL_PASS}" export BUILD_STATE='${state}' bash jenkins/jenkins_notifier.sh """ } } catch (e) { echo "WARNING: Bitbucket notification (${state}) failed: ${e.message}" } } // OS versions this build covers; every (project, osVersion) pair runs in parallel. def osVersions = params.OsVersions.split(',').collect { it.trim() }.findAll { it } if (params.ProjectName != 'ALL') { projects = [params.ProjectName] } // One parallel branch per (project, osVersion) combination. Outputs are isolated // under rpms/${project}/${osVersion} so concurrent OS builds never collide. def builds = [:] projects.each { project -> osVersions.each { osVersion -> def buildVersion = spec_suffix_for_os.containsKey(osVersion) ? spec_suffix_for_os[osVersion] : osVersion def rpmsDir = "rpms/${project}/${osVersion}" builds["${project} (${osVersion})"] = { stage("Prepare ${project} (${osVersion})") { sh "rm -rf ${rpmsDir}" sh "mkdir -p ${rpmsDir}" } stage("Build DEB ${project} (${osVersion})") { def imageName = "${BUILD_CONTAINER_REGISTRY}/${BUILD_CONTAINER_PREFIX}/${project}_${osVersion}" def buildContainer = docker.image("${imageName}") def guezMode = (project == 'guez') ? 'ON' : 'OFF' def dockerOpts = "--init --shm-size=2g" + " -e HOME=/shd/CTC/TOOLS" + " -e PROJECT_BASE_DIR=/tmp/legatus" + " -e PROJECT=${project}" + " -e OS_VERSION=${osVersion}" + " -e LTS_VERSION=${LTS_VERSION}" + " -e GUEZ_MODE=${guezMode}" + " -e BUILD_VERSION=${buildVersion}" + " -e BUILD_NUMBER=${env.BUILD_NUMBER}" + " -e BUILD_TAG=${env.BUILD_TAG}" buildContainer.inside(dockerOpts) { sh "bash jenkins/jenkins_builder.sh" } } stage("Publish ${project} (${osVersion})") { if (params.PublishArtifactRepo) { withCredentials([usernamePassword(credentialsId: 'internal-repo-uploader', usernameVariable: 'CURL_USER', passwordVariable: 'CURL_PASS')]) { sh """ export CURL_CRED="\${CURL_USER}:\${CURL_PASS}" export PROJECT='${project}' export OS_VERSION='${osVersion}' export LTS_VERSION='${LTS_VERSION}' export BUILD_NUMBER='${env.BUILD_NUMBER}' export ARTIFACTREPO='${env.ARTIFACTREPO}' export ARTIFACTFOLDER='${project}' bash jenkins/jenkins_publisher.sh """ } def tdsUrl = readFile("url-${project}-${osVersion}.txt").trim() def tdsVersion = readFile("tdsversion-${project}-${osVersion}.txt").trim() def link = """${project} ${tdsVersion} (OS ${osVersion})""" currentBuild.description = currentBuild.description ? "${currentBuild.description}
${link}" : link } else { echo "Artifact-repo publish skipped for ${project} (OS ${osVersion}, PublishArtifactRepo=false)" } } stage("Cleanup ${project} (${osVersion})") { sh "rm -rf ${rpmsDir}" } } } } notifyBitbucketStatus('INPROGRESS') try { stage("Initialization") { if (params.ClearWorkspace) { cleanWs() checkout([ $class: 'GitSCM', branches: scm.branches, doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'SubmoduleOption', disableSubmodules: false, parentCredentials: true, recursiveSubmodules: true, reference: '', trackingSubmodules: false]], userRemoteConfigs: scm.userRemoteConfigs ]) } echo "Legatus build initialized — branch '${env.BRANCH_NAME}', project(s): ${projects.join(', ')}, LTS ${env.LTS_VERSION}, OS version(s) (parallel): ${osVersions.join(', ')}" } parallel builds stage("Finalization") { echo "Legatus build completed — branch '${env.BRANCH_NAME}', project(s): ${projects.join(', ')} (LTS ${env.LTS_VERSION}), OS version(s): ${osVersions.join(', ')}" } currentBuild.result = 'SUCCESS' } catch (e) { currentBuild.result = 'FAILURE' throw e } finally { notifyBitbucketStatus(currentBuild.result == 'SUCCESS' ? 'SUCCESSFUL' : 'FAILED') }