| description | Running Playwright tests on Harness CI with Currents reporting and parallel sharding |
|---|
This guide explains how to run Playwright tests on Harness Continuous Integration and report results to Currents. It follows Harness NextGen pipeline patterns (Run steps, stage parallelism, secrets).
{% hint style="warning" %}
CURRENTS_CI_BUILD_ID is mandatory for Harness. Harness is not in Currents’ auto-detected CI providers. If you omit it, Currents may generate a different build ID per job or shard: parallel Playwright shards will not merge into one run, reporting and orchestration break, and retries can collide with or duplicate prior runs. Always set CURRENTS_CI_BUILD_ID in every Run step (see below).
{% endhint %}
Currents
- Organization and project at https://app.currents.dev
- Project ID and Record Key — see record-key.md
CURRENTS_CI_BUILD_IDset in CI for every Playwright step (mandatory on Harness — see CI Build ID)@currents/playwrightinstalled and configured — see currents-playwright
Harness
- A CI pipeline with a Build (
CI) stage - A Docker registry connector that can pull your Playwright image (for example
mcr.microsoft.com/playwright). ReplaceYOUR_DOCKER_CONNECTORin the examples with your connector reference (for exampleaccount.harnessImageRegistryor your org’s Docker Hub connector).
- In Harness, create an encrypted text secret at the appropriate scope (project, org, or account).
- Use a stable identifier (Harness derives it from the name). Example identifier:
currents_record_key. - Reference it only by identifier in expressions, not the display name. See Add and reference text secrets.
{% hint style="warning" %}
Avoid $ in secret values when possible; the shell may expand it. If unavoidable, follow Harness guidance (for example quoting or base64 encoding) in the text secrets documentation.
{% endhint %}
Use the same Playwright + Currents setup as other CI providers.
playwright.config.ts (reporter):
{% code title="playwright.config.ts" overflow="wrap" %}
import { currentsReporter } from "@currents/playwright";
import { defineConfig } from "@playwright/test";
export default defineConfig({
reporter: [currentsReporter()],
use: {
trace: "retain-on-failure-and-retries",
video: "retain-on-failure",
screenshot: "on",
},
// ...projects, testDir, etc.
});{% endcode %}
currents.config.ts:
{% code title="currents.config.ts" %}
import { CurrentsConfig } from "@currents/playwright";
const config: CurrentsConfig = {
projectId: process.env.CURRENTS_PROJECT_ID ?? "",
recordKey: process.env.CURRENTS_RECORD_KEY ?? "",
};
export default config;{% endcode %}
You must provide CURRENTS_CI_BUILD_ID (environment variable or reporter config). It is a required input for correct Currents behavior on Harness — not optional.
Without a stable, explicit value:
- Each parallel shard may get its own ID → multiple runs instead of one combined run
- Reruns may reuse or collide with IDs → stale or rejected uploads — see the CI Build ID FAQ
The value must be:
- Unique per pipeline execution (each execution gets its own Currents run)
- Identical across all parallel Playwright shards in the same execution (shards merge into one run)
- Different when you retry the same logical build, when you need a fresh run — see CI Build ID
Harness resolves expressions before the step runs. Common choices:
| Approach | Expression (example) | Notes |
|---|---|---|
| Execution only | <+pipeline.executionId> |
Unique per execution; confirm behavior for re-runs in your Harness edition |
| Execution + sequence | Concatenate <+pipeline.executionId> with <+pipeline.sequenceId> using + or .concat() |
See Harness variables; helps separate retries when sequenceId changes |
Compose multi-part IDs with the concatenation patterns documented under Harness variables (for example combining <+pipeline.identifier>, <+pipeline.executionId>, and <+pipeline.sequenceId>).
Add a Run step in your CI stage. Set Container Registry to your Docker connector and Image to a Playwright image tag that matches your @playwright/test version.
execution:
steps:
- step:
type: Run
name: playwright_currents
identifier: playwright_currents
spec:
connectorRef: YOUR_DOCKER_CONNECTOR
image: space.vars.PW_IMAGE_ROUTE + ":" + space.vars.LATEST_PW_IMAGE_VERSION
shell: Bash
command: |-
npm ci
npx playwright install chrome
npx playwright test
envVariables:
CI: "true"
CURRENTS_PROJECT_ID: YOUR_CURRENTS_PROJECT_ID
CURRENTS_RECORD_KEY: <+secrets.getValue("currents_record_key")>
CURRENTS_CI_BUILD_ID: <+pipeline.executionId>
- Replace
YOUR_CURRENTS_PROJECT_IDwith your project ID, or use a pipeline variable (for example<+pipeline.variables.currents_project_id>). - Replace
currents_record_keywith your secret’s identifier.
Use stage-level parallelism so Harness runs multiple copies of the stage. Playwright’s --shard is 1-based; Harness parallel indices are 0-based, so use HARNESS_NODE_INDEX + 1 for the shard index.
Do not rely on Harness split_tests for Playwright unless you intentionally drive a custom split; native sharding matches the rest of Currents’ CI docs and keeps setup simple.
- stage:
name: playwright_tests
identifier: playwright_tests
type: CI
strategy:
parallelism: 3
maxConcurrency: 3
spec:
cloneCodebase: true
platform:
os: Linux
arch: Amd64
runtime:
type: Cloud
spec: {}
execution:
steps:
- step:
type: Run
name: playwright_currents_shard
identifier: playwright_currents_shard
spec:
connectorRef: YOUR_DOCKER_CONNECTOR
image: space.vars.PW_IMAGE_ROUTE + ":" + space.vars.LATEST_PW_IMAGE_VERSION
shell: Bash
command: |-
npm ci
npx playwright install chrome
SHARD_INDEX=$((HARNESS_NODE_INDEX + 1))
npx playwright test --shard=${SHARD_INDEX}/${HARNESS_NODE_TOTAL}
envVariables:
CI: "true"
HARNESS_NODE_INDEX: <+strategy.iteration>
HARNESS_NODE_TOTAL: <+strategy.iterations>
CURRENTS_PROJECT_ID: YOUR_CURRENTS_PROJECT_ID
CURRENTS_RECORD_KEY: <+secrets.getValue("currents_record_key")>
CURRENTS_CI_BUILD_ID: <+pipeline.executionId>
- Tune
parallelismandmaxConcurrencyper best practices for looping strategies. CURRENTS_CI_BUILD_IDis mandatory — the same value must reach every shard (the<+pipeline.executionId>expression above resolves identically for all parallel instances of the same execution).
| Variable | Required | Description |
|---|---|---|
CURRENTS_PROJECT_ID |
Yes | Currents project ID from the dashboard |
CURRENTS_RECORD_KEY |
Yes | Record key; inject via <+secrets.getValue("SECRET_IDENTIFIER")> (or org/account-scoped variant) |
CURRENTS_CI_BUILD_ID |
Yes (mandatory) | Required on Harness. Stable ID shared by all shards in one execution; must change appropriately on retries — see CI Build ID |
CI |
Optional | Set to true so tools behave as in CI |
HARNESS_NODE_INDEX |
Parallel only | <+strategy.iteration> — 0-based shard index |
HARNESS_NODE_TOTAL |
Parallel only | <+strategy.iterations> — must match parallelism |
You can define pipeline or stage variables for non-secret settings (for example project ID) and reference them with expressions such as <+pipeline.variables.currents_project_id>. Precedence for environment variables in Harness is step > stage > pipeline. See Variables (open-source YAML) and Harness variables (expressions).
If you use the open-source pipeline schema (kind: pipeline), environment variables are often declared under spec.options.envs (pipeline-wide) or spec.envs on a ci stage, and Run steps use spec.container and spec.script. The Currents requirements are the same: include CURRENTS_CI_BUILD_ID (mandatory), other CURRENTS_* variables, and npx playwright test with optional --shard. Map them to your schema per CI stage reference.
- Harness CI Run step settings
- Speed up CI with parallelism
- Currents: CI optimization, Playwright orchestration
{% hint style="info" %} Got stuck configuring CI? Reach out to support.md. {% endhint %}