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 processes the upload before replying. A 202 response with accepted confirms processing is complete; partial means work remains. The packaged integrations resend safely until completion. Check the delivery log on the CI page in Jira for each result.
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.6, pytest plugin 0.2.5, GitHub Action 0.3.6, upload CLI 0.3.8, Cypress plugin 0.1.5, Azure DevOps task 0.1.4 and Nexus runner 0.6.9. Free to use with Nexus. © Resync Consulting Limited. Checksums for every file: SHA256SUMS.txt.
Packages
Where the files come from. The upload CLI, Playwright reporter and Cypress plugin packages and the pytest plugin are the same files published on npm and PyPI. The GitHub Action and Azure DevOps task archives were prepared locally. The release manifest identifies this download set and its SHA-256 checksums. This download set is not a GitHub-attested release.
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.
b6fa948c457f9af06c0a36195635056b756e8869f46edfebbfe496f43991eaaa
Install
From npm:
npm install --save-dev @resyncnz/nexus-playwright-reporter
Or from the download above:
npm install --save-dev https://nexus.resync.nz/downloads/nexus-playwright-reporter-0.2.6.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.
0f8e1e5a2c84c9daa5ae06470e3e5151be7b374b8d36a883059269ca7d42e424
5e0de50c234c923f41f92dd86a5657b38041ee122aec2c4d2d11fb70a26a9d02
Install
From PyPI:
pip install pytest-nexus
Or from the download above:
pip install https://nexus.resync.nz/downloads/pytest_nexus-0.2.5-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.
9e7d06d0e2e39069cd7fe75383b74e213852cf5951c6a3685490e5f8c1e44a8d
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.6.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+.
8203b702dcc3ec95c72e43b5b9dc14747cbf142f37cf0f05d1758e879eec9cc7
e936fc72ed209aeaf4ddb0b298bc8243fcf46a1eeafa59715b6265bd42c8415b
Install
Run it straight from npm, with nothing to download:
npx @resyncnz/nexus-upload results.xml --project NEX --environment staging
Or 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.8.mjs
echo "8203b702dcc3ec95c72e43b5b9dc14747cbf142f37cf0f05d1758e879eec9cc7 nexus-upload.mjs" | sha256sum -c -
Or add the downloaded npm package to your project: npm install --save-dev https://nexus.resync.nz/downloads/nexus-upload-0.3.8.tgz, then run npx nexus-upload.
A report of more than 500 results is sent in parts of up to 500, one after another, into the same cycle and build. The tool waits and resends when Nexus asks it to slow down. A Postman/Newman report over 500 requests is the one exception: the tool stops with a clear message before sending.
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.
9b414ac9378d34c3eed7c82861b71515d2876ea137ed15cb5d6ebf2a9848b35b
Install
From npm:
npm install --save-dev @resyncnz/nexus-cypress
Or from the download above:
npm install --save-dev https://nexus.resync.nz/downloads/nexus-cypress-0.1.5.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.
445453b1dc36cca357f959e1884e01dd90d2fd045c6ce344dd3539eaba01457e
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.4.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+.
21e36d4155d96e1da1f08a2b3afae0a0b47893e02b48219d7e8534216e076955
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
The published runner executes your configured local test suites. It does not fetch approved Playwright scripts stored on Nexus Test Cases; that workflow requires a compatible runner and setup guide that are not yet available through these public downloads.
Nexus requires runner 0.6.2 or later (that minimum has not changed; 0.6.9 is the current published runner). To upgrade, run npx @resyncnz/nexus-runner@latest, or replace nexus-runner.mjs with the newest file here.
Start a cycle in your CI
Run in CI starts GitHub Actions, GitLab.com, Azure DevOps Pipelines or Bitbucket Pipelines from a Nexus cycle. A project administrator connects the target, branch, workflow or pipeline, and access token once. Nexus sends only the project, cycle, environment and build values the administrator selects.
Tokens stay in Forge secret storage, are never shown again and are deleted when the connection is removed. A second press within 60 seconds is blocked, and each run is recorded in the audit log. Tests run in your pipeline and the report comes back into the same cycle.
Cloud-hosted services only. For self-hosted Jenkins or GitLab, use the customer-hosted Nexus runner. Jenkins jobs can also upload reports with the upload tool.
Set up your service · Example pipelines
Connect your framework
Playwright uses the Nexus reporter; Selenium with pytest uses the Nexus pytest plugin. Cypress supports its reporter or JUnit report plus upload. Upload Cucumber JSON, JUnit XML or Mocha mochawesome JSON. Robot Framework also works.
Results match Test Cases by Automation Key or issue key. Nexus records pass/fail per run, and failed runs can raise a linked Jira Bug.
Read test evidence as JSON
A project administrator can opt a key into Read test data to read paged cases, cycles, runs, step results and coverage for that project. This permission is off by default and is never added to existing keys automatically. Records with Jira issue security are excluded, sensitive test data is masked and people appear only as Atlassian account IDs.
Each key is limited to 60 requests a minute and 2,000 an hour. Read the API guide or download the OpenAPI definition.
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.8.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.8.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.8.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.8.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.8.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.