Что вы предпочитаете использовать в Jenkins: Freestyle Project или Pipeline (включая Shared Libraries)?

«Что вы предпочитаете использовать в Jenkins: Freestyle Project или Pipeline (включая Shared Libraries)?» — вопрос из категории CI/CD, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для всех новых и сложных проектов я использую Pipeline-as-Code (Jenkinsfile), а для стандартизации и переиспользования логики — Shared Libraries. Freestyle Project оставляю только для очень простых, разовых задач.

Почему Pipeline и Shared Libraries:

  1. Контроль версий и воспроизводимость: Jenkinsfile хранится вместе с кодом приложения в Git. Это дает полную историю изменений, возможность отката и гарантирует, что сборка на любом Jenkins-агенте будет идентичной.
  2. Сложные workflow: Pipeline позволяет легко описывать параллельные этапы, условия, обработку ошибок (retry, timeout) и ручные утверждения (input).
  3. Shared Libraries для DRY (Don't Repeat Yourself): Вместо копирования одинаковых шагов в каждый Jenkinsfile, я выношу общую логику (например, развертывание в определенное окружение, отправку уведомлений, сбор артефактов) в библиотеку.

Пример Declarative Pipeline с вызовом метода из Shared Library:

// Jenkinsfile в репозитории приложения
@Library('my-shared-lib@main') _

pipeline {
    agent any
    parameters {
        choice(name: 'ENVIRONMENT', choices: ['dev', 'staging', 'prod'], description: 'Target environment')
    }
    stages {
        stage('Build & Test') {
            steps {
                script {
                    mySharedLib.buildMavenApp()
                    mySharedLib.runIntegrationTests()
                }
            }
        }
        stage('Deploy') {
            steps {
                // Метод из библиотеки, который знает, как деплоить в выбранное окружение
                mySharedLib.deployToKubernetes(params.ENVIRONMENT)
            }
        }
    }
}

Структура Shared Library (vars/mySharedLib.groovy):

def call(Map config = [:]) {
    this.buildMavenApp = { ... }
    this.deployToKubernetes = { env -> 
        sh "kubectl apply -f k8s/manifests-${env}.yaml"
    }
    return this
}

Такой подход позволяет централизованно обновлять логику CI/CD для десятков проектов, обеспечивая согласованность и безопасность (например, единый способ обработки секретов).