265 lines
9.8 KiB
Plaintext
265 lines
9.8 KiB
Plaintext
// Loading code requires a NODE context
|
|
// But we want the code accessible outside the node Context
|
|
// So declare common (object created by the LOAD operation) outside the Node block.
|
|
def common
|
|
|
|
// This step is necessary to get the files directly from the git repo, as for the
|
|
// first build it is not yet cloned into the workspace. Normally we use an agent
|
|
// of a certain label (like core-os_buildagent) to have define credentials to get
|
|
// the files. In the current case we use any agent.
|
|
node() {
|
|
def repoPreCloneDir = "repo-preclone"
|
|
def nodeHostname = sh(returnStdout: true, script: "set +x && hostname | cut -d '_' -f1").trim()
|
|
def cloneCredentials = ("${nodeHostname}" == "nwl") ? 'nmgit_credentials' : 'gitCredentials'
|
|
|
|
dir(repoPreCloneDir) {
|
|
// clone the repository to get the file with the target list
|
|
sshagent (credentials: [cloneCredentials]) {
|
|
sh "set +x && git clone --depth 1 --branch main ssh://git@bitbucket.gad.local:7999/nm-nsp/nwl-ci.git ."
|
|
}
|
|
|
|
// load common file
|
|
common = load "./jobs/Jenkinsfile_Common"
|
|
}
|
|
sh("rm -rf ${repoPreCloneDir}")
|
|
}
|
|
|
|
// declarative pipeline
|
|
pipeline {
|
|
agent any
|
|
|
|
parameters {
|
|
string(name: 'BUILD_BRANCH', defaultValue: 'main', description: 'Enter the branch of the NWL to build (default = main), will skip deployment if not main')
|
|
booleanParam(name: 'CLEAN_BUILD', defaultValue: true, description: 'do a clean build, i.e. remove the yocto directory and start from scratch')
|
|
booleanParam(name: 'DEPLOY_TO_NEXUS', defaultValue: true, description: 'deploy the built artifact to Nexus')
|
|
booleanParam(name: 'SKIP_SSTATE_UPLOAD', defaultValue: false, description: 'skip uploading/synchronizing the sstate-cache to the mirror')
|
|
booleanParam(name: 'DEBUGGING', defaultValue: false, description: 'debugging mode, removes quiet mode for bitbake')
|
|
}
|
|
|
|
options {
|
|
timeout(time: 5, unit: 'HOURS')
|
|
disableConcurrentBuilds()
|
|
buildDiscarder(
|
|
logRotator(numToKeepStr: '20', daysToKeepStr: '7')
|
|
)
|
|
}
|
|
|
|
// ToDo: Remove this statement unless necessary, The cron trigger is set on
|
|
// the job configuration and should be sufficient - untested.
|
|
triggers {
|
|
cron('H H(5-6) * * 1-5')
|
|
}
|
|
|
|
stages {
|
|
|
|
stage('Check Parameters') {
|
|
steps {
|
|
script {
|
|
printJobParameters()
|
|
checkJobParameters(common)
|
|
setDisplayName(common)
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Prepare') {
|
|
steps {
|
|
script {
|
|
if(params.CLEAN_BUILD) {
|
|
println "CLEAN BUILD REQUESTED, cleaning..."
|
|
common.cleaningClonedRepoDir()
|
|
}
|
|
setupEnvironment(common, "${params.BUILD_BRANCH}")
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Update Source Revisions') {
|
|
steps {
|
|
script {
|
|
updateTheSourceRevisions(common, "${env.BRANCH_TO_BUILD}")
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Build All Targets') {
|
|
steps {
|
|
script {
|
|
buildAllTargets(common, "${env.BRANCH_TO_BUILD}")
|
|
}
|
|
}
|
|
}
|
|
|
|
} // stages
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
def printJobParameters() {
|
|
println "----------------------------------\n\
|
|
Job Parameters:\n\
|
|
----------------------------------\n\
|
|
BUILD_BRANCH = ${params.BUILD_BRANCH}\n\
|
|
CLEAN_BUILD = ${params.CLEAN_BUILD}\n\
|
|
DEPLOY_TO_NEXUS = ${params.DEPLOY_TO_NEXUS}\n\
|
|
SKIP_SSTATE_UPLOAD = ${params.SKIP_SSTATE_UPLOAD}\n\
|
|
DEBUGGING = ${params.DEBUGGING}\n\
|
|
----------------------------------\n"
|
|
}
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
def checkJobParameters(commonHelpers) {
|
|
// Check the selected target and overwrite it with a default one when triggered by a timer
|
|
if(commonHelpers.isJobTriggeredByTimer()) {
|
|
println "INFO: Triggered by Timer"
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
def setDisplayName(commonHelpers) {
|
|
def buildName = "#${env.BUILD_NUMBER}"
|
|
def postfix = commonHelpers.isJobTriggeredByTimer() ? "-nightly" : ""
|
|
currentBuild.displayName = "${buildName}${postfix}"
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
def setupEnvironment(commonHelpers, selectedBranch) {
|
|
env.BUILD_JOB = "${env.TARGET_BUILD_JOB}"
|
|
env.SRCREV_JOB = "${env.SRCREV_UPDATE_JOB}"
|
|
env.BRANCH_TO_BUILD = "${selectedBranch}"
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
def runUpdateSrcRevJob(commonHelpers, buildBranch, isCleanRequested, isDryRun) {
|
|
def updateJob = null
|
|
try {
|
|
updateJob = build(job: "${env.SRCREV_JOB}",
|
|
quietPeriod: 0,
|
|
propagate: false,
|
|
wait: true,
|
|
parameters: [string(name: 'BUILD_BRANCH', value: buildBranch),
|
|
booleanParam(name: 'CLEAN_BUILD', value: isCleanRequested),
|
|
booleanParam(name: 'DRY_RUN', value: isDryRun)]
|
|
)
|
|
}
|
|
catch(Exception e) {
|
|
error("Exception: " + e.toString())
|
|
}
|
|
// assert to be sure
|
|
if(updateJob == null) {
|
|
error("Something went really wrong with ${env.SRCREV_JOB}")
|
|
}
|
|
if(updateJob.getResult() != 'SUCCESS') {
|
|
error("Failed to update the source revisions, check the job")
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
def updateTheSourceRevisions(commonHelpers, buildBranch) {
|
|
def branchToBuild = buildBranch
|
|
|
|
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
|
runUpdateSrcRevJob(commonHelpers, buildBranch, true, false)
|
|
copyArtifacts(projectName: "${env.SRCREV_JOB}", target: ".", flatten: true)
|
|
branchToBuild = sh(returnStdout: true, script: "cat ./${env.NIGHTLY_BRANCH_FILE}").trim()
|
|
} // end catchError
|
|
|
|
// update the branch to build if the source revisions are updated
|
|
env.BRANCH_TO_BUILD = "${branchToBuild}"
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
def getTargetsFromList() {
|
|
def theTargets = sh(returnStdout: true, script: "set +x && cat ./jobs/nwlTargets | grep -v select").trim().split("\n")
|
|
return theTargets
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
def isMachineSane(machine) {
|
|
// ToDo: place here any exclusions if necessary
|
|
return true
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
def runBuildJob(commonHelpers, buildTarget, buildBranch) {
|
|
def buildJob = null
|
|
def theBuildResult = 'SUCCESS'
|
|
Boolean hasException = false
|
|
try {
|
|
buildJob = build(job: "${env.BUILD_JOB}",
|
|
quietPeriod: 0,
|
|
propagate: false,
|
|
wait: true,
|
|
parameters: [string(name: 'TARGET', value: buildTarget),
|
|
string(name: 'BUILD_BRANCH', value: buildBranch),
|
|
booleanParam(name: 'CLEAN_BUILD', value: params.CLEAN_BUILD),
|
|
booleanParam(name: 'DEPLOY_TO_NEXUS', value: params.DEPLOY_TO_NEXUS),
|
|
booleanParam(name: 'SKIP_SSTATE_UPLOAD', value: params.SKIP_SSTATE_UPLOAD),
|
|
booleanParam(name: 'FORCE_SRC_REV_UPDATE', value: false),
|
|
booleanParam(name: 'DEBUGGING', value: params.DEBUGGING)]
|
|
)
|
|
}
|
|
catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e) {
|
|
println "job ${env.BUILD_JOB} for TARGET=${buildTarget} was cancelled or aborted"
|
|
theBuildResult = 'ABORTED'
|
|
}
|
|
catch(Exception e) {
|
|
hasException = true
|
|
theBuildResult = 'FAILURE'
|
|
println "Exception caught: " + e.toString()
|
|
}
|
|
finally {
|
|
if(!hasException && (buildJob != null)) {
|
|
theBuildResult = buildJob.getResult()
|
|
}
|
|
return theBuildResult
|
|
}
|
|
// assert to be sure
|
|
if(buildJob == null) {
|
|
error("Something went really wrong with ${env.BUILD_JOB} (TARGET=${buildTarget})")
|
|
}
|
|
return buildJob.getResult()
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
def buildMachine(commonHelpers, machine, buildBranch) {
|
|
Boolean isMachineSuccessfullyBuilt = true
|
|
println "BUILDING ${machine}"
|
|
commonHelpers.setupTimeMeasurement()
|
|
// NOTE: this catchError statement is needed in case of an
|
|
// abort of the build job or similar failures
|
|
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
|
|
def buildJobStatus = runBuildJob(commonHelpers, machine, buildBranch)
|
|
if(buildJobStatus != 'SUCCESS') {
|
|
isMachineSuccessfullyBuilt = false
|
|
if(buildJobStatus == 'ABORTED') {
|
|
currentBuild.result = 'ABORTED'
|
|
}
|
|
}
|
|
}
|
|
if(!isMachineSuccessfullyBuilt) {
|
|
println "Failed building properly machine ${machine}"
|
|
}
|
|
commonHelpers.printMeasuredTimeToNow("building ${machine}")
|
|
return isMachineSuccessfullyBuilt
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
def buildAllTargets(commonHelpers, buildBranch) {
|
|
Boolean areBuildsSuccessful = true
|
|
def firstMachineFailing = ""
|
|
def listOfTargets = getTargetsFromList()
|
|
println "list of all targets = " + listOfTargets
|
|
|
|
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
|
for (machine in listOfTargets) {
|
|
if(!commonHelpers.isCurrentJobAborted() && isMachineSane(machine)) {
|
|
Boolean isMachineSuccess = buildMachine(commonHelpers, machine, buildBranch)
|
|
if(!isMachineSuccess && areBuildsSuccessful) {
|
|
areBuildsSuccessful = false
|
|
firstMachineFailing = machine
|
|
}
|
|
} // end isMachineSane
|
|
} // end for
|
|
|
|
// if there are builds failing, throw error to mark stage and build as FAILURE:
|
|
if(!areBuildsSuccessful) {
|
|
error("Failing build - first machine failing = ${firstMachineFailing}")
|
|
}
|
|
} // end catchError
|
|
} |