yocto-img-build/Jenkinsfile

270 lines
9.8 KiB
Groovy

// declarative pipeline
pipeline {
agent {
node {
label 'lxbuild4'
}
}
parameters {
choice(name: 'MACHINE_TYPE', choices: ['select...', 'am335x-nrhw20', 'am335x-nmhw21', 'imx8-nmhw23', 'am335x-nmhw24', 'am335x-hw25', 'am335x-hw26'], description: 'choose target platform')
choice(name: 'IMAGE_TYPE', choices: ['bootloader', 'release', 'dev', 'vcu', 'lava', 'fct', 'minimal', 'sdk'], description: 'choose target platform')
string(name: 'RLS_VERSION', defaultValue: '', description: 'Set the version to build and use committed submodules')
booleanParam(name: 'CLEAN_BUILD', defaultValue: false, description: 'clean all temp directories before build starts')
}
environment {
PACKAGE_NAME = 'nm-os'
MACHINE = "${MACHINE_TYPE}"
SHARED_BUILD = "${WORKSPACE}/build"
build_deploy = "${SHARED_BUILD}/tmp/deploy/images/${MACHINE}"
build_licenses = "${SHARED_BUILD}/tmp/deploy/licenses"
buildhistory = "${SHARED_BUILD}/buildhistory"
DISTO_VERSION_FILE = "${SHARED_BUILD}/conf/distro_version.inc"
SUBMODULE_VERION_FILE = "${WORKSPACE}/submodule_revisions"
AUTOREV_VERSION_FILE = "${WORKSPACE}/autorev_revisions.inc"
}
options {
timeout(time: 8, unit: 'HOURS')
buildDiscarder(
logRotator(numToKeepStr: '50',
daysToKeepStr: '1',
artifactNumToKeepStr: '50',
artifactDaysToKeepStr: '1'
)
)
disableConcurrentBuilds()
}
stages {
stage('prepare') {
steps {
script {
if("${params.MACHINE_TYPE}" == "select...") {
error("Missing machine type --> select parameter MACHINE_TYPE for a proper build")
}
handle_submodules("${params.RLS_VERSION}")
version = build_version("${params.RLS_VERSION}")
println "----------------------------------\n Job Parameters:\n----------------------------------\n\
MACHINE_TYPE = ${params.MACHINE_TYPE}\n\
IMAGE_TYPE = ${params.IMAGE_TYPE}\n\
CLEAN_BUILD = ${params.CLEAN_BUILD}\n\
RLS_VERSION = ${params.RLS_VERSION}\n\
--> version = ${version}\n\
----------------------------------\n"
env.BUILD_VERSION = "${version}"
currentBuild.displayName = "${version}-${MACHINE}-${IMAGE_TYPE}" //replace Bitbake timestamp after building
change_distro_version("${version}")
}
writeFile file: 'VERSION', text: "${PACKAGE_NAME}: ${BUILD_VERSION}"
}
}
stage('clean') {
when { expression { return params.CLEAN_BUILD } }
steps {
dir ("${SHARED_BUILD}/tmp") { deleteDir() }
dir ("${SHARED_BUILD}/tmp-glibc") { deleteDir() }
}
}
stage('collect versions') {
steps {
script {
revisions = getAutoRevHashes()
writeFile(file: "${env.AUTOREV_VERSION_FILE}", text: "${revisions}")
}
}
post {
success {
archiveArtifacts(artifacts: "${env.SUBMODULE_VERION_FILE},${env.AUTOREV_VERSION_FILE},${env.DISTO_VERSION_FILE}", onlyIfSuccessful: false)
}
}
}
stage('build') {
steps {
script {
build_and_archive()
}
dir ('tmp/artifacts') {
zip archive: true, dir: "${WORKSPACE}/tmp/build-output", glob: "*", zipFile: "${PACKAGE_NAME}-${BUILD_VERSION}-${machine}-${IMAGE_TYPE}.zip"
}
sh "rm -rf ${WORKSPACE}/tmp"
}
}
} // stages
}
def isRelease(versionParam) {
if((versionParam == "") || (versionParam == "latest")) {
return false
}
return true
}
def handle_submodules(versionParam) {
sh 'git submodule init'
if(isRelease(versionParam)) {
sh 'git submodule update' // set all submodules to freezed commit
}
else {
sh 'git submodule update --remote --rebase' // update all submodules to HEAD
}
submoduleStatus = sh(returnStdout: true, script: "git submodule status").trim() // print submodule hashes to jenkins log
println "${submoduleStatus}"
writeFile(file: "${env.SUBMODULE_VERION_FILE}", text: "${submoduleStatus}")
}
def build_version(versionParam) {
sh 'git fetch -p'
sh 'git fetch -t'
def gitCmd = "git describe --tags"
if(!isRelease(versionParam)) {
gitCmd = "${gitCmd} --dirty"
}
gitversion = sh(returnStdout: true, script: "${gitCmd}").trim()
String[] versionArr = "${gitversion}".split("-")
if(isRelease(versionParam)) {
String newVersionStr = versionParam
versionArr[0] = newVersionStr
}
else {
def buildnbr = getTopUpstreamBuildNumber()
String nightlyPart = versionArr[0] + ".Test${buildnbr}"
versionArr[0] = nightlyPart
}
rlsVersion = versionArr.join("-")
return rlsVersion
}
def change_distro_version(versionString){
println "Set the distro version to ${versionString}..."
def versionTag = "DISTRO_VERSION = \"${versionString}\""
writeFile(file: "${env.DISTO_VERSION_FILE}", text: "${versionTag}")
}
def cleanup_distro_version() {
println "cleaning repository regarding distro version..."
sh(script:"git clean -f ${env.DISTO_VERSION_FILE}")
}
def build_and_archive() {
if (params.IMAGE_TYPE == 'sdk') {
sh "bash -c '. ./env.image-ostree && bitbake -k netmodule-linux-image -c populate_sdk'"
zip archive: true, dir: "${HOME}/yocto-share/build/tmp/deploy/sdk", glob: '*.sh', zipFile: "${PACKAGE_NAME}-${BUILD_VERSION}-${MACHINE}-sdk.zip"
}
else if (params.IMAGE_TYPE == 'bootloader') {
sh "bash -c '. ./env.common && bitbake virtual/bootloader'"
dir ('tmp/build-output') {
sh 'cp ${build_deploy}/*u-boot-${MACHINE_TYPE}.img . || true'
sh 'cp ${build_deploy}/*u-boot-${MACHINE_TYPE}.xmodem.bin . || true'
sh 'cp ${build_deploy}/imx-boot . || true'
sh 'cp ${build_deploy}/imx-boot.sd . || true'
}
}
else if (params.IMAGE_TYPE == 'vcu') {
build('vcu', 'vcu', false)
archive('vcu', false)
}
else if (params.IMAGE_TYPE == 'lava' || params.IMAGE_TYPE == 'fct' || params.IMAGE_TYPE == 'minimal') {
build(params.IMAGE_TYPE, params.IMAGE_TYPE, true)
archive(params.IMAGE_TYPE, true)
}
else if (params.IMAGE_TYPE == 'release') {
build('ostree', '', false)
archive('', false)
}
else {
build('ostree', params.IMAGE_TYPE, false)
archive(params.IMAGE_TYPE, false)
}
}
def build(env_in, image_type_in, single_fitImage) {
def env = "${env_in}" == "" ? "" : "-${env_in}"
def image_type = "${image_type_in}" == "" ? "" : "-${image_type_in}"
if (single_fitImage) {
sh "bash -c '. ./env.image${env} && bitbake -k virtual/netmodule-image'"
} else {
/* The following workaround can be removed once the explanation for the missing lic has been found */
if (! fileExists("build/tmp/deploy/licenses/gpsd"))
sh "bash -c '. ./env.image${env} && bitbake -fc populate_lic gpsd'"
if (! fileExists("build/tmp/deploy/licenses/ostree-kernel-initramfs"))
sh "bash -c '. ./env.image${env} && bitbake -fc populate_lic ostree-kernel-initramfs'"
sh "bash -c '. ./env.image${env} && bitbake -k netmodule-linux-image${image_type}'"
}
}
def archive(image_type_in, single_fitImage) {
def image_type = "${image_type_in}" == "" ? "" : "-${image_type_in}"
dir ("tmp/build-output") {
def image_basename = "netmodule-linux-image${image_type}-${MACHINE}"
def basename_in = "${build_deploy}/${image_basename}"
def basename_out = "./image${image_type}-${MACHINE}"
sh "cp ${basename_in}.manifest ${basename_out}.manifest"
sh "bash -c '${WORKSPACE}/openembedded-core/scripts/buildhistory-collect-srcrevs -p ${buildhistory} > srcrev-${MACHINE}${image_type}.inc'"
sh label: 'Copy License Manifest', returnStatus: true, script: """
LATEST_LICENSE_DIR=\$(ls -Artd ${build_licenses}/netmodule-linux-image${image_type}* | tail -n 1)
cp \$LATEST_LICENSE_DIR/license.manifest ${basename_out}_license.manifest"""
if (single_fitImage == false) {
sh label: 'Copy initramfs License Manifest', returnStatus: true, script: """
LATEST_LICENSE_DIR=\$(ls -Artd ${build_licenses}/initramfs-ostree-image-${MACHINE}-* | tail -n 1)
cp \$LATEST_LICENSE_DIR/license.manifest initramfs-ostree-image_license.manifest
"""
}
if(single_fitImage){
if(image_type_in == "minimal")
sh "cp ${build_deploy}/initramfs-linux/fitImage-${image_basename}-${MACHINE} fitImage-${image_basename}"
else
sh "cp ${build_deploy}/fct-linux/fitImage-${image_basename}-${MACHINE} fitImage-${image_basename}"
sh "cp ${basename_in}.tar.gz ${basename_out}.tar.gz"
}
else {
sh "cp ${build_deploy}/fitImage-${MACHINE}.bin ."
sh "cp ${basename_in}.ota-ext4 ${basename_out}.ota-ext4"
sh "cp ${basename_in}.wic ${basename_out}.wic"
def ostree_archive = "ostree_repo${image_type}.tar.gz"
sh "tar czf ./${ostree_archive} -C ${build_deploy}/ostree_repo ."
archiveArtifacts artifacts: "${ostree_archive}", onlyIfSuccessful: true
sh "rm -f ./${ostree_archive}"
}
}
}
def getTopUpstreamBuildNumber() {
// Iterating though all upstream jobs:
// currentBuild.upstreamBuilds.each { item ->
// echo "upstream build: ${item}"
// def nbr = item.getNumber()
// echo "nbr=${nbr}"
// }
def upstreamJobList = currentBuild.upstreamBuilds
def nbrOfUpstreamJobs = upstreamJobList.size()
if (nbrOfUpstreamJobs == 0)
return 0;
def topJob = upstreamJobList[nbrOfUpstreamJobs-1]
println "Top upstream project: " + topJob.getFullDisplayName()
def topJobNbr = topJob.getNumber()
println "Top upstream job build Number = ${topJobNbr}"
return topJobNbr
}
def getAutoRevHashes() {
sh(script: "bash -c '. ./env.image-ostree && bitbake netmodule-linux-image-dev --runall=fetch'")
def revs = sh(returnStdout: true, script: "bash -c \". ./env.image-ostree && clear && buildhistory-collect-srcrevs | sort | uniq | grep -v \"#\"\"").trim()
return revs
}