是否有任何方法可以通过Jenkins脚本控制台使用groovy脚本清理Jenkins Worflowjob工作区?

时间:2019-04-03 12:17:44

标签: groovy jenkins-pipeline jenkins-plugins jenkins-job-dsl jenkins-groovy

为什么又要问这种类型的问题?

这个问题似乎已经被问过多次了,但是所有答案对于Jenkins Pipeline作业都是无关紧要的(插件:workflow-job)。

情况

我要将一堆旧的自由式作业从旧的Jenkins独立服务器迁移到分布式Jenkins env,我决定将它们转换为Jenkins Pipeline作业(不能将Blue ocean用作SCM is SVN

无论如何,对于某些作业来说,清理它们的工作空间是不理想的,因为它们属于健全性/验证作业,并且由于SVN检出和已构建的东西很大(2万个文件中有2GB,只需删除它就可以了)慢)。

但是,我偶尔(临时)需要删除此类作业的工作区。 而且我不想这样做:

而且我没有读写该从属节点上的FS的权限(这是最简单的操作)。

谷歌搜索

在互联网上快速搜索使我产生了数十种结果[1234,...]如何从内部清理WS()从Jenkins脚本控制台运行了Groovy脚本。

不幸的是,它们都没有尝试删除作业的真实org.jenkinsci.plugins.workflow.job.WorkflowJob项目实例的工作空间。

我的Groovy尝试清理WS

基于从互联网上收集到的答案,我启动了Groovy清理脚本,该脚本可以从Jenkins script console <Jenkins:port/script>

执行
import hudson.model.*
import com.cloudbees.hudson.*
import com.cloudbees.hudson.plugins.*
import com.cloudbees.hudson.plugins.folder.*
import org.jenkinsci.plugins.workflow.job.*

//jobsToRetrieve = ["aFolder/aJobInFolder","topLevelJob"]
jobsToRetrieve = ["Sandbox/PipelineTests/SamplePipeline"]

enumerateItems(Hudson.instance.items)

def enumerateItems(items) {
  items.each { item ->
    println("===============::: GENERAL INFO::: =======================")
    println(" item: " + item)
    println(" item FN:  " + item.fullName)
    println(" item.getClass " + item.getClass())
    println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

    if ( !(item instanceof Folder)) {
      jobName = item.getFullDisplayName()
      println(" :::jobname::: " + jobName)
      if (jobsToRetrieve.contains(item.getFullName())) {
        if (item instanceof WorkflowJob) {
          println("XXXXXXXXXXXXX--- THIS IS THE JOB --- XXXXXXXXXXXXXXXXXXXXX")
          println(" item.workspace: " + item.WORKSPACE)
          println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
          println(" following methods ain't implemented for WorkflowJob type of Item\nand it will blow out.")
          //see https://javadoc.jenkins.io/hudson/model/FreeStyleProject.html
          println(" customWS: " + item.getCustomWorkspace())
          println(" WS:" + item.getWorkspace())
          item.doDoWipeOutWorkspace()
        }
      }
    } else {
        println(" :::foldername::: " + item.displayName)
        enumerateItems(((Folder) item).getItems())
    }
    println("==========================================================")
  }
}

结果(有点希望,但令人失望)

如您所见,我的脚本会因以下调用而爆炸:

item.getCustomWorkspace()
item.getWorkspace()
item.doDoWipeOutWorkspace()

MissingMethodException

groovy.lang.MissingMethodException: No signature of method: org.jenkinsci.plugins.workflow.job.WorkflowJob.doDoWipeOutWorkspace() is applicable for argument types: () values: []
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
    at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:49)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
    at Script1$_enumerateItems_closure1.doCall(Script1.groovy:33)

仅因为这些方法不适用于此类商品,而仅适用于hudson.model.FreeStyleProject

问题:那我该如何删除管道作业的工作空间?

还有另外一个Jenkins plugin: Workspace Cleanup,可能是通过在cleanWs()内调用stage() {}在Jenkinsfile中使用的,但是我不知道如何从Jenkinsfile的外部使用它(例如从我的groovy脚本运行Jenkins脚本控制台)。

是增强Jenkins Pipeline作业插件的错误/要求吗? 还是有其他方法可以将项目投射到可以访问所需功能的位置?

2 个答案:

答案 0 :(得分:2)

这不是最漂亮的方法,但是您可以执行OS命令:

def isWin = Jenkins.instance.windows
def cmd = isWin ? "rmdir /s /q $workspace" : "rm -rf $workspace"

cmd.execute()

如果您只使用一次代码或不使用多个操作系统,则可以将代码缩短为相应的命令:

"rm -rf $workspace".execute()

答案 1 :(得分:0)

好的,对此进行更多的调查并进行更多的谷歌搜索,并听听您的想法(one受到 Daniel Spilker 的特别启发,我)达到了我想要的目标, >

通过Jenkins脚本控制台独立于CLEAN-UP Pipeline Job的WORKSPACE

(仅使用Jenkins可用的方式,不会弄乱Job的配置,不会更新Jenkinsfile,也不会重播)

代码并不出奇的困难,对于手动演示,它看起来像这样:

Jenkins jenkins = Jenkins.instance
Job item = jenkins.getItemByFullName('Sandbox/PipelineTests/SamplePipeline')
println("RootDir: " + item.getRootDir())

for (Node node in jenkins.nodes) {
  // Make sure slave is online
  if (!node.toComputer().online) {
    println "Node '$node.nodeName' is currently offline - skipping workspace cleanup"
    continue
  }

  println "Node '$node.nodeName' is online - performing cleanup:"

  // Do some cleanup
  FilePath wrksp = node.getWorkspaceFor(item)
  println("WRKSP "  + wrksp)
  println("ls " + wrksp.list())
  println("Free space " + wrksp.getFreeDiskSpace())
  println("===== PERFORMING CLEAN UP!!! =====")
  wrksp.deleteContents()
  println("ls now " + wrksp.list())
  println("Free space now " + wrksp.getFreeDiskSpace())
}

如果找到您的工作,其输出如下:

结果

RootDir: /var/lib/jenkins/jobs/Sandbox/jobs/PipelineTests/jobs/SamplePipeline
....
.... other node's output noise
....
Node 'mcs-ubuntu-chch' is online - performing cleanup:
WRKSP /var/lib/jenkins/workspace/Sandbox/PipelineTests/SamplePipeline
ls [/var/lib/jenkins/workspace/Sandbox/PipelineTests/SamplePipeline/README.md, /var/lib/jenkins/workspace/Sandbox/PipelineTests/SamplePipeline/.git]
Free space 3494574714880
===== PERFORMING CLEAN UP!!! =====
ls now []
Free space now 3494574919680

任务完成:)

参考文献

主要是Jenkins javadoc