Синтаксис Пайплайна Jenkins: Подробное руководство для начинающих

Разберитесь в синтаксисе пайплайна Jenkins с помощью этого подробного руководства для начинающих. Изучите основы Декларативных и Скриптовых пайплайнов, включая агенты, стадии, шаги, пост-действия, среды, параметры и лучшие практики. Получите возможность эффективно создавать надежные рабочие процессы CI/CD с помощью практических примеров и действенных советов.

Синтаксис конвейеров Jenkins: Полное руководство для начинающих

Синтаксис конвейеров Jenkins позволяет описать процесс сборки, тестирования и развертывания в Jenkinsfile, который хранится вместе с вашим кодом. Это важно, потому что изменения в конвейере можно просматривать, версионировать и откатывать, как и код приложения.

Если вы новичок в конвейерах Jenkins, начните с декларативного синтаксиса. Он структурирован, читаем и покрывает большинство CI/CD-процессов без глубоких знаний Groovy.

Декларативный и скриптовый конвейеры

Jenkins поддерживает два стиля конвейеров.

Декларативный конвейер использует строгую структуру pipeline { ... }. Это лучший выбор по умолчанию для большинства команд, так как Jenkins может проверять структуру файла и отображать этапы в интерфейсе.

Скриптовый конвейер использует Groovy внутри блоков node { ... }. Он дает больше контроля, но его легче превратить в сложный для поддержки конвейер, если ваша команда не знакома с Groovy.

Сначала используйте декларативный. Переходите к скриптовому только тогда, когда нужна логика, которую декларативный не может выразить.

Минимальный декларативный конвейер

Базовый Jenkinsfile содержит агента, этапы и шаги:

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                echo 'Building the application'
                sh 'mvn clean package'
            }
        }

        stage('Test') {
            steps {
                sh 'mvn test'
            }
        }
    }
}

agent any указывает Jenkins запускать конвейер на любом доступном агенте. Каждый stage отображается отдельно в интерфейсе Jenkins. Блок steps содержит команды, которые выполняет Jenkins.

На агентах Windows используйте bat вместо sh:

bat 'gradlew.bat test'

Директива agent

Директива agent определяет, где будет выполняться конвейер или этап.

Запуск на любом доступном агенте:

agent any

Запуск на агенте с определенной меткой:

agent { label 'linux && docker' }

Пропуск глобального агента и выбор для каждого этапа:

pipeline {
    agent none

    stages {
        stage('Build') {
            agent { label 'linux' }
            steps {
                sh './build.sh'
            }
        }
    }
}

agent none полезен, когда разные этапы требуют разных сред, например, Linux для сборки и Windows для тестирования установщика.

Этапы и шаги

Используйте этапы, чтобы разделить конвейер на понятные части: получение кода, сборка, тестирование, упаковка, развертывание.

stages {
    stage('Checkout') {
        steps {
            checkout scm
        }
    }

    stage('Unit Tests') {
        steps {
            sh 'npm test'
        }
    }
}

Делайте этапы осмысленными. Этап с названием Run и пятьюдесятью командами сложно отлаживать. Конвейер с двадцатью мелкими этапами создает шум. Стремитесь к этапам, которые соответствуют реальным контрольным точкам процесса.

Переменные окружения

Используйте environment для значений, которые нужны на нескольких этапах:

pipeline {
    agent any

    environment {
        APP_NAME = 'orders-api'
        IMAGE = "registry.example.com/team/orders-api:${env.BUILD_NUMBER}"
    }

    stages {
        stage('Build Image') {
            steps {
                sh 'docker build -t "$IMAGE" .'
            }
        }
    }
}

В строках Groovy вы можете читать переменные через env.APP_NAME. В шагах оболочки Jenkins экспортирует переменные окружения, поэтому $APP_NAME и $IMAGE работают внутри оболочки.

Не помещайте секреты в environment. Используйте учетные данные Jenkins с withCredentials.

Параметры

Параметры позволяют выбирать значения при ручном запуске сборки:

pipeline {
    agent any

    parameters {
        string(name: 'BRANCH_NAME', defaultValue: 'main', description: 'Ветка Git для сборки')
        booleanParam(name: 'RUN_TESTS', defaultValue: true, description: 'Запустить модульные тесты')
        choice(name: 'DEPLOY_ENV', choices: ['dev', 'staging', 'prod'], description: 'Целевая среда')
    }

    stages {
        stage('Show Inputs') {
            steps {
                echo "Ветка: ${params.BRANCH_NAME}"
                echo "Цель развертывания: ${params.DEPLOY_ENV}"
            }
        }
    }
}

Используйте параметры для того, что может меняться между запусками. Не используйте их для обхода проверки изменений в продакшене.

Условные этапы с when

Директива when управляет выполнением этапа:

stage('Deploy to Production') {
    when {
        branch 'main'
    }
    steps {
        sh './deploy-prod.sh'
    }
}

Также можно использовать выражение:

stage('Test') {
    when {
        expression { return params.RUN_TESTS }
    }
    steps {
        sh 'npm test'
    }
}

Помещайте when на этап, а не внутрь steps.

Пост-действия

Блоки post выполняются после завершения этапа или конвейера. Они полезны для публикации отчетов о тестировании, архивирования артефактов сборки и очистки.

pipeline {
    agent any

    stages {
        stage('Test') {
            steps {
                sh 'mvn test'
            }
            post {
                always {
                    junit 'target/surefire-reports/*.xml'
                }
            }
        }
    }

    post {
        failure {
            echo 'Конвейер завершился ошибкой'
        }
        always {
            cleanWs()
        }
    }
}

junit публикует результаты тестов, даже если тесты не прошли. cleanWs() из плагина Workspace Cleanup, поэтому установите этот плагин перед использованием.

Опции

Используйте options для настройки поведения конвейера:

pipeline {
    agent any

    options {
        timestamps()
        timeout(time: 30, unit: 'MINUTES')
        disableConcurrentBuilds()
        buildDiscarder(logRotator(numToKeepStr: '20'))
    }

    stages {
        stage('Build') {
            steps {
                sh './build.sh'
            }
        }
    }
}

Эти опции делают логи более читаемыми, останавливают зависшие сборки, предотвращают одновременные запуски одной задачи и ограничивают историю старых сборок.

Практический конвейер для начинающих

Этот пример получает код, собирает Java-проект, публикует результаты тестов и архивирует упакованный JAR:

pipeline {
    agent { label 'linux' }

    options {
        timestamps()
        timeout(time: 30, unit: 'MINUTES')
        disableConcurrentBuilds()
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }

        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }

        stage('Publish') {
            steps {
                junit 'target/surefire-reports/*.xml'
                archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
            }
        }
    }
}

Это лучшая отправная точка, чем огромный конвейер развертывания. Как только сборка станет надежной, добавьте публикацию образов, сканирование безопасности или этапы развертывания.

Основы скриптового конвейера

Простой скриптовый конвейер выглядит так:

node('linux') {
    stage('Checkout') {
        checkout scm
    }

    stage('Build') {
        sh 'mvn clean package'
    }
}

Не помещайте блок pipeline {} декларативного конвейера внутрь скриптового. Держите два стиля отдельно, если у вас нет особой, проверенной причины смешивать небольшие скриптовые секции внутри декларативных блоков script { ... }.

Хорошие привычки при работе с конвейерами

Храните Jenkinsfile в системе контроля версий. Держите секреты в учетных данных Jenkins. Давайте этапам имена, соответствующие выполняемой работе. Публикуйте отчеты в блоках post, чтобы даже при сбоях оставались полезные данные. Добавляйте тайм-ауты, чтобы сборка не зависала на всю ночь.

Большинство проблем начинающих конвейеров возникают из-за скрытых предположений: инструмент существует на одном агенте, но не на другом, секрет жестко закодирован, или отчет публикуется только при успехе. Сделайте эти предположения явными в конвейере, и Jenkins станет гораздо более надежным.