Агрегация результатов нисходящих параметризованных заданий в Дженкинсе

У меня есть задание сборки Jenkins, которое запускает несколько тестовых заданий с использованием имени теста в качестве параметра с помощью параметра Jenkins Parameterized Trigger Plugin. Это запускает ряд тестовых сборников для нескольких исполнителей, которые все работают правильно.

Теперь я хочу обобщить результаты, используя "Агрегатные нисходящие результаты тестирования" - "Автоматически агрегировать все последующие тесты". Я включил это в задание сборки и установил отпечатки пальцев, чтобы они были признаны в качестве нисходящих заданий. На странице Build jobs lastBuild я вижу, что они распознаются как последующие сборки:

Downstream Builds

Тест # 1- # 3

Когда я нажимаю "Сводные результаты теста", однако он показывает только последние из них (Тест № 3). Это может быть хорошим поведением, если в задании всегда выполняются те же тесты, но мои все запускают разные части моего набора тестов.

Есть ли способ получить это, чтобы агрегировать все соответствующие тестовые сборки ниже по течению?

Дополнительно: Агрегированные результаты теста работают, если вы копируете тестовое задание. Это не идеально, поскольку у меня есть большое количество тестовых наборов.

Ответ 1

Я расскажу о решении для руководства (как упоминалось в комментариях) и предоставит более подробную информацию, если вам это нужно позже:

Пусть P - родительское задание, а D - задание ниже по течению (вы можете легко расширить подход к нескольким последующим заданиям).

  • Экземпляр (сборка) P вызывает D через Параметрированный триггерный плагин с помощью шага сборки ( не как шаг после сборки) и ждет завершения D. Наряду с другими параметрами P передает D параметр - позвольте ему PARENT_ID - на основе P build BUILD_ID.
  • D выполняет тесты и архивирует их как артефакты (вместе с отчетами jUnit - если применимо).
  • P затем выполняет внешний Python (или внутренний Groovy) script, который находит соответствующую сборку D через PARENT_ID (вы перебираете сборки D и проверяете значение параметра PARENT_ID). Затем script копирует артефакты из D в P и P, публикует их.

Если вы используете Python (что я делаю), используйте оболочку Python JenkinsAPI. Если вы используете Groovy - используйте Groovy Плагин и запустите script как систему script. Затем вы можете получить доступ к Jenkins через Java API.

Ответ 2

Я придумал следующее решение с использованием декларативных конвейеров.

Требуется установка плагина "Копировать артефакт".

В последующем задании установите переменную env с путем (или путем к шаблону) для файла результатов:

post {
  always {
    steps {
      script { // Rem: Must be BEFORE execution that may fail   env.RESULT_FILE='Devices\\resultsA.xml'
      }
      xunit([GoogleTest(
        pattern: env.RESULT_FILE,
      )])
    }
  }
}

Обратите внимание, что я использую xunit, но то же самое применимо и к junit

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

def runs=[]

pipeline {
  agent any
  stages {
    stage('Tests') {
      parallel {
        stage('test A') {
          steps {
            script {
              runs << build(job: "test A", propagate: false)
            }
          }
        }
        stage('test B') {
          steps {
            script {
              runs << build(job: "test B", propagate: false)
            }
          }
        }
      }
    }
  }
  post {
    always {
      script {
        currentBuild.result = 'SUCCESS'
        def result_files = []
        runs.each {
          if (it.result != 'SUCCESS') {
            currentBuild.result = it.result
          }
          copyArtifacts(
            filter: it.buildVariables.RESULT_FILE,
            fingerprintArtifacts: true,
            projectName: it.getProjectName(),
            selector: specific(it.getNumber().toString())
          )
          result_files << it.buildVariables.RESULT_FILE
        }
        env.RESULT_FILE = result_files.join(',')
        println('Results aggregated from ' + env.RESULT_FILE)
      }
      archiveArtifacts env.RESULT_FILE
      xunit([GoogleTest(
        pattern: env.RESULT_FILE,
      )])
    }
  }
}

Обратите внимание, что родительское задание также устанавливает переменную "env", чтобы оно могло быть агрегировано родительским заданием.