Как правильно выполнить рефакторинг этого скриптового конвейера Jenkins для хранения общего кода в одном файле? - PullRequest
1 голос
/ 27 февраля 2020

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

Я просмотрел здесь много вопросов о Jenkinsfiles и groovy и включаю их, но ни один из них, похоже, не подходит добраться до моей проблемы. Я хочу максимально упростить задачу для остальной части моей команды, позволив им указать в одной простой структуре данных все задания, которые они хотят выполнить в этом каталоге, например:

def targets = [
  "Build number 1" : "make build",
  "Some other run command" : "custom_script"
]

Моя идея должен был создать шаблон Jenkinsfile, чтобы они использовали его, который выглядел примерно так:

def targets = [.....]
node {
   scm......

   load "common/Jenkinsfile"
}

, а затем общий / Jenkinsfile, чтобы включить код для превращения этих целей в этапы:

    try {
    targets.each {entry ->
        stage (entry.key) {
           sh "${complicated_command_prefix} $entry.value  ${complicated_command_suffix}"
        }
      }
    }
    catch (e) {
    emailext (
     // yadda yadda
            )
       throw e  
   }

Это работает, если я помещаю этот код прямо в мой Jenkinsfile вместо команды load. Но очевидно, что загрузка делает что-то более сложное, чем #include препроцессора C, потому что код не работает с нагрузкой.

Сначала я получаю ошибку, связанную с целями, которые не определены (потому что это вне объем загружаемого файла предположительно). Кто-то предложил добавить "env." в качестве префикса перед целями, и это разрешило синтаксическую ошибку, но этапы фактически не выполняются.

Итак ... как я могу правильно передать «цели» в загруженный файл, чтобы сгенерированные этапы были должным образом обработаны? С другой стороны, есть ли другие варианты, чтобы сделать эту работу лучше?

Редактировать: я пытался вставить свои "цели def" непосредственно в загруженный общий файл, и этапы обрабатываются правильно. Таким образом, проблема не в том, что загруженный файл не выполняет то, что должен, а просто в том, что он не получает значение «target» из родительского Jenkinsfile.

Ответы [ 2 ]

0 голосов
/ 28 февраля 2020

Вот один из возможных способов его рефакторинга при превращении неявной зависимости в target в явную, что облегчает понимание и поддержку кода.

Шаблон Jenkinsfile:

def targets = [.....]
node {
   scm......

   processTargets = load "common/Jenkinsfile"
   processTargets( targets )
}

common / Jenkinsfile:

void call( Map targets ) {
    try {
      targets.each {entry ->
        stage (entry.key) {
           sh "${complicated_command_prefix} $entry.value  ${complicated_command_suffix}"
        }
      }
    }
    catch (e) {
      emailext (
        // yadda yadda
      )
      throw e  
   }
}

// very important: return instance of the script class, which load() will return
return this  

Определяя стандартную функцию call, объект, возвращаемый load, можно вызывать как функцию : processTargets( targets ). Если вы определяете функции с разными именами, вы можете вызывать их так:

common = load "common/Jenkinsfile"
common.myFunction1( foo )
common.myFunction2( bar )
0 голосов
/ 27 февраля 2020

Разобрался! Я обнаружил это странное поведение переменной области видимости в Jenkinsfile , которое объясняло, что если я пропущу def , переменная будет видна снаружи. И это. Так что теперь я определяю цели без def . Успех!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...