在Jenkins Pipeline中獲取自上次成功構建后的文件變更
背景
最近調整了一下項目的流水線,希望可以根據代碼文件的變更自動識別修改的模塊,從而進行相應服務的構建打包部署,簡單記錄一下。
具體實現
我們的項目是基于Maven多模塊的,隨著業務的發展,微服務模塊的數量也從幾個擴展到了十幾個,以前無腦構建所有服務的情況可能效率就會非常低了,所以需要獲取文件變更動態構建修改的微服務模塊。
一開始,我使用的是Git命令,獲取上次成功構建的GIT_COMMIT,然后進行比較獲取對應的文件變更,但是這種情況對于Merge Request的場景好像不適用,因為原分支多次push之后再MR,Git命令也就只能獲取最后的一次提交,之前的變更就撈不到,所以結果不是很準確。當然肯定有其他Git命令可以實現,我對于Git本身也不是那么熟練,后面就嘗試去找其他的方式。我這邊也貼一下具體的Pipeline腳本
pipeline {agent anyenvironment {// 定義其他環境變量}stages {stage('Detect Changes') {steps {script {// 獲取上次成功構建的GIT_COMMIT,這里假設你的Jenkins配置了Gitdef lastSuccessfulCommit = sh(script: "git rev-parse HEAD^1",returnStdout: true).trim()// 獲取自上次成功構建以來發生變動的文件列表def changedFiles = sh(script: "git diff --name-only $lastSuccessfulCommit HEAD",returnStdout: true).trim()// 解析文件路徑,決定需要構建的模塊def buildModules = []if (changedFiles.contains("module1")) {buildModules += 'module1'}if (changedFiles.contains("module2")) {buildModules += 'module2'}// 將需要構建的模塊列表存儲在環境變量中以便后續使用env.BUILD_MODULES = buildModules.join(',')echo "Modules to be built: ${env.BUILD_MODULES}"}}}// 其他階段stage('Build Modules') {when {expression {return env.BUILD_MODULES.contains('module1')}}steps {echo 'Building module1...'}}// 定義其他模塊的構建階段}
}
后面去Google搜索了一下其他人的做法,發現Jenkins本身是支持獲取上一次的變更文件列表的,參考了stackoverflow上面的寫法,具體實現如下
pipeline {agent anyenvironment {// 定義其他環境變量}stages {stage('Detect Changes') {steps {script {def changedFiles = "Changes:\n"build = currentBuildwhile(build != null && build.result != 'SUCCESS') {changedFiles += "In ${build.id}:\n"for (changeLog in build.changeSets) {for(entry in changeLog.items) {for(file in entry.affectedFiles) {changedFiles += "* ${file.path}\n"}}}build = build.previousBuild}echo changedFiles// 解析文件路徑,決定需要構建的模塊def buildModules = []if (changedFiles.contains("module1")) {buildModules += 'module1'}if (changedFiles.contains("module2")) {buildModules += 'module2'}// 將需要構建的模塊列表存儲在環境變量中以便后續使用env.BUILD_MODULES = buildModules.join(',')echo "Modules to be built: ${env.BUILD_MODULES}"}}}// 其他階段stage('Build Modules') {when {expression {return env.BUILD_MODULES.contains('module1')}}steps {echo 'Building module1...'}}// 定義其他模塊的構建階段}
}
參考
https://stackoverflow.com/questions/38084806/how-to-get-the-changes-since-the-last-successful-build-in-jenkins-pipeline