Code Monkey home page Code Monkey logo

test-summary-buildkite-plugin's Introduction

Test Summary Buildkite Plugin

A Buildkite plugin that adds a single annotation for all your test failures using buildkite-agent annotate.

Supported formats:

  • JUnit
  • Checkstyle
  • TAP^
  • Plain text files with one failure per line

^ Current TAP support is fairly limited. If you have an example TAP file that is not being interpreted correctly, feel free to open an issue or pull request.

Example

Upload test results as artifacts using any supported format. If you include the $BUILDKITE_JOB_ID in the path, a link to the build will be included in the annotation. Some examples:

steps:
  - label: rspec
    command: rspec
    parallelism: 10
    # With spec_helper.rb:
    # RSpec.configure do |config|
    #   config.add_formatter('RspecJunitFormatter', "artifacts/rspec-#{ENV['BUILDKITE_JOB_ID']}.xml")
    # end
    artifact_paths: "artifacts/*"

  - label: eslint
    command: yarn run eslint -f checkstyle -o artifacts/eslint.xml
    artifact_paths: "artifacts/*"

  - label: ava
    command: bash -c "yarn --silent test --tap > artifacts/ava.tap"
    artifact_paths: "artifacts/*"

  - label: rubocop
    # The emacs format is plain text with one failure per line
    command: rubocop -f emacs -o artifacts/rubocop.txt
    artifact_paths: "artifacts/*"

Wait for all the tests to finish:

  - wait: ~
    continue_on_failure: true

Add a build step using the test-summary plugin:

  - label: annotate
    plugins:
      - bugcrowd/test-summary#v1.11.0:
          inputs:
            - label: rspec
              artifact_path: artifacts/rspec*
              type: junit
            - label: eslint
              artifact_path: artifacts/eslint.xml
              type: checkstyle
            - label: ava
              artifact_path: artifacts/ava.tap
              type: tap
            - label: rubocop
              artifact_path: artifacts/rubocop.txt
              type: oneline
          formatter:
            type: details
          context: test-summary

See buildkite annotation of all the failures. There are some example annotations included below.

Configuration

Inputs

The plugin takes a list of input sources. Each input source has:

  • label: the name used in the heading to identify the test group.
  • artifact_path: a glob used to download one or more artifacts.
  • type: one of junit, checkstyle, tap or oneline.
  • encoding: The file encoding to use. Defaults to UTF-8.
  • strip_colors: Remove ANSI color escape sequences. Defaults to false.
  • crop: (oneline type only) Number of lines to crop from the start and end of the file, to get around default headers and footers. Eg:
crop:
  start: 3
  end: 2
  • job_id_regex: Ruby regular expression to extract the job_id from the artifact path. It must contain a named capture with the name job_id. Defaults to (?<job_id>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}).

Junit specific options:

  • summary: Customise how the summary is generated. Includes:
    • format: A ruby format string for converting the junit xml attributes into a summary. All attributes are available in <element>.<attr-name> format.
    • details_regex: A ruby regular expression, run over the body text of each failure. Any named captures generated by this regex will be available to the format string. This is useful if some information is only available in the contents of the failure. Eg:
summary:
  format: '%{testsuites.name}: %{testsuite.name}: %{testcase.classname}: %{failure.message}%{error.message}'
summary:
  format: '%{location}: %{testcase.name}'
  details_regex: '(?<location>\S+:\d+)'
  • message: Set this to false if the failure message attribute is not worth showing in the annotation. Defaults to true.
  • details: Set this to false if the body of the failure is not worth showing in the annotation. Defaults to true.

Formatter

There are two formatter types, summary and details.

The summary formatter includes a single line for each failure.

example summary annotation

The details formatter includes extra information about the failure in an accordion (if available). This is the default option.

example details annotation

Other formatter options are:

  • show_first: The number of failures to show before hiding the rest inside an accordion. If set to zero, all failures will be hidden by default. If set to a negative number, all failures will be shown. Defaults to 20.

Other options

  • context: The Buildkite annotation context. Defaults to test-summary.
  • style: Set the annotation style. Defaults to error.
  • fail_on_error: Whether the command should return non-zero exit status on failure. Defaults to false so failing to annotate a build does not cause the entire pipeline to fail.
  • run_without_docker: Set the enviroment to run without docker. Defaults to false.

Truncation

Buildkite has a maximum annotation size of 100 kilobytes. If there are too many failures to fit within this limit, the plugin will truncate the failures for each input.

Developing

To run the tests:

docker-compose run --rm test rspec

If you have ruby set up, you can just run:

bundle install
rspec

To generate sample markdown and HTML based on the files in spec/sample_artifacts:

bin/run-dev

Note: The sample HTML files use hardcoded references to buildkite assets. If the page is not displaying correctly, try updating the css files in templates/test_layout.html.haml based on what buildkite is currently serving.

test-summary-buildkite-plugin's People

Contributors

alekstorm avatar dependabot[bot] avatar dreyks avatar maschwenk avatar philwo avatar seanson avatar tessereth avatar ticky avatar timnew avatar toolmantim avatar yinonrousso avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

test-summary-buildkite-plugin's Issues

Plugin Parsing buildkite-agent as a directory instead of command

I'm experiencing errors trying to use this plugin.

Error: Errno::ENOENT: No such file or directory - buildkite-agent

Full Stack Trace

Running plugin github.com/bugcrowd/test-summary-buildkite-plugin#v1.4.0 command hook | 7s
-- | --
  | $ /buildkite/plugins/github-com-bugcrowd-test-summary-buildkite-plugin-v1-4-0/hooks/command
  | Found tag v1.4.0, pulling from docker hub
  | v1.4.0: Pulling from tessereth/test-summary-buildkite-plugin
  | ff3a5c916c92: Already exists
  | 8e2da6035957: Pull complete
  | 42e99ed6de92: Pull complete
  | 70c638bbd0d9: Pull complete
  | 6707ebcdc256: Pull complete
  | 72dd2f0132d6: Pull complete
  | 06c7a1fb7b48: Pull complete
  | 31374a9fe479: Pull complete
  | 1026ef473bca: Pull complete
  | Digest: sha256:242107f59f9c9a2a29e6d9b70892548adc513f91eb396c10b79e1b0790d4821a
  | Status: Downloaded newer image for tessereth/test-summary-buildkite-plugin:v1.4.0
  | $ buildkite-agent artifact download junit_rspec_report_*.xml tmp/test-summary
  | Errno::ENOENT: No such file or directory - buildkite-agent
  |  
  | /usr/src/app/lib/test_summary_buildkite_plugin/agent.rb:21:in `popen'
  | /usr/src/app/lib/test_summary_buildkite_plugin/agent.rb:21:in `run'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:40:in `files'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:29:in `failures'
  | /usr/src/app/lib/test_summary_buildkite_plugin/formatter.rb:22:in `markdown'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:49:in `input_markdown'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:60:in `block in markdown_with_truncation'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:60:in `map'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:60:in `markdown_with_truncation'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:17:in `markdown'
  | /usr/src/app/lib/test_summary_buildkite_plugin/runner.rb:19:in `run'
  | /usr/src/app/lib/test_summary_buildkite_plugin.rb:19:in `run'
  | ./bin/run:10:in `<main>'
  | No errors found! 🎉

This is how I've set up my pipeline:

 - name: 'Test'
    label: tests
    command: '.buildkite/test'
    artifact_paths:
      - "junit_rspec_report_*.xml"

  - wait: ~
    continue_on_failure: true

  - name: ':scroll: Annotate'
    plugins:
      bugcrowd/test-summary#v1.4.0:
        inputs:
          - label: tests
            artifact_path: "junit_rspec_report_*.xml"
            type: junit

Not sure if I'm missing something important in my set up or if this is a broader issue. Please let me know what other info I can provide to help debug.

Show test line numbers in rspec failure messages

image

This rspec failure output would be more immediately actionable if it included line numbers like rspec output locally:

rspec ./foo/bar.rb :528 # Foo bar spec name

Is there a setting for this? Or if you point me to appropriate place in the code, I'd be happy to dig in and submit a PR for this change! Thanks for the great tool!

RuntimeError: attempted adding second root element to document

I'm just trying to wire this plugin up for the first time so may be doing something wrong, but...

My ESLint annotations come through, but my RSpec ones fail with the following output:

$ buildkite-agent artifact download tmp/rspec*.xml tmp/test-summary
  | 2018-12-14 05:48:27 INFO   Searching for artifacts: "tmp/rspec*.xml"
  | 2018-12-14 05:48:27 INFO   Found 4 artifacts. Starting to download to: /usr/src/app/tmp/test-summary
  | 2018-12-14 05:48:27 INFO   Successfully downloaded "tmp/rspec-6851529f-2c42-4030-8d93-19eb32e0db87.xml" 158119 bytes
  | 2018-12-14 05:48:27 INFO   Successfully downloaded "tmp/rspec-fed778c5-42ec-41bb-b6f3-1d427f6f677d.xml" 394107 bytes
  | 2018-12-14 05:48:27 INFO   Successfully downloaded "tmp/rspec-81677cf4-bff2-4353-97e6-e40310958b93.xml" 447761 bytes
  | 2018-12-14 05:48:27 INFO   Successfully downloaded "tmp/rspec-6492fbdd-064e-498d-9178-de6f8a8c0e13.xml" 460360 bytes
  |  
  | REXML::ParseException: #<RuntimeError: attempted adding second root element to document>
  | /usr/local/lib/ruby/2.5.0/rexml/document.rb:96:in `add'
  | /usr/local/lib/ruby/2.5.0/rexml/element.rb:904:in `add'
  | /usr/local/lib/ruby/2.5.0/rexml/child.rb:22:in `initialize'
  | /usr/local/lib/ruby/2.5.0/rexml/parent.rb:14:in `initialize'
  | /usr/local/lib/ruby/2.5.0/rexml/element.rb:60:in `initialize'
  | /usr/local/lib/ruby/2.5.0/rexml/element.rb:902:in `new'
  | /usr/local/lib/ruby/2.5.0/rexml/element.rb:902:in `add'
  | /usr/local/lib/ruby/2.5.0/rexml/element.rb:298:in `add_element'
  | /usr/local/lib/ruby/2.5.0/rexml/document.rb:103:in `add_element'
  | /usr/local/lib/ruby/2.5.0/rexml/parsers/treeparser.rb:34:in `parse'
  | /usr/local/lib/ruby/2.5.0/rexml/document.rb:288:in `build'
  | /usr/local/lib/ruby/2.5.0/rexml/document.rb:45:in `initialize'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:102:in `new'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:102:in `file_contents_to_failures'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:65:in `filename_to_failures'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:29:in `block in failures'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:29:in `map'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:29:in `failures'
  | /usr/src/app/lib/test_summary_buildkite_plugin/formatter.rb:22:in `markdown'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:49:in `input_markdown'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:60:in `block in markdown_with_truncation'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:60:in `map'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:60:in `markdown_with_truncation'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:17:in `markdown'
  | /usr/src/app/lib/test_summary_buildkite_plugin/runner.rb:19:in `run'
  | /usr/src/app/lib/test_summary_buildkite_plugin.rb:20:in `run'
  | ./bin/run:10:in `<main>'
  | ...
  | attempted adding second root element to document
  | Line: 69
  | Position: 14204
  | Last 80 unconsumed characters:
  |  
  |  
  | /usr/local/lib/ruby/2.5.0/rexml/parsers/treeparser.rb:96:in `rescue in parse'
  | /usr/local/lib/ruby/2.5.0/rexml/parsers/treeparser.rb:21:in `parse'
  | /usr/local/lib/ruby/2.5.0/rexml/document.rb:288:in `build'
  | /usr/local/lib/ruby/2.5.0/rexml/document.rb:45:in `initialize'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:102:in `new'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:102:in `file_contents_to_failures'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:65:in `filename_to_failures'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:29:in `block in failures'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:29:in `map'
  | /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:29:in `failures'
  | /usr/src/app/lib/test_summary_buildkite_plugin/formatter.rb:22:in `markdown'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:49:in `input_markdown'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:60:in `block in markdown_with_truncation'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:60:in `map'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:60:in `markdown_with_truncation'
  | /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:17:in `markdown'
  | /usr/src/app/lib/test_summary_buildkite_plugin/runner.rb:19:in `run'
  | /usr/src/app/lib/test_summary_buildkite_plugin.rb:20:in `run'
  | ./bin/run:10:in `<main>'

Only thing of note really here is that I am parallelising with Knapsack so there are multiple RSpec files to stitch together here...

Any ideas?

handle junit error fields

I have some tests that output test failures into an xunit report with error fields rather than failure fields. These are for ember tests running with testem configured with xunit output. Would it be possible to also handle error fields?

Example XML

<testcase classname="Chrome 66.0" name="Unit | Component | autocomplete: shows default results when defaultCategory is set" time="0.070">
<error message="has results after focusing">
<![CDATA[
at Object.<anonymous> (http://localhost:9001/assets/tests.js:2188:20) at runTest (http://localhost:9001/assets/test-support.js:15012:30) at Test.run (http://localhost:9001/assets/test-support.js:14998:6) at http://localhost:9001/assets/test-support.js:15210:12 at advanceTaskQueue (http://localhost:9001/assets/test-support.js:14611:6) at Object.advance (http://localhost:9001/assets/test-support.js:14592:4)
]]>
</error>
</testcase>

Allow setting a custom summary format for junit

Junit splits the information about which test is running across multiple fields:

  • testsuites -> name
  • testsuite -> name
  • testcase -> name, classname, file
  • error/failure -> message
  • buried in the error body

And different junit generators put different useful (or not so useful) information in each field. It would be convenient to allow the user to specify which bits to use in what order for the summary message. Maybe something like:

summary_format: "#{testsuites.name}: #{error.message} (#{testcase.file})"

The advanced version would allow a regex for pulling something out of the error body.

Artifact pull does not support proxy environment variables

When running in an environment where internet access requires going through a proxy, the plugin will get an i/o timeout:

2020-01-28 05:57:58 FATAL  Failed to download artifacts: Get https://agent.buildkite.com/v3/builds/<uuid>/artifacts/search?query=report.xml: dial tcp 54.84.180.199:443: i/o timeout

Errors are ignored in junit.xml

It looks like plugin ignores errors in junit.xml

Pipeline step:

  - label: test-summary
    plugins:
      - bugcrowd/test-summary#v1.11.0:
          inputs:
            - label: angular-tests
              artifact_path: .tmp/angular-junit.xml
              type: junit
            - label: browser-tests
              artifact_path: .tmp/test/junit/*.xml
              type: junit
          formatter:
            type: summary

junit xml that contains errors:

<testsuites>
  <testsuite name="parent_suite" timestamp="2020-04-07T22:57:13" time="1.956" tests="1" failures="0" errors="1" skipped="0">
    <properties>
      <property name="specId" value="0" />
      <property name="suiteName" value="parent_suite" />
      <property name="capabilities" value="chrome.80_0_3987_132.linux" />
      <property name="file" value="./test/features/group/browser-test.spec.js" />
    </properties>
    <testcase classname="chrome.80_0_3987_132.linux.parent_suite" name="test_case" time="0.446">
      <error message="done() called multiple times" />
      <system-err><![CDATA[Error: done() called multiple times at multiple (/app/node_modules/@wdio/mocha-framework/node_modules/mocha/lib/runnable.js:314:26) at done (/app/node_modules/@wdio/mocha-framework/node_modules/mocha/lib/runnable.js:326:14) at /app/node_modules/@wdio/mocha-framework/node_modules/mocha/lib/runnable.js:400:11 at processTicksAndRejections (internal/process/task_queues.js:97:5)]]></system-err>
    </testcase>
  </testsuite>
</testsuites>

plugin execution logs:

~~~ Running plugin test-summary command hook
$ /var/lib/buildkite-agent/plugins/github-com-bugcrowd-test-summary-buildkite-plugin-v1-11-0/hooks/command
Found tag v1.11.0, pulling from docker hub
v1.11.0: Pulling from bugcrowd/test-summary-buildkite-plugin
Digest: sha256:8341161915a5a5b44b814b4ac5ef257b46bc6784df6847718ac9761e45471c3b
Status: Image is up to date for bugcrowd/test-summary-buildkite-plugin:v1.11.0
docker.io/bugcrowd/test-summary-buildkite-plugin:v1.11.0
$ buildkite-agent artifact download .tmp/angular-junit.xml tmp/test-summary
2020-04-07 22:59:29 INFO   Searching for artifacts: ".tmp/angular-junit.xml"
2020-04-07 22:59:29 INFO   Found 1 artifacts. Starting to download to: /usr/src/app/tmp/test-summary
2020-04-07 22:59:30 INFO   Successfully downloaded ".tmp/angular-junit.xml" 98189 bytes

$ buildkite-agent artifact download .tmp/test/junit/*.xml tmp/test-summary
2020-04-07 22:59:30 INFO   Searching for artifacts: ".tmp/test/junit/*.xml"
2020-04-07 22:59:30 INFO   Found 29 artifacts. Starting to download to: /usr/src/app/tmp/test-summary
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-1.chrome.xml" 7137 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-3.chrome.xml" 2838 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-2.chrome.xml" 5752 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-0.chrome.xml" 13980 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-4.chrome.xml" 4580 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-5.chrome.xml" 1268 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-1.chrome.xml" 3414 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-0.chrome.xml" 18582 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-2.chrome.xml" 9335 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-3.chrome.xml" 1719 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-4.chrome.xml" 11362 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-0.chrome.xml" 8362 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-1.chrome.xml" 6402 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-2.chrome.xml" 11734 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-3.chrome.xml" 4031 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-5.chrome.xml" 963 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-4.chrome.xml" 8788 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-0.chrome.xml" 9772 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-1.chrome.xml" 6246 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-3.chrome.xml" 3165 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-4.chrome.xml" 2254 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-2.chrome.xml" 7680 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-5.chrome.xml" 919 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-1.chrome.xml" 7023 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-2.chrome.xml" 5306 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-3.chrome.xml" 2292 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-0.chrome.xml" 31582 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-4.chrome.xml" 5820 bytes
2020-04-07 22:59:31 INFO   Successfully downloaded ".tmp/test/junit/results-0-5.chrome.xml" 962 bytes

No errors found! 🎉
$ cd /var/lib/buildkite-agent/plugins/github-com-bugcrowd-test-summary-buildkite-plugin-v1-11-0
# OLDPWD changed
# PWD changed

Create a structured data file containing the aggregated results

It would be really handy to create and artifact-store a single file containing the aggregated test results, so that that could be processed conveniently in one place. For example, this would allow me to take that file and push the results to both elasticsearch and prometheus so I can offer up the data how my users expect to be able to find it, so they can analyse across builds (flaky test detection) and alert on failures.

Annotate fails with large volume of test failure output

If you manage to catastrophically break something and cause a large number of tests to fail which have several lines of output, at some point, the plugin will fail due to limits on the size of Buildkite annotations:

The annotation body must be less than 50 kilobytes

It would be nice in this case to possibly truncate the annotation body so the annotation can still be made instead of failing out.

code should be <pre>'d

When running a test that outputs things like:
web__build_editor__20276

for a test failure, this output gets mangled in the summary:
web__build_editor__20276

I suspect a missing <code><pre class="diff"></pre></code> somewhere.

Use environment variable to get artifacts and download it outside docker

Currently, I am facing a problem that the mounted buildkite-agent can not run within docker, as stated #23 (comment).

So I am wondering is that necessary to mount the binary file into the container? If it is for downloading the artifacts, is that possible to download it before the docker step? To extract which artifacts to be downloaded, can this be done via environment variables like BUILDKITE_PLUGIN_INPUTS_1_ARTIFACT_PATH? Please kindly correct me if I missed something! Thanks!

Buildkite doc

Usage feedback

I tried out this plugin today and it worked great. Thank you for developing it.

Background: I was going to use the buildkite provided plugin, but really like the feature to separate my types of tests (as mentioned on the buildkite plugin's issue board). Plus, it seems that this may become the official plugin.

One issue I ran into, which I think is actually a non-issue:

$ buildkite-agent artifact download micheletest/be-results.xml tmp/test-summary
--
  | 2018-04-30 18:02:53 INFO   Searching for artifacts: "micheletest/be-results.xml"
  | 2018-04-30 18:03:53 FATAL  Failed to download artifacts: Get https://agent.buildkite.com/v3/builds/89bc3a56-16b9-4da7-872a-3d92165371a1/artifacts/search?query=micheletest%2Fbe-results.xml: net/http: request canceled (Client.Timeout exceeded while awaiting headers)
  | /usr/src/app/lib/test_summary_buildkite_plugin/agent.rb:27:in `run': Command 'buildkite-agent artifact download micheletest/be-results.xml tmp/test-summary' failed (exit status: 1) (RuntimeError)
  | from /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:39:in `files'
  | from /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:77:in `failures_raw'
  | from /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:28:in `failures'
  | from /usr/src/app/lib/test_summary_buildkite_plugin/formatter.rb:15:in `markdown'
  | from /usr/src/app/lib/test_summary_buildkite_plugin/runner.rb:12:in `block in run'
  | from /usr/src/app/lib/test_summary_buildkite_plugin/runner.rb:12:in `map'
  | from /usr/src/app/lib/test_summary_buildkite_plugin/runner.rb:12:in `run'
  | from /usr/src/app/lib/test_summary_buildkite_plugin.rb:17:in `run'
  | from ./bin/run:10:in `<main>'
  |  
  | 🚨 Error: The plugin github.com/bugcrowd/test-summary-buildkite-plugin#v1.0.0 command hook exited with status 1

I fixed that by properly naming my files. I had 15 parallel generated files with the same name of be-results.xml, and intended to rename them to include BUILDKITE_JOB_ID regardless. Once I did that, the download error went away.

JUnit results not recognizing errors when there are multiple test suites

Jest's JUnit plugin outputs (I think valid) XML that has multiple test suites:

<testsuites name="jest tests" tests="2" failures="1" time="7.298">
<testsuite name="Login" errors="0" failures="1" skipped="0" timestamp="2018-05-08T23:03:15" time="7.298" tests="2">
<testcase classname="Login should load without error" name="Login should load without error" time="2.735">
<failure>
Error: Expected image to match or be a close match to snapshot but was 8.546910755148742% different from snapshot (6723 differing pixels). See diff for details: /app/__tests__/__image_snapshots__/__diff_output__/login-js-login-should-load-without-error-2-diff.png at Object.<anonymous>.module.exports (/app/src/screenshot.js:41:17) at <anonymous> at process._tickCallback (internal/process/next_tick.js:188:7)
</failure>
</testcase>
<testcase classname="Login should log in successfully" name="Login should log in successfully" time="0.028"></testcase>
</testsuite>
</testsuites>

However, the plugin doesn't seem to recognize the failure:

Status: Image is up to date for tessereth/test-summary-buildkite-plugin:v1.2.0
--
  | $ buildkite-agent artifact download reports/e2e-junit.xml tmp/test-summary
  | 2018-05-08 23:04:10 INFO   Searching for artifacts: "reports/e2e-junit.xml"
  | 2018-05-08 23:04:11 INFO   Found 1 artifacts. Starting to download to: /usr/src/app/tmp/test-summary
  | 2018-05-08 23:04:11 INFO   Successfully downloaded "reports/e2e-junit.xml" 928 bytes
  |  
  | No errors found! 🎉


Errors are not caught properly when truncating and one input fails to download

$ /etc/buildkite-agent/plugins/github-com-bugcrowd-test-summary-buildkite-plugin-v1-7-0/hooks/command
Found tag v1.7.0, pulling from docker hub
v1.7.0: Pulling from tessereth/test-summary-buildkite-plugin
Digest: sha256:429443972bad9a2f3b06f14782c2d4aa4620cfdc78d9cb0c73234e2a160a553e
Status: Image is up to date for tessereth/test-summary-buildkite-plugin:v1.7.0

<truncated>

$ buildkite-agent artifact download artifacts/validate.txt tmp/test-summary
2018-10-10 00:24:24 INFO   Searching for artifacts: "artifacts/validate.txt"
2018-10-10 00:24:24 FATAL  No artifacts found for downloading
 
RuntimeError: Command 'buildkite-agent artifact download artifacts/validate.txt tmp/test-summary' failed (exit status: 1)
 
/usr/src/app/lib/test_summary_buildkite_plugin/agent.rb:27:in `run'
/usr/src/app/lib/test_summary_buildkite_plugin/input.rb:40:in `files'
/usr/src/app/lib/test_summary_buildkite_plugin/input.rb:29:in `failures'
/usr/src/app/lib/test_summary_buildkite_plugin/formatter.rb:22:in `markdown'
/usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:49:in `input_markdown'
/usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:60:in `block in markdown_with_truncation'
/usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:60:in `map'
/usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:60:in `markdown_with_truncation'
/usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:17:in `markdown'
/usr/src/app/lib/test_summary_buildkite_plugin/runner.rb:19:in `run'
/usr/src/app/lib/test_summary_buildkite_plugin.rb:19:in `run'
./bin/run:10:in `<main>'
Markdown is too large (52087 B > 50000 B), truncating
$ buildkite-agent artifact download artifacts/validate.txt tmp/test-summary
2018-10-10 00:24:24 INFO   Searching for artifacts: "artifacts/validate.txt"
2018-10-10 00:24:24 FATAL  No artifacts found for downloading
/usr/src/app/lib/test_summary_buildkite_plugin/agent.rb:27:in `run': Command 'buildkite-agent artifact download artifacts/validate.txt tmp/test-summary' failed (exit status: 1) (RuntimeError)
	from /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:40:in `files'
	from /usr/src/app/lib/test_summary_buildkite_plugin/input.rb:29:in `failures'
	from /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:64:in `map'
	from /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:64:in `max_truncate'
	from /usr/src/app/lib/test_summary_buildkite_plugin/truncater.rb:28:in `markdown'
	from /usr/src/app/lib/test_summary_buildkite_plugin/runner.rb:19:in `run'
	from /usr/src/app/lib/test_summary_buildkite_plugin.rb:19:in `run'
	from ./bin/run:10:in `<main>'
 
Command failed with exit status: 1
/etc/buildkite-agent/plugins/github-com-bugcrowd-test-summary-buildkite-plugin-v1-7-0/hooks/command: line 9: BUILDKITE_PLUGIN_TEST_SUMMARY_FAIL_ON_ERROR: unbound variable
🚨 Error: The command exited with status 1

Optional flag to not run using docker

The shear details that come from this summary generation is incredible. I'd love to be able to use this. We're running in an environment that has access to ruby, but not to docker though. I was curious if you would be open to an optional argument to the plugin that would execute the formatter directly rather than using docker run? I'd be more than happy to make the PR for this feature as well.

Show summary line for tests run and passed

... so that it's possible to see that "the normal number of" tests ran and passed. Sometimes someone might delete a swathe of tests or change build-automation in a way that causes them to no longer run (by mistake); the summary line would allow that to be noticed slightly easier (though I recognise it's definitely not a guarantee). Ideally inside a success or info annotation?

invalid access token

hey
getting

Failed to download artifacts: GET https://agent.buildkite.com/v3/builds/d9e8b43c-90f3-45db-8400-172af62f84f5/artifacts/search?query=log%2Frspec%2A.xml: 401 Invalid access token
--
  |  
  | TestSummaryBuildkitePlugin::Agent::CommandFailed: Command 'buildkite-agent artifact download log/rspec*.xml tmp/test-summary' failed (exit status: 1)

is there something i should configure?

Checkstyle formatter not tolerant to optional attributes

Checkstyle formatter should be more tolerant to missing attributes on <error>. For example:

<error severity="error" message="Needless blank line(s)" source="no-consecutive-blank-lines" />
<error line="106" column="1" severity="error" message="Needless blank line(s)" source="no-consecutive-blank-lines" />

line and column appear to be optional.

I can't really find a formal definition for Checkstyle but it seems these attributes are not always required, so the formatter should be tolerant of that (while not necessarily laying out the red carpet for it)

Differentiate between errors and warnings

Currently it appears that all errors/warnings/etc show up in the red annotate block at the top of BK builds.

image

When a step (such as eslint) outputs warnings, it would be nice to see these differently to the current red error block.

TSLint/ESlint JUnit format

The Junit format that tslint spits out via tslint --format junit --out junit.xml looks like this:

<?xml version="1.0" encoding="utf-8"?>
<testsuites package="tslint">
    <testsuite name="/var/lib/buildkite-agent/builds/my-org/my-pipeline/src/pages/editor/editing/charts/stories/shapes.stories.tsx">
        <testcase name="Line 1, Column 1: no-unused-variable">
            <failure type="error">All imports on this line are unused.</failure>
        </testcase>
    </testsuite>
    <testsuite name="/var/lib/buildkite-agent/builds/my-org/my-pipeline/src/pages/editor/main.tsx">
        <testcase name="Line 75, Column 13: quotemark">
            <failure type="error">&quot; should be &#39;</failure>
        </testcase>
        <testcase name="Line 75, Column 9: no-unused-variable">
            <failure type="error">&#39;x&#39; is declared but its value is never read.</failure>
        </testcase>
        <testcase name="Line 75, Column 18: semicolon">
            <failure type="error">Missing semicolon</failure>
        </testcase>
    </testsuite>
    <testsuite name="/var/lib/buildkite-agent/builds/my-org/my-pipeline/src/pages/editor/publish/design_spec_menus/create/stories/create_design_menu.stories.tsx">
        <testcase name="Line 4, Column 1: no-unused-variable">
            <failure type="error">All imports on this line are unused.</failure>
        </testcase>
    </testsuite>
    <testsuite name="/var/lib/buildkite-agent/builds/my-org/my-pipeline/src/pages/editor/search/object_panel/object_panel_configuration.ts">
        <testcase name="Line 3, Column 1: no-unused-variable">
            <failure type="error">All imports on this line are unused.</failure>
        </testcase>
    </testsuite>
    <testsuite name="/var/lib/buildkite-agent/builds/my-org/my-pipeline/src/pages/editor/tailoring/assistant/panel/panel.tsx">
        <testcase name="Line 3, Column 1: no-unused-variable">
            <failure type="error">All imports on this line are unused.</failure>
        </testcase>
    </testsuite>
    <testsuite name="/var/lib/buildkite-agent/builds/my-org/my-pipeline/src/pages/editor/tailoring/assistant/static_cards/welcome_card/welcome_card_messages.ts">
        <testcase name="Line 1, Column 1: no-unused-variable">
            <failure type="error">All imports on this line are unused.</failure>
        </testcase>
    </testsuite>
    <testsuite name="/var/lib/buildkite-agent/builds/my-org/my-pipeline/src/ui/publish/menu/print/address_autocomplete_input/stories/address_autocomplete_input.stories.tsx">
        <testcase name="Line 4, Column 1: no-unused-variable">
            <failure type="error">All imports on this line are unused.</failure>
        </testcase>
    </testsuite>
    <testsuite name="/var/lib/buildkite-agent/builds/my-org/my-pipeline/src/ui/publish/menu/print/order_details/page_select/tests/page_select.tests.tsx">
        <testcase name="Line 3, Column 1: no-unused-variable">
            <failure type="error">All imports on this line are unused.</failure>
        </testcase>
    </testsuite>
    <testsuite name="/var/lib/buildkite-agent/builds/my-org/my-pipeline/src/ui/publish/menu/print/proofing_flow/proofing_flow/proofing_flow_presenter.ts">
        <testcase name="Line 3, Column 1: no-unused-variable">
            <failure type="error">All imports on this line are unused.</failure>
        </testcase>
    </testsuite>
</testsuites>

which unfortunately results in something unreadable like this:

tslint

any chance we could resolve a name attribute of a testsuite to a file path and use that as the information in the generated annotation if it starts with ${BUILDKITE_BUILD_PATH}?

Happy to open a pull request!

ARM support?

Hello, we've recently migrated to an ARM stack, and it's looking like our results step is failing:

# # Compile junit tests
  - label: ":coverage: Results"
    agents:
      queue: east-2-testrunner-v1
    plugins:
      - bugcrowd/test-summary#v1.11.0:
          inputs:
            - label: ":ruby: Rspec"
              artifact_path: "artifacts/rspec*"
              type: junit
          formatter:
            type: details
          context: test-summary

This is the output from buildkite:

Screen Shot 2021-04-19 at 3 59 23 PM

Wondering what it would take to get this running on ARM?

Upload an artefact listing all failures in machine readable format

As someone with occasionally flaky tests, it would be convenient to be able to see which tests tend to fail repeatedly across branches. Given this plugin is already collating all that data in a human-readable format, it would be useful to also make a machine-readable form. Then other tools can consume that for statistics purposes (via the rest api).

Use with dockerized buildkite-agent

The latest buildkite-agent docker container uses docker 17.12 (the one on the ubuntu 18.04 repos) which does not have the --mount flag. NG, because this plugin uses the --mount flag. I guess I could file this issue with buildkite but I know you better.

--mount type=bind,src=$(which buildkite-agent),dst=/usr/bin/buildkite-agent \

n.b. I have no idea if I can get this to work inside the container anyway, but this is a first step.

Failing to create a build annotation shouldn't fail the pipeline

If the rest of a build succeeds, having the annotation step fail can block later steps in the pipeline (eg deploys). This is not desirable behaviour. Suggested fix:

  1. By default, wrap processing each input in a rescue block, log the exception and continue
  2. By default, wrap the top level run in a rescue block, log the exception and continue
  3. Add a configuration flag to actually fail on errors for people who really want/need it

Annotation fails with large number of test failures

Failed to annotate build: POST https://agent.buildkite.com/v3/jobs/0fd9db38-9c2b-4360-970a-cde6b566d44b/annotations: 400 The annotation body must be less than 50 kilobytes

Ideally this would truncate after a certain number of failures, but instead it fails entirely.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.