Giter Site home page Giter Site logo

buildkite-plugins / test-collector-buildkite-plugin Goto Github PK

View Code? Open in Web Editor NEW
11.0 9.0 20.0 141 KB

πŸ” Upload JSON or JUnit files to Buildkite Test Analytics

License: MIT License

Shell 100.00%
analytics buildkite buildkite-plugin json junit test data

test-collector-buildkite-plugin's Introduction

Test Collector Buildkite Plugin Build status

A Buildkite plugin for uploading JSON or JUnit files to Buildkite Test Analytics ✨

Options

These are all the options available to configure this plugin's behaviour.

Required

files (string or array of strings)

One or more patterns of files to upload to Test Analytics, relative to the root of the searching path (./ by default). May contain * to match any number of characters of any type (unlike shell expansions, it will match / and . if necessary). Can be either a single pattern in a string or any number of them in an array.

formatΒ (string)

Format of the file.

Only the following values are allowed: junit, json

Optional

api-token-env-nameΒ (string)

Name of the environment variable that contains the Test Analytics API token.

Default value: BUILDKITE_ANALYTICS_TOKEN

api-url (string)

Full URL for the API to upload to. Defaults to https://analytics-api.buildkite.com/v1/uploads

base-path (string)

Where to search for files to upload. Defaults to the working directory .

branches (string)

String containing a regex to only do an upload in branches that match it (using the case-insensitive bash =~ operator against the BUILDKITE_BRANCH environment variable).

For example:

  • prod will match any branch name that contains the substring prod
  • ^stage- will match all branches that start with stage-
  • -ISSUE-[0-9]*$ will match branches that end with ISSUE-X (where X is any number)

Important: you may have to be careful to escape special characters like $ during pipeline upload

debugΒ (boolean)

Print debug information to the build output.

Default value: false.

Can also be enabled with the environment variable BUILDKITE_ANALYTICS_DEBUG_ENABLED.

exclude-branches (string)

String containing a regex avoid doing an upload in branches that match it (using the case-insensitive bash =~ operator against the BUILDKITE_BRANCH environment variable ).

For example:

  • prod will exclude any branch name that contains the substring prod
  • ^stage- will exclude all branches that start with stage-
  • -SECURITY-[0-9]*$ will exclude branches that end with SECURITY-X (where X is any number)

Important:

  • you may have to be careful to escape special characters like $ during pipeline upload
  • exclusion of branches is done after the inclusion (through the branches option)

follow-symlinks (boolean)

By default the plugin will not follow symlinked folders, set this option to true to do so. This will add the -L option to the find command used to get the files to upload.

missing-error (integer)

Exit code of the hook when no files are found to upload as long as the step's command has not failed already.

This should allow you to use a special exit code to soft-fail on when no files to upload. Warning: make sure that the exit code used can not be generated by your command to avoid hiding actual step failures.

Default value: 1

timeout(number)

Maximum number of seconds to wait for each file to upload before timing out.

Default value: 30

annotation-link(boolean)

Adds an annotation to the build run with a link to the uploaded report.

Default value: false

upload-concurrency(number)

The number of concurrent file uploads to perform to the Buildkite analytics API.

Default value: 1

Requirements

This plugin requires jq for parsing JSON data. If jq is not found on the agent, sed will be used as a fallback. Ensure that sed is also available to handle scenarios where jq cannot be used.

Fallback Behavior

If jq is unavailable, the plugin will attempt to parse the results using sed. This ensures that the plugin remains functional even if the preferred JSON parser is missing.

Examples

Upload a JUnit file

To upload a JUnit file to Test Analytics from a build step:

steps:
  - label: "πŸ”¨ Test"
    command: "make test"
    plugins:
      - test-collector#v1.10.1:
          files: "test/junit-*.xml"
          format: "junit"

Upload a JSON file

To upload a JSON file to Test Analytics from a build step:

steps:
  - label: "πŸ”¨ Test"
    command: "make test"
    plugins:
      - test-collector#v1.10.1:
          files:
            - "test-data-*.json"
          format: "json"

Using build artifacts

You can also use build artifacts generated in a previous step:

steps:
  # Run tests and upload 
  - label: "πŸ”¨ Test"
    command: "make test --junit=tests-N.xml"
    artifact_paths: "tests-*.xml"

  - wait

  - label: "πŸ” Test Analytics"
    command: buildkite-agent artifact download "tests-*.xml" .
    plugins:
      - test-collector#v1.10.1:
          files: "tests-*.xml"
          format: "junit"

Branch filtering

Only upload on the branches that end with -qa

steps:
  - label: "πŸ”¨ Test"
    command: "make test"
    plugins:
      - test-collector#v1.10.1:
          files: "test-data-*.json"
          format: "json"
          branches: "-qa$"

Do not upload on the branch that is exactly named legacy:

steps:
  - label: "πŸ”¨ Test"
    command: "make test"
    plugins:
      - test-collector#v1.10.1:
          files: "test-data-*.json"
          format: "json"
          exclude-branches: "^legacy$"

Only upload on branches that start with stage- but do not contain hotfix

steps:
  - label: "πŸ”¨ Test"
    command: "make test"
    plugins:
      - test-collector#v1.10.1:
          files: "test-data-*.json"
          format: "json"
          branches: "^stage-"
          exclude-branches: "hotfix"

βš’ Developing

You can use the bk cli to run the pipeline locally:

bk local run

Or if you want to run just the tests, you can use the docker Plugin Tester:

docker run --rm -ti -v "${PWD}":/plugin buildkite/plugin-tester:latest

πŸ‘©β€πŸ’» Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/buildkite-plugins/test-collector-buildkite-plugin

πŸ“œ License

The package is available as open source under the terms of the MIT License.

test-collector-buildkite-plugin's People

Contributors

benvernier-sc avatar butterkitty avatar drjosh9000 avatar ivannalisetska avatar js-murph avatar jtszalay avatar juanitofatas avatar nate-thirdwave avatar pzeballos avatar renovate[bot] avatar tirsen avatar tjschuck avatar tomowatt avatar toolmantim avatar toote avatar xg-wang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

test-collector-buildkite-plugin's Issues

Performance of test-collector is unacceptably slow.

Hi! As per our other issue, we enabled the test collecter recently. We started with a smaller project and were very happy with the results so we enabled it on our "main" project.

According to Test Analytics, we have just shy of 10k tests, generated from and it takes ~2.5 minutes to run them. Using the test-collector plugin, it's taking over 8 minutes to upload the tests, from ~500 junit xml files. This is actually longer than the rest of our pipeline takes to run.

missing-error ENV flag does not appear to be respected

We have a step defined like below

      - label: Run Physical Device Tests
        commands:
          - "ci/common/physical_device_test.sh"
        key: "physical_device_test_skippy"
        # other args omitted for brevity
        soft_fail: true
        env:
          ENABLE_SKIPPY: "true"
        plugins:
          - test-collector#v1.8.0:
              files: "**/build/fladle/*/results/*/JUnitReport.xml"
              format: "junit"
              debug: true
              api-token-env-name: ...
        retry: *retry_errors
        timeout_in_minutes: 60

The physical_device_test.sh script invoked in the command may sometimes intelligently skip running tests, so we want dynamically set the test-collector to exit with 0 in this case when it doesn't find any files. In practice the script does this in that event

export BUILDKITE_PLUGIN_TEST_COLLECTOR_MISSING_ERROR='0'

But it seems that this env is not respected when the plugin runs. Is it possible that it's resolving this env too eagerly (i.e. beginning of the step) rather than at test-result-collection-time? Or are we misunderstanding how that env is supposed to be used (or is it not visible to the test-collector plugin since it's set in the commands block)?

path which includes symlink won't find any files

Setting the pattern to e.g. bazel-testlogs/*/test.xml fails because find's -path argument doesn't follow symlinks when matching.
Allowing to set the base working directory to bazel-testlogs/ instead of just . would fix this.

Hook error disguises previous build error

If an earlier step fails (for example due to a compilation error) then the hook will give an error message and the user thinks it's this hook that has failed.

$ /plugins/github-com-buildkite-plugins-test-collector-buildkite-plugin-v1-0-0/hooks/pre-exit
No files found matching '**/out/test-results/**/*.xml'
🚨 Error: Error tearing down bootstrap: The plugin test-collector pre-exit hook exited with status 1

I'm still a buildkite noob. Can a plugin hook know the exit code of a previous step? In that case I think it should not fail with the "No files found" error. (It should still try to upload any files it finds of course, we want to submit failed test runs as well.)

It needs to return the error code from the original build error as we use that for retry logic.

Messages with parentheses do not get reported correctly

When the $BUILDKITE_MESSAGE environment variable contains parentheses, the message is not being reported correctly to BK Test Analytics.

Attached below is a screenshot of a run the plugin did (incorrect name), vs a fixed version I uploaded manually via a cURL command (correct name).

Screenshot 2024-01-19 at 10 29 21β€―am

readarray in the pre-exit hook doesn't work on Amazon Linux 2.

Hey! πŸ‘‹πŸ»

I know this is still a WIP but just wanted to note that I tried running this plugin on Amazon Linux 2 and found that this line throws an error:
https://github.com/buildkite-plugins/test-collector-buildkite-plugin/blob/main/hooks/pre-exit#L86

The error is related to the -d flag not being available.

/var/lib/buildkite-agent/plugins/github-com-buildkite-plugins-test-collector-buildkite-plugin-main/hooks/pre-exit: line 86: readarray: -d: invalid option
readarray: usage: readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]

I created a fork as a workaround: https://github.com/jmpa-io/test-collector-buildkite-plugin/blob/main/hooks/pre-exit#L86, so I'm not blocked πŸ‘πŸ»

Let me know if there's a fix in place and I can get rid of the fork! Thanks for providing the plugin, it's really useful to us :)

Nested JUnit testsuite causes duplication

Hi folks!

We've run into a problem where nested testsuites – i.e. <testsuite>s within <testsuite>s cause duplication in the Buildkite interface.

So this JUnit.xml

<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
  <testsuite name="Full Suite" tests="1" assertions="6" errors="0" warnings="1" failures="0" skipped="5" time="0.03">
    <testsuite name="Unit Tests" tests="1" assertions="6" errors="0" warnings="0" failures="0" skipped="0" time="0.03">
      <testsuite name="DuplicatedTest" file="/app/tests/DuplicatedTest.php" tests="1" assertions="6" errors="0" warnings="0" failures="0" skipped="0" time="0.03">
        <testcase name="testcase1" class="DuplicatedTest" classname="DuplicatedTest" file="/app/trunk/application/tests/validator/DuplicatedTest.php" line="115" assertions="2" time="0.01"/>
        <testcase name="testcase2" class="DuplicatedTest" classname="DuplicatedTest" file="/app/trunk/application/tests/validator/DuplicatedTest.php" line="115" assertions="2" time="0.01"/>
        <testcase name="testcase3" class="DuplicatedTest" classname="DuplicatedTest" file="/app/trunk/application/tests/validator/DuplicatedTest.php" line="115" assertions="2" time="0.01"/>
      </testsuite>
    </testsuite>
  </testsuite>
</testsuites>

will result in this duplication:

image

whereas when the outer testsuites are removed, there's no duplication:

<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
  <testsuite name="DuplicatedTest" file="/app/tests/DuplicatedTest.php" tests="1" assertions="6" errors="0" warnings="0" failures="0" skipped="0" time="0.03">
    <testcase name="testcase1" class="DuplicatedTest" classname="DuplicatedTest" file="/app/trunk/application/tests/validator/DuplicatedTest.php" line="115" assertions="2" time="0.01"/>
    <testcase name="testcase2" class="DuplicatedTest" classname="DuplicatedTest" file="/app/trunk/application/tests/validator/DuplicatedTest.php" line="115" assertions="2" time="0.01"/>
    <testcase name="testcase3" class="DuplicatedTest" classname="DuplicatedTest" file="/app/trunk/application/tests/validator/DuplicatedTest.php" line="115" assertions="2" time="0.01"/>
  </testsuite>
</testsuites>

image

NB: This is the plugin we're using to perform in upload in the pipeline, but happy to move this issue to another repo if it makes more sense.

Support absolute paths

We have some code which sticks our JUnit XML in /tmp/junit.xml. I can't use the test-collector to upload this as-is because a ./ is always prefixed to the path. I'm not sure why that is, but it'd be nice to at least have like an absolute_path option which avoids doing that.

Multiple entires for 'files'

We have a in-house script to push the junit tests created when the plugin wasn't available.

It relies on the test results download via the artifacts plugin:

 - artifacts#v1.5.0:
        download: [ "*/build/test-results/test/TEST-*.xml", "*/build/test-results/integrationTest/TEST-*.xml" ]

As the plugin supports only one path for files, I've attempted to use "*/build/test-results/*/TEST-*.xml" instead but apparently it doesn't cover all the files uploaded.

Please either make it supports ** or just more than one path.

error parsing report url

In a test run of 16 jobs, one job failed with this error. I'm not sure, but I'm guessing their was some API error from Buildkite's API.

It would be nice if we could output the API error in the job to make this easier to debug

Using jq to parse the report URL
jq: parse error: Invalid numeric literal at line 1, column 10

Unexpected output in logs

It's not an issue for me (the plugin still works) but thought the unexpected output could be confusing for some users.

I set up a new test suite which uses the Test Collector Plugin. It runs successfully and uploads to TA but I noticed some unexpected output:

/var/lib/buildkite-agent/plugins/github-com-buildkite-plugins-test-collector-buildkite-plugin-v1-10-1/hooks/pre-exit: line 179: kill: (1249389) - No such process

Line 179 takes me to this line in the code:

if ! kill -0 "${uploads_in_progress[index]}" > /dev/null; then

Is the problem that we are only redirecting stdout to /dev/null? Is it intentional we are not redirecting stderr?

References:

mapfile: command not found

When setting annotation-link: true the plugin fails with the following error message:

.../github-com-buildkite-plugins-test-collector-buildkite-plugin-v1-10-1/hooks/pre-exit: line 50: mapfile: command not found

I'm on version v1.10.1. Our CI is running on macOS.

Support soft failures

I'd like an option to fail softly - that is, rescue errors (e.g. talking to the buildkite API or reading the junit.xml) and log them but do not fail the build. We've seen a few errors like this at Anthropic which block us from using this plugin for Test Analytics, since we'd much prefer to drop some metrics rather than spuriously fail builds.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

buildkite
buildkite.yaml
  • shellcheck v1.3.0
  • plugin-linter v3.0.0
  • docker-compose v4.3.0
docker-compose
docker-compose.yml
  • buildkite/plugin-tester v3.0.1

  • Check this box to trigger a request for Renovate to run again on this repository

Support configurable API endpoint URL for debugging purposes

We currently hard-code the API endpoint URL which test executions are posted.

curl_args+=("https://analytics-api.buildkite.com/v1/uploads")

For debugging/testing purposes (internal for Buildkite), we could make the URL configurable.
For this plugin, perhaps we could make this configurable with an optional environment variable?

As an example, the Ruby collector supports this functionality

https://github.com/buildkite/test-collector-ruby/blob/7d6bbb80493c094be3c6cb3d4c8377eb7ed66a5f/lib/buildkite/test_collector.rb#L51

Annotation printing `\n` instead of newlines

We've enabled the annotation-link on the test-collector plugin.
The annotation appears like this:

image

We would expect it to be (I've manually edited the annotation)
image

Our agent is running on ubuntu 20.04, if that helps?

Hook error disguises previous build error (not fixed)

The fixed in #11 for #10 didn't seem to work for our scenario.
Our test timed out yesterday and generated the exit status 143, but the error code has still disguises

Logs
image

Buildlike Timeline output
image

I believe the error is linked to the loop downloading files running despite no files found matching .
https://github.com/buildkite-plugins/test-collector-buildkite-plugin/blob/v1.4.0/hooks/pre-exit#L113

Maybe something like an early exit would fix it.

if [[ "${#matching_files[@]}" -eq "0" ]]; then
  echo "No files found matching '${FILES_PATTERN}'"
  if [[ -z "${BUILDKITE_COMMAND_EXIT_STATUS+x}" ]] || [[ "${BUILDKITE_COMMAND_EXIT_STATUS}" -eq "0" ]]; then
    exit 1
  fi
  exit ${BUILDKITE_COMMAND_EXIT_STATUS}	
fi

for file in "${matching_files[@]}"; do
  echo "Uploading '$file'..."
  if ! upload "$TOKEN_VALUE" "$FORMAT" "${file}"; then
    echo "Error uploading, will continue"
  fi
done

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.