当前位置: 首页 > 知识库问答 >
问题:

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

澹台华翰
2023-03-14

我们使用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仍然存在。

我正在寻找任何解决方案来调整这个脚本化管道(以及声明性管道,如果您知道怎么做的话),以便能够删除由构建创建的所有目录。

共有3个答案

宗翔宇
2023-03-14

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

    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 */
         }
    }
庄飞
2023-03-14

解决方案是在stage($job\u name-Build)步骤中添加try/catch/finally,如

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

这并没有删除所有涉及的目录(因为詹金斯问题https://issues.jenkins-ci.org/browse/JENKINS-41805),但它删除了所有大量的目录(包含代码/构建/工件...)。

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

钱飞翼
2023-03-14

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

您可以触发在生成完成后运行的作业,该作业将删除这些目录。为此,可以使用类似于pipeline deletedir-*的模式。

 类似资料:
  • 我遇到了JENKINS-38706。由于它已经开放了一段时间,我正在努力解决这个问题。 我的问题是我正在运行一个多节点管道,其中一个节点是Windows从节点,具有255个字符路径限制。 因此,我正在尝试更改我的Windows从属阶段的工作区,而不是使用多分支管道使用的C:\jenkins\workspace\job-分支-随机字符,我正在尝试将其移动到c:\w\Jobs\分支。 它立即失效: 我

  • 问题内容: 我们正在运行Jenkins 2.x,并且喜欢新的Pipeline插件。但是,由于存储库中有如此多的分支,因此磁盘空间会迅速填满。 是否有任何与Pipeline兼容的插件,我可以在成功构建后清除工作空间? 问题答案: 您可以将其用作管道Jenkinsfile的最后一步(假设您没有更改工作目录)。

  • 摘要:当使用并行构建时,Groovy中的工作区路径与shell不同。如何从DSL或Groovy获取实际工作区? 细节: 我们的工作区是通过定义的。 我试图使用一个相对路径,简单地,在当前目录中打开该文件,该目录通常是工作区根目录。当运行为shell,它工作正常,我可以阅读没有任何问题。 但是使用Groovy: 请注意然后它将无法声明

  • 我们正在运行詹金斯2。x和爱的新管道插件。但是,由于存储库中有这么多分支,磁盘空间很快就会填满。 是否有任何与管道兼容的插件,我可以在成功构建时清除工作区?

  • 对于一个新项目,我想使用Jenkins CI的新管道功能。我们的Git存储库中有几个分支,应该以同样的方式进行测试。它还应该自动跟踪和处理新的分支。因此,我创建了一个多分支管道作业。但它的配置有两个问题: 1) 为了被Jenkins标记为有效,分行需要一个“Jenkinsfile”。如果这不存在,詹金斯将忽略该分支。有没有办法标记与模式匹配的所有分支,而不需要在其中包含此文件? 2) 每个分支都应

  • 我不确定我问这个问题的方式是否正确。当我触发多分支管道作业并在Jenkinsfile中执行“checkout scm”时,它是签出pull请求还是主pull请求?