Parallel Builds
Split your visual tests across multiple machines or processes. All shards contribute screenshots to a single build.
How It Works
Give multiple test runs the same parallel-id. Vizzly groups their screenshots into one build.
The first shard creates the build. Subsequent shards with the same parallel-id add their screenshots to that build. When all shards finish, you call finalize to process comparisons.
Important: Each parallel-id must be unique per build. Reusing a parallel-id after finalization adds screenshots to the existing build instead of creating a new one.
Basic Usage
Use the same parallel-id across all shards:
# Shard 1vizzly run "npm test -- --shard=1/3" --parallel-id "build-12345"
# Shard 2vizzly run "npm test -- --shard=2/3" --parallel-id "build-12345"
# Shard 3vizzly run "npm test -- --shard=3/3" --parallel-id "build-12345"
# After all shards completevizzly finalize "build-12345"You can also set VIZZLY_PARALLEL_ID instead of using the flag.
CI Examples
GitHub Actions
Use github.run_id and github.run_attempt to create a unique ID for each workflow run:
jobs: visual-tests: strategy: matrix: shard: [1/4, 2/4, 3/4, 4/4] steps: - name: Run visual tests run: | npx vizzly run "npm test -- --shard=${{ matrix.shard }}" \ --parallel-id="${{ github.run_id }}-${{ github.run_attempt }}" env: VIZZLY_TOKEN: ${{ secrets.VIZZLY_TOKEN }}
finalize-build: needs: visual-tests if: always() steps: - name: Finalize build run: npx vizzly finalize "${{ github.run_id }}-${{ github.run_attempt }}" env: VIZZLY_TOKEN: ${{ secrets.VIZZLY_TOKEN }}Note the if: always() on the finalize job. This runs finalization even if tests fail, which is critical for seeing your visual test results.
GitLab CI
GitLab provides CI_PIPELINE_ID which is unique per pipeline:
visual_tests: parallel: 4 script: - | npx vizzly run "npm test -- --shard=${CI_NODE_INDEX}/${CI_NODE_TOTAL}" \ --parallel-id="${CI_PIPELINE_ID}" variables: VIZZLY_TOKEN: $VIZZLY_TOKEN
finalize_build: needs: [visual_tests] when: always script: - npx vizzly finalize "${CI_PIPELINE_ID}" variables: VIZZLY_TOKEN: $VIZZLY_TOKENCircleCI
CircleCI’s CIRCLE_WORKFLOW_ID uniquely identifies each workflow:
jobs: visual-tests: parallelism: 4 steps: - run: name: Run visual tests command: | npx vizzly run "npm test -- --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}" \ --parallel-id="${CIRCLE_WORKFLOW_ID}" environment: VIZZLY_TOKEN: $VIZZLY_TOKEN
finalize-build: steps: - run: npx vizzly finalize "${CIRCLE_WORKFLOW_ID}" environment: VIZZLY_TOKEN: $VIZZLY_TOKEN
workflows: visual-testing: jobs: - visual-tests - finalize-build: requires: [visual-tests]Test Framework Integration
Playwright
Playwright has built-in sharding:
npx vizzly run "npx playwright test --shard=1/4" --parallel-id="build-123"npx vizzly run "npx playwright test --shard=2/4" --parallel-id="build-123"npx vizzly run "npx playwright test --shard=3/4" --parallel-id="build-123"npx vizzly run "npx playwright test --shard=4/4" --parallel-id="build-123"Jest
Split by test file patterns or directories:
npx vizzly run "npx jest tests/visual/components" --parallel-id="build-123"npx vizzly run "npx jest tests/visual/pages" --parallel-id="build-123"What Happens Without Finalize
If you don’t call finalize, your build stays in created status. Vizzly won’t process comparisons or update GitHub PR checks.
The build exists and you can see uploaded screenshots, but you won’t get pass/fail results.
Finalize Behavior
The finalize command finds the build with the given parallel-id and transitions it to completed status. This triggers:
- Screenshot comparisons
- GitHub PR status checks
- Build review workflows (if enabled)
You can only finalize once. Calling finalize on an already-completed build does nothing.
Common Mistakes
Reusing parallel IDs across builds: Each build needs a unique parallel-id. If you reuse an ID from a previous build, new screenshots get added to the old build instead of creating a new one.
# Bad - same ID for different commitsvizzly run "npm test" --parallel-id="my-tests"
# Good - unique ID per buildvizzly run "npm test" --parallel-id="build-${COMMIT_SHA}"Not finalizing when shards fail: Always finalize, even if some shards fail. Use if: always() in GitHub Actions or when: always in GitLab CI.
Forgetting the API token on finalize: The finalize command needs VIZZLY_TOKEN just like run does.
Next Steps
- CLI Commands - Full command reference
- Test Framework Integration - Framework-specific setup
- Client API Reference - SDK integration details