// Loading code requires a NODE context // But we want the code accessible outside the node Context // So declare yoctocommon (object created by the LOAD operation) outside the Node block. def yoctocommon // declarative pipeline pipeline { agent { node { label "${params.NODE_NAME}" } } parameters { choice(name: 'MACHINE', choices: ['select...', 'armada-385-nrhw18', 'am335x-nrhw20', 'am335x-nmhw21', 'imx8-nmhw23', 'am335x-nmhw24', 'am335x-hw25', 'am335x-hw26'], description: 'choose target platform') choice(name: 'IMAGE_TYPE', choices: ['dev', 'bootloader', 'release', 'vcu'], description: 'choose image type') string(name: 'RLS_VERSION', defaultValue: '', description: 'Set the version to build and use committed submodules') string(name: 'NODE_NAME', defaultValue: 'lxbuild4', description: 'Overwrite default node name to build on') booleanParam(name: 'CLEAN_BUILD', defaultValue: false, description: 'clean all temp directories before build starts') } environment { WORK_DIR = "tmp" IMG_OUTPUT_DIR = "${WORK_DIR}/build-output" } options { timeout(time: 5, unit: 'HOURS') buildDiscarder( logRotator(numToKeepStr: '80', daysToKeepStr: '7', artifactNumToKeepStr: '80', artifactDaysToKeepStr: '7' ) ) disableConcurrentBuilds() } stages { stage('prepare') { steps { script { if("${params.MACHINE}" == "select...") { currentBuild.result = 'ABORTED' error("Missing machine type --> select parameter MACHINE for a proper build") } cleanLeftOvers(env.IMG_OUTPUT_DIR) // this definition is needed for selecting the // correct build directory env.BUILD_DIR_POSTFIX = "" // take the correct user ID for the ssh connection of // the belonging build server if("${params.NODE_NAME}" == "lxbuild4") { env.SSH_ID = '6b90ac7f-9596-4e43-923b-6c9179a10d8a' } else if("${params.NODE_NAME}" == "lxbuild3") { env.SSH_ID = '70c27394-cb7d-4304-aed1-89e15a3a78d0' } else { env.SSH_ID = '' } println "SSH_ID used: ${env.SSH_ID}" // load yocto common file env.ROOTDIR = pwd() yoctocommon = load "${env.ROOTDIR}/Jenkinsfile_Common" // clean-up no longer needed packages yoctocommon.cleanWorkspace() // Prepare Build Environment env.YOCTO_DEPLOYS = "${env.BUILD_DEPLOY_DIR}/${params.MACHINE}" yoctocommon.handleSubmodules("${params.RLS_VERSION}") yoctocommon.handleAutoRevIncludeFile("${params.RLS_VERSION}") version = yoctocommon.getVersionString("${params.RLS_VERSION}", "${params.IMAGE_TYPE}") env.BUILD_VERSION = "${version}" currentBuild.displayName = "${version}-${params.MACHINE}-${params.IMAGE_TYPE}" //replace Bitbake timestamp after building printJobParameters() yoctocommon.changeDistroVersion("${version}") yoctocommon.syncSources("${env.BINARY_STORAGE_URL}", "${env.DOWNLOAD_DIR}") } writeFile file: 'VERSION', text: "${env.PACKAGE_NAME}: ${env.BUILD_VERSION}" } } stage('clean') { when { expression { return params.CLEAN_BUILD } } steps { script { cleaning(params.IMAGE_TYPE) } } } stage('build') { steps { script { build(params.IMAGE_TYPE) // archive a bootloader package: // the bootloader is also built with the dev image, hence we combine it def isBootLoaderOnly = (params.IMAGE_TYPE == 'bootloader').toBoolean() if(isBootLoaderOnly || (params.IMAGE_TYPE == 'dev')) { createBslPackage(env.IMG_OUTPUT_DIR, params.MACHINE) archivePackage(yoctocommon, env.IMG_OUTPUT_DIR, 'bootloader', !isBootLoaderOnly) } // archive an image package: // skip for bootloader only builds if(!isBootLoaderOnly) { createImagePackage(params.IMAGE_TYPE, env.IMG_OUTPUT_DIR) archiveOSTreeArtifact(env.IMG_OUTPUT_DIR) archivePackage(yoctocommon, env.IMG_OUTPUT_DIR, params.IMAGE_TYPE, false) } } } post { always { script { cleanLeftOvers(env.WORK_DIR) yoctocommon.cleanupAutoRevIncludeFile("${params.RLS_VERSION}") yoctocommon.syncSources("${env.DOWNLOAD_DIR}", "${env.BINARY_STORAGE_URL}") } } } } stage('collect versions') { steps { script { revisions = yoctocommon.getAutoRevHashes('ostree') writeFile(file: "${env.AUTOREV_VERSION_FILE}", text: "${revisions}") } } post { success { archiveArtifacts(artifacts: "${env.SUBMODULE_VERION_FILE}, ${env.AUTOREV_VERSION_FILE}, ${env.DISTRO_VERSION_FILE}", onlyIfSuccessful: false) } } } } // stages } //----------------------------------------------------------------------------- def printJobParameters() { println "----------------------------------\n\ Job Parameters:\n\ ----------------------------------\n\ MACHINE = ${params.MACHINE}\n\ IMAGE_TYPE = ${params.IMAGE_TYPE}\n\ CLEAN_BUILD = ${params.CLEAN_BUILD}\n\ RLS_VERSION = ${params.RLS_VERSION}\n\ --> version = ${env.BUILD_VERSION}\n\ ----------------------------------\n" } //----------------------------------------------------------------------------- def cleanLeftOvers(cleaningDir) { sh "rm -rf ${cleaningDir}" } //----------------------------------------------------------------------------- def cleaning(imgType) { sshagent (credentials: [env.SSH_ID]) { def tgtImgType = "${imgType}" == "bootloader" ? "dev" : "${imgType}" tgtImgType = "${tgtImgType}" == "release" ? "" : "${tgtImgType}" def imgTypePostfix = "${tgtImgType}" == "" ? "" : "-${tgtImgType}" def distroPostfix = "ostree" if (tgtImgType == "vcu") distroPostfix = "vcu" sh "bash -c '. ./env.image-${distroPostfix} > /dev/null && bitbake -q -fc cleanall netmodule-linux-image${imgTypePostfix}'" } dir ("${env.SHARED_BUILD}/tmp") { deleteDir() } dir ("${env.SHARED_BUILD}/tmp-glibc") { deleteDir() } } //----------------------------------------------------------------------------- def build(imgType) { sshagent (credentials: [env.SSH_ID]) { def tgtImgType = "${imgType}" == "bootloader" ? "dev" : "${imgType}" tgtImgType = "${tgtImgType}" == "release" ? "" : "${tgtImgType}" def imgTypePostfix = "${tgtImgType}" == "" ? "" : "-${tgtImgType}" def distroPostfix = "ostree" if (tgtImgType == "vcu") distroPostfix = "vcu" sh "bash -c '. ./env.image-${distroPostfix} > /dev/null && bitbake -q -k netmodule-linux-image${imgTypePostfix}'" } } //----------------------------------------------------------------------------- def createBslPackage(outputDir, machine) { dir(outputDir) { String machineStr = machine String[] machineArr = machineStr.split('-') println "get bootloader artifacts for package..." if(machineArr[0] == 'imx8') { sh "cp ${env.YOCTO_DEPLOYS}/imx-boot ." sh "cp ${env.YOCTO_DEPLOYS}/imx-boot.sd ." } else if(machineArr[0] == 'armada') { sh "cp ${env.YOCTO_DEPLOYS}/*u-boot-spl.kwb ." sh "cp ${env.YOCTO_DEPLOYS}/*u-boot-${params.MACHINE}*.kwb ." sh "cp ${env.YOCTO_DEPLOYS}/*u-boot-${params.MACHINE}*.xmodem.bin ." } else { sh "cp ${env.YOCTO_DEPLOYS}/*u-boot-${params.MACHINE}*.img ." sh "cp ${env.YOCTO_DEPLOYS}/*u-boot-${params.MACHINE}*.xmodem.bin ." } } } //----------------------------------------------------------------------------- def createImagePackage(imgType, outputDir) { dir (outputDir) { println "get image artifacts for package..." def imgTypePostfix = "${imgType}" == "" ? "" : "-${imgType}" imgTypePostfix = "${imgTypePostfix}" == "-release" ? "" : "${imgTypePostfix}" def image_basename = "netmodule-linux-image${imgTypePostfix}-${params.MACHINE}" def basename_built = "${env.YOCTO_DEPLOYS}/${image_basename}" def basename_archive = "./image${imgTypePostfix}-${params.MACHINE}" sh "cp ${basename_built}.manifest ${basename_archive}.manifest" sh "bash -c '${WORKSPACE}/openembedded-core/scripts/buildhistory-collect-srcrevs -p ${env.BUILD_HISTORY_DIR} > srcrev-${params.MACHINE}${imgTypePostfix}.inc'" sh label: 'Copy License Manifest', returnStatus: true, script: """ LATEST_LICENSE_DIR=\$(ls -Artd ${env.BUILD_LICENSE_DIR}/netmodule-linux-image${imgTypePostfix}* | tail -n 1) cp \$LATEST_LICENSE_DIR/license.manifest ${basename_archive}_license.manifest """ sh label: 'Copy initramfs License Manifest', returnStatus: true, script: """ LATEST_LICENSE_DIR=\$(ls -Artd ${env.BUILD_LICENSE_DIR}/initramfs-ostree-image-${params.MACHINE}-* | tail -n 1) cp \$LATEST_LICENSE_DIR/license.manifest initramfs-ostree-image_license.manifest """ sh "cp ${basename_built}.ota-ext4 ${basename_archive}.ota-ext4" sh "cp ${basename_built}.wic ${basename_archive}.wic" sh "tar czf ./ostree_repo${imgTypePostfix}.tar.gz -C ${env.YOCTO_DEPLOYS}/ostree_repo ." } } //----------------------------------------------------------------------------- def archivePackage(yoctocommon, pkgDir, imgType, doCleanPkgDir) { yoctocommon.archiveImages(pkgDir, imgType) if(doCleanPkgDir) { println "cleaning pkgDir..." sh "rm -rf ./${pkgDir}/*" } } //----------------------------------------------------------------------------- def archiveOSTreeArtifact(outputDir) { archiveArtifacts artifacts: "${outputDir}/ostree_repo*.tar.gz", onlyIfSuccessful: true sh "rm -f ./${outputDir}/ostree_repo*.tar.gz" }