# Sharding

Several CI jobs can upload parts of one build. The check reports once, after the last part.

## When you know the shard count

Each job passes its shard and the total. The first job to upload creates the build, the others join it, and the build finishes when every shard is done.

```yaml .github/workflows/visual.yml
jobs :
   visual :
     runs-on :  ubuntu-latest
     strategy :
       matrix :
         shard : [ 1 ,  2 ,  3 ,  4 ]
     steps :
      -  uses :  actions/checkout@v7
         with :
           fetch-depth :  0
      -  run :  npm ci
      -  run :  npx playwright install --with-deps chromium
      -  run :  npx playwright test --shard ${{ matrix.shard }}/4
      -  run :  npx stateofpixel upload screenshots --shard ${{ matrix.shard }}/4
```

While shards upload, the check says "Waiting for screenshots (2 of 4 shards)". The [Playwright reporter](https://stateofpixel.com/docs/playwright.md) reads Playwright's own `--shard`, so with it you skip the upload step. [Storybook](https://stateofpixel.com/docs/storybook.md) capture splits the stories only with `--shard i/n`, like `--shard 2/4`. It does not take `--shard auto`.

## When you do not

Each job uploads with `--shard auto`, and one last job calls `finalize`:

```yaml .github/workflows/visual.yml
jobs :
   visual :
     # ... each job ends with:
     steps :
      -  run :  npx stateofpixel upload screenshots --shard auto

   finalize :
     needs :  visual
     if :  always()
     runs-on :  ubuntu-latest
     steps :
      -  uses :  actions/checkout@v7
         with :
           fetch-depth :  0
      -  run :  npx stateofpixel finalize --skip-if-empty
```

`--skip-if-empty` makes `finalize` report a build with no changes when no shard ran, so the check still reports.

## How shards find each other

Shards of one build share a nonce. On GitHub Actions it is the run id plus the attempt, so every job of a run joins the same build. When you re-run failed jobs, they join the build of the earlier attempt while it is still waiting for shards. Once that build has finished or expired, a re-run starts a fresh build. On CircleCI it is the workflow id. Elsewhere, set it yourself:

```
export  STATEOFPIXEL_TOKEN = sop_...
export  STATEOFPIXEL_NONCE = " $CI_PIPELINE_ID "

npx   stateofpixel   upload   screenshots   --shard   2/4
```

## Builds that never finish

A build that is not finished 60 minutes after its first shard expires. The check shows "Build never finished". See [how to recover](https://stateofpixel.com/docs/troubleshooting.md#the-check-says-build-never-finished). A build takes up to 256 shards.
