Я новичок как в Дженкинс, так и в Groovy:)
Есть репозиторий Bitbucket, а именно. jenkins-stage , который содержит скриптовый конвейерный код (.groovy скрипты в src, vars и т. Д.).Основные конвейеры обращаются к нескольким служебным классам (которые являются частью самого репозитория jenkins-stage), например, в виде линии:
def call(body) {
def config = [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
def componentName = null
body.delegate = config
body()
.
.
.
node(globalVars.getAgent('buildAgent')) {
try {
def callHandler = ServiceLocator.getInstance().getNotifyHandler(this)
def dataUtility = ServiceLocator.getInstance().getDataUtility(this)
stage(CLEAN_STAGE) {
.
.
.
}
catch (err) {
if (err.message.contains("failed in build") == false ) {
build_status = "Exception ${err.message} in build ${env.BUILD_ID}"
callHandler.NotifyFail(build_status, PIPELINE_NAME )
}
throw err
}
}
}
}
Моя задача состоит в том, чтобы «реорганизовать» несколько классов и переместить их в общийМногоразовая библиотека.Таким образом, несколько конвейеров будут использовать один и тот же служебный код.
Существует несколько классов, в качестве примеров я приведу только пару. ServiceLocator , используемый в приведенном выше конвейере, просто возвращает нужную утилиту:
PipelineService .groovy
/**
* This is the base class for any components that wants to
* call pipeline methods and access to the jenkins internal calls
* (such as node, stage, sh, env, etc)
*/
class PipelineService implements Serializable {
def script
def env
PipelineService(Script script) {
this.script = script
this.env = script?.env
}
}
NotifyHandler .groovy (используется для публикации статуса сборки заданий Jenkins в Artifactory, отправки электронных писем и т. д.)
class NotifyHandler extends PipelineService {
NotifyHandler(Script script) {
super(script)
}
def NotifyStart(message, pipelineName) {
script.println "Pipeline: ${pipelineName} Notify commit: ${env.GIT_COMMIT} build start: ${message}"
postBuildStatus('INPROGRESS', pipelineName, env.BUILD_URL, env.GIT_COMMIT, message)
}
def NotifySuccess(message, pipelineName) {
script.println "Pipeline: ${pipelineName} Notify commit: ${env.GIT_COMMIT} build success: ${message}"
if (env.GIT_TAG != null && env.GIT_TAG != '') {
sendEmail(message, pipelineName)
}
postBuildStatus('SUCCESSFUL', pipelineName, env.BUILD_URL, env.GIT_COMMIT, message)
}
def NotifyFail(message, pipelineName) {
script.println "Pipeline: ${pipelineName} Notify commit: ${env.GIT_COMMIT} build fail: ${message}"
sendEmail(message, pipelineName)
postBuildStatus('FAILED', pipelineName, env.BUILD_URL, env.GIT_COMMIT, message)
}
def sendEmail(message, pipelineName) {
def emailBody = """
<br>Job name: <b>${env.JOB_NAME}</b></br>
<br>Change made by: <b>${env.GIT_COMMITTER_NAME}</b></br>
<br>Commit message is: <b>"${env.GIT_COMMIT_MESSAGE}"</b></br>
<p>${message} in pipeline: ${pipelineName}. <a href="${env.BUILD_URL}">Build link.</a></p>"""
.
.
.
}
def postBuildStatus(state, build_name, build_url, commit, message) {
.
.
.
// the key here should be the build name, as the uniqueness of the build status
// in bitbucket is kept using the commit hash and the key
def jsonBody = """
{
"state": "${state}",
"key": "${build_name}",
"name": "${build_name}",
"url": "${build_url}",
"description": "${message}"
}
"""
def response = script.httpRequest url: 'https://git.net/rest/build-status/1.0/commits/' + commit,
ignoreSslErrors: true,
eptType: 'APPLICATION_JSON',
authentication: 'stash-api-credentials',
httpMode: 'POST',
contentType: 'APPLICATION_JSON',
requestBody: jsonBody
// We never reach this code
script.println('Response from bitbucket:')
script.println('Status: ' + response.status)
script.println('content: ' + response.content)
return response
}
}
DataUtility .groovy
import com.cloudbees.groovy.cps.NonCPS
import java.util.regex.Matcher
import java.util.regex.Pattern
class DataUtility extends PipelineService {
DataUtility(Script script) {
super(script)
}
String createPropertiesString(commitId, commiterName, commiterEmail, buildTS, buildName, jiraNumber, buildNumber) {
//Commiter name looks like "Name Surname", we have to remove the whitespace between, whitespace will interrupt curl put properties request
return "CommitID=${commitId};Commiter=${commiterName};Email=${commiterEmail};JIRA=${jiraNumber};build.name=${buildName};build.number=${buildNumber};build.timestamp=${buildTS}".replaceAll("\\s", "")
}
String createJiraNumber(branchName) {
// The name should contain only capital letters after '/' , digits and have '-' between them
Pattern jiraPattern = Pattern.compile("/([A-Z]+\\-[0-9]+)")
def jiraNumber = null
Matcher matcher = jiraPattern.matcher(branchName)
if (matcher.find()) {
jiraNumber = matcher.group().substring(1)
}
return jiraNumber
}
@NonCPS
def getBuildInfoFromGitRepo(creds, path, commitId) {
def process = ['curl', '-u', "${creds}", '-k', "${path}?at=${commitId}"].execute()
script.writeFile file: "${env.WORKSPACE}/buildInfo.json", text: process.text
}
def updateBuildInfo(json, listOfUpdates) {
for (i in listOfUpdates) {
script.println 'Current component: ' + i
def iName = i.substring(0, i.lastIndexOf(':'))
if (json.contains(iName)) {
json = json.replaceAll(/"${iName}:[^"]+/, "\"${i}")
}
}
return json
}
}
Я имею в видук документации общей библиотеки Jenkins .Предположим, я создаю новый проект / Bitbucket repo, а именно. pipe-utilities , тогда я могу использовать аннотацию @library в Jenkinsfile jenkins-stage, чтобы использовать мою новую библиотеку.У меня есть следующие вопросы / проблемы:
- Прежде всего, я на правильном пути?
- Я считаю, что ServiceLocator не требуется, особенно после обращения к ' Динамическая загрузка библиотек '
- Необходимо / рекомендуется создавать сценарии в каталоге vars, которые будут выступать в качестве переменных в конвейерах на этапах jenkins?Нужно ли каким-либо образом использовать служебные классы с помощью этих сценариев?
- Согласно ' доступу к шагам ', 'Библиотечные классы не могут напрямую вызывать такие шаги, как sh или git.'.Хотя я не видел этот сценарий в текущих служебных классах, я не уверен, был ли добавлен класс PipelineService для решения этой проблемы!Я не понял этот раздел «Доступ к шагам»: (