一、概述
與任何編程環(huán)境一樣,在 Jenkins 流水線中,集中化功能、共享公共代碼和代碼重用都是快速、有效地進行開發(fā)的基本技術(shù)。這些實踐鼓勵使用標(biāo)準(zhǔn)方法來調(diào)用功能,為更復(fù)雜的操作創(chuàng)建構(gòu)建塊并隱藏復(fù)雜性。它們還可以用于提供一致性以及鼓勵約定優(yōu)于配置以簡化任務(wù)。
Jenkins 允許用戶完成所有這些操作的 一個關(guān)鍵方法就是,使用共享流水線庫。共享流水線庫是由存儲在代碼倉庫中的代碼組成的,該代碼倉庫由 Jenkins 自動下載并可供流水線使用。
二、可信庫和不可信庫
可信庫
可信庫可以調(diào)用/使用 Java 中的任何方法、 Jenkins API 、Jenkins 插件、 Groovy 語言等。對可信庫進行更新應(yīng)該需要適當(dāng)級別的源碼版本控制訪問和驗證
不可信庫
- 不可信代碼是被調(diào)用和使用限制的代碼 調(diào)用先前列出的方法類型不允許使用相同的自由度,而且它不能像可信代碼那樣訪問更大的內(nèi)部對象集合。
- 不可信代碼運行在 Groovy 沙箱中,它具有一個可“安全”調(diào)用的方法列表。在沙箱中運行時, Jenkins 會監(jiān)控庫代碼是否在嘗試調(diào)用不存在于安全列表中的任何方法。如果是,則停止執(zhí)行代碼并且必須由管理員授予批準(zhǔn)。
三、內(nèi)部庫與外部庫
內(nèi)部庫
這是一種管理庫的舊方法,但仍然是一種選擇。 Jenkins 包含一個內(nèi)部 Git 倉庫,可用于存儲內(nèi)部庫或測試目的。放置在此庫中的任何內(nèi)容對于所有腳本都是可信的,但推送代碼到該庫的任何人都必須具有相應(yīng)的管理權(quán)限。
內(nèi)部 Git 倉庫有 一個特定的名稱: workflowLibs.git 。它可以通過 SSH 訪問或 HTTP 訪問與 Git 一起工作。
SSH訪問
系統(tǒng)管理→全局安全配置
指定一個端口并保存
用戶列表
選admin用戶
設(shè)置
講linux服務(wù)器的公鑰粘貼到下方
到linux機器上執(zhí)行如下命令
git clone ssh://admin@192.168.1.2:22222/workflowlibs.git
HTTP 訪問
git clone http://192.168.1.2:8080/workflowLibs.git
一旦復(fù)制了 內(nèi)部倉庫 ,它的初始狀態(tài)為空。要開始使用它,你需要切換到工作目錄并創(chuàng)一個新的主分支:
cd workflowLibs/
git checkout -b master
外部庫
配置一個外部庫
系統(tǒng)管理→系統(tǒng)配置→Global Pipeline Libraries
參數(shù)解釋:
Name:庫的名稱(將在腳本中使用它來進行訪問)
Default Version:可以是分支或標(biāo)簽
Load implicitly:隱式加載。如果選中,腳本將自動訪問這個庫,而不需要通過@Library請求它;
Allow default version to be overridden:可以通過在@Library 注解中指定@version 來覆蓋默認(rèn)版本,如@Library('libname@version')_
Includ@Library changes in recent job changes:在最近的任務(wù)變更集中包含@Library 更改。
可以通過在注解中添加 changelog = <boolean> 參數(shù)來覆蓋此設(shè)置,如:@Library(value="libname[@version]",changelog=truejfalse)
四、在流水線腳本中使用庫
從源碼版本控制中自動下載庫
加載庫到腳本中
如果有內(nèi)容,那么 workflowlibs 全局內(nèi)部庫將會被自動加載。你可以使用隱式加載復(fù)選項指定用于流水線的外部庫應(yīng)該被自動加載。
如果你選擇了隱式加載庫,你仍然可以使用以下格式的import 語句指定一組方法
//導(dǎo)人 一些方法的合集
import static org.demo.Utilities.*
如果不使用自動加載庫的選項,則必須在流水線腳本中使用語句來顯式地加載庫并使其可用 。有幾種不同的方法可以做到這 點
@Library 注解
在基于Java 的語 句中,注解是可以放在代碼中以增加(或“注解”)其他代碼的元數(shù)據(jù)。
在使用 Jenkins 流水線語法的情況下,注解結(jié)構(gòu)不僅用作注解, 且能更多地用作另一種語法構(gòu)造。
具體來說,你可以在流水線腳本中使用 Library 注解來 加載庫。要 加載庫的名稱以及可選的版本都被指定為參數(shù)。此處是其基本語法:
@Library ('<libname>[@<version>]')_ [<import statement>]
關(guān)于語法有以下要點。
以下是一些簡單的示例:
//加載 一個庫的默認(rèn)版本
@Library ('mylib')_
//加載一個庫的指定版本并覆蓋默認(rèn)版本
@Library('yourlib@2.0')_
//用一條語句訪 問多個庫
@Library(['myLib','yourlib@master')
//帶導(dǎo)人語句的注解
@Library('mylib@l.0') import static org.demo.Utilities.*
注解會被放置在腳本的開頭,腳本式流水線的 node 行上方,或者聲明式流水線中pipeline 上方。
庫步驟
從Jenkins 2.7 開始,可以在流水線中使用實際的 library 步驟。語法類似于注解:
library "<libname>[@<version>]"
由于這是 一個實際的流水線步驟,因此可以將其放置在流水線中的任何位置。它還允許使用變 量代替參數(shù)。例如,你可以將其定義為從內(nèi)置 BRANCH_NAME 變量代表的當(dāng)前任何版本中獲取共享庫。
library "<libname>@$<BRANCH_NAME>"
庫指令
在聲明式流水線中,我們還有另 一個用于提取庫的選項。我們可以使用 libraries 指令指定要加載的庫。在指令中,我們可以使用 lib 語句指定庫。
五、Jenkins 項目中的庫范圍
如果在 Jenkins 全局/根級別指定隱式加載 ,則所 有任務(wù)都將自動下載庫并且?guī)炜捎谩?br> 但是,如果你配置文件夾并隱式地加載一 個指定的共享庫,則只有該文件夾中的任務(wù)才能自動下載和訪問庫
六、共享庫代碼的結(jié)構(gòu)
一個共享庫樹有 3個子樹:src 、vars和 resources 。
src
此區(qū)域旨在使用標(biāo)準(zhǔn) Java 目錄結(jié)構(gòu)的 Groovy 文件進行設(shè)置(即src/org/foo/bar.groovy),當(dāng)執(zhí)行流水線時,它將被添加到類路徑中。
示例一:
創(chuàng)建 一個不包 在類中的簡單方怯
在外部庫創(chuàng)建groovy文件:src/org/demo/build.groovy
build.groovy的內(nèi)容:
//org.demo.build.groovy
package org.demo
def mvnBuild(args) {
sh """
echo "mvn -q ${args} -Dmaven.test.skip=true"
"""
}
在腳本式流水線中引用:
node() {
def myBuild = new org.demo.build()
myBuild.mvnBuild("clean install")
}
示例二:
創(chuàng)建 一個封閉類(以便定義超類) ,然后,你可以在類的構(gòu)造函數(shù)或方法中通過將 steps 對象傳遞給 一個方法來獲取訪問所有 DSL 步驟的權(quán)限。
src/org/demo/Utilities.groovy
//org.demo.Utilities.groovy
class Utilities implements Serializable {
def steps
Utilities(steps) {this.steps = steps}
def mvnBuild(args) {
steps.sh """
echo "mvn -q ${args} -Dmaven.test.skip=true"
"""
}
}
由于我們將其封裝在 一個類中,因此該類必須實現(xiàn) Serializable 以支持在流水線停 止或重新啟動 時能保存狀態(tài)。
腳本式流水線
@Library('share_library') import org.demo.Utilities
def utils = new Utilities(steps)
node() {
step([$class: 'WsCleanup']) //清理工作空間
utils.mvnBuild "clean install"
}
示例三:
其它項(如環(huán)境變量)可以用與步驟相同的方式進行傳遞。在下面的代碼中,我們傳入 env 對象并在我 的代碼中使用它
src/org/demo/Utilities.groovy
//org.demo.Utilities.groovy
class Utilities implements Serializable {
def env
def steps
Utilities(env,steps) {
this.env = env
this.steps = steps
}
def mvnBuild(args) {
steps.sh """
echo "構(gòu)建號:${env.BUILD_NUMBER}"
echo "mvn -q ${args} -Dmaven.test.skip=true"
"""
}
}
腳本式流水線代碼:
@Library('share_library') import org.demo.Utilities
def utils = new Utilities(env,steps)
node() {
step([$class: 'WsCleanup']) //清理工作空間
utils.mvnBuild "clean install"
}
示例四(推薦使用
)
對于更簡單的情況,你只需傳人Script 對象,該對象已經(jīng)可以訪問所有內(nèi)容。在這種情況下,我們將它傳遞給靜態(tài)方法:
src/org/demo/Utilities.groovy腳本
//org.demo.Utilities.groovy
package org.demo
class Utilities {
static def mvnBuild(script,args) {
script.sh """
echo "構(gòu)建號:${script.env.BUILD_NUMBER}"
echo "mvn -q ${args} -Dmaven.test.skip=true"
"""
}
}
腳本式流水線代碼
@Library('share_library') import static org.demo.Utilities.*
node() {
step([$class: 'WsCleanup']) //清理工作空間
mvnBuild this, "clean install"
}
vars
你可以在一 個Groovy文件的vars區(qū)域 定義可能想要用于流水線 中變量 的任何方法。
示例
vars/timedCommand.groovy
// vars/timedCommand.groovy
def setCommand(commandToRun) {
cmd = commandToRun
}
def getCommand() {
cmd
}
def runCommand() {
timestamps {
cmdOut = sh(script:"${cmd}",returnStdout:true).trim()
}
}
def getOutput() {
cmdOut
}
cmd 和cmdOut 在此處不是字段,而是按需創(chuàng)建的對象。
腳本式流水線代碼:
@Library('share_library')_
node() {
step([$class: 'WsCleanup']) //清理工作空間
timedCommand.cmd = 'echo 123'
echo timedCommand.cmd
timedCommand.runCommand()
echo timedCommand.getOutput()
}
全局變量的自動文檔引用
在vars目錄下創(chuàng)建文件timedCommand.txt
內(nèi)容為:
# 變量文檔說明
xxxx
當(dāng)執(zhí)行過使用timedCommand變量的流水線后,在流水線語法→全局變量
可以看到有關(guān)timedCommand變量的文檔說明
像使用步驟一樣使用全局變量
你可以創(chuàng)建全局變量定義,其行為類似于流水線腳本中的步驟。也就是說,它們可以像常規(guī)流水線步驟 一樣被調(diào)用 。
解決這個問題的方法是在全局變量的定義中定義 call 方法。
示例一:
vars/timedCommand2.groovy
//vars/timedCommand2.groovy
def call(cmd,logFilePath) {
timestamps {
cmdOutput = sh(script:"${cmd}",returnStdout:true).trim()
}
echo cmdOutput
writeFile file:"${logFilePath}", text:"${cmdOutput}"
}
腳本式流水線:
@Library('share_library')_
node() {
step([$class: 'WsCleanup']) //清理工作空間
timedCommand2 'ls -la','test.log'
}
示例二
腳本式流水線
@Library('share_library')_
node() {
step([$class: 'WsCleanup']) //清理工作空間
timedCommandWindow {
echo "在Windows上執(zhí)行"
}
timedCommandLinux {
echo "在Linux上執(zhí)行"
}
}
示例三(推薦使用)
我們可以擴展調(diào)用機制來創(chuàng)建 一個簡單的框架,使得我們在腳本中使用“步驟”更簡單并且更像是具有多個值的標(biāo)準(zhǔn) DSL 調(diào)用
這是通過將參數(shù)傳遞給 一個映射, 并在步驟中的其他處理環(huán)節(jié)引用映射來實現(xiàn)的。
vars/timedCommand3.groovy
//vars/timedCommand3.groovy
def call(body) {
//收集賦值并傳送到我們的映射中
def settings= [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = settings
body()
timestamps {
cmdOutput = sh(script:"${settings.cmd}",returnStdout:true).trim()
}
echo cmdOutput
writeFile file:"${settings.logFilePath}", text:"${cmdOutput}"
}
通過 def settings = [] 語法聲明了 一個Groovy 映射。然后將傳參保存在映射中,然后我們可以執(zhí)行任何步驟。這里用于 delegate 的引用與 Groovy能有關(guān)。
腳本式流水線:
@Library('share_library')_
node() {
step([$class: 'WsCleanup']) //清理工作空間
timedCommand3 {
cmd = 'ls -la'
logfilePath = 'log.out'
}
}
這種方式最有價值的地方在于,允許我們使用命名參數(shù)調(diào)用函數(shù),并且無關(guān)參數(shù)的順序,這可以使我們的流水線腳本中的代碼更簡單且更容易理解和維護。
resources
非Groovy 文件可以存儲在此目錄中。它們可以通過外部庫中的 libraryResource 步驟加載。
語法:
def datafile = libraryResource 'org/conf/data/lib/datafile.ext'
六、使用第三方庫
七、直接加載代碼
groovy調(diào)用其它groovy腳本定義的方法
八、從外部 SCM 加載代碼
依賴遠(yuǎn)程 加載器插件 (Pipeline Remote Loader plugin )
九、回放外部代碼和庫
可以直接修改代碼,并點擊運行,旨在驗證修改的代碼,并不會改變原來的代碼,主要用于臨時驗證代碼文章來源:http://www.zghlxwxcb.cn/news/detail-403415.html
十、深入研究可信與不可信代碼
十一、參考文章
《Jenkins2權(quán)威指南》
Jenkins 設(shè)置共享庫
Jenkins共享庫使用文章來源地址http://www.zghlxwxcb.cn/news/detail-403415.html
到了這里,關(guān)于jenkins擴展你的流水線(共享庫)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!