Как получить список запущенных сборок jenkins через groovy script?

есть ли способ получить список запущенных сборок в Jenkins через системный скрипт Groovy? Я попытался выполнить цикл через занятых исполнителей, но из объекта исполнителя я не могу получить объект сборки:

def busyExecutors = Jenkins.instance.computers
                                .collect { 
                                  c -> c.executors.findAll { it.isBusy() }
                                }
                                .flatten() // reminder: transforms list(list(executor)) into list(executor)

busyExecutors.each { e -> 
  println('=====print out methods of executor object=======');
  println e.metaClass.methods*.name.sort().unique();

}

Я также могу нацелить работу, которая меня интересует, так:

def item = hudson.model.Hudson.instance.getItem("my_job");
println item.metaClass.methods*.name.sort().unique(); 

но тогда мне придется перебирать 100 (если не больше) сборок и спрашивать каждую сборку, запущены ли они.

должен быть более простой / лучший способ получить список запуск сборок.

существует много информации о том, как делать различные вещи с помощью системных скриптов Groovy (некоторые из которых я написал), но я не могу понять, как получить список запущенных сборок:

как получить имя узла текущего запущенного задания в jenkins, используя в Groovy

https://wiki.jenkins-ci.org/display/JENKINS/Jenkins + скрипт + консоль

https://gist.github.com/dnozay/e7afcf7a7dd8f73a4e05

как сделать работу Дженкинса / Хадсона наблюдать за некоторыми другими заданиями и решать, строить или нет?

3 ответов


Я нашел пару способов сделать это без использования REST API или синтаксического анализа XML:

runningBuilds = Jenkins.instance.getView('All').getBuilds().findAll() { it.getResult().equals(null) }

это предполагает, что вы не удалили или не изменили представление "все" по умолчанию в Jenkins. Конечно, вы можете заменить другое имя представления, если точно знаете, в каком представлении будут находиться ваши сборки. Или вы можете попробовать такой подход:

runningBuilds = Jenkins.instance.getItems().collect { job->
  job.builds.findAll { it.getResult().equals(null) }
}.flatten()

хотя этот подход не требует имени представления, он также имеет ограничения. Он не сойдет в папки или разветвленную Трубопроводы или что-то в этом роде. Вам нужно будет вручную спуститься в папки или придумать какой-то способ сделать это автоматически. Например, вот версия, которая работает на производство многофилиальных:

Jenkins.instance.getItemByFullName(multibranchPipelineProjectName).getItems().each { repository->
  repository.getItems().each { branch->
    branch.builds.each { build->
      if (build.getResult().equals(null)) {
        // do stuff here ...
      }
    }
  }
}

Я думаю, что может быть более точный метод для использования, чем build.getResult().equals(null) чтобы определить, работает ли сборка или нет, но у меня возникли проблемы с поиском хороших документов API, поэтому я не уверен. Это был только первый метод, который я нашел, используя Object introspection, который работал.

опять же из-за отсутствия документов API, я не уверен, есть ли существенная разница между Jenkins.instance.getItems() который я использовал здесь и Jenkins.instance.getAllItems() который использовался в ответ.

наконец, обратите внимание, что все это относительно неэффективные методы. Они повторяют каждую сборку каждого задания, поэтому, если вы сохраняете длинную историю сборок (по умолчанию для сохранения истории только 10 сборок на задание) или имеете тысячи заданий, это может занять некоторое время. См.как мне эффективно перечислить * * все * * текущие задания на Дженкинсе с помощью Groovy на вопрос, который спрашивает, Как сделать эту задачу более эффективно.


Это не особенно эффективно (но гораздо эффективнее, чем использование API). Он распечатает все текущие сборки с помощью HTML-ссылки. Можно запустить в консоли скрипта или через scriptler.

def now = new Date()  // Get the current time
// Get a list of all running jobs
def buildingJobs = Jenkins.instance.getAllItems(Job.class).findAll { 
  it.isBuilding() }

buildingJobs.each { job->
    // Enumerate all runs
    allRuns = job._getRuns()
    allRuns.each { item ->
        // If NOT currently building... check the next build for this job
        if (!item.isBuilding()) return

        // Access and calculate time information for this build.
        def startedAt = new Date(item.getStartTimeInMillis())
        def duration_mins = ((now.getTime() - item.getStartTimeInMillis()) / 60000).intValue()

        estDurationMins = (item.getEstimatedDuration() / 60000).intValue()
        String jobname = item.getUrl()
        jobname = jobname.replaceAll('job/', '')  // Strip redundant folder info.

        println "${duration_mins.toString().padLeft(5)}/" +
            "${estDurationMins.toString().padLeft(4)}  - " +
            "<a href=${baseURL}${item.getUrl()}>${jobname}</a>"
    }
}

вы можете использовать REST API для получения списка запущенных сборок. Используя следующий url:

http://myjenkins/jenkins/computer/api/xml?depth=1

вы получите следующий ответ, который содержит <executor> элементы. Только выполняя построения есть <url> элемент внутри <executor>. Обратите внимание также, что выполняя построения и <idle>false</idle> значение:

<computerSet>
    <busyExecutors>1</busyExecutors>
    <computer>
        ...
        <executor>
            <idle>true</idle>
            <likelyStuck>false</likelyStuck>
            <number>0</number>
            <progress>-1</progress>
        </executor>
        <executor>
            <currentExecutable>
                <number>328</number>
                <!-- This is the url from the current running build -->
                <url>http://myJenkins/jenkins/job/someJob/328/</url>             
            </currentExecutable>
            <currentWorkUnit/>
            <idle>false</idle>
            <likelyStuck>false</likelyStuck>
            <number>1</number>
            <progress>24</progress>
        </executor>
        ...
    </computer> 
<computerSet>

следовательно, используйте REST API с XPath-выражения на url чтобы получить только запущенные сборки (обратите внимание, что &wrapper параметр-это имя корневого элемента xml, чтобы избежать ошибок при XPath-выражения не соответствует или возвращает более одного узла):

http://myJenkins/jenkins/computer/api/xml?depth=1&xpath=//url&wrapper=builds

вы получите что-то вроде:

<builds>
    <url>
http://myJenkins/jenkins/job/someJob/300/
    </url>
    <url>
http://myJenkins/jenkins/job/another/332/
    </url>
</builds>

так в Groovy вы можете получить REST API, проанализировать возвращенный Xml, а затем применить регулярное выражение к каждому <url> чтобы получить данные из запущенных сборок:

// get the xml from the rest api
def builds = 'http://myJenkins/jenkins/computer/api/xml?depth=1&xpath=//url&wrapper=builds'.toURL().text
// parse the xml result
def xml = new XmlSlurper().parseText(builds)
// for each url get the job name
def jobNames = xml.url.collect{ url ->
    // regex to get the jobName and a build number
    def group = (url =~ /.*\/job\/([^\/]+)\/(\d+)/)
    println group[0] // [http://myJenkins/jenkins/job/someJob/300, someJob, 300]
    def jobName = group[0][1]
    return jobName
    // to get the build number
    // def buildNr = group[0][2]
}
println jobNames