11name : E2E tests
22on : push
3+ concurrency :
4+ group : ${{ github.workflow }}-${{ github.ref }}
5+ cancel-in-progress : true
36env :
47 APP_ENV : test
58 NODE_ENV : test
1114 matrix :
1215 php_version :
1316 - ' 8.3'
14- - ' 8.4'
17+ # The specs are split round-robin over the sorted spec list, see the
18+ # "Select the specs for this shard" step. To split the suite further, add a
19+ # shard here *and* bump SHARD_TOTAL below to match.
20+ shard : [1, 2, 3, 4]
1521 fail-fast : false
1622 env :
1723 GEOCODE_EARTH_API_KEY : ${{ secrets.GEOCODE_EARTH_API_KEY }}
@@ -22,12 +28,28 @@ jobs:
2228 AWS_ACCESS_KEY_ID : ${{ secrets.AWS_ACCESS_KEY_ID }}
2329 AWS_SECRET_ACCESS_KEY : ${{ secrets.AWS_SECRET_ACCESS_KEY }}
2430 PHP_VERSION : ${{ matrix.php_version }}
31+ # Number of entries in matrix.shard. Deliberately not strategy.job-total, which
32+ # would also count any other matrix dimension (a second PHP version, say) and
33+ # would then silently make each shard run only a fraction of its specs.
34+ SHARD_TOTAL : 4
2535 steps :
2636 - name : Set timezone
2737 uses : szenius/set-timezone@v2.0
2838 with :
2939 timezoneLinux : " Europe/Paris"
3040 - uses : actions/checkout@v4
41+ # Round-robin over the sorted spec list rather than a hand-maintained list per
42+ # shard: every spec is always picked up by exactly one shard, including new ones,
43+ # and interleaving the sorted order spreads the slow directories evenly.
44+ - name : Select the specs for this shard
45+ id : shard
46+ run : |
47+ specs=$(find cypress/e2e -name '*.cy.js' | sort \
48+ | awk -v i="${{ matrix.shard }}" -v n="$SHARD_TOTAL" '(NR - 1) % n == (i - 1)' \
49+ | paste -sd, -)
50+ if [ -z "$specs" ]; then echo "No spec selected for this shard" >&2; exit 1; fi
51+ echo "Shard ${{ matrix.shard }}/$SHARD_TOTAL: $(echo "$specs" | tr ',' '\n' | wc -l) specs"
52+ echo "specs=$specs" >> "$GITHUB_OUTPUT"
3153 - name : Run CoopCycle Web
3254 uses : ./.github/actions/run-coopcycle-web
3355 timeout-minutes : 10
@@ -43,14 +65,13 @@ jobs:
4365 # Install only Cypress binary; everything else is already installed by the webpack docker image
4466 # https://docs.cypress.io/app/continuous-integration/overview#Missing-binary
4567 install-command : npx cypress install
46- spec : |
47- cypress/e2e/**/*.cy.js
68+ spec : ${{ steps.shard.outputs.specs }}
4869 # after the test run completes store videos and any screenshots
4970 - name : Upload images for failed tests
5071 uses : actions/upload-artifact@v4
5172 if : failure()
5273 with :
53- name : cypress-screenshots
74+ name : cypress-screenshots-shard-${{ matrix.shard }}
5475 path : cypress/screenshots
5576 if-no-files-found : ignore # 'warn' or 'error' are also available, defaults to `warn`
5677 - name : Show Symfony warnings on failure
5980 - name : Upload Symfony logs on failure
6081 if : failure()
6182 uses : ./.github/actions/upload-symfony-logs
83+ with :
84+ name : symfony-logs-shard-${{ matrix.shard }}
0 commit comments