如果标记为“永远保留此构建”,则不要删除Jenkins构建 - 用于删除Jenkins构建的Groovy脚本

时间:2013-09-23 19:16:28

标签: groovy jenkins build forever

我有以下Groovy脚本,它删除给定Jenkins作业的所有构建,除了用户提供的一个构建号(即想要保留)。

/*** BEGIN META {
  "name" : "Bulk Delete Builds except the given build number",
  "comment" : "For a given job and a given build number, delete all build except the user provided one.",
  "parameters" : [ 'jobName', 'buildNumber' ],
  "core": "1.409",
  "authors" : [
     { name : "Arun Sangal" }
  ]
} END META **/


// NOTE: Uncomment parameters below if not using Scriptler >= 2.0, or if you're just pasting the script in manually.
// ----- Logic in this script takes 5000 as the infinite number, decrease / increase this value from your own experience.
// The name of the job.
//def jobName = "some-job"

// The range of build numbers to delete.
//def buildNumber = "5"

def lastBuildNumber = buildNumber.toInteger() - 1;
def nextBuildNumber = buildNumber.toInteger() + 1;


import jenkins.model.*;
import hudson.model.Fingerprint.RangeSet;

def jij = jenkins.model.Jenkins.instance.getItem(jobName);

println("Keeping Job_Name: ${jobName} and build Number: ${buildNumber}");
println ""

def setBuildRange = "1-${lastBuildNumber}"
def range = RangeSet.fromString(setBuildRange, true);
jij.getBuilds(range).each { it.delete() }
println("Builds have been deleted - Range: " + setBuildRange)

setBuildRange = "${nextBuildNumber}-5000"
range = RangeSet.fromString(setBuildRange, true);
jij.getBuilds(range).each { it.delete() }
println("Builds have been deleted - Range: " + setBuildRange)

这适用于任何Jenkins工作。例如:如果您的Jenkins作业名称是“TestJob”并且您有15个构建,即构建#1以在Jenkins中构建15,并且您想要删除所有但保留构建#13,则此脚本将删除构建(构建#1) -12和14-15 - 即使你将任何构建标记为“永远保持这个构建”)并且只保留构建#13。


现在,我想要的是:

  1. 我应该在此脚本中更改为不删除构建 - 如果构建在Jenkins中标记为“永远保留此构建”。我尝试了脚本并将其删除,以便永远保持构建。

  2. 让我们说,如果我在Jenkins中使用“Build name setter plugin”,它可以给我构建名称作为我想要的名称,而不是仅仅构建为构建#1或#2,或者# 15,我将构建为构建#2.75.0.1,2.75.0.2,2.75.0.3,.....,2.75.0.15(因为我将构建名称/描述设置为使用包含2.75.0的变量(作为发布版本值)并以实际Jenkins作业的内部编号为后缀,即最后的第4位 - 例如:将名称设置为:

    ${ENV,var="somepropertyvariable"}.${BUILD_NUMBER}
    

    在这种情况下,我将开始将Jenkins构建为2.75.0.1到2.75.0.x(其中x是该版本的最后构建#(2.75.0))。类似地,当我将属性发布版本更改为下一个版本2.75.1或2.76.0时,相同的Jenkins作业将开始给我构建为2.75.1.0,2.75.1.1,....,2.75.1。 x或2.76.0.1,2.76.0.2,....,2.76.0.x等。在发布版本更改期间,假设我们的构建将从1开始(正如我上面提到的2.75.1和2.76.0发行版本)。

    在这种情况下,如果我的Jenkins作业的构建历史记录(显示2.75.0.x,2.75.1.x和2.76.0.x的所有构建版本),那么我应该在此脚本中进行哪些更改以包含第3个参数/参数。第3个参数将采用发布/版本值,即2.75.0或2.75.1或2.76.0,然后此脚本应仅删除该版本上的内部版本号(并且不应删除其他版本的版本)。

3 个答案:

答案 0 :(得分:1)

如果要测试构建是否已标记为永久构建,请使用

if (!build.isKeepLog()) {
    // Build can be deleted
} else {
    // Build is marked permanent
}

我认为您应该能够在每个构建中使用getName() method来检查是否应该删除给定的构建。 API JavaDoc可能相当模糊,因此我经常继续GitHub并查看Jenkins插件的代码,该插件执行类似于我需要的操作。 public Scriptler repository也很有用。

答案 1 :(得分:1)

最终答案:这包括使用Artifactor的REST API调用从Artifactory中删除构建工件。此脚本将删除给定版本/版本的Jenkins / Artifactory构建/工件(有时候会有一段时间 - 给定的Jenkins作业可以为ex:2.75.0.1,2.75.0.2,2.75.0.3创建多个版本/版本构建。 ......,2.75.0.54,2.76.0.1,2.76.0.2,......,2.76.0.16,2.76.1.1,2.76.1.2,......,2.76.1.5)。在这种情况下,对于该作业的每个新版本,我们从1新开始构建#。如果必须删除除一个/甚至所有版本之外的所有版本(根据自己的需要更改脚本)并且不要更改旧版本/其他版本,请使用以下脚本。

Scriptler目录链接http://scriptlerweb.appspot.com/script/show/103001

享受!

/*** BEGIN META {
  "name" : "Bulk Delete Builds except the given build number",
  "comment" : "For a given job and a given build numnber, delete all builds of a given release version (M.m.interim) only and except the user provided one. Sometimes a Jenkins job use Build Name setter plugin and same job generates 2.75.0.1 and 2.76.0.43",
  "parameters" : [ 'jobName', 'releaseVersion', 'buildNumber' ],
  "core": "1.409",
  "authors" : [
     { name : "Arun Sangal - Maddys Version" }
  ]
} END META **/

import groovy.json.*
import jenkins.model.*;
import hudson.model.Fingerprint.RangeSet;
import hudson.model.Job;
import hudson.model.Fingerprint;

//these should be passed in as arguments to the script
if(!artifactoryURL) throw new Exception("artifactoryURL not provided")
if(!artifactoryUser) throw new Exception("artifactoryUser not provided")
if(!artifactoryPassword) throw new Exception("artifactoryPassword not provided")
def authString = "${artifactoryUser}:${artifactoryPassword}".getBytes().encodeBase64().toString()
def artifactorySettings = [artifactoryURL: artifactoryURL, authString: authString]

if(!jobName) throw new Exception("jobName not provided")
if(!buildNumber) throw new Exception("buildNumber not provided")

def lastBuildNumber = buildNumber.toInteger() - 1;
def nextBuildNumber = buildNumber.toInteger() + 1;

def jij = jenkins.model.Jenkins.instance.getItem(jobName);

def promotedBuildRange = new Fingerprint.RangeSet()
promotedBuildRange.add(buildNumber.toInteger())
def promoteBuildsList = jij.getBuilds(promotedBuildRange)
assert promoteBuildsList.size() == 1
def promotedBuild = promoteBuildsList[0]
// The release / version of a Jenkins job - i.e. in case you use "Build name" setter plugin in Jenkins for getting builds like 2.75.0.1, 2.75.0.2, .. , 2.75.0.15 etc.
// and over the time, change the release/version value (2.75.0) to a newer value i.e. 2.75.1 or 2.76.0 and start builds of this new release/version from #1 onwards.
def releaseVersion = promotedBuild.getDisplayName().split("\\.")[0..2].join(".")

println ""
println("- Jenkins Job_Name: ${jobName} -- Version: ${releaseVersion} -- Keep Build Number: ${buildNumber}");
println ""

/** delete the indicated build and its artifacts from artifactory */
def deleteBuildFromArtifactory(String jobName, int deleteBuildNumber, Map<String, String> artifactorySettings){
    println "     ## Deleting >>>>>>>>>: - ${jobName}:${deleteBuildNumber} from artifactory"
                                def artifactSearchUri = "api/build/${jobName}?buildNumbers=${deleteBuildNumber}&artifacts=1"
                                def conn = "${artifactorySettings['artifactoryURL']}/${artifactSearchUri}".toURL().openConnection()
                                conn.setRequestProperty("Authorization", "Basic " + artifactorySettings['authString']);
                                conn.setRequestMethod("DELETE")
    if( conn.responseCode != 200 ) {
        println "Failed to delete the build artifacts from artifactory for ${jobName}/${deleteBuildNumber}: ${conn.responseCode} - ${conn.responseMessage}"
    }
}

/** delete all builds in the indicated range that match the releaseVersion */
def deleteBuildsInRange(String buildRange, String releaseVersion, Job theJob, Map<String, String> artifactorySettings){
    def range = RangeSet.fromString(buildRange, true);
    theJob.getBuilds(range).each {
        if ( it.getDisplayName().find(/${releaseVersion}.*/)) {
            println "     ## Deleting >>>>>>>>>: " + it.getDisplayName();
            deleteBuildFromArtifactory(theJob.name, it.number, artifactorySettings)
            it.delete();
        }
    }
}

//delete all the matching builds before the promoted build number
deleteBuildsInRange("1-${lastBuildNumber}", releaseVersion, jij, artifactorySettings)

//delete all the matching builds after the promoted build number
deleteBuildsInRange("${nextBuildNumber}-${jij.nextBuildNumber}", releaseVersion, jij, artifactorySettings)

println ""
println("- Builds have been successfully deleted for the above mentioned release: ${releaseVersion}")
println ""

答案 2 :(得分:0)

好的 - 问题2的解决方案就在这里:我还在努力解决问题1。

http://scriptlerweb.appspot.com/script/show/102001

<强> bulkDeleteJenkinsBuildsExceptOne_OfAGivenRelease.groovy

/*** BEGIN META {
  "name" : "Bulk Delete Builds except the given build number",
  "comment" : "For a given job and a given build numnber, delete all builds of a given release version (M.m.interim) only and except the user provided one. Sometimes a Jenkins job use Build Name setter plugin and same job generates 2.75.0.1 and 2.76.0.43",
  "parameters" : [ 'jobName', 'releaseVersion', 'buildNumber' ],
  "core": "1.409",
  "authors" : [
     { name : "Arun Sangal" }
  ]
} END META **/


// NOTE: Uncomment parameters below if not using Scriptler >= 2.0, or if you're just pasting the script in manually.
// ----- Logic in this script takes 5000 as the infinite number, decrease / increase this value from your own experience.
// The name of the job.
//def jobName = "some-job"

// The release / version of a Jenkins job - i.e. in case you use "Build name" setter plugin in Jenkins for getting builds like 2.75.0.1, 2.75.0.2, .. , 2.75.0.15 etc.
// and over the time, change the release/version value (2.75.0) to a newer value i.e. 2.75.1 or 2.76.0 and start builds of this new release/version from #1 onwards.
//def releaseVersion = "2.75.0"

// The range of build numbers to delete.
//def buildNumber = "5"

def lastBuildNumber = buildNumber.toInteger() - 1;
def nextBuildNumber = buildNumber.toInteger() + 1;


import jenkins.model.*;
import hudson.model.Fingerprint.RangeSet;

def jij = jenkins.model.Jenkins.instance.getItem(jobName);
//def build = jij.getLastBuild();

println ""
println("- Jenkins Job_Name: ${jobName} -- Version: ${releaseVersion} -- Keep Build Number: ${buildNumber}");
println ""
println "  -- Range before given build number: ${buildNumber}"
println ""

def setBuildRange = "1-${lastBuildNumber}"
def range = RangeSet.fromString(setBuildRange, true);
jij.getBuilds(range).each {
  if ( it.getDisplayName().find(/${releaseVersion}.*/)) {
     println "     ## Deleting >>>>>>>>>: " + it.getDisplayName();

     // Trying to find - how to NOT delete a build in Jenkins if it's marked as "keep this build forever". If someone has an idea, please update this script with a newer version in GitHub.
     //if ( !build.isKeepLog()) {
          it.delete();
     //} else {
     //   println "build -- can't be deleted as :" + build.getWhyKeepLog();
     //}
  }
}



println ""
println "  -- Range after  given build number: ${buildNumber}"
println ""
setBuildRange = "${nextBuildNumber}-5000"
range = RangeSet.fromString(setBuildRange, true);
jij.getBuilds(range).each {
  if ( it.getDisplayName().find(/${releaseVersion}.*/)) {
     println "     ## Deleting >>>>>>>>>: " + it.getDisplayName();
     it.delete();
  }
}

println ""
println("- Builds have been successfully deleted for the above mentioned release: ${releaseVersion}")
println ""

enter image description here

也可以通过Jenkins作业调用此脚本(需要脚本编写器脚本中提到的3个参数) - 或者也可以从浏览器调用它:使用以下链接:

http:// YourJenkinsServerName:PORT / job / Some_Jenkins_Job_That_You_Will_Create / buildWithParameters?jobName = Test_AppSvc&amp; releaseVersion = 2.75.0&amp; buildNumber = 15