Создание интеграции с сервисом Jenkins при помощи пользовательских скриптов
Пользовательские скрипты доступны только в Self-Hosted версии
Существует два способа работы с Jenkins, которые можно использовать отдельно или вместе:
- Запуск задач Jenkins по событию в Gitflic (или другому триггеру)
- Создание “зеркальных” конвейеров из Jenkins в Gitflic
Запуск задач по событиям
В рамках такого вида интеграции задачи в Jenkins запускаются по событиям gitflic при помощи REST-API Jenkins.
Настройка
Интеграция осуществляется при помощи REST-API Jenkins. Для работы с ним необходимо изнакомиться с документацией Jenkins: https://www.jenkins.io/doc/book/using/remote-access-api/
На настройках Item
, которым вы хотите управлять, необходимо включить настройку Trigger builds remotely (e.g., from scripts) и указать название (не содержание) REST-API токена Jenkins, который вы хотите связать с данным Item
После, необходимо создать переменные для скрипта. Переходим во вкладку проекта “Скрипты”, далее - во вкладку переменные
Необходимо создать переменные:
JENKINS_BASE_URL - базовый путь к Jenkins
JENKINS_JOB_NAME - название запускаемой задачи
JENKINS_TOKEN_NAME - имя токена REST-API Jenkins
JENKINS_TOKEN - токен REST-API Jenkins
JENKINS_BASIC_AUTH_BASE64 - базовая аутентификация REST-API Jenkins
Создадим скрипт. Для этого перейдём во вкладку проекта “Скрипты” и нажмём на “Новый скрипт +”
В качестве тестовой настройки можете использовать следующий код:
const url = '${JENKINS_BASE_URL}/job/${JENKINS_JOB_NAME}/build?token=${JENKINS_TOKEN_NAME}'
req = http.post(url, {}, { headers: { "Authorization": `Basic ${JENKINS_BASIC_AUTH_BASE64}` } });
console.log(JSON.stringify(req))
req.code
В качестве переменных укажите все, которые создали ранее.
Триггеры можно указать любые, в качестве отладки рекомендуем использовать событие BRANCH_UPDATE (push).
При обновлении ветки в вашем проекте, результатом работы скрипта будет запуск Item в Jenkins:
Создание “зеркальных” конвейеров
При таком варианте интеграции, запущенные в Jenkins конвейеры будут отображаться в Gitflic на странице CI/CD, однако не будут выполняться агентами. В таком случае при запуске конвейера в Jenkins создаётся “пустой” конвейер (который не обрабаывается раннерами и не имеет логов выполнения) в Gitflic, и по окончании его выполнения в Jeknins, обновляется статус в Gitflic, при этом также после выполнения отображаются стадии и их статусы, время выполнения пайплайна в Jenkins.
В итоге, Gitflic только отображает информацию о конвейерах, которые уже в свою очередь выполняются в Jenkins.
Настройка
Настройка Gitflic
Сперва необходимо создать скрипт, который будет обрабатывать запросы с Jenkins. Для этого перейжите на вкладку “Скрипты” и нажмите на кнопку “Новый скрипт”
Далее укажите название и описание, в качестве скрипта используйте код ниже:
let res = undefined;
console.log(request);
request = JSON.parse(request);
const event = request.event;
function createStages(stages, pipelineId) {
return stages.map(stage => pipelineService.createStage(pipelineId, stage.name, stage.status));
}
if (event == "new_pipeline") {
console.log("creating pipeline");
res = pipelineService.createBlank(projectId, request.ref);
}
if (event == "pipeline_finished") {
console.log("finished pipeline");
pipelineService.changeStatus(request.uuid, request.pipelineStatus);
createStages(request.stages, request.uuid);
pipelineService.setExecutionTime(request.uuid, request.duration);
res = "ok";
}
res;
Нажмите на кнопку “Создать скрипт +”
После сохранения, проверьте корректность отображения скрипта. Скопируйте UUID скрипта для настройки Jenkins
Создайте файл Jenkinsfile
в репозитории со следующим содержанием:
pipeline {
agent any
stages {
stage('echo'){
steps {
echo 'hello Jenkins from Gitflic!!! =)'
}
}
}
}
Настройка Jenkins
Для работы интеграции необходимо установить следующие плагины:
Git
Credentials
Pipeline: multibranch
, Groovy events listener plugin
.
Перейдите в настрйоки Jenkins, в секцию System.
На данной странице необходимо определить несколько глобальных переменных, а именно:
GITFLIC_API_BASE_URL - основной путь REST-API Gitflic
GITFLIC_API_TOKEN - токен REST-API Gitflic
GITFLIC_INTEGRATION_SCRIPT_UUID - UUID скрипта, которого мы создали ранее
GITFLIC_PROJECT_ALIAS - название проекта, к которому привязан скрипт
GITFLIC_PROJECT_OWNER_ALIAS - имя автора проекта, к которому привязан скрипт
Далее в блоке Groovy events listener plugin напишите следующий код:
@Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.1')
@Grab('commons-codec:commons-codec:1.9')
import groovyx.net.http.*;
import static groovyx.net.http.ContentType.JSON;
import jenkins.model.*;
def restPath = "/rest-api/project/${env.GITFLIC_PROJECT_OWNER_ALIAS}/${env.GITFLIC_PROJECT_ALIAS}/script/${env.GITFLIC_INTEGRATION_SCRIPT_UUID}";
def restClient = new RESTClient("${env.GITFLIC_API_BASE_URL}");
restClient.headers['Authorization'] = "token ${env.GITFLIC_API_TOKEN}";
def client = [
executeScript: { Map postParams ->
restClient.post(
path: restPath,
body: postParams,
requestContentType: JSON
)
}
];
if (event == Event.JOB_STARTED) {
def ref = env.BRANCH_NAME;
if (ref.startsWith("origin/")) {
ref = ref.substring(7);
}
def resp = client.executeScript([
"event": "new_pipeline",
"ref": ref
]);
if (!context.hasProperty('pipelineUuidByBuildId')) {
context.pipelineUuidByBuildId = [:];
}
if (resp.status / 100 == 2 && resp.data.result == "SUCCESS") {
context.pipelineUuidByBuildId[env.BUILD_ID] = resp.data.returnedValue.id;
}
}
if (event == Event.JOB_COMPLETED) {
if (context.containsKey("pipelineUuidByBuildId") && context.get("pipelineUuidByBuildId").containsKey(env.BUILD_ID)) {
def runResult = run.getResult();
def pipelineUuid = context.pipelineUuidByBuildId[env.BUILD_ID];
context.pipelineUuidByBuildId.remove(env.BUILD_ID);
def pipelineStatus = getStatus(runResult.toString());
client.executeScript([
"event": "pipeline_finished",
"pipelineStatus": pipelineStatus,
"uuid": pipelineUuid,
"stages": getStages(run).collect{ ["name": it.name, "status": getStatus(it.state)] },
"duration": run.getDuration(),
"timestamp": run.getTimeInMillis(),
]);
}
}
def getStatus(rawStatus) {
switch (rawStatus.toUpperCase()) {
case "SUCCESS": return "SUCCESS";
case "UNSTABLE":
case "FAILURE": return "FAILED";
case "NOT_BUILT": return "SKIPPED";
case "ABORTED": return "CANCELED";
}
}
def getStages(run) {
def plugin = Jenkins.instance.pluginManager.plugins.find({it.getShortName() == "pipeline-graph-view"});
def classLoader = plugin.classLoader;
def graphApiClassName = "io.jenkins.plugins.pipelinegraphview.utils.PipelineGraphApi";
def graphApiClass = classLoader.loadClass(graphApiClassName);
return graphApiClass.getConstructor(run.class).newInstance(run).createTree().stages;
}
Теперь создайте конвейер в Jenkins.
Перейдите на основную страницу и добавьте Multibranch pipeline
Перейдите в настройки нового конвейера и добавим источник в виде git-репозитория проект в Gitflic
Сохраните и запустите конвейер.
В начале выполнения конвйера, в Gitflic появится “пустой” конвейер.
По окончании выполнения конвейера в Jenkins, его статус обновится в соответствии со статусом в Jenkins, будут добавлены стадии и время выполнения конвейера