Jenkins 多分支管道:构建结束时清理工作区/删除目录



我们使用 Jenkins 多分支(脚本化)管道并行运行多个构建。每个目录都将创建一个新的唯一命名目录来签出代码并运行测试。目录是唯一命名的,因为它们包含分支名称,但也包含随机部分,如"JAA2A5HUZB7TRE4OTVXU7S..."。

这意味着在每次构建之后,X 目录(X = 并行作业数 * 分支数)保留在 Jenkins 节点上,从而填满磁盘空间。

我想知道如何自动删除这些目录。

我的初始管道的简化版本如下所示

// Initialize the matrix
def matrix = [
'foo',
'bar',
]
// Initialize empty tasks map
def tasks = [:]
// Job status
successful = true
// Fill our tasks map from the Matrix data
for (x in matrix) {
def job_name = x
tasks[job_name] = {
node('libvirt') {
// Checkout repository first
stage("$job_name - Checkout") {
checkout scm
}
// Then build the machine
gitlabCommitStatus('build') {
stage("$job_name - Build") {
sh "./bin/build.sh ${job_name}"
}
}
}
}
}
}

//// Pipeline ////
notifyBuild('STARTED')
// Run tasks in parallel
try {
parallel tasks
} catch(e) {
throw e
} finally {
if (successful) {
notifyBuild('SUCCESS')
} else {
notifyBuild('FAILED')
}
}
// Methods
def notifyBuild(String buildStatus = 'STARTED') {
// used to send formatted e-mails 
}

我首先添加了这样的deleteDir()

} finally {
if (successful) {
notifyBuild('SUCCESS')
} else {
notifyBuild('FAILED')
}
node('libvirt') {
deleteDir()
}
}

它会引发错误并使生成失败。

然后我添加了这样的cleanWs()

} finally {
if (successful) {
notifyBuild('SUCCESS')
} else {
notifyBuild('FAILED')
}
node('libvirt') {
cleanWs()
}
}

输出为

Running on node in /srv/jenkins/workspace/pipeline-deletedir-DRD7EKBEMMWJQZW6KKMQVVBTJTPTKLRAE2ITDK7V7IB5PTFXZUZA
[Pipeline] {
[Pipeline] step
[WS-CLEANUP] Deleting project workspace...[WS-CLEANUP] done
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

但是目录/SRV/Jenkins/workspace/pipeline-deletedir-DRD7EKBEMMWJQZW6KKMQVVBTJTPTKLRAE2ITDK7V7IB5PTFXZUZA 仍然存在。

我正在寻找任何解决方案来调整此脚本化管道(如果您知道如何操作,则适用于声明式管道),以便能够删除构建创建的所有目录。

解决方案是在阶段("$job_name - 构建")步骤中添加一个 try/catch/finally ,类似于

gitlabCommitStatus('build') {
stage("$job_name - Build") {
try {
sh "./bin/build.sh ${job_name}"
} catch (Exception e) {
raise e
} finally {
deleteDir()
}
}
}

这不会删除所有涉及的目录(因为这个 Jenkins 问题 https://issues.jenkins-ci.org/browse/JENKINS-41805),但它会删除所有庞大的目录(包含代码/构建/工件......

您需要添加"raise e",否则构建将始终返回成功,即使其中一个失败。

首先,您不能删除仍在运行构建的目录deleteDir()步骤只是删除工作区的内容。

您可以触发在构建完成后运行的作业,该作业会删除这些目录。为此,您可以使用类似pipeline-deletedir-*.

这并不能直接回答您的问题(我个人使用 deleteDir() 并且对我来说它有效),但作为保存磁盘位置的替代方案,您可以考虑丢弃多分支管道中的"旧"构建:

stage ('Remove old builds') {
//keep 10 builds per branch
properties([[$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '10']]]); 
}

我认为最好的方法是在所有阶段之后添加帖子部分:

stages {
stage("$job_name - Build") {
sh "./bin/build.sh ${job_name}"
}
}

post {
always {
echo 'One way or another, I have finished'
deleteDir() /* clean up our workspace */
}
}

最新更新