CI: parallel typecheck and unit test jobs, end-to-end suite in two shards (#63)
* CI: run typecheck and unit tests as parallel jobs They ran one after the other in one job (177-334s on Diffinery's runners); as two jobs each pays the install and build but they overlap, so Deploy, which waits for CI, starts sooner. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ruyx3Qr4jYrZEpPi466deb * E2E: run the suite in two parallel shards The suite ran its files one after another (441-504s of tests on Diffinery's runners). e2e.test.mjs takes about as long as all the other files together, so it gets a shard of its own and every other test/e2e/*.test.mjs file runs in the second shard, the only one that installs a browser. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ruyx3Qr4jYrZEpPi466deb --------- Co-authored-by: Claude <noreply@anthropic.com>
Canberk Demirci authored · GitHub committed signed1 parent 50797a8commit bc58f9afc627a717d7b851844f73641a9044897bBrowse files
2 files changed+41−7
modified.github/workflows/ci.yml+21−4View file
| @@ -16,8 +16,10 @@ | ||
| 16 | 16 | cancel-in-progress: true |
| 17 | 17 | |
| 18 | 18 | jobs: |
| 19 | - check: | |
| 20 | - name: Typecheck and test | |
| 19 | + # Two jobs in parallel: each needs the install and build, but typecheck and the unit | |
| 20 | + # tests together took longer than either does alone. | |
| 21 | + typecheck: | |
| 22 | + name: Typecheck and bundle | |
| 21 | 23 | runs-on: ubuntu-latest |
| 22 | 24 | timeout-minutes: 20 |
| 23 | 25 | steps: |
| @@ -32,8 +34,23 @@ | ||
| 32 | 34 | run: pnpm -r --if-present build |
| 33 | 35 | - name: Typecheck |
| 34 | 36 | run: pnpm -r --if-present typecheck |
| 35 | - - name: Unit tests | |
| 36 | - run: pnpm -r --if-present test | |
| 37 | 37 | - name: Bundle the Worker (dry run) |
| 38 | 38 | working-directory: apps/diffinery |
| 39 | 39 | run: pnpm exec wrangler deploy --dry-run --env dev --outdir dist |
| 40 | + | |
| 41 | + test: | |
| 42 | + name: Unit tests | |
| 43 | + runs-on: ubuntu-latest | |
| 44 | + timeout-minutes: 20 | |
| 45 | + steps: | |
| 46 | + - uses: actions/checkout@v4 | |
| 47 | + - uses: pnpm/action-setup@v4 | |
| 48 | + - uses: actions/setup-node@v4 | |
| 49 | + with: | |
| 50 | + node-version: 22 | |
| 51 | + cache: pnpm | |
| 52 | + - run: pnpm install --frozen-lockfile | |
| 53 | + - name: Build | |
| 54 | + run: pnpm -r --if-present build | |
| 55 | + - name: Unit tests | |
| 56 | + run: pnpm -r --if-present test |
modified.github/workflows/e2e.yml+20−3View file
| @@ -13,10 +13,21 @@ | ||
| 13 | 13 | cancel-in-progress: true |
| 14 | 14 | |
| 15 | 15 | jobs: |
| 16 | + # The suite in two parallel shards of about the same length: the git, pull request | |
| 17 | + # and Actions file on its own, and every other test/e2e/*.test.mjs file (so a new | |
| 18 | + # file runs without editing this). Only the second shard needs a browser (passkeys). | |
| 16 | 19 | e2e: |
| 17 | - name: End-to-end (git, PRs, Actions, passkeys) | |
| 20 | + name: End-to-end (${{ matrix.name }}) | |
| 18 | 21 | runs-on: ubuntu-latest |
| 19 | 22 | timeout-minutes: 20 |
| 23 | + strategy: | |
| 24 | + fail-fast: false | |
| 25 | + matrix: | |
| 26 | + include: | |
| 27 | + - name: git, PRs, Actions | |
| 28 | + shard: core | |
| 29 | + - name: passkeys, registry, email, security | |
| 30 | + shard: rest | |
| 20 | 31 | steps: |
| 21 | 32 | - uses: actions/checkout@v4 |
| 22 | 33 | - uses: pnpm/action-setup@v4 |
| @@ -26,5 +37,11 @@ | ||
| 26 | 37 | cache: pnpm |
| 27 | 38 | - run: pnpm install --frozen-lockfile |
| 28 | 39 | - run: pnpm -r --if-present build |
| 29 | - - run: pnpm --filter @diffinery/app exec playwright install --with-deps chromium | |
| 30 | - - run: pnpm --filter @diffinery/app e2e | |
| 40 | + - if: matrix.shard == 'rest' | |
| 41 | + run: pnpm --filter @diffinery/app exec playwright install --with-deps chromium | |
| 42 | + - name: Run the shard's tests | |
| 43 | + working-directory: apps/diffinery | |
| 44 | + run: | | |
| 45 | + if [ "${{ matrix.shard }}" = core ]; then files=test/e2e/e2e.test.mjs; else files=$(ls test/e2e/*.test.mjs | grep -v '/e2e\.test\.mjs$'); fi | |
| 46 | + echo "$files" | |
| 47 | + node --test --test-concurrency=1 --test-timeout=600000 $files |