ContactSign inSign up
Contact

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.

.github/workflows/chromatic.yml
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.

.gitlab-ci.yml
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.

.circleci/config.yml
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.

Jenkinsfile
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.

.semaphore/semaphore.yml
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.

your-workflow.yml
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