Как я могу сослаться на каталог Jenkinsfile с помощью Pipeline?
У меня есть отличный файл, я хочу запустить из Jenkinsfile.
то есть. load script.groovy
Однако я не уверен, как я могу ссылаться на этот файл, если он хранится в том же каталоге, что и Jenkinsfile. Я загружаю Jenkinsfile из Git. Я заметил, что это создает папку с именем workspace@script
, Он не помещает это в каталог рабочей области. Я мог бы жестко закодировать папку, но я не уверен, что правила в этом, и кажется немного избыточным, чтобы проверить код снова.
java.io.FileNotFoundException: /opt/jenkins_home/jobs/my_job/workspace/script.groovy (No such file or directory)
По умолчанию он загружается из рабочей области, а не из workspace@script
Я пытаюсь преобразовать сценарий BuildFlow в сценарий конвейера (рабочий процесс). Но я нахожу, что это не так просто, как копировать и вставлять.
Jenkinsfile
node {
//get parameters from Job
def builds = builds.tokenize(",")
def ip_address_node = ip_address_node.trim()
def port_node = port_node.trim()
def branch = branch.trim()
def workspace = pwd()
stage 'Checking out code from esb repository'
git branch: branch, url: 'ssh://git@giturl/integration_bus.git'
load '../workspace@script/esb_deploybar_pipeline/deploy_esb.groovy'
}
deploy_esb.groovy (это из старого buildflow, пытающегося запустить в конвейере)
import groovy.transform.ToString
import groovy.transform.EqualsAndHashCode
@EqualsAndHashCode
@ToString
class BarDeploy {
String barFile
String app
String integrationServer
}
//parse csv
def csvItemsApps = new HashSet<BarDeploy>();
def csvItemsLibs = new HashSet<BarDeploy>();
def deploymentMapFile = new File(workspace + "/ESB_Deployment_Map.csv")
def isFirstLine = true
stage 'Parsing ESB Deployment CSV'
deploymentMapFile.withReader { reader ->
while(line = reader.readLine()) {
if(isFirstLine)
{
isFirstLine = false
continue
}
csvLine = line.split(",")
app = csvLine[0]
intServer = csvLine[1]
def barDeploy = new BarDeploy()
barDeploy.app = app
barDeploy.integrationServer = intServer
csvItemsApps.add(barDeploy)
//get shared libs
if(csvLine.length > 2 && csvLine[2] != null)
{
def sharedLibs = csvLine[2].split(";")
sharedLibs.each { libString ->
if(!libString.isAllWhitespace())
{
def lib = new BarDeploy()
lib.app = libString
lib.integrationServer = intServer
csvItemsLibs.add(lib)
}
};
}
}
};
//get list of bar files to deploy from html and consolidate bar files to deploy with apps in csv
for (int i = 0; i < builds.size(); i+=3)
{
if(builds[i].equals("false"))
{
//Don't deploy bar if checkbox isn't selected
continue
}
foundInCSV = false
appToDeploy = builds[i + 1]
barFileToDeploy = builds[i + 2]
iterator = csvItemsApps.iterator()
while (iterator.hasNext())
{
barDeploy = iterator.next()
if(appToDeploy.equalsIgnoreCase(barDeploy.app))
{
barDeploy.barFile = barFileToDeploy
foundInCSV = true
}
}
iterator = csvItemsLibs.iterator()
while (iterator.hasNext())
{
barDeploy = iterator.next()
if(appToDeploy.equalsIgnoreCase(barDeploy.app))
{
barDeploy.barFile = barFileToDeploy
foundInCSV = true
}
}
if(foundInCSV == false)
{
throw new RuntimeException("App: " + appToDeploy + " not found in ESB_Deployment_Map.csv. Please add CSV Entry.")
}
}
//Do deploy, deploy shared libs first
deployCSVItemsInParallel(ip_address_node,port_node,branch,env_key,csvItemsLibs)
deployCSVItemsInParallel(ip_address_node,port_node,branch,env_key,csvItemsApps)
def deploy(ip_address_node,port_node,branch,deployItem,env_key)
{
def integrationServer = deployItem.integrationServer
def app = deployItem.app
def barFile = deployItem.barFile
if(barFile == null)
{
return;
}
println("Triggering Build -> ESB App = " + app + ", Branch = "
+ branch + ", Barfile: " + barFile + ", Integration Server = " + integrationServer + ", IP Address: " + ip_address_node
+ ", Port: " + port_node + ", Env_Key: " + env_key)
build_closure = { ->
build("esb_deploybar",
ip_address_node: ip_address_node, port_node: port_node,
integrationServer: integrationServer, branch: branch, app: app, barFile: barFile, env_key: env_key)
}
return build_closure
}
def deployCSVItemsInParallel(ip_address_node,port_node,branch,env_key,csvItems)
{
def build_closures = []
iterator = csvItems.iterator()
while (iterator.hasNext())
{
barDeploy = iterator.next()
def build_closure = deploy(ip_address_node,port_node,branch,barDeploy,env_key)
if(build_closure != null)
{
build_closures.add(build_closure)
}
}
if(build_closures?.size() > 0)
{
parallel(build_closures)
}
}
5 ответов
Есть один сценарий, о котором я не видел никого. Вот как можно загрузить скрипты Groovy, когда задание должно выполняться на агенте / подчиненном Jenkins, а не на главном.
Поскольку мастер - это тот, который проверяет проект конвейера Jenkins из SCM, скрипты Groovy находятся только в файловой системе мастера. Так что пока это будет работать
node {
def workspace = pwd()
def Bar = load "${workspace}@script/Bar.groovy"
Bar.doSomething()
}
Это только счастливое совпадение, потому что узел, который клонирует конвейер из SCM, является тем же самым, который пытается загрузить в него скрипты groovy. Однако, просто добавив имя другого агента для выполнения:
node("agent1"){
def workspace = pwd()
def Bar = load "${workspace}@script/Bar.groovy"
Bar.doSomething()
}
Сбой, в результате чего:
java.io.IOException: java.io.FileNotFoundException: /Jenkins/workspace/Foo_Job@script/Bar.groovy (No such file or directory)
Это потому, что этот путь:
/Jenkins/workspace/Foo_Job@script/
Существует только на главной коробке Дженкинса. Нет в коробке запущенного агента1.
Поэтому, если вы столкнулись с этой проблемой, обязательно загрузите скрипты groovy из мастера в глобально объявленные переменные, чтобы агент мог затем использовать их:
def Bar
node {
def workspace = pwd()
if(isUnix()){
Bar = load "${workspace}@script/Bar.groovy"
}
else{
Bar = load("..\\workspace@script\\Bar.groovy")
}
}
node("agent1"){
Bar.doSomething()
}
Примечание. Переменная, используемая для передачи модуля между узлами, должна быть объявлена вне блоков узлов.
Если файл deploy_esb.groovy хранится в том же SCM, что и Jenkinsfile, вы можете сделать:
node {
def workspace = pwd()
load "${workspace}@script/esb_deploybar_pipeline/deploy_esb.groovy"
}
Если этот файл script.groovy находится в корне вашего проекта, например Jenkinsfile, он будет извлечен из git в ту же папку, что и ваш Jenkinsfile. Таким образом, команда, которую вы используете, должна работать хорошо.
Вы получаете какую-то ошибку? Пожалуйста, предоставьте более подробную информацию, если это так.
РЕДАКТИРОВАТЬ: теперь я могу видеть, что находится в вашем Jenkinsfile, я вижу, что вы проверяете git проект с именем gration_bus, в котором находится Groovy скрипт. Вы можете указать место, где это проверено, вот так:
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'esb_deploy']], submoduleCfg: [], userRemoteConfigs: [[url: 'ssh://git@giturl/integration_bus.git']]])
в отличие от того, что у вас есть
git branch: branch, url: 'ssh://git@giturl/integration_bus.git'
Тогда вы сможете ссылаться на скрипт groovy в папке esb_deploy следующим образом
load 'esb_deploy/esb_deploybar_pipeline/deploy_esb.groovy'
Это должно работать
load "${WORKSPACE}/../${JOB_NAME}@script/esb_deploy/esb_deploybar_pipeline/deploy_esb.groovy"
Вы можете просто предположить, что все файловые операции в Jenkinsfile
относятся к текущему рабочему пространству (которое является рабочим пространством по умолчанию при использовании load
внутри node
).
Так что если целевой файл (скажем, deploy_esb.groovy
) находится внутри папки foo
в вашем SCM это должно работать без дополнительной настройки:
git branch: branch, url: 'ssh://git@giturl/integration_bus.git'
load 'foo/deploy_esb.groovy'
Или это если файл для загрузки находится в том же хранилище, что и Jenkinsfile
:
checkout scm
load 'foo/deploy_esb.groovy'
Была такая же проблема. Закончилось дополнительной операцией клонирования, чтобы получить копию репозитория сценария в рабочей директории dir, чтобы я мог надежно получать к нему доступ к файлам groovy:
dir ('SCRIPTS_DIR') {
checkout scm
commonScripts = load 'subdir/Common.groovy' // no def, so script is global
}