Existe-t-il un moyen par lequel Jenkins peut connaître le numéro de version Maven d'un projet après le traitement du POM?
J'ai quelques projets où la gestion des versions est contrôlée par Maven, et dans un travail post-construction, nous aimerions créer un paquet Debian et appeler des scripts Shell. Ce dont j'ai besoin, c’est que le numéro de version utilisé par Maven soit disponible en tant que variable d’environnement Jenkins afin que je puisse le transmettre aux actions post-génération.
Pour être clair, j'ai pas besoin de savoir comment faire en sorte que Jenkins transmette un numéro de version à Maven; à la place, je veux que Maven transmette un numéro de version à Jenkins!
Après avoir beaucoup fouillé (je n'avais jamais réalisé à quel point Jenkins est mal documenté!), J'ai trouvé une solution assez triviale.
Post Step
à votre build Maven de type Execute **system** Groovy script
Script:
import hudson.model.*;
import hudson.util.*;
def thr = Thread.currentThread();
def currentBuild = thr?.executable;
def mavenVer = currentBuild.getParent().getModules().toArray()[0].getVersion();
def newParamAction = new hudson.model.ParametersAction(new hudson.model.StringParameterValue("MAVEN_VERSION", mavenVer));
currentBuild.addAction(newParamAction);
La variable d'environnement de construction appelée MAVEN_VERSION
sera désormais disponible pour une substitution dans d'autres étapes post-génération de la manière habituelle (${MAVEN_VERSION}
). Je l'utilise pour le marquage Git entre autres choses.
Vous pouvez utiliser la variable $ {POM_VERSION}, introduite avec https://issues.jenkins-ci.org/browse/JENKINS-18272
Avait le même besoin et résolu comme suggéré avec Groovy en analysant le pom.
import jenkins.util.*;
import jenkins.model.*;
def thr = Thread.currentThread();
def currentBuild = thr?.executable;
def workspace = currentBuild.getModuleRoot().absolutize().toString();
def project = new XmlSlurper().parse(new File("$workspace/pom.xml"))
def param = new hudson.model.StringParameterValue("project.version", project.version.toString())
currentBuild.addAction(new hudson.model.ParametersAction(param));
Ajoutez ce script en tant qu'étape de publication du type "Exécuter le script Groovy du système" (il n'est donc pas nécessaire d'installer Groovy) et collez le code dans la "commande Groovy".
Nous avons utilisé le Groovy Postbuild Plugin .
String regex = '.*\\[INFO\\] Building .+ (.+)';
def matcher = manager.getLogMatcher(regex);
if (matcher == null) {
version = null;
} else {
version = matcher.group(1);
}
Ajouter ceci à Jenkins pour une utilisation ultérieure est un peu délicat. Donnez un coup de feu, même si je me souviens de cela nous causant des maux de tête. (Désolé, nous l'avons fait il y a longtemps)
def addBuildParameter(String key, String value) {
manager.build.addAction(new hudson.model.ParametersAction(new hudson.model.StringParameterValue(key,value)));
}
J'ai utilisé Pipeline Utility Steps plugin dans un travail de pipeline déclaratif pour obtenir la version Maven. Dans l'exemple ci-dessous, j'utilise une variable de script au lieu d'une variable d'environnement, car elle peut être modifiée et transmise entre les étapes.
def TAG_SELECTOR = "UNINTIALIZED"
pipeline {
agent any
stages {
stage('Build') {
steps {
sh "mvn --batch-mode -U deploy"
script {
TAG_SELECTOR = readMavenPom().getVersion()
}
echo("TAG_SELECTOR=${TAG_SELECTOR}")
}
}
}
}
Remarque: Vous devez approuver la méthode getVersion () après la création du travail dans Manage jenkins> approbation de script en cours de traitement.
Voir également:
Exécutez le plugin Maven "exec-maven-plugin" dans "Exécuter Shell" comme une "étape conditionnelle" a fonctionné pour moi:
mvn -q -Dexec.executable="echo" -Dexec.args='${projects.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec
Intégrer dans Jenkins:
-> "Add post-build step"
-> "Conditional steps (single or multiple)"
-> "Execute Shell:"
export MY_POM_VERSION = `mvn -q -Dexec.executable =" echo " -Dexec.args = '$ {projects.version}' - org-code-recursive.mojo: plugin exec-maven: 1.3.1: exec` && [[ "$ {MY_POM_VERSION}" == "THE_VERSION_TO_BE_MATCHED"]] && echo "CONDITION_IS_MET"
-> "Steps to run if condition is met"
-> Add any build step you need
Remarques:
Cette approche est plus fiable qu'un "grep" et pourrait constituer une alternative si le plug-in Jenkins Ruby n'est pas installé.
Solution:
POM_VERSION=$( \
xmlstarlet sel \
-N x='http://maven.Apache.org/POM/4.0.0' \
-t \
-v '//x:project/x:version/text()' \
pom.xml \
)
Explication:
Vous pouvez le faire dans une ligne à l'aide d'un outil XPath en ligne de commande, comme ceux mentionnés à " Comment exécuter des one-liners XPath depuis un shell? ". J'ai choisi XMLStarlet , mais ils ont tous une syntaxe similaire.
Lors de l'analyse d'un POM, vous devez prendre en compte les espaces de noms. Les docs ici m'ont aidé à comprendre cela.
Pour obtenir le texte d'un élément dans XPath, utilisez la fonction text () comme expliqué dans XPath: sélectionnez le nœud de texte .
Mon POM ressemble à ceci:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.Apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.Apache.org/POM/4.0.0 http://maven.Apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.foo.bar</groupId>
<artifactId>foobar</artifactId>
<version>1.0.6-SNAPSHOT</version>
<packaging>jar</packaging>
L'inconvénient est que si l'espace de nom change, vous devez modifier la commande.
Utilisez 'Execute System Groovy Script' comme suit:
import jenkins.util.*;
import jenkins.model.*;
def thr = Thread.currentThread();
def currentBuild = thr?.executable;
def projectManager = build.getProject()
def file = projectManager.getWorkspace().child("pom.xml");
def project = new XmlSlurper().parseText(file.readToString())
def param = new hudson.model.StringParameterValue("currentVersion", project.version.toString())
currentBuild.addAction(new hudson.model.ParametersAction(param));
En utilisant le script Execute System Groovy, vous avez un accès direct à la construction, à partir de laquelle vous pouvez obtenir le projet et donc le fichier "enfant" dans ce cas pom.xml.
Vous n'avez pas besoin de créer un nouveau fichier et, comme vous pouvez le constater, il offre un accès très puissant à chaque fichier de l'espace de travail.
Basé sur @ Akom`s answer , les étapes préalables à l’utilisation de POM_VERSION sont les suivantes:
Scénario
mvn org.Apache.maven.plugins:maven-help-plugin:evaluate -Dexpression=project.version -l project_version
# grep for the version pattern rather than not mentioning '\['
echo "POM_VERSION=$(grep -E '^[0-9.]+(-SNAPSHOT)?$' project_version)" > your_property_file
Vous pouvez aussi faire:
MAVEN_VERSION=`grep A -2 -B 2 "<your_project_name>" pom.xml | grep version | cut -d\> -f 2 | cut -d\< -f 1`-commit-"`echo $GIT_COMMIT`"
Explication: en supposant que le nom de votre projet se trouve dans une ligne ou deux au-dessus/au-dessous de la version, comme un pom normal:
<groupId>org.Apache.bigtop</groupId>
<artifactId>bigpetstore</artifactId>
<version>1.0-SNAPSHOT</version>
Ensuite, vous pouvez facilement grep pour artifactId, utilisez les actions grep "avant/après" pour aspirer la version, puis extrayez la version et utilisez la simple commande "cut" unix pour séparer le contenu entre "version". Mots clés.
J'aime l’intégration Jenkins-groovy, mais c’est beaucoup plus facile et fonctionnera même sur un serveur de build sur lequel vous n’avez pas le contrôle (par exemple, parce que bash est universel).