實現Jenkinsfile與Json的轉換
最近在做個需求,需要支援Jenkinsfile和json的轉換。
方法1:使用現有的jenkins外掛
參考的是這篇文章。下面介紹一下將外掛打包成映象的步驟:
-
本地安裝jdk和maven,jdk建議採用的版本為8(該工程會依賴一個名為
tools.jar
的包,jdk 9之後移除了該包)如果本地沒有找到
tools.jar
,可以下載一個1.8版本的jdk,然後在pom.xml
中增加如下依賴<dependency> <groupId>jdk.tools</groupId> <artifactId>jdk.tools</artifactId> <version>1.8.0</version> <scope>system</scope> <systemPath>/root/jdk1.8.0_271/lib/tools.jar</systemPath> </dependency>
-
clone pipeline-model-definition-plugin工程
-
在/root/.m2/目錄下建立
settings.xml
,內容來自Jenkins官方:<settings> <pluginGroups> <pluginGroup>org.jenkins-ci.tools</pluginGroup> </pluginGroups> <profiles> <!-- Give access to Jenkins plugins --> <profile> <id>jenkins</id> <activation> <activeByDefault>true</activeByDefault> <!-- change this to false, if you don't like to have it on per default --> </activation> <repositories> <repository> <id>repo.jenkins-ci.org</id> <url>https://repo.jenkins-ci.org/public/</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>repo.jenkins-ci.org</id> <url>https://repo.jenkins-ci.org/public/</url> </pluginRepository> </pluginRepositories> </profile> </profiles> <mirrors> <mirror> <id>repo.jenkins-ci.org</id> <url>https://repo.jenkins-ci.org/public/</url> <mirrorOf>m.g.o-public</mirrorOf> </mirror> </mirrors> </settings>
-
執行
mvn install
進行編譯 -
由於主要用到的是Jenkinsfile和json之間的轉換關係,因此主要用的是如下兩個REST API:
-
Conversion to JSON representation from Jenkinsfile
- URL:
JENKINS_URL/pipeline-model-converter/toJson
- Parameters:
jenkinsfile
- theJenkinsfile
contents - Info: Takes a
Jenkinsfile
and converts it to the JSON representation for itspipeline
step. - Returns: JSON with a
result
field that will either besuccess
orfailure
. Ifsuccess
, the JSON representation will be in thejson
field. Iffailure
, there'll be an additional array in theerrors
field of the error messages encountered.
- URL:
-
Conversion to Jenkinsfile from JSON representation
- URL:
JENKINS_URL/pipeline-model-converter/toJenkinsfile
- Parameters:
json
- the JSON representation of the model - Info: Takes the JSON representation of the model and converts it to the contents for a
Jenkinsfile
invoking thepipeline
step. - Returns: JSON with a
result
field that will either besuccess
orfailure
. Ifsuccess
, theJenkinsfile
contents will be in thejenkinsfile
field. Iffailure
, there'll be an additional array in theerrors
field of the error messages encountered.
- URL:
上述兩個API在
pipeline-model-definition-plugin/pipeline-model-definition
目錄下,因此在該目錄下直接執行:mvn hpi:run -Dhost=0.0.0.0 -Djetty.port=8080
即可。 -
-
將json轉換為Jenkinsfile的操作如下:
完整的返回值如下:
{ "status": "ok", "data": { "result": "success", "json": { "pipeline": { "stages": [ { "name": "Hello", "branches": [ { "name": "default", "steps": [ { "name": "echo", "arguments": [ { "key": "message", "value": { "isLiteral": true, "value": "Hello World" } } ] } ] } ] } ], "agent": { "type": "any" } } } } }
-
將Jenkinsfile轉換為json的操作如下
-
製作容器映象時,只需要將本地工程和
/root/.m2
上傳到容器,生成對應的映象即可,下面Dockerfile假設生成的映象為pipeline-model-definition-plugin:latest
FROM pipeline-model-definition-plugin:latest WORKDIR /usr/pipeline-model-definition-plugin/pipeline-model-definition ENV PATH=$PATH:/usr/local/bin/maven-3.6.3/bin ENTRYPOINT ["sh", "-c", "mvn hpi:run -Dhost=0.0.0.0"]
我自己打包了一個映象:
docker pull quay.io/woodliu/pipeline-model-definition-plugin
需要注意的是,本外掛提供的轉換API toJenkinsfile和toJson並不是萬能的,只能支援jenkins標準的引數型別,例如對於gitParameter
這樣的引數就無法解析(擴充套件功能),一種解決方式是獨立解析擴充套件的引數,然後將其插入解析好的標準JenkinsFile中;另外一個方式就是寫一個jenkinsfile的解析器。
參考
-
mvn hpi的命令可以參考官方文件
-
可以執行
mvn hpi:hpi
生成對應的hpi
檔案,如:/pipeline-model-definition-plugin/pipeline-model-definition/target/pipeline-model-definition.hpi
方法2:解析原生的jenkinsfile檔案
在GitHub上有一個支援jenkinsfile解析的專案,該專案使用rust的pest crate來編寫jenkinsfile的語法,支援對jenkinsfile的格式驗證。Pest官方文件中給出了一個非常好的對json語法的解析例子,主要是使用遞迴的方式來解析語法。
pest官方提供了一個編輯器,可以使用該編輯器檢視經過pest解析之後的欄位,對了解pest的工作方式非常有用。如,使用jdp專案提供的pest檔案解析如下jenkinsfile:
pipeline {
agent {
docker {
reuseNode true
image 'maven:3-alpine'
label 'my-defined-label'
args '-v /tmp:/tmp'
registryUrl 'https://myregistry.com/'
registryCredentialsId 'myPredefinedCredentialsInJenkins'
}
}
stages {
stage('Build') {
steps { sh 'make' }
}
}
}
對應的解析結果如下:
- preceeding_junk: ""
- opening_brace: "{"
- agentDecl > agentBlock
- opening_brace: "{"
- dockerAgent
- opening_brace: "{"
- bool: "true"
- string > single_quoted
- single_quote: "\'"
- inner_single_str: "maven:3-alpine"
- single_quote: "\'"
- string > single_quoted
- single_quote: "\'"
- inner_single_str: "my-defined-label"
- single_quote: "\'"
- string > single_quoted
- single_quote: "\'"
- inner_single_str: "-v /tmp:/tmp"
- single_quote: "\'"
- string > single_quoted
- single_quote: "\'"
- inner_single_str: "https://myregistry.com/"
- single_quote: "\'"
- string > single_quoted
- single_quote: "\'"
- inner_single_str: "myPredefinedCredentialsInJenkins"
- single_quote: "\'"
- closing_brace: "}"
- closing_brace: "}"
- stagesDecl
- opening_brace: "{"
- stage
- string > single_quoted
- single_quote: "\'"
- inner_single_str: "Build"
- single_quote: "\'"
- opening_brace: "{"
- stepsDecl
- opening_brace: "{"
- step > simple_step
- IDENT: "sh"
- args > string > single_quoted
- single_quote: "\'"
- inner_single_str: "make"
- single_quote: "\'"
- closing_brace: "}"
- closing_brace: "}"
- closing_brace: "}"
- closing_brace: "}"
- ending_junk: ""
- EOI: ""
Pest語法重點標註:
當使用靜默規則時,解析結果中將不會出現該規則欄位。當解析下面規則時,解析結果中將不會存在silent,即
parsed.as_rule()
中不會存在silentsilent = _{ ... }
當使用原子語法時,整個規則體將視為一個規則,如double_quoted = ${ (quote ~ inner_double_str ~ quote) },在解析時會將
quote ~ inner_double_str ~ quote
視為一個規則,而不是三個。這有利於獲取一段完整的字串。atomic = @{ ... } compound_atomic = ${ ... }
我嘗試使用該專案解析jenkinsfile,但發現實現起來太過複雜,且jenkinsFile的語法也是一言難盡。如下,當step中帶括號和不帶括號混用時會導致解析錯誤。
steps {
echo 'test'
dir('command') {
sh "sh ./saas.sh ${params.channel} ${params.buildType} "
}
}
有精力的大神可以在此基礎上實現解析JenkinsFile的功能。
參考
- pest文件