首页 > 解决方案 > 作业中的批量更新参数

问题描述

我们有很多作业都基于构建参数值执行 SCM 签出:比如REPO_URL=ssh://url。随着时间的推移,这些参数的名称和值累积了微小的差异:REPOURLrepo_url=ssh://url/=ssh://url:port等。

我们需要将它们简化为具有单个参数名称和单个值的公分母。我们如何批量更新 50 多个作业中的参数?

标签: jenkinsjenkins-groovy

解决方案


使用Jenkins 脚本控制台

注意:这些本质上是破坏性操作,因此请确保在生产中运行之前在一些备用作业上测试了您的代码!!!

更改参数的默认值

Jenkins.instance.getAllItems(Job)
// filter jobs by name if needed
.findAll { it.fullName.startsWith('sandbox/tmp-magic') }
.each {
  it
  .getProperty(ParametersDefinitionProperty)
  .getParameterDefinition('MAGIC_PARAMETER')
  // `each` ensures nothing happens if `get` returns null; also see paragraph below
  .each {
    it.defaultValue = 'shmagic'
  }
  // the job has changed, but next config reload (f.x. at restart) will overwrite our changes
  // so we need to save job config to its config.xml file
  it.save()
}

而不是.getParameterDefinition('MAGIC_PARAMETER')你可以使用

.parameterDefinitions
.findAll { it.name == 'MAGIC_PARAMETER' }

,findAll如果您需要 fx 更改具有不同名称的多个参数的值,则更改谓词 - 然后您通过each{}.

更改参数名称(和值)

这有点棘手,因为显然您不能编辑 的名称ParameterDefinition,只能替换列表中的一个。

Jenkins.instance.getAllItems(Job)
.findAll { it.fullName.startsWith('sandbox/tmp-magic') }
.each {
  def parameters = it.getProperty(ParametersDefinitionProperty).parameterDefinitions
  def oldParameter = parameters.find { it.name == 'FOO' }
  // avoid changing jobs without this parameter
  if (!oldParameter)
    return
  def idx = parameters.indexOf(oldParameter)
  // preserve original value if necessary
  def oldValue = oldParameter.defaultValue
  parameters[idx] = new StringParameterDefinition('GOOD_FOO', oldValue)
  it.save()
}

加分:在 Freestyle 和 Pipeline From SCM 作业中替换 SCM 步骤的值

我们的一些工作使用 MercurialSCM 插件,一些使用 MultiSCM 插件来检查多个 repos,所以这就是我测试它的方式。

import hudson.plugins.mercurial.MercurialSCM
import org.jenkinsci.plugins.multiplescms.MultiSCM
import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition
import org.jenkinsci.plugins.workflow.job.WorkflowJob

Jenkins.instance.getAllItems(Job)
.findAll { it.fullName.startsWith('sandbox/tmp-magic') }
.each {
  print "Checking $it ... "
  if (it.class == FreeStyleProject && it.scm) {
    println "Freestyle"
    it.scm = replaceWhateverScm(it.scm)
    it.save()
  } else if (it.class == WorkflowJob) {
    print "Pipeline ... "
    def flow = it.definition
    if (flow.class == CpsScmFlowDefinition) {
      println "ScmFlow"
      def scm = replaceWhateverScm(flow.scm)
      def newFlow = new CpsScmFlowDefinition(scm, flow.scriptPath)
      newFlow.lightweight = flow.lightweight
      it.definition = newFlow
      it.save()
    } else
      println "unsupported definition"
  } else
    println "unsupported job"
}

def replaceWhateverScm(scm) {
  if (scm.class == MercurialSCM) {
    println "replacing MercurialSCM"
    return replaceMercurialSource(scm)
  }
  if (scm.class == MultiSCM) {
    println "replacing MultiSCM"
    // cannot replace part of MultiSCM, replace whole scm instead
    return new MultiSCM(
      scm.configuredSCMs
      .collect { (it.class == MercurialSCM) ? replaceMercurialSource(it) : it }
    )
  }
  throw new Exception("unknown class ${scm.class}")
}

def replaceMercurialSource(MercurialSCM original) {
  if (!original.source.toLowerCase().contains('repo_url'))
    return original
  def s = new MercurialSCM('<new_url>')
  for (v in ["browser","clean","credentialsId","disableChangeLog","installation","modules","revision","revisionType","subdir",]) {
    s."$v" = original."$v"
  }
  return s
}```

推荐阅读