Выполнение двух похожих конвейеров Jenkinsfile без дублирования кода

#jenkins #jenkins-pipeline

#дженкинс #дженкинс-конвейер

Вопрос:

Я использую Jenkins с декларативным конвейером для непрерывного тестирования одного из моих проектов на Python. Я хотел бы обобщить свой Jenkinsfile , чтобы протестировать свой проект с несколькими версиями Python, возможно, параллельно. Допустим, мой текущий файл Jenkinsfile выглядит следующим образом:

 pipeline {
  stages {
    stage('Checkout') {
      dir("src") {
        steps {
          checkout scm
        }
      }
    }
    stage('Install') {
      sh """
      python3.4 -m venv virtualenv
      source virtualenv/bin/activate
      python3.4 -m pip install src
      """
    }
  }
}
  

Я попытался параметризовать генерацию конвейера, переместив его в функцию следующим образом:

 def generatePipeline(version) {
  pipeline {
    stages {
      stage('Checkout') {
        dir("src") {
          steps {
            checkout scm
          }
        }
      }
      stage('Install') {
        sh """
        python${version} -m venv virtualenv
        source virtualenv/bin/activate
        python${version} -m pip install src
        """
      }
    }
  }
}

generatePipeline("3.4")
  

Дженкинс выдает сообщение с ошибкой java.lang.NoSuchMethodError: No such DSL method 'stages' found among steps (далее следует огромный список).

Я безуспешно загружал бесчисленное множество других вещей (включая установку generatePipeline в разделяемую библиотеку), но я действительно не понимаю, как работают декларативные конвейеры (или даже Groovy). Есть ли способ сгенерировать несколько похожих конвейеров без дублирования всего общего кода?

Комментарии:

1. Вы хотите это: jenkins.io/doc/book/pipeline/shared-libraries

2. @MattSchuchard Спасибо, я пробовал это, но у меня не получилось заставить это работать. Не могли бы вы, пожалуйста, немного подробнее рассказать о шагах, которые необходимо предпринять? Например, нужно ли мне хранить разделяемую библиотеку в отдельном репозитории SCM или я могу поместить ее в тот же репозиторий, что и мой Jenkinsfile (что я бы предпочел)? Нужно ли мне пометить его как доверенный, если он находится в том же репозитории? И, самое главное, что должна возвращать функция в моей разделяемой библиотеке? Конвейер, набор этапов, что-то совсем другое …?

Ответ №1:

Вы должны передать контекст сценария конвейера в свой метод и вызвать pipline из него.

 
    def generatePipeline(version, context) {
        context.pipeline {
            stages {
                //...
            }
        }
    }

    generatePipeline("3.4", this)

  

Комментарии:

1. Дженкинс жалуется java.lang.NoSuchMethodError: No such DSL method 'stages' found among steps [...] . Редактировать: сообщение завершается на ...] or globals [currentBuild, docker, env, params, pipeline, scm] . Я вижу pipeline там, что, возможно, объясняет, почему Дженкинс не жаловался на это даже без context .

2. Я думаю, проблема здесь в том, что вы пытаетесь использовать декларативный синтаксис конвейера, который не допускает такого гибкого синтаксиса Groovy. Взгляните на синтаксис скриптового конвейера .