Извлечь версию pom в трубопроводе Дженкинса

Я создал конвейер и использую встроенное определение сценария groovy конвейера и не могу получить версию pom. Я попробовал это, которое работает в отличной консоли, но в сценарии сборки Jenkins:

def project = new XmlSlurper().parse(new File("pom.xml"))
def pomv = project.version.toString()

Согласно документации Дженкинс имеет $POM_VERSION но значение не имеет ничего, когда я назначаю его переменной и выводю его.

def pomv = "$POM_VERSION"

ИЛИ ЖЕ

def pomv = '$POM_VERSION"

У кого-нибудь есть идея?

11 ответов

Использование readMavenPom как это:

pom = readMavenPom file: 'pom.xml'
pom.version

См. Модель ссылки для свойств (как и выше версия).

Чтобы это работало, нужно установить плагин Pipeline Utility Steps

В Jenkins 2.138.3 есть два разных типа конвейеров.

Декларативные и скриптовые конвейеры.

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

конвейер Дженкинса: агент против узла?

Вот пример декларативного конвейера:

pipeline {

    agent any


    environment {
    //Use Pipeline Utility Steps plugin to read information from pom.xml into env variables
    IMAGE = readMavenPom().getArtifactId()
    VERSION = readMavenPom().getVersion()
    }


    stages {

        stage('Test') {
            steps {
                echo "${VERSION}"
            }

        }

    }

}

Пример скриптового конвейера

node('master') {

  stage('Test') {
    IMAGE = readMavenPom().getArtifactId()
    VERSION = readMavenPom().getVersion()
    echo "IMAGE: ${IMAGE}"
    echo "VERSION: ${VERSION}"
  }

}

Вот несколько хороших ссылок:

Декларативный https://github.com/jenkinsci/pipeline-examples/blob/master/declarative-examples/jenkinsfile-examples/mavenDocker.groovy

Сценарий https://bulldogjob.com/articles/726-exploring-jenkins-pipelines-a-simple-delivery-flow

Страница Начало работы с конвейером показала еще один вариант. Работает без дополнительных плагинов.

Чуть более надежную версию можно найти в общей библиотеке ces-build-lib (она также имеет несколько базовых модульных тестов):

def version() {
    def matcher = readFile('pom.xml') =~ '<version>(.+?)</version>'
    matcher ? matcher[0][1] : null
}

Это всегда соответствует первому <version> тег можно найти в pom.xml, В большинстве случаев это должна быть версия модуля maven или его родителя.

Я обычно использую readFile шаг вместо new File() где это возможно.

Так это будет выглядеть так:

def project = new XmlSlurper().parseText(readFile('pom.xml'))
def pomv = project.version.text()

Также убедитесь, что версия не наследуется от родителя. В этом случае вам понадобится:

def pomv = project.parent.version.text()

Не в последнюю очередь будьте осторожны XmlSlurper не сериализуем. Вы вообще хотите использовать

@com.cloudbees.groovy.cps.NonCPS

в тех случаях. Я настоятельно рекомендую прочитать учебник Github - Сериализация локальных переменных.

Ты можешь попробовать readMavenPom функция, которая доступна.

Более подробная информация здесь: https://jenkins.io/doc/pipeline/steps/pipeline-utility-steps/

Я обычно использую карту, чтобы сделать это.

 def pomFile = readFile(pomName)
 def pom = new XmlParser().parseText(pomFile)
 def gavMap = [:]
 gavMap['groupId'] =  pom['groupId'].text().trim()
 gavMap['artifactId'] =  pom['artifactId'].text().trim()
 gavMap['version'] =  pom['version'].text().trim()

конвейер jenkins добавить этот этап. больше см.

          stage('info')
    {
        steps
        {
            script
            {
                def version = sh script: 'mvn help:evaluate -Dexpression=project.version -q -DforceStdout', returnStdout: true
                def artifactId = sh script: 'mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout', returnStdout: true
                
            }

        }
    }

Я только что улучшил решение @haridsv без использования grep:

#!/usr/bin/env
def call(String mvnBin = 'mvn',String pom_file = 'pom.xml') {

return sh(
        script: mvnBin+''' -N -f '''+pom_file+''' org.apache.maven.plugins:maven-help-plugin:evaluate -Dexpression=project.version -q -DforceStdout''',
        returnStdout: true).trim()
}

Вам лучше не использовать readMavenPom, так как он будет устаревшим (см. PR https://github.com/jenkinsci/pipeline-utility-steps-plugin/pull/47/commits/eeebaa891a006c083ce10f883b7c1264533bb692). Вы можете скопировать и вставить это в файл, такой как valuMavenPomVersion.groovy:-)

Maven — источник истины, используйте его напрямую.

Например, чтобы получить стоимость имуществаfoo.barиз pom.xml в Jenkinsfile:

      def bar = sh(script: 'mvn help:evaluate -Dexpression=foo.bar -q -DforceStdout', returnStdout: true)

Кроме того, документы Pipeline Utility Steps предлагают избегать использованияreadMavenPom.

Избегайте использования этого шага и напишите MavenPom. Лучше использовать шаг sh для запуска целей mvn.

Похоже на readMavenPom это самый простой ответ, но так как он требует установки дополнительного конвейерного плагина, вот еще один, который использует родной подход maven вместо загрузки xml (на основе этого ответа)

def mvn_project_version(pom_file) {
    return sh(
        script: """mvn -N -f $pom_file org.apache.maven.plugins:maven-help-plugin:evaluate -Dexpression=project.version |
                   grep -Ev '(^\\s*\\[|Download\\w+:)'""",
        returnStdout: true).trim()
}

Из-за использования grep Команда this может не работать на некоторых платформах, которые не совместимы с posix, но вы всегда можете обработать вывод в Groovy вместо передачи по конвейеру grep,

Я только начинаю с Jenkisfile и у меня была такая же проблема, как и у вас. поскольку XmlSlurper а также XmlParser запрещены конфигурацией по умолчанию, я перечислил ниже функцию, чтобы извлечь версию maven:

String readProjectVersion(String pom) {
    //Take value of the <project> tag
    def matcher = pom.trim() =~ /(?s)<project[^>]*>(.*)<\/project>/
    def pomWithoutProject = matcher[0][1].trim()

    //remove every tag except <version>, since only project version is not encapsulated in the other tag e.g. dependency, parent, plugin
    def nonVersionMatcher = pomWithoutProject =~ /(?s)\s*(?!<version>)<([a-zA-Z][a-zA-Z0-9]*)\b[^>]*>(.*?)<\/\1>\s*/
    def versionTag = nonVersionMatcher.replaceAll("").trim()
    //Take value of the <version> tag
    def versionTagMatcher = versionTag =~ /<version>(.*)<\/version>/
    if (versionTagMatcher.matches()) {
        return versionTagMatcher[0][1]
    }
    //no version tag, version should be inherited from parent version
    def parentVersionMatcher = pomWithoutProject =~ /(?s)\s*<parent>.*<version>(.*)<\/version>.*<\/parent>\s*/
    return parentVersionMatcher[0][1]
}

Я проверил это решение для файлов, в которых родительский объект был объявлен, версия была первым оператором, версия была последним оператором и с наличием версии во вложенных тегах, таких как dependency, plugin и т.п.

Другие вопросы по тегам