Setting this up for the first time? Start with the automation setup guide to configure Nexus and your test tool, then follow the CI setup guide to connect your pipeline. Each guide takes you through setup on both sides and a first-result check.
One execution history for manual and automated testing.
Use the Nexus reporter for Playwright or the pytest plugin for Selenium suites run with pytest. Other tools connect by producing a supported result file and uploading it through the CLI or API. Every matched result is recorded against Nexus Test Executions in Jira.
Your CI platforms, connected.
Send the report after tests finish, even when a test fails. The connection is an upload step in your pipeline, with results recorded against Nexus Test Executions in Jira.
How it works
Nexus replies 202 straight away and processes the report in the background. The per-test outcome (matched, unmatched or skipped) is in the delivery log on the CI page in Jira.
Before you start (once per project):
- In Jira, open Project settings → Nexus → CI. Create an API key with the ingest scope and copy it. It is shown once. Copy the results URL from the same page.
- Store both as secrets in your CI system, named
NEXUS_URLandNEXUS_API_KEY. Never put the key in a pipeline file. - Start each test's name with its Test Case's Automation Key, for example
NEX-12: login works.
The reporters, the GitHub Action, the upload CLI and the Azure DevOps task all read the same settings: NEXUS_URL, NEXUS_API_KEY, NEXUS_PROJECT, and optionally NEXUS_ENVIRONMENT, NEXUS_TEST_SET (a cycle to record into), NEXUS_BUILD, NEXUS_COMMIT and NEXUS_COMPONENT. Build and commit are filled in from your CI system when you don't set them. None of them prints your key.
Current versions: Playwright reporter 0.2.3, pytest plugin 0.2.3, GitHub Action 0.3.4, upload CLI 0.3.4, Cypress plugin 0.1.2, Azure DevOps task 0.1.2 and Nexus runner 0.6.5. Free to use with Nexus. © Resync Consulting Limited. Checksums for every file: SHA256SUMS.txt.
Packages
Playwright reporter
For Playwright Test. It sends the whole run at the end, so you don't need an extra pipeline step. Node 18+, Playwright 1.40+, no other dependencies.
b9d04b711a8d85556630b6fea94f37c0e0a97b5145bf3206b7fa88e3ac604f3c
Install
npm install --save-dev https://nexus.resync.nz/downloads/nexus-playwright-reporter-0.2.3.tgz
Configure
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [
['list'],
['@resyncnz/nexus-playwright-reporter', { project: 'NEX', environment: 'staging' }],
],
});
The URL and key come from NEXUS_URL and NEXUS_API_KEY. Other options: testSet, component, failOnUploadError (fail the run if the upload fails; off by default) and enabled (for example !!process.env.CI).
Example
test('NEX-12: mandatory fields show validation errors', async ({ page }) => { ... });
Put the key on the test's own title, not on a describe block.
pytest plugin
For pytest, including Selenium suites. It sends the session's JUnit XML report when the run ends. Python 3.8+, pytest 7+, no other dependencies.
1ce4c606b815488c2a4e50ceb250fabe8c81c332c2da1ea28b836c54c1e3af20
60986955917a9aebb07dccbfbc8636ef5c05dfc345fb4a2c7e242b24a103f9c3
Install
pip install https://nexus.resync.nz/downloads/pytest_nexus-0.2.3-py3-none-any.whl
The plugin loads by itself and does nothing until a Nexus URL is set.
Configure and run
export NEXUS_URL=... # from your CI secrets
export NEXUS_API_KEY=...
pytest --nexus-project NEX --nexus-environment staging
Other options: --nexus-test-set, --nexus-component, --nexus-fail-on-upload-error and --no-nexus. If you already pass --junitxml, that file is the one sent.
Example
def test_NEX_11_valid_user_signs_in(driver):
...
Python names can't contain -, so use _. Nexus reads NEX_11 as NEX-11.
GitHub Action
For GitHub Actions, with any results file. It needs only bash and curl, so it runs on Linux, macOS and Windows runners. You keep a copy in your repository.
63aa5e1fdff7392984d4f193ba57f62eff5af177deb79413dd76c4e06e559a02
Install
Unzip it into .github/actions/nexus-upload and commit the folder:
mkdir -p .github/actions/nexus-upload
curl -fsSLo nexus-action.zip https://nexus.resync.nz/downloads/nexus-github-action-0.3.4.zip
unzip -o nexus-action.zip -d .github/actions/nexus-upload && rm nexus-action.zip
git add .github/actions/nexus-upload
Configure
Add NEXUS_URL and NEXUS_API_KEY under Settings → Secrets and variables → Actions in GitHub.
Example
steps:
- uses: actions/checkout@v4
# ... run your tests, writing results.xml ...
- name: Send results to Nexus
if: ${{ always() }}
uses: ./.github/actions/nexus-upload
with:
url: ${{ secrets.NEXUS_URL }}
api-key: ${{ secrets.NEXUS_API_KEY }}
project: NEX
file: results.xml
environment: staging
if: always() sends the results even when tests fail. Those are the runs you most want recorded. Set fail-on-error: 'false' if an upload problem should only warn.
Upload CLI
For any CI system and any results file: JUnit XML, xUnit XML, NUnit XML, TestNG XML, Robot Framework XML, Cucumber JSON, Mocha JSON, mochawesome JSON, Playwright JSON or Postman/Newman JSON. It detects the format for you. One file, no dependencies, Node 16+.
8aeaad9b8710d88c3688d8a1fe3ad00ef897a982e8ab79475f6390b55270f88f
56157e3cb1d945331f1611e34581d0ae431c9f1e381d251bcaceef28fcee499d
Install
Download the script in your CI job, and check it if you like:
curl -fsSLo nexus-upload.mjs https://nexus.resync.nz/downloads/nexus-upload-0.3.4.mjs
echo "8aeaad9b8710d88c3688d8a1fe3ad00ef897a982e8ab79475f6390b55270f88f nexus-upload.mjs" | sha256sum -c -
Or add the npm package to your project: npm install --save-dev https://nexus.resync.nz/downloads/nexus-upload-0.3.4.tgz, then run npx nexus-upload.
Example
export NEXUS_URL=... # from your CI secrets
export NEXUS_API_KEY=...
node nexus-upload.mjs results.xml --project NEX --environment staging
Other options: --test-set, --component, --format, --soft (warn but exit 0) and --dry-run. Run node nexus-upload.mjs --help for the full list. Exit codes: 0 sent, 1 Nexus refused the file or couldn't be reached, 2 a usage or file problem.
Cypress plugin
For Cypress. It sends the whole run when Cypress finishes (after:run), with each failure's error and stack. Node 18+, Cypress 12+, no other dependencies.
038f175a0543ee8d204dddb22bc19bbe5c1618012b0c7e6a45cdc6e66e7e2af8
Install
npm install --save-dev https://nexus.resync.nz/downloads/nexus-cypress-0.1.2.tgz
Configure
// cypress.config.js
const { defineConfig } = require('cypress');
const nexus = require('@resyncnz/nexus-cypress');
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
nexus(on, config, { project: 'NEX', environment: 'staging' });
return config;
},
},
});
The URL and key come from NEXUS_URL and NEXUS_API_KEY. Other options: testSet, component, failOnUploadError and enabled. If another plugin also uses after:run, call sendResults(results, options) from your own handler instead.
Example
it('NEX-12: mandatory fields show validation errors', () => { ... });
Azure DevOps task
For Azure Pipelines. A pipeline task, NexusUpload@0, that sends one or more results files. It keeps the key in Azure's secret masker and marks the step "Succeeded with issues" rather than failing when you ask it to.
df7341c7da0c30bdc0baf49cdf90fb6c559140a64ad8762b2986e0b736a396b1
Install
Unzip it and upload the task to your Azure DevOps organisation once, with Microsoft's tfx tool and a personal access token that can manage agent pools:
unzip nexus-azure-devops-task-0.1.2.zip -d nexus-task
npx tfx-cli build tasks upload --task-path nexus-task/NexusUpload \
--service-url https://dev.azure.com/YOUR-ORG --auth-type pat --token YOUR-PAT
Configure
Add NEXUS_URL and NEXUS_API_KEY as secret pipeline variables.
Example
- task: NexusUpload@0
displayName: Send results to Nexus
condition: succeededOrFailed()
inputs:
resultsFiles: '**/results.xml'
nexusUrl: $(NEXUS_URL)
apiKey: $(NEXUS_API_KEY)
project: NEX
environment: staging
Other inputs: format, testSet, component, stepMatching, systemOut, failOnError and failIfNoFiles. Prefer not to install a task? Use the upload CLI example instead.
Nexus runner
Lets testers start your automated tests from a Nexus cycle with Run automation. The runner runs where your tests already run (a laptop, a CI agent or a container), asks Nexus for queued runs, runs your test command and posts the results back. Nexus never connects to your machines. One file, no dependencies, Node 18+.
dac9ef5c7957826dea74e5b36d1e455ab733eda6afd9309e135a87373f8837dc
d0dfa5885afa51b6fcbddf74fce29abfb5e354ba8b6f5823748fcff959472c65
Set up
- In Jira, open Project settings → Nexus → Automation. It builds the config for each of your test tools and shows the runner URL.
- Save the runner and the config (as
nexus-runner.config.json) next to your tests, and setNEXUS_API_KEY. - Check the setup, then start it:
node nexus-runner.mjs --test # checks the config and the connection
node nexus-runner.mjs # keeps polling for queued runs
node nexus-runner.mjs --once # one poll, for a scheduled CI job
Nexus requires runner 0.6.2 or later. To upgrade, replace nexus-runner.mjs with the newest file here.
CI examples
Each example sends results.xml with the upload CLI after the tests have run, even when they failed. Replace NEX with your project key. The job needs Node 16 or later and curl.
GitHub Actions
- name: Send results to Nexus
if: ${{ always() }}
env:
NEXUS_URL: ${{ secrets.NEXUS_URL }}
NEXUS_API_KEY: ${{ secrets.NEXUS_API_KEY }}
run: |
curl -fsSLo nexus-upload.mjs https://nexus.resync.nz/downloads/nexus-upload-0.3.4.mjs
node nexus-upload.mjs results.xml --project NEX --environment staging
GitLab CI
nexus-results:
stage: .post
image: node:22
when: always
needs:
- job: test
artifacts: true
script:
- curl -fsSLo nexus-upload.mjs https://nexus.resync.nz/downloads/nexus-upload-0.3.4.mjs
- node nexus-upload.mjs results.xml --project NEX --environment staging
Add NEXUS_URL and NEXUS_API_KEY under Settings → CI/CD → Variables, with Masked on for the key.
Azure Pipelines
- script: |
curl -fsSLo nexus-upload.mjs https://nexus.resync.nz/downloads/nexus-upload-0.3.4.mjs
node nexus-upload.mjs results.xml --project NEX --environment staging
displayName: Send results to Nexus
condition: succeededOrFailed()
env:
NEXUS_URL: $(NEXUS_URL)
NEXUS_API_KEY: $(NEXUS_API_KEY)
Azure doesn't pass secret variables to scripts on its own, so map them in env as shown.
Bitbucket Pipelines
pipelines:
default:
- step:
name: Test
image: node:22
script:
- npm ci
- npm test # writes results.xml
after-script:
- curl -fsSLo nexus-upload.mjs https://nexus.resync.nz/downloads/nexus-upload-0.3.4.mjs
- node nexus-upload.mjs results.xml --project NEX --environment staging
after-script runs whether the tests passed or failed. Add the two values as secured repository variables.
Jenkins
post {
always {
withCredentials([
string(credentialsId: 'nexus-url', variable: 'NEXUS_URL'),
string(credentialsId: 'nexus-api-key', variable: 'NEXUS_API_KEY')
]) {
sh '''
curl -fsSLo nexus-upload.mjs https://nexus.resync.nz/downloads/nexus-upload-0.3.4.mjs
node nexus-upload.mjs results.xml --project NEX --environment staging
'''
}
}
}
Store the URL and key as two Secret text credentials. The agent needs Node on its path.
More detail, including the plain curl request these helpers make, is in the CI guide.
Troubleshooting
HTTP 401: the key was refused
- The key is wrong, was revoked, or belongs to another project. Keys work for one project only.
- The key doesn't have the ingest scope. Create a new key with that scope in Project settings → Nexus → CI.
- Check the secret has no extra spaces or line breaks, and that the job can read it. Some CI systems hide secrets from pull requests made from forks.
Results show as unmatched
Nexus matches each result to a Test Case by the Automation Key in the test's name. It never guesses. Open the Test Case in Jira, copy its Automation Key, and put it at the start of the test name:
| Test tool | Name the test like this |
|---|---|
| Playwright, Jest, Mocha, Cypress | test('NEX-12: login works', ...) |
| pytest | def test_NEX_12_login_works(): |
| JUnit, TestNG, NUnit | void NEX_12_loginWorks() or @DisplayName("NEX-12: login works") |
| Cucumber | A @NEX-12 tag on the scenario, or Scenario: NEX-12 login works |
| Postman (Newman) | pm.test('NEX-12: login works', ...) |
The key must be on the test itself, not only on a surrounding group. The delivery log on the CI page lists every unmatched name.
The report is too big
One upload can be at most 5 MB and 500 results. The helpers check the size before sending; Nexus answers 413 if a report is still too large. Split the run into shards or jobs, and send one report per shard.
Anything else
Check the delivery log in Project settings → Nexus → CI first. If you're still stuck, email nexus-support@resync.co.nz with the helper's output. Never send your API key.