Не удаляйте сборку Jenkins, если она помечена как Сохранить эту сборку навсегда — скрипт Groovy для удаления сборок Jenkins

У меня есть следующий сценарий 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 называется «TestJob», и у вас есть 15 сборок, т.е. сборка № 1 до сборки 15 в Jenkins, и вы хотите удалить все, кроме сборки № 13, тогда этот скрипт удалит сборки (сборка № 1). -12 и 14-15 - даже если вы пометите любую сборку как "Сохранить эту сборку навсегда") и сохраните только сборку №13.


Теперь я хочу:

  1. что я должен изменить в этом скрипте, чтобы не удалять сборку - если сборка помечена в Jenkins как «Сохранить эту сборку навсегда». Я попробовал скрипт, и он также удалил эту сборку навсегда.

  2. Допустим, если я использую «Плагин установки имени сборки» в Jenkins, который может дать мне имена сборок в виде того имени, которое я хочу, то есть вместо того, чтобы просто собирать сборку № 1, № 2 или № 15, я получу сборку как build# 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. х или 2.76.0.1, 2.76.0.2, ...., 2.76.0.х и так далее. При смене релизной версии, скажем, наша сборка снова начнется с 1 (как я упоминал выше для релизных версий 2.75.1 и 2.76.0).

    В этом случае, если история сборки моего задания Jenkins (показывает все сборки для 2.75.0.x, 2.75.1.x и 2.76.0.x), то какое изменение я должен внести в этот скрипт, чтобы включить третий параметр/аргумент . Этот третий аргумент будет принимать значение выпуска/версии, то есть либо 2.75.0, либо 2.75.1, либо 2.76.0, а затем этот скрипт должен удалять номера сборки только в этом выпуске (и НЕ ДОЛЖЕН удалять сборки других выпусков).


person AKS    schedule 23.09.2013    source источник


Ответы (3)


Если вы хотите проверить, отмечена ли сборка как постоянная, используйте

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

Я думаю, вы должны иметь возможность использовать метод getName() для каждой сборки, чтобы проверить, следует ли удалять данную сборку. API JavaDoc может быть довольно неясным, поэтому я часто захожу на GitHub и просматриваю код подключаемого модуля Jenkins, который выполняет что-то похожее на то, что мне нужно. Также может быть полезен общедоступный репозиторий Scriptler.

person gareth_bowles    schedule 23.09.2013
comment
Откуда я беру эту сборку (в build.isKeepLog), спасибо - person AKS; 24.09.2013
comment
сборка = jij.getLastBuild(); if ( !build.isKeepLog()) возвращает false в обоих случаях — либо если сборка помечена как хранимая навсегда, либо нет. - person AKS; 24.09.2013
comment
Это звучит неправильно; У меня есть сценарии, которые используют isKeepLog() для контроля того, является ли сборка постоянной, и они работают нормально. Не могли бы вы выложить где-нибудь весь свой сценарий, и я посмотрю? - person gareth_bowles; 24.09.2013
comment
Конечно. Я попытался включить его, установить сохранение сборки навсегда, он возвращает false, когда я печатаю build.isKeepLog(). См. мой ОКОНЧАТЕЛЬНЫЙ сценарий ответа, который удаляет как Jenkins, так и Artifactory, создает артефакты данного выпуска/версии задания Jenkins. Если бы вы могли сделать этот скрипт, а не удалять сборки Keep forever, это было бы здорово. - person AKS; 25.09.2013
comment
Вы должны включить свою логику if (!build.isKeepLog()) ... непосредственно перед строкой: it.delete(); в финальном сценарии. - person AKS; 25.09.2013

Окончательный ответ: это включает в себя удаление артефактов сборки из Artifactory, а также использование вызова REST API Artifactor. Этот скрипт удалит сборки/артефакты Jenkins/Artifactory данного выпуска/версии (как иногда с течением времени — данное задание Jenkins может создавать несколько сборок выпуска/версии, например: 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 ""
person AKS    schedule 24.09.2013

ОК - решение моего вопроса 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 ""

введите здесь описание изображения

Можно также вызвать этот скрипт через задание Jenkins (требуется 3 параметра, как указано в скрипте scriptler) - ИЛИ также вызвать его из браузера: используя следующую ссылку:

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

person AKS    schedule 24.09.2013
comment
Этот скрипт будет нормально работать с плагином Jenkins Scriptler. См. прикрепленное изображение для вывода. Если вы хотите запустить этот сценарий из задания Jenkins, то в разделе «Сборка» вызовите сценарий Scriptler, укажите местоположение/имя файла, установите флажок, чтобы задание jenkins использовало параметры для этого сценария сценария (показано выше), вот и все. Для этого задания jenkins требуется 3 параметра строкового формата — jobName, releaseVersion и buildNumber. - person AKS; 24.09.2013