Написание скриптовых конвейеров Jenkins (Scripted Pipelines)

Beginner

Введение

Jenkins поддерживает два стиля конвейеров (Pipeline). Declarative Pipeline использует структурированный блок pipeline { ... }, в то время как Scripted Pipeline использует код на языке Groovy с вызовами node, stage и отдельных шагов. Scripted Pipeline удобен в тех случаях, когда рабочий процесс требует более прямого управления потоком выполнения с помощью Groovy.

В этой лабораторной работе вы создадите задание конвейера с именем scripted-pipeline-demo, запустите простой скриптовый конвейер, а затем обновите его, добавив условие if и блок очистки try/finally.

Написание базового скриптового конвейера

На этом этапе вы напишете первую версию Scripted Pipeline. Блок node запрашивает у Jenkins выделение исполнителя (executor) и рабочей области. Внутри него stage обозначает видимую часть рабочего процесса, а sh выполняет команду оболочки.

Создайте файл /home/labex/project/scripted-pipeline.groovy:

cat > /home/labex/project/scripted-pipeline.groovy <<'GROOVY'
node {
    stage('Prepare') {
        echo 'Preparing scripted pipeline'
        sh 'pwd'
    }

    stage('Build') {
        echo 'Building with scripted syntax'
        sh 'echo Compiling scripted pipeline demo'
    }
}
GROOVY

Выведите содержимое файла с нумерацией строк, чтобы проверить структуру:

nl -ba /home/labex/project/scripted-pipeline.groovy

Вы должны увидеть блок node, содержащий этапы Prepare и Build.

Создание задания конвейера на основе скрипта

На этом этапе вы создадите задание Jenkins Pipeline, которое хранит Groovy-скрипт внутри конфигурации. Задания Jenkins Pipeline сохраняются в формате XML в директории /var/jenkins_home/jobs. Мы воспользуемся Python для экранирования XML-символов в Groovy-скрипте перед записью конфигурации, чтобы кавычки и фигурные скобки сохранились корректно.

Сгенерируйте конфигурацию задания Pipeline:

python3 - <<'PY'
from html import escape
from pathlib import Path

script = Path("/home/labex/project/scripted-pipeline.groovy").read_text()
config = f"""<?xml version='1.1' encoding='UTF-8'?>
<flow-definition plugin="workflow-job">
  <actions/>
  <description>Run a Jenkins scripted Pipeline example.</description>
  <keepDependencies>false</keepDependencies>
  <properties/>
  <definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps">
    <script>{escape(script)}</script>
    <sandbox>true</sandbox>
  </definition>
  <triggers/>
  <disabled>false</disabled>
</flow-definition>
"""
Path("/home/labex/project/scripted-pipeline-config.xml").write_text(config)
PY

Скопируйте конфигурацию задания в Jenkins и перезагрузите его:

docker exec jenkins mkdir -p /var/jenkins_home/jobs/scripted-pipeline-demo
docker cp /home/labex/project/scripted-pipeline-config.xml jenkins:/var/jenkins_home/jobs/scripted-pipeline-demo/config.xml
/home/labex/project/reload-jenkins.sh

Убедитесь, что Jenkins успешно загрузил задание Pipeline:

curl -fsS http://localhost:8080/job/scripted-pipeline-demo/api/json | grep -o '"name":"scripted-pipeline-demo"'

Запуск скриптового конвейера

На этом этапе вы запустите задание конвейера и проверите результат. Jenkins защищает POST-запросы с помощью crumb (токена безопасности), поэтому первая команда запрашивает crumb и сохраняет его в файле cookie для последующего использования.

Запустите первую сборку:

CRUMB=$(curl -fsS -c /tmp/jenkins-scripted-build.cookies 'http://localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
curl -fsS -b /tmp/jenkins-scripted-build.cookies -H "$CRUMB" -X POST http://localhost:8080/job/scripted-pipeline-demo/build

Дождитесь завершения сборки #1:

until curl -fsS http://localhost:8080/job/scripted-pipeline-demo/1/api/json >/tmp/scripted-build-1.json 2>/dev/null && grep -q '"building":false' /tmp/scripted-build-1.json; do
  echo "Waiting for scripted pipeline build #1..."
  sleep 3
done

Проверьте результат сборки:

curl -fsS http://localhost:8080/job/scripted-pipeline-demo/1/api/json | grep -o '"result":"SUCCESS"'

Успешный результат подтверждает, что Jenkins принял синтаксис Scripted Pipeline и выполнил шаги оболочки.

Добавление управляющих конструкций Groovy

На этом этапе вы обновите Scripted Pipeline, добавив управляющие конструкции Groovy. Блок if будет определять, должен ли выполняться этап Test. Блок try/finally гарантирует, что сообщение об очистке будет выведено даже в случае сбоя одного из этапов.

Замените скрипт конвейера на более функциональную версию:

cat > /home/labex/project/scripted-pipeline.groovy <<'GROOVY'
node {
    def runTests = true

    try {
        stage('Prepare') {
            echo 'Preparing scripted pipeline'
            sh 'pwd'
        }

        stage('Build') {
            echo 'Building with scripted syntax'
            sh 'echo Compiling scripted pipeline demo'
        }

        if (runTests) {
            stage('Test') {
                echo 'Tests enabled by Groovy condition'
                sh 'echo Running scripted pipeline tests'
            }
        }
    } finally {
        echo 'Pipeline cleanup complete'
    }
}
GROOVY

Перегенерируйте конфигурацию задания и перезагрузите Jenkins:

python3 - <<'PY'
from html import escape
from pathlib import Path

script = Path("/home/labex/project/scripted-pipeline.groovy").read_text()
config = f"""<?xml version='1.1' encoding='UTF-8'?>
<flow-definition plugin="workflow-job">
  <actions/>
  <description>Run a Jenkins scripted Pipeline example.</description>
  <keepDependencies>false</keepDependencies>
  <properties/>
  <definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps">
    <script>{escape(script)}</script>
    <sandbox>true</sandbox>
  </definition>
  <triggers/>
  <disabled>false</disabled>
</flow-definition>
"""
Path("/home/labex/project/scripted-pipeline-config.xml").write_text(config)
PY
docker cp /home/labex/project/scripted-pipeline-config.xml jenkins:/var/jenkins_home/jobs/scripted-pipeline-demo/config.xml
/home/labex/project/reload-jenkins.sh

Убедитесь, что обновленная конфигурация задания содержит текст нового этапа Test:

docker exec jenkins grep -n 'Tests enabled by Groovy condition' /var/jenkins_home/jobs/scripted-pipeline-demo/config.xml

Просмотр лога обновленного конвейера

На этом этапе вы запустите обновленный Scripted Pipeline и изучите вывод консоли. В логе должны отобразиться сообщение условного этапа Test и сообщение об очистке из блока finally.

Запустите вторую сборку:

CRUMB=$(curl -fsS -c /tmp/jenkins-scripted-build.cookies 'http://localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
curl -fsS -b /tmp/jenkins-scripted-build.cookies -H "$CRUMB" -X POST http://localhost:8080/job/scripted-pipeline-demo/build

Дождитесь завершения сборки #2:

until curl -fsS http://localhost:8080/job/scripted-pipeline-demo/2/api/json >/tmp/scripted-build-2.json 2>/dev/null && grep -q '"building":false' /tmp/scripted-build-2.json; do
  echo "Waiting for scripted pipeline build #2..."
  sleep 3
done

Выведите важные строки консоли:

curl -fsS http://localhost:8080/job/scripted-pipeline-demo/2/consoleText | grep -E 'Tests enabled|Running scripted pipeline tests|Pipeline cleanup complete|Finished: SUCCESS'

Откройте Firefox в интерфейсе рабочего стола и перейдите по адресу http://localhost:8080/job/scripted-pipeline-demo/2/console. На странице консоли должны отобразиться вывод этапа Test и сообщение об очистке.

Вывод консоли Jenkins scripted Pipeline

Резюме

Вы написали Jenkins Scripted Pipeline с использованием шагов node, stage, echo и sh, запустили его как задание конвейера, а затем добавили управляющие конструкции Groovy if и try/finally. Вы проверили обе версии конвейера, проанализировав результаты сборки Jenkins и вывод консоли.