// 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 // 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: 'DRY_RUN', defaultValue: true, description: 'do a dry run, i.e. without committing and pushing') } options { timeout(time: 1, unit: 'HOURS') buildDiscarder( logRotator(numToKeepStr: '10') ) } stages { stage('Prepare') { steps { script { printJobParameters() setDisplayName() // load common file common = load "./jobs/Jenkinsfile_Common" handleCleanBuild(common) common.gitCheckout("${env.YOCTO_REPO_URL}", "${params.BUILD_BRANCH}", "${env.YOCTO_REPO_DIR}", true, false) } } } stage('Update') { steps { script { updateTheSourceRevisions(common, "${env.YOCTO_REPO_DIR}", "${params.BUILD_BRANCH}") commitAndPushTheChanges(common, "${env.YOCTO_REPO_DIR}", "${params.BUILD_BRANCH}") } } post { always { script { common.cleanupRepository("${env.YOCTO_REPO_DIR}") } } } } } // stages } //----------------------------------------------------------------------------- def printJobParameters() { println "----------------------------------\n\ Job Parameters:\n\ ----------------------------------\n\ BUILD_BRANCH = ${params.BUILD_BRANCH}\n\ CLEAN_BUILD = ${params.CLEAN_BUILD}\n\ DRY_RUN = ${params.DRY_RUN}\n\ ----------------------------------\n" } //--------------------------------------------------------------------------------------------------------------------- def setDisplayName() { def buildName = "#${env.BUILD_NUMBER}" def theBranch = "${params.BUILD_BRANCH}" def cleaning = ("${params.CLEAN_BUILD}" == true) ? "-clean" : "" currentBuild.displayName = "${buildName}-${theBranch}${cleaning}" } //--------------------------------------------------------------------------------------------------------------------- def handleCleanBuild(commonHelpers) { if(params.CLEAN_BUILD) { println "CLEAN BUILD REQUESTED, cleaning..." commonHelpers.cleaningClonedRepoDir() } } //--------------------------------------------------------------------------------------------------------------------- def updateTheSourceRevisions(commonHelpers, repoDir, theBranch) { dir(repoDir) { commonHelpers.gitUpdateSubmodulesCheckoutBranch(theBranch, true, true) commonHelpers.printSubmoduleStatus(true) } } //--------------------------------------------------------------------------------------------------------------------- def createPR(theBranch) { def prReviewer = "bard" def prProject = "NM-NSP" def prRepo = "netmodule-wireless-linux" def bitbucketRestApiUrl = "https://bitbucket.gad.local/rest/api/1.0" def prTitle = "Nightly: Src Rev Update" def prDescription = "CI is updating the source revisions to HEAD" def prRepository = "\"repository\": {\"slug\": \"${prRepo}\", \"name\": null, \"project\": {\"key\": \"${prProject}\"}}" def prDataJson = "{\"title\": \"${prTitle}\", \"description\": \"${prDescription}\",\ \"state\": \"OPEN\", \"open\": true, \"closed\": false,\ \"fromRef\": {\"id\": \"refs/heads/${theBranch}\", ${prRepository}},\ \"toRef\": {\"id\": \"refs/heads/main\", ${prRepository}},\ \"locked\": false,\ \"reviewers\": [{\"user\": {\"name\": \"${prReviewer}\"}}], \"links\": {\"self\": [null]}}" def prUrl = "${bitbucketRestApiUrl}/projects/${prProject}/repos/${prRepo}/pull-requests" def authHeader = "Authorization: Bearer MDI1NjczNzAyMTI3OrbDBQestfmsi/Iys5qvKP4Tgulp" def acceptHeader = "Accept: application/json" def contentHeader = "Content-Type: application/json" def prResponse = sh(returnStdout: true, script: "curl --request POST --url '${prUrl}' \ --header '${authHeader}' \ --header '${acceptHeader}' \ --header '${contentHeader}' \ --data '${prDataJson}'").toString() if(prResponse.contains("error")) { error("Failed creating PR/MR:\n${prResponse}") } } //--------------------------------------------------------------------------------------------------------------------- def commitAndPushTheChanges(commonHelpers, repoDir, origBranch) { def commitMsg = "srcrev: updated source revisions by Jenkins Job" def nightlyBranch = "nightly" def usedBranch = "${origBranch}" def branchFile = "${env.NIGHTLY_BRANCH_FILE}" dir(repoDir) { if(sh(returnStdout: true, script: "git status | grep \"modified:\" | wc -l").toInteger() != 0) { def changedItems = sh(returnStdout: true, script: "git status") sh(label: "Stage tracked and changed git files", returnStdout: true, script: "git add \\*") if(params.DRY_RUN) { println "DRY RUN: commit message = '${commitMsg}'\n changes = ${changedItems}" sh(script: "git reset HEAD > /dev/null") } else { def theCredentials = commonHelpers.getGitCredentialID() println "Commit and Push changes; message = '${commitMsg}'\nchanges = ${changedItems}" sshagent (credentials: [theCredentials]) { // ToDo: replace the user.email and user.name once a CI user is setup in the // active directory. sh(label: "Commit and push changes", returnStdout: true, script: """ git config --global user.email "marc.mattmueller@netmodule.com" git config --global user.name "Marc Mattm\u00fcller" git checkout -B ${nightlyBranch} git commit -m "${commitMsg}" git push --force --set-upstream origin ${nightlyBranch} """) } usedBranch = "${nightlyBranch}" createPR("${nightlyBranch}") } } // if changes available } writeFile(file: branchFile, text: "${usedBranch}") archiveArtifacts(artifacts: branchFile, onlyIfSuccessful: true) }