t.me/atinfo_chat Telegram группа по автоматизации тестирования

Отправка ссылки на отчеты либо самих отчетов Allure на почту из Jenkins

Теги: #<Tag:0x00007f9aff28f888> #<Tag:0x00007f9aff28f770> #<Tag:0x00007f9aff28f5e0> #<Tag:0x00007f9aff28f428> #<Tag:0x00007f9aff28f090> #<Tag:0x00007f9aff28ede8>

Добрый день! У меня на проекте в jenkins есть прикрученный allure, который формирует по каждой сборке отчет. Вопрос состоит в следующем - как отправить сформированный отчет через электронную почту? Или ссылку на него? При попытке сделать или так или так уперся намертво))

Если пытаюсь отправить сам отчет, используя плагин Email Extension Plugin, то как я понял, приаттачить к письму нельзя директорию с отчетом, а можно только файл или архив. Для архивации использую послесборочную операцию “архивация артефактов”, но не знаю как получить для Email Extension Plugin значение переменных, и для получения относительной ссылки на директорию с артефактами, имеющую вид $JENKINS_HOME/job//builds//archive
Если пытаюсь отправить ссылку на отчет, сталкиваюсь с уже озвученной проблемой - формирование относительной ссылки.
Кто как решал подобные задачи у себя?

Какую версию jenkins плагина вы используете?
Начиная с версии 2.13 allure-report сохраняеися в виде архива. Выглядит это вот так: https://ci.qameta.io/job/allure-java/job/master/

Да, есть такой отчет, но возникает тот же вопрос - он же хранится в артефактах, верно? Как его привязать к отправляемому письму?

Вопрос про формирование динамической ссылки отпадает, но появляется другой: не получается прикрепить отчет к письму. Судя по логам он успешно формируется

[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 19.720 s
[INFO] Finished at: 2017-08-22T18:15:16+03:00
[INFO] Final Memory: 50M/525M
[INFO] ------------------------------------------------------------------------
[Tests] $ /var/lib/jenkins/tools/ru.yandex.qatools.allure.jenkins.tools.AllureCommandlineInstallation/allure/bin/allure generate /var/lib/jenkins/workspace/Tests/target/allure-results -o /var/lib/jenkins/workspace/Tests/allure-report
send analytics
Report successfully generated to /var/lib/jenkins/workspace/Tests/allure-report
Allure report was successfully generated.
Creating artifact for the build.
Artifact was added to the build.
Email was triggered for: Always
Sending email for trigger: Always
ERROR: Error accessing files to attach: Expecting Ant GLOB pattern, but saw ‘/var/lib/jenkins/workspace/Tests/allure-report/*.zip’. See http://ant.apache.org/manual/Types/fileset.html for syntax

Пробую также следующую строку для аттача http://joxi.ru/Vm6L3ybTx3WwPA. Ошибка как в предыдущем посте не отображается, но и файла в письме нет

А обязательно именно прикреплять сам отчем к письму ? Можно же такой вариант - паблишим репорт через HTMLPublisherPlugin, а в письме уже указываем ссылку на этот репорт, примерно так оно выглядит:
"Check test report at ${env.BUILD_URL}Cucumber_Report/ to view the results.", Cucumber_Report - это reportName, который указывается при паблишинге html репорта.

Вот это посмотрите - Запуск тестов в определенное время, а также формирование нормальных отчетов на почту, парень создавал себе шаблон html и вставлял его в плагин и на выходе получал письмо с линком

Я бы вам посоветовал почитать, как на groovy сделать свой шаблон и подгрузить его в директорию дженкинса и использовать, как кастомный шаблон и там прописать и линки и информацию о билде…

Templates - https://github.com/jenkinsci/email-ext-plugin/tree/master/src/main/resources/hudson/plugins/emailext/templates

Я себе когда-то этот шаблон - https://gist.github.com/x-cray/2828336 переделал под себя.

Шаблон кладется в директорию - JENKINS_HOME\email-templates. В default contents плагина (редактирование джобы) добавляете название шаблона - http://take.ms/RV1Na

В шаблоне, что выше скинул - я вот так линк формировал Allure отчета:

<a href="${rooturl}${build.url}allure/">Allure report</a>
<a href="${rooturl}${build.url}console">Console log</a>
  1. название шаблона: build-report.groovy
  2. указать в default contents плагина: ${SCRIPT, template="build-report.groovy"}
  3. шаблон подгрузить в директорию: JENKINS_HOME\email-templates
  4. на всяк случай код шаблона, который я переделывал под себя:
<!DOCTYPE html>
<head>
  <title>Build report</title>
  <style type="text/css">
    body
    {
      margin: 0px;
      padding: 15px;
    }

    body, td, th
    {
      font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Tahoma, sans-serif;
      font-size: 10pt;
    }

    th
    {
      text-align: left;
    }

    h1
    {
      margin-top: 0px;
    }

    li
    {
      line-height: 15pt;
    }

    .change-add
    {
      color: #272;
    }

    .change-delete
    {
      color: #722;
    }

    .change-edit
    {
      color: #247;
    }

    .grayed
    {
      color: #AAA;
    }

    .error
    {
      color: #A33;
    }

    pre.console
    {
      color: #333;
      font-family: "Lucida Console", "Courier New";
      padding: 5px;
      line-height: 15px;
      background-color: #EEE;
      border: 1px solid #DDD;
    }
  </style>
</head>
<body>

<h1>Build ${build.result}</h1>
<table>
  <tr><th>Build URL:</th><td><a href="${rooturl}${build.url}">${rooturl}${build.url}</a></td></tr>
  <tr><th>Project:</th><td>${project.name}</td></tr>
  <tr><th>Date of build:</th><td>${it.timestampString}</td></tr>
  <tr><th>Build duration:</th><td>${build.durationString}</td></tr>
</table>

<!-- CHANGE SET -->
<% changeSet = build.changeSet
if (changeSet != null) {
  hadChanges = false %>
  <h2>Changes</h2>
  <ul>
<% 	changeSet.each { cs ->
    hadChanges = true
    aUser = cs.author %>
      <li>Commit <b>${cs.revision}</b> by <b><%= aUser != null ? aUser.displayName : it.author.displayName %>:</b> (${cs.msg})
        <ul>
<%        cs.affectedFiles.each { %>
          <li class="change-${it.editType.name}"><b>${it.editType.name}</b>: ${it.path}</li>
<%        } %>
        </ul>
      </li>
<%  }

  if (!hadChanges) { %>	
      <li>No Changes</li>
<%  } %>
  </ul>
<% } %>

<!-- ARTIFACTS -->
<% artifacts = build.artifacts
if (artifacts != null && artifacts.size() > 0) { %>
  <h2>Build artifacts</h2>
    <ul>
<%    artifacts.each() { f -> %>		
      <li><a href="${rooturl}${build.url}artifact/${f}">${f}</a></li>
<%    } %>
    </ul>
<% } %>

<% 
  testResult = build.testResultAction

  if (testResult) {
    jobName = build.parent.name
    rootUrl = hudson.model.Hudson.instance.rootUrl
    testResultsUrl = "${rootUrl}${build.url}testReport/"

    lastBuildSuccessRate = String.format("%.2f", (testResult.totalCount - testResult.result.failCount) * 100f / testResult.totalCount)
    lastBuildDuration = String.format("%.2f", testResult.result.duration)

    startedPassing = []
    startedFailing = []
    failing = []

    previousFailedTestCases = new HashSet()
    currentFailedTestCase = new HashSet()

    if (build.previousBuild?.testResultAction) {
      build.previousBuild.testResultAction.failedTests.each {
        previousFailedTestCases << it.simpleName + "." + it.safeName
      }
    }

    testResult.failedTests.each { tr ->
        packageName = tr.packageName
        className = tr.simpleName
        testName = tr.safeName
        displayName = className + "." + testName
        
        currentFailedTestCase << displayName
        url = "${rootUrl}${build.url}testReport/$packageName/$className/$testName"
        if (tr.age == 1) {
          startedFailing << [displayName: displayName, url: url, age: 1]
        } else {
          failing << [displayName: displayName, url: url, age: tr.age]
        }
    }

    startedPassing = previousFailedTestCases - currentFailedTestCase
    startedFailing = startedFailing.sort {it.displayName}
    failing = failing.sort {it.displayName}
    startedPassing = startedPassing.sort()
%>

<% if (testResult) { %>
<h2>Test Results</h2>
<ul>
  <li>Total tests ran: <a href="${testResultsUrl}">${testResult.totalCount}</a></li>
  <li>Failure count and delta: ${testResult.failCount} ${testResult.failureDiffString}</li>
  <li>Success rate: ${lastBuildSuccessRate}% </li>
</ul> 
<% } %>

<% if (startedPassing) { %>
<h3>Following tests started passing. Good work!</h3>
<ul>
  <% startedPassing.each { %>
    <li>${it}</li>
  <% } %>
</ul>
<% } %>

<% if (startedFailing) { %>
<h3>Following tests started FAILING. Have the last change caused it!!</h3>
<ul>
  <% startedFailing.each { %>
    <li><a href="${it.url}">${it.displayName}</a></li>
  <% } %>
</ul>
<% } %>

<% if (failing) { %>
<h3>Following tests are conitnuously failing. Someone should look into it!!!</h3>
<ul>
  <% failing.each { %>
    <li><a href="${it.url}">${it.displayName}</a> (Failing since ${it.age} runs)</li>
  <% } %>
</ul>
<% } %>

<% } %>

<!-- BUILD FAILURE REASONS -->
<% if (build.result == hudson.model.Result.FAILURE) {
  log = build.getLog(100).join("\n")
  warningsResultActions = build.actions.findAll { it.class.simpleName == "WarningsResultAction" }

  if (warningsResultActions.size() > 0) { %>
    <h2>Build errors</h2>
    <ul>
    <% warningsResultActions.each {
        newWarnings = it.result.newWarnings
        if (newWarnings.size() > 0) {
          newWarnings.each {
            if (it.priority.toString() == "HIGH") { %>
              <li class="error">In <b>${it.fileName}</b> at line ${it.primaryLineNumber}: ${it.message}</li>
          <% }} %>
    <% }} %>
    </ul>
  <% } %>

<h2>Console output</h2>
<pre class="console">${log}</pre>

<% } %>

</body>
2 Симпатий

Отпишите если что-то заработает.

Я переверстал под себя тот шаблон закинул его в директорию Jenkins, указал в плагине, и все работает как часы :slight_smile:

Как все это сделать, выше описал. :slight_smile:

Подскажите пожалуйста, ${rooturl} и ${build.url} должны быть где и как определены? Через шаблон отправить письмо не получилось, в письме пришла ошибка

Exception evaluating property 'failCount' for hudson.tasks.test.AggregatedTestResultAction

поэтому в default content просто содержимое шаблона скопировал, но в письме самих ссылок не было, был просто текст

Allure report Console log