2012-03-27 576 views
44

在處理POM之後,Jenkins構建是否可以知道項目的Maven版本號?在Jenkins中獲取Maven版本

我有一些項目,其中版本控制是由Maven控制的,在後期構建工作中,我們想創建一個Debian包並調用一些shell腳本。我需要的是Maven曾經作爲Jenkins環境變量提供的版本號,所以我可以將它傳遞給構建後的操作。

要清楚,我是而不是需要知道如何讓Jenkins將版本號傳遞給Maven;相反,我希望Maven將一個版本號傳遞給Jenkins!

+0

只是一個建議:這個是什麼:http://mojo.codehaus.org/deb-maven-plugin/ – khmarbaise 2012-03-28 09:04:51

回答

21

很多四處之後(我從來沒有意識到不良的記錄詹金斯怎麼樣了!)我發現了一個很平凡的解決方案。

  1. 安裝Groovy插件
  2. 添加Post Step到Maven構建類型的Execute **system** Groovy script
  3. 粘貼在Groovy的下面的代碼片段:

腳本:

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); 

調用的構建環境變量MAVEN_VERSION現在可用於以通常方式替換到其他構建後步驟(${MAVEN_VERSION})。我將其用於Git標記等。

+2

這個工程就像一個魅力,如果你更新'def mavenVer ='行到什麼在你的[稍後跟進](http://stackoverflow.com/a/10205702/487663) - def mavenVer = currentBuild.getParent() .getModules()。toArray()[0] .getVersion();' – 2012-09-26 13:13:36

+0

確實將「def mavenVer ...」替換爲上一條評論中的代碼。 – 2012-10-29 15:25:24

+1

這與'POM_VERSION'相同,因爲這個bug .jenkins-ci.org/browse/JENKINS-24869 – yegeniy 2016-10-31 14:35:55

3

我們使用了Groovy Postbuild Plugin

String regex = '.*\\[INFO\\] Building .+ (.+)'; 
    def matcher = manager.getLogMatcher(regex); 
    if (matcher == null) { 
     version = null; 
    } else { 
     version = matcher.group(1); 
    } 

將此添加到Jenkins供以後使用有點棘手。給我一個鏡頭,雖然我記得這讓我們頭疼。 (很抱歉,我們在很久以前這樣做)

def addBuildParameter(String key, String value) { 
    manager.build.addAction(new hudson.model.ParametersAction(new hudson.model.StringParameterValue(key,value))); 
} 
+0

你會怎樣做,然後'版本'可用於其他事情步驟的工作? – 2012-03-28 11:22:56

+0

你好,我有點擴大了答案。祝你好運! – 2012-03-28 11:41:25

+0

此解決方案適用於在POM文件中使用變量有動態填充的版本號的情況。在這些情況下使用POM_VERSION或解析pom.xml文件將不起作用。 – swbandit 2015-02-10 15:42:51

2

與Groovy解析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)); 

添加此腳本類型的後工序「執行系統Groovy腳本」(所以安裝的Groovy是沒有必要的),並粘貼在「常規命令」的代碼。

+0

請參閱[項目版本從maven到sonar -using-hudson](http://stackoverflow.com/questions/14691818/project-version-from-maven-to-sonar-using-hudson/15879456# 15879456) – Sylvain 2013-04-08 12:51:57

+0

我嘗試在shell腳本步驟中使用'$ {project.version}',之後它失敗了:''''''''''''''''''''''' 。似乎jenkins不允許var名稱中的'dot'? – yetanothercoder 2013-05-20 10:01:09

+0

這在Jenkins 2.46+中似乎不起作用。雖然Groovy提取的版本很好,但我的Freestyle項目的其餘部分中的'project.version'環境變量是空的。在Jenkins 2+中有沒有改變它的作用?我試圖以'$ {project.version}'的形式訪問這個var' – 2017-07-26 21:14:43

0

你也可以這樣做:

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`" 

說明:假設你一兩行中有你的項目名稱高於/低於版本像一個正常的POM:

<groupId>org.apache.bigtop</groupId> 
<artifactId>bigpetstore</artifactId> 
<version>1.0-SNAPSHOT</version> 

然後你就可以很容易地對於artifactId使用grep,使用「before/after」grep操作來吸引版本,然後grep版本,並使用簡單的unix「cut」命令來拼接出「版本」標籤之間的內容。

我喜歡Jenkins-groovy集成,但是這很容易,即使在你不能控制的構建服務器上(即bash是通用的),它也能工作。

+0

這個工作就像一個魅力,但是獲取了多個版本信息,因爲它也包含一個版本標籤。 在它爲我工作的grep和管道之前添加一個頭 MAVEN_VERSION ='head「」「pom.xml | grep A -2 -B 2 | grep版本| cut -d \> -f 2 | cut -d \ <-f 1'-commit-「'echo $ GIT_COMMIT'」 – JoeDred 2014-07-10 06:58:00

+0

@JoeDred我仍然獲得多個版本。但我的 「另一版本」 是不是從依賴,但是從性能:** cz.px.iis \t IIS的核心納克 \t 罐子 \t 2.1.1-SNAPSHOT \t \t \t 7.7.5 \t \t UTF-8 \t \t 1.8 \t \t 1.8 \t **和輸出是__2.1.1-SNAPSHOT 7.7.5__ – agad 2017-01-18 15:43:05

+0

@agad也許你應該限制你管道的第一個grep。 Head採用可選參數-n或--lines。試試** head --help **,它顯示了它是如何使用的。 – JoeDred 2017-01-20 07:03:36

56

您可以使用$ {POM_VERSION}變量,這與https://issues.jenkins-ci.org/browse/JENKINS-18272

+0

太棒了!驗證你需要Jenkins maven plugin v2.3或更高版本的'$ {POM_VERSION}'工作,我認爲它需要是一個Maven項目類型。 – 2014-05-13 12:55:08

+1

這不適合我。 Jenkins中的Maven Interation插件是2.5版本,仍然是這樣說的:$ {ENV,var =「POM_VERSION」}:如果我嘗試直接或通過上述方式嘗試使用此變量,則會導致錯誤的替換。 「Build Number Set」插件框中的「$ {POM_VERSION}。$ {BUILD_NUMBER}」中無法識別宏'POM_VERSION'。 – 2014-07-30 20:46:28

+2

請記住,POM_VERSION不會考慮可能已傳遞給maven構建過程的任何環境變量。例如: $ {CUSTOM_VERSION} 將爲空或具有默認值。 – swbandit 2015-02-04 18:13:41

1

介紹,執行中的「執行shell」的Maven插件「的exec-Maven的插件」作爲「條件步」工作對我來說:

mvn -q -Dexec.executable="echo" -Dexec.args='${projects.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec 

整合詹金斯:

-> "Add post-build step" 
    -> "Conditional steps (single or multiple)" 
     -> "Execute Shell:" 

出口MY_POM_VERSION =`MVN -q -Dexec.executable =「ECH o「 -Dexec.args ='$ {projects.version}' - 非遞歸org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` & & [[ 」$ {MY_POM_VERSION}「 == 「THE_VERSION_TO_BE_MATCHED」]] & &呼應 「CONDITION_IS_MET」

-> "Steps to run if condition is met" 
     -> Add any build step you need 

注:

  • THE_VERSION_TO_BE_MATCHED已與您交換版本
  • '& & echo「CONDITION_IS_MET」'僅用於調試目的。出於同樣的目的,您可以在mvn命令之後添加一個'& & echo「MY_POM_VERSION = $ {MY_POM_VERSION}」',以便了解發生了什麼。

這種方法比「grep」更可靠,如果沒有安裝Jenkins Ruby插件,它可能是一種替代方案。

6

正如已經指出的其他答案,如果您使用Maven項目類型,您可以訪問$ POM_VERSION變量。但如果你不是,你可以使用這一系列的步驟(醜陋但可靠)。這樣做依賴於相同版本的maven來確定pom版本(同時處理複雜的父/子pom繼承,其中<版本>可能甚至不存在給孩子)。

  1. Maven的一步這一目標:

    org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version -l version.log

  2. 殼牌邁:(您可能需要調整路徑取決於你的層次結構件version.log)

    echo "POM_VERSION=$(grep -v '\[' version.log)" > props.properties

  3. 進樣環境變量步驟(環境噴油器插件):

    屬性文件路徑:props.properties

現在你可以使用$ POM_VERSION彷彿這是一個Maven項目。

這是幹什麼的:使用maven打印輸出一起輸出的版本,然後輸出只剩下版本的輸出亂碼,使用屬性文件格式將其寫入文件,然後將其注入到構建中環境。這比像mvn ..... | grep -v '\['這樣的單線程更好的原因在於,使用Maven步驟不會對已安裝的Maven版本做出假設,並且將通過與任何其他Maven步驟相同的自動安裝進行處理。

+0

存在grep過濾器的一個問題:如果你沒有存儲庫中的插件,你會得到還有POM_VERSION中的「下載...」行。例如:'+ echo'POM_VERSION =正在下載:...' – apa64 2017-11-22 08:23:57

0

解決方案:

POM_VERSION=$(\ 
    xmlstarlet sel \ 
    -N x='http://maven.apache.org/POM/4.0.0' \ 
    -t \ 
    -v '//x:project/x:version/text()' \ 
    pom.xml \ 
) 

說明:

您可以在一個班輪使用命令行工具的XPath,如在 「How to execute XPath one-liners from shell?」 提到的那些做到這一點。我選擇了XMLStarlet,但它們都有類似的語法。

解析POM時,必須考慮命名空間。文檔here幫助我弄清楚了這一點。

爲了獲取XPath中元素的文本,可以使用text()函數,如XPath: select text node中所述。

我POM看起來是這樣的:

<?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> 

的這裏的缺點是,如果命名空間的變化,你必須改變的命令。

0

我在聲明式管道作業中使用Pipeline Utility Steps插件來獲取Maven版本。在下面的示例中,我使用腳本變量而不是環境變量,因爲可以修改並在各階段之間傳遞。

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}") 
      } 
     } 
    } 
} 

注:您必須在創建工作後,批准的getVersion()方法管理詹金斯>在處理腳本審批

參見: