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

jenkins
allure
Теги: #<Tag:0x00007fedc4548238> #<Tag:0x00007fedc45480d0>

(Тест Тестов) #1

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

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


(Artem Eroshenko) #2

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


(Тест Тестов) #3

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


(Тест Тестов) #4

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

[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


(Тест Тестов) #5

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


(Valentin Buryakov) #6

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


(Eugene Moskalenko) #7

Вот это посмотрите - Запуск тестов в определенное время, а также формирование нормальных отчетов на почту, парень создавал себе шаблон 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>

(Mr Ds Low) #8

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


(Eugene Moskalenko) #9

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

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