Sharded Vitest Runs
When running your Vitest tests over multiple shared CI jobs, you’ll need to wait for all jobs to complete, ensuring the results are saved in either the default test results directory or a custom directory accessible by the next job as artifacts. You can then run Chromatic in a job that depends on all the shards.
See Vitest’s sharding documentation for an example on how to merge Vitest’s own test reports.
GitHub Actions
If you’re working with GitHub Actions, you can configure a job matrix to run Vitest tests in parallel across multiple instances. Enabling this option will run a separate job for every combination of the provided values, merge the test results as a single artifact, and make them available to the Chromatic job when it runs.
name: 'UI Tests'
on: push
jobs:
vitest:
name: Run Vitest
strategy:
matrix:
shard: [1, 2]
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.60.0-noble
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version: 24.15.0
- name: Install dependencies
run: npm ci
- name: Run Vitest tests
run: npx vitest run --shard=${{ matrix.shard }}/${{ strategy.job-total }}
env:
HOME: /root
- uses: actions/upload-artifact@v7
if: ${{ !cancelled() }}
with:
name: chromatic-archives-${{ matrix.shard }}_${{ strategy.job-total }}
path: .vitest/chromatic
include-hidden-files: true
retention-days: 30
chromatic:
name: Run Chromatic
needs: vitest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version: 24.15.0
- name: Install dependencies
run: npm ci
- name: Download all workflow run artifacts
uses: actions/download-artifact@v8
with:
path: .vitest/chromatic
pattern: chromatic-archives-*
merge-multiple: true
- name: Run Chromatic tests
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
vitest: true
GitLab Pipelines
To run Vitest tests in parallel across shared CI jobs in GitLab, you can use the parallel option in your GitLab CI workflow. The job will be split into multiple smaller jobs running in parallel sequentially named based on the values of the environment variables. The results will be saved as an artifact and accessible by the Chromatic job when it runs.
image: node:krypton
stages:
- UI_Tests
cache:
key: $CI_COMMIT_REF_SLUG-$CI_PROJECT_DIR
paths:
- .npm/
before_script:
- npm ci
Vitest:
stage: UI_Tests
needs: []
image: mcr.microsoft.com/playwright:v1.60.0-noble
parallel: 2
script:
- npx vitest run --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
allow_failure: true
artifacts:
when: always
paths:
- '.vitest/'
expire_in: 4 weeks
Chromatic:
stage: UI_Tests
needs: [Vitest]
script:
- npx chromatic --vitest --project-token=$CHROMATIC_PROJECT_TOKEN
CircleCI
To run Vitest tests in parallel across shared CI jobs in CircleCI, you can use the parallelism option in your CircleCI workflow to set the number of parallel jobs to run. You’ll also need to override the default parallelization environment variables to allow the Vitest test runner to split the tests across the instances. When finished, the test results will be saved as an artifact and accessible by the Chromatic job when it runs.
version: 2.1
executors:
vitest-noble-development:
docker:
- image: mcr.microsoft.com/playwright:v1.60.0-noble
chromatic-ui-testing:
docker:
- image: cimg/node:24.15.0
jobs:
Vitest:
executor: vitest-noble-development
parallelism: 2
working_directory: ~/repo
steps:
- checkout
- restore_cache:
name: Restore NPM cache
keys:
- v1-dependencies-{{ checksum "package-lock.json" }}
- v1-dependencies-
- run:
name: 'Install Vitest dependencies'
command: npm ci
- run:
name: 'Run Vitest tests'
command: SHARD="$((${CIRCLE_NODE_INDEX}+1))"; npx vitest run --shard=${SHARD}/${CIRCLE_NODE_TOTAL}
when: always
- store_artifacts:
path: ./.vitest/chromatic
- persist_to_workspace:
root: .
paths:
- .vitest/chromatic
Chromatic:
executor: chromatic-ui-testing
working_directory: ~/repo
steps:
- checkout
- restore_cache:
name: Restore NPM cache
keys:
- v1-dependencies-{{ checksum "package-lock.json" }}
- v1-dependencies-
- run: npm ci
- attach_workspace:
at: .
- run:
name: 'Run Chromatic'
command: npx chromatic --vitest --project-token=${CHROMATIC_PROJECT_TOKEN}
workflows:
UI_Tests:
jobs:
- Vitest
- Chromatic:
requires:
- Vitest
Jenkins
If you’re working with Jenkins, you can configure your pipeline to run Vitest tests in parallel, distributed across multiple stages, save the test results as artifacts, and run Chromatic in a separate stage that depends on the test results from the previous job.
pipeline {
agent any
tools {nodejs "node"}
stages {
stage('Install dependencies') {
steps {
sh 'npm ci'
}
}
stage('Vitest'){
environment {
MAX_SHARDS = '2'
}
parallel {
stage('Shard #1') {
agent {
docker {
image 'mcr.microsoft.com/playwright:v1.60.0-noble'
reuseNode true
}
}
environment {
SHARD = '1'
}
steps {
sh 'npm ci'
sh "npx vitest run --shard=${SHARD}/${env.MAX_SHARDS}"
}
post {
always {
archiveArtifacts '.vitest/**'
}
}
}
stage('Shard #2') {
agent {
docker {
image 'mcr.microsoft.com/playwright:v1.60.0-noble'
reuseNode true
}
}
environment {
SHARD = '2'
}
steps {
sh 'npm ci'
sh "npx vitest run --shard=${SHARD}/${env.MAX_SHARDS}"
}
post {
always {
archiveArtifacts '.vitest/**'
}
}
}
}
}
stage('Chromatic') {
environment {
CHROMATIC_PROJECT_TOKEN = credentials('chromatic-project-token')
}
steps {
sh "npx chromatic --vitest"
}
}
}
}
Semaphore
To run Vitest tests in parallel across shared CI jobs in Semaphore, you can use the parallelism option in your workflow. The job will be split into multiple smaller jobs running in parallel sequentially named based on the values of the environment variables. The results will be saved as an artifact and accessible by the Chromatic job when it runs.
version: v1.0
name: UI Tests
agent:
machine:
type: e2-standard-2
os_image: ubuntu2404
global_job_config:
prologue:
commands:
- checkout
blocks:
- name: Vitest
dependencies: []
task:
agent:
machine:
type: e2-standard-2
os_image: ubuntu2404
containers:
- name: Vitest
image: mcr.microsoft.com/playwright:v1.60.0-noble
jobs:
- name: Run Vitest
commands:
- cache restore npm-$SEMAPHORE_GIT_BRANCH-$(checksum package-lock.json)-$(checksum .semaphore/semaphore.yml)
- npm ci
- cache store npm-$SEMAPHORE_GIT_BRANCH-$(checksum package-lock.json)-$(checksum .semaphore/semaphore.yml) ~/.npm
- npx vitest run --shard=$SEMAPHORE_JOB_INDEX/$SEMAPHORE_JOB_COUNT
parallelism: 2
epilogue:
always:
commands:
- artifact push workflow --force .vitest
- name: Run Chromatic
dependencies: ['Vitest']
task:
prologue:
commands:
- sem-version node 24.15.0
- artifact pull workflow .vitest
secrets:
- name: CHROMATIC_PROJECT_TOKEN
jobs:
- name: Chromatic
commands:
- cache restore npm-$SEMAPHORE_GIT_BRANCH-$(checksum package-lock.json)-$(checksum .semaphore/semaphore.yml)
- npm ci
- npx chromatic --vitest
Other CI providers
If you’re using a different CI provider, you’ll need to adapt your workflow to run Vitest tests in parallel across shared CI jobs and enable Chromatic to run after all instances have finished. Here’s an example of how you might do this in a generic CI provider.
image: node:krypton
- run:
name: "Vitest"
displayName: "Run Vitest tests"
container: mcr.microsoft.com/playwright:v1.60.0-noble
options:
parallel: 2
artifacts:
- .vitest/**
command: |
npm ci
npx vitest run --shard=$CI_JOB_INDEX/$CI_TOTAL_JOBS
- run:
name: "Chromatic"
displayName: "Run Chromatic"
requires: [Vitest]
command: npx chromatic --vitest --project-token=$CHROMATIC_PROJECT_TOKEN