refactor: speed up E2E test workflows and eliminate npm cache-restore failures (#36599)

Workers no longer run `npm ci` — `node_modules` and framework binaries
are restored from actions/cache populated once by a new `prep-deps` job.
This closes the intermittent EEXIST/ENOENT failure inside npm's own
cacache writer that occasionally fails `npm ci` on a runner. Removing
`npm ci` from workers also cuts ~5 min of duplicated install work per worker.

dispatch-begin now runs as its own job after prep-deps so it fires once the
per-worker test-server setup is the only remaining work before dispatch-run.
This commit is contained in:
sabril
2026-05-19 11:26:39 +08:00
committed by GitHub
parent 1d1580cb3c
commit 9d318dc4cd
5 changed files with 314 additions and 48 deletions
+103 -9
View File
@@ -16,25 +16,119 @@ All pipelines follow the **smoke-then-full** pattern: smoke tests run first, ful
```
.github/workflows/
├── e2e-tests-ci.yml # PR orchestrator
├── e2e-tests-on-merge.yml # Merge orchestrator (master/release branches)
├── e2e-tests-on-release.yml # Release cut orchestrator
├── e2e-tests-cypress.yml # Shared wrapper: cypress smoke -> full
├── e2e-tests-playwright.yml # Shared wrapper: playwright smoke -> full
├── e2e-tests-cypress-template.yml # Template: actual cypress test execution
── e2e-tests-playwright-template.yml # Template: actual playwright test execution
├── e2e-tests-ci.yml # PR orchestrator
├── e2e-tests-on-merge.yml # Merge orchestrator (master/release branches)
├── e2e-tests-on-release.yml # Release cut orchestrator
├── e2e-tests-cypress.yml # Shared wrapper: routes to v1 or v2 template
├── e2e-tests-playwright.yml # Shared wrapper: routes to v1 or v2 template
├── e2e-tests-cypress-template-v2.yml # Active: cypress + test-system-io dispatch
── e2e-tests-playwright-template-v2.yml # Active: playwright + test-system-io dispatch
├── e2e-tests-cypress-template.yml # Deprecated v1 (legacy in-job execution)
└── e2e-tests-playwright-template.yml # Deprecated v1 (legacy in-job execution)
```
> **v1 templates are deprecated.** They remain available behind a feature flag during cutover but receive no further changes. New work targets the v2 templates exclusively. The wrappers route by `vars.E2E_USE_TEST_IO_DISPATCH` — `'true'` selects v2, anything else falls back to v1.
### Call hierarchy
```
e2e-tests-ci.yml ─────────────────┐
e2e-tests-on-merge.yml ───────────┤──► e2e-tests-cypress.yml ──► e2e-tests-cypress-template.yml
e2e-tests-on-release.yml ─────────┘ e2e-tests-playwright.yml ──► e2e-tests-playwright-template.yml
e2e-tests-on-merge.yml ───────────┤──► e2e-tests-cypress.yml ─────┐
e2e-tests-on-release.yml ─────────┘ e2e-tests-playwright.yml ──
┌──────────────────────────┘
│ routes on E2E_USE_TEST_IO_DISPATCH
v2 (active) ──► e2e-tests-{cypress,playwright}-template-v2.yml
v1 (legacy) ──► e2e-tests-{cypress,playwright}-template.yml
```
---
## Workflow Architecture (v2)
v2 splits the template into five jobs — `prepare-run`, `prep-deps`, `dispatch-begin`, `workers` (matrix), and `report` — and pushes spec-level execution to [Test System IO](https://github.com/mattermost/mattermost-test-system-io) so workers stay thin and identical.
```
┌──────────────────────────────────────────────────────────────────────────┐
│ Template v2: e2e-tests-{cypress,playwright}-template-v2.yml │
│ │
│ ┌───────────────────┐ ┌──────────────────────────────┐ │
│ │ prepare-run │ │ prep-deps │ │
│ │ (1 runner) │ parallel │ (1 runner) │ │
│ │ │ ◄────────────► │ │ │
│ │ • build workers │ │ Cypress: │ │
│ │ matrix [1..N] │ │ • cypress/node_modules │ │
│ │ • compute commit │ │ • ~/.cache/Cypress (binary)│ │
│ │ status context │ │ │ │
│ │ • emit composite │ │ Playwright: │ │
│ │ identity │ │ • webapp/platform/{client, │ │
│ │ │ │ types}/{lib,node_mod} │ │
│ │ │ │ • playwright/node_modules │ │
│ │ │ │ • playwright/lib/dist │ │
│ │ │ │ • ~/.cache/ms-playwright │ │
│ │ │ │ (chromium only) │ │
│ │ │ │ │ │
│ │ │ │ → saved to actions/cache │ │
│ └─────────┬─────────┘ └───────────────┬──────────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────────────────────────┐ │
│ │ │ dispatch-begin │ │
│ │ │ • register run with │ │
│ │ │ Test System IO │ │
│ │ │ • runs immediately before │ │
│ │ │ workers to minimise the │ │
│ │ │ inactivity-timeout window │ │
│ │ └───────────────┬──────────────┘ │
│ │ │ │
│ └────────────────────┬─────────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ workers (matrix, fail-fast: false) │ │
│ │ Cypress full: N=40 | Playwright full: N=10 │ │
│ │ │ │
│ │ each worker, in parallel: │ │
│ │ 1. sparse-checkout actions + full checkout-repo │ │
│ │ 2. setup-node │ │
│ │ 3. restore caches ◄─── actions/cache (from prep-deps) │ │
│ │ (fail-on-cache-miss: true) │ │
│ │ 4. cloud-init + start-server (docker compose stack) │ │
│ │ 5. prepare-cypress | prepare-playwright (run setup project) │ │
│ │ 6. dispatch-run ──────────────────────────────────┐ │ │
│ │ (pulls specs from Test System IO, runs locally, │ │ │
│ │ posts result, loops until queue is empty) │ │ │
│ │ 7. cloud-teardown │ │ │
│ └────────────────────┬────────────────────────────────────┼───────┘ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────────────────────────────────────────┐ │ │
│ │ report │ │ │
│ │ • pull aggregated results from Test System IO │ ◄────┘ │
│ │ • post commit status │ │
│ │ • send webhook notification │ │
│ └─────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────────┬─┘
┌───────────────────────────▼───┐
│ Test System IO (external) │
│ • spec-level dispatch │
│ • result aggregation │
│ • retry orchestration │
└───────────────────────────────┘
```
### Key properties
- **Spec-level vs. job-level parallelism.** The matrix sizes the runner pool; Test System IO does the spec assignment. Slow specs don't block a worker — fast workers keep pulling the next spec from the queue.
- **Cache-only workers.** `prep-deps` installs once per workflow run and saves to `actions/cache`. Every worker restores with `fail-on-cache-miss: true` and runs zero `npm ci`. Eliminates the 40-way `EEXIST/ENOENT` race in npm's shared cacache writer.
- **dispatch-begin runs late.** It depends on `prep-deps` so the gap between Test System IO run registration and the first worker calling `dispatch-run` is just per-worker setup (~35 min). Registering earlier risks the run timing out before any worker checks in, bulk-failing every spec.
- **Playwright slim slice.** Playwright only consumes `@mattermost/client` and `@mattermost/types` from webapp, so prep-deps caches just those two packages' built `lib/` and `node_modules` (~1030 MB) instead of the full `webapp/node_modules` tree (~12 GB).
- **Browser/binary caches.** Cypress caches `~/.cache/Cypress` (cypress binary lives outside node_modules); playwright caches `~/.cache/ms-playwright` (chromium only). Both keyed on the framework's lockfile so they invalidate on version bumps.
- **No retry plumbing in the template.** Test System IO handles per-spec retries; the workflow only sees aggregated results.
---
## Pipeline 1: PR (`e2e-tests-ci.yml`)
Runs E2E tests for every PR commit after the enterprise docker image is built. Fails if the commit is not associated with an open PR.
+6
View File
@@ -25,6 +25,12 @@ jobs:
cache-dependency-path: |
e2e-tests/cypress/package-lock.json
e2e-tests/playwright/package-lock.json
webapp/package-lock.json
- name: ci/npm-cache-verify
# Heal any partial/dangling entries left in the restored ~/.npm cache
# before running `npm ci`. Avoids the intermittent EEXIST/ENOENT
# failures in npm's cacache writer.
run: npm cache verify
# Cypress check
- name: ci/cypress/npm-install
@@ -135,7 +135,7 @@ env:
SERVER_IMAGE: "${{ inputs.server_image_repo }}/${{ inputs.server_edition == 'fips' && 'mattermost-enterprise-fips-edition' || inputs.server_edition == 'team' && 'mattermost-team-edition' || 'mattermost-enterprise-edition' }}:${{ inputs.server_image_tag }}"
jobs:
dispatch-begin:
prepare-run:
runs-on: ubuntu-24.04
permissions:
contents: read
@@ -193,13 +193,62 @@ jobs:
run: |
echo "workers=$(jq -nc --argjson n ${{ inputs.workers }} '[range(1; $n+1)]')" >> $GITHUB_OUTPUT
echo "start_time=$(date +%s)" >> $GITHUB_OUTPUT
# Install cypress node_modules once, then workers restore from cache.
prep-deps:
name: prep-deps
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
contents: read
steps:
- name: ci/checkout-repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.commit_sha }}
fetch-depth: 1
- name: ci/setup-node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version-file: ".nvmrc"
- name: ci/cache-cypress-deps
# node_modules + the cypress binary (downloaded to ~/.cache/Cypress by
# cypress's postinstall, not into node_modules). Both must be cached;
# otherwise workers see "cypress npm package installed but binary missing".
id: cache-cypress
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: |
e2e-tests/cypress/node_modules
~/.cache/Cypress
key: e2e-cypress-deps-${{ runner.os }}-${{ hashFiles('e2e-tests/cypress/package-lock.json') }}
- name: ci/install-cypress-deps
if: steps.cache-cypress.outputs.cache-hit != 'true'
working-directory: e2e-tests/cypress
run: npm ci
# Register the Test System IO run AFTER prep-deps so workers reach
# dispatch-run within Test System IO's inactivity window.
dispatch-begin:
runs-on: ubuntu-24.04
needs: [prepare-run, prep-deps]
permissions:
contents: read
id-token: write
statuses: write
steps:
- name: ci/checkout-repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.commit_sha }}
fetch-depth: 1
- name: ci/dispatch-begin
uses: mattermost/mattermost-test-system-io/.github/actions/test-system-io-dispatch-begin@a2ea7f005484c28fedf51e16645f6d3bd683fd63 # 2026-05-16
with:
use-staging: ${{ vars.E2E_USE_STAGING_TEST_IO_URL != 'false' }}
framework: cypress
repo-dir: ${{ github.workspace }}
composite-identity: ${{ steps.composite-identity.outputs.composite-identity-json }}
composite-identity: ${{ needs.prepare-run.outputs.composite-identity-json }}
total-reports-expected: ${{ inputs.workers }}
retest-on-fail: ${{ inputs.retest_on_fail }}
cypress-stage: ${{ inputs.cypress_stage }}
@@ -217,16 +266,16 @@ jobs:
name: dispatch-run-${{ matrix.worker_index }}
runs-on: ubuntu-24.04
timeout-minutes: 30
needs: dispatch-begin
needs: [prepare-run, dispatch-begin]
permissions:
contents: read
id-token: write
strategy:
fail-fast: false
matrix:
worker_index: ${{ fromJSON(needs.dispatch-begin.outputs.workers-matrix) }}
worker_index: ${{ fromJSON(needs.prepare-run.outputs.workers-matrix) }}
env:
COMPOSITE_IDENTITY: ${{ needs.dispatch-begin.outputs.composite-identity-json }}
COMPOSITE_IDENTITY: ${{ needs.prepare-run.outputs.composite-identity-json }}
SERVER: "${{ inputs.server }}"
MM_LICENSE: "${{ secrets.MM_LICENSE }}"
ENABLED_DOCKER_SERVICES: "${{ inputs.enabled_docker_services }}"
@@ -260,29 +309,26 @@ jobs:
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version-file: ".nvmrc"
cache: npm
cache-dependency-path: "e2e-tests/cypress/package-lock.json"
- name: ci/get-webapp-node-modules
working-directory: webapp
run: make node_modules
- name: ci/restore-cypress-deps
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: |
e2e-tests/cypress/node_modules
~/.cache/Cypress
key: e2e-cypress-deps-${{ runner.os }}-${{ hashFiles('e2e-tests/cypress/package-lock.json') }}
fail-on-cache-miss: true
- name: ci/cloud-init
working-directory: e2e-tests
run: make cloud-init
- name: ci/start-server
working-directory: e2e-tests
run: make start-server
# `npm ci` in the host context replaces the container-built native
# binaries with host-built ones, since the dispatch adapter spawns
# `npx cypress run` on the host.
- name: ci/prepare-cypress
working-directory: e2e-tests/cypress
run: npm ci
- name: ci/dispatch-run
uses: mattermost/mattermost-test-system-io/.github/actions/test-system-io-dispatch-run@a2ea7f005484c28fedf51e16645f6d3bd683fd63 # 2026-05-16
with:
use-staging: ${{ vars.E2E_USE_STAGING_TEST_IO_URL != 'false' }}
framework: cypress
composite-identity: ${{ needs.dispatch-begin.outputs.composite-identity-json }}
composite-identity: ${{ needs.prepare-run.outputs.composite-identity-json }}
repo-dir: ${{ github.workspace }}
artifacts-root: ${{ github.workspace }}/worker-artifacts
github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -306,7 +352,7 @@ jobs:
report:
runs-on: ubuntu-24.04
needs: [dispatch-begin, workers]
needs: [prepare-run, dispatch-begin, workers]
if: always()
permissions:
contents: read
@@ -324,7 +370,7 @@ jobs:
uses: mattermost/mattermost-test-system-io/.github/actions/test-system-io-summary@a2ea7f005484c28fedf51e16645f6d3bd683fd63 # 2026-05-16
with:
use-staging: ${{ vars.E2E_USE_STAGING_TEST_IO_URL != 'false' }}
composite-identity: ${{ needs.dispatch-begin.outputs.composite-identity-json }}
composite-identity: ${{ needs.prepare-run.outputs.composite-identity-json }}
framework: cypress
report-type: ${{ inputs.report_type }}
image-tag: ${{ inputs.server_image_tag }}
@@ -101,7 +101,7 @@ env:
SERVER_IMAGE: "${{ inputs.server_image_repo }}/${{ inputs.server_edition == 'fips' && 'mattermost-enterprise-fips-edition' || inputs.server_edition == 'team' && 'mattermost-team-edition' || 'mattermost-enterprise-edition' }}:${{ inputs.server_image_tag }}"
jobs:
dispatch-begin:
prepare-run:
runs-on: ubuntu-24.04
permissions:
contents: read
@@ -158,13 +158,104 @@ jobs:
run: |
echo "workers=$(jq -nc --argjson n ${{ inputs.workers }} '[range(1; $n+1)]')" >> $GITHUB_OUTPUT
echo "start_time=$(date +%s)" >> $GITHUB_OUTPUT
# Build @mattermost/client + @mattermost/types and install playwright deps once,
# then workers restore from cache. Playwright only consumes those two packages
# from webapp, so we cache just their built lib/ instead of all of webapp/node_modules.
prep-deps:
name: prep-deps
runs-on: ubuntu-24.04
timeout-minutes: 15
permissions:
contents: read
steps:
- name: ci/checkout-repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.commit_sha }}
fetch-depth: 1
- name: ci/setup-node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version-file: ".nvmrc"
- name: ci/cache-platform-pkgs
# `webapp/node_modules/@mattermost/{client,types}` are the workspace
# symlinks Node walks up to find when platform/client requires
# @mattermost/types. Without them, module resolution fails inside
# the slim slice.
id: cache-platform-pkgs
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: |
webapp/node_modules/@mattermost/client
webapp/node_modules/@mattermost/types
webapp/platform/client/lib
webapp/platform/client/node_modules
webapp/platform/types/lib
webapp/platform/types/node_modules
key: e2e-platform-pkgs-${{ runner.os }}-${{ hashFiles('webapp/package-lock.json', 'webapp/platform/client/src/**', 'webapp/platform/client/tsconfig*.json', 'webapp/platform/types/src/**', 'webapp/platform/types/tsconfig*.json') }}
- name: ci/build-platform-pkgs
# Full webapp install is needed for tsc + workspace linking; the
# postinstall builds platform/{client,types}/lib. We only cache those.
if: steps.cache-platform-pkgs.outputs.cache-hit != 'true'
working-directory: webapp
run: make node_modules
- name: ci/cache-playwright-deps
# Caches node_modules + the rolled-up @mattermost/playwright-lib dist
# so workers don't re-run rollup on every job.
id: cache-playwright
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: |
e2e-tests/playwright/node_modules
e2e-tests/playwright/lib/dist
e2e-tests/playwright/lib/node_modules
key: e2e-playwright-deps-${{ runner.os }}-${{ hashFiles('e2e-tests/playwright/package-lock.json', 'e2e-tests/playwright/lib/src/**', 'e2e-tests/playwright/lib/package.json', 'e2e-tests/playwright/lib/rollup.config.js', 'e2e-tests/playwright/lib/tsconfig.json') }}
- name: ci/install-playwright-deps
# `npm ci` creates symlinks at node_modules/@mattermost/{client,types}
# → webapp/platform/{client,types}; targets must already be built.
# The postinstall then builds lib/dist via rollup. Skip browser
# download here — chromium is cached separately below.
if: steps.cache-playwright.outputs.cache-hit != 'true'
working-directory: e2e-tests/playwright
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1"
run: npm ci
- name: ci/cache-playwright-browsers
# Cache chromium binary (~150MB) keyed on the playwright lockfile so a
# version bump invalidates. Restored by workers; no docker image needed.
id: cache-pw-browsers
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('e2e-tests/playwright/package-lock.json') }}
- name: ci/install-playwright-chromium
if: steps.cache-pw-browsers.outputs.cache-hit != 'true'
working-directory: e2e-tests/playwright
run: npx playwright install chromium
# Register the Test System IO run AFTER prep-deps so workers reach
# dispatch-run within Test System IO's inactivity window.
dispatch-begin:
runs-on: ubuntu-24.04
needs: [prepare-run, prep-deps]
permissions:
contents: read
id-token: write
statuses: write
steps:
- name: ci/checkout-repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.commit_sha }}
fetch-depth: 1
- name: ci/dispatch-begin
uses: mattermost/mattermost-test-system-io/.github/actions/test-system-io-dispatch-begin@a2ea7f005484c28fedf51e16645f6d3bd683fd63 # 2026-05-16
with:
use-staging: ${{ vars.E2E_USE_STAGING_TEST_IO_URL != 'false' }}
framework: playwright
repo-dir: ${{ github.workspace }}
composite-identity: ${{ steps.composite-identity.outputs.composite-identity-json }}
composite-identity: ${{ needs.prepare-run.outputs.composite-identity-json }}
total-reports-expected: ${{ inputs.workers }}
retest-on-fail: ${{ inputs.retest_on_fail }}
playwright-project: ${{ inputs.playwright_project }}
@@ -177,16 +268,16 @@ jobs:
name: dispatch-run-${{ matrix.worker_index }}
runs-on: ubuntu-24.04
timeout-minutes: 30
needs: dispatch-begin
needs: [prepare-run, dispatch-begin]
permissions:
contents: read
id-token: write
strategy:
fail-fast: false
matrix:
worker_index: ${{ fromJSON(needs.dispatch-begin.outputs.workers-matrix) }}
worker_index: ${{ fromJSON(needs.prepare-run.outputs.workers-matrix) }}
env:
COMPOSITE_IDENTITY: ${{ needs.dispatch-begin.outputs.composite-identity-json }}
COMPOSITE_IDENTITY: ${{ needs.prepare-run.outputs.composite-identity-json }}
SERVER: "${{ inputs.server }}"
MM_LICENSE: "${{ secrets.MM_LICENSE }}"
ENABLED_DOCKER_SERVICES: "${{ inputs.enabled_docker_services }}"
@@ -214,31 +305,53 @@ jobs:
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version-file: ".nvmrc"
cache: npm
cache-dependency-path: "e2e-tests/playwright/package-lock.json"
- name: ci/get-webapp-node-modules
working-directory: webapp
run: make node_modules
- name: ci/restore-platform-pkgs
# Built lib/ for @mattermost/client and @mattermost/types, plus the
# webapp workspace symlinks under webapp/node_modules/@mattermost/.
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: |
webapp/node_modules/@mattermost/client
webapp/node_modules/@mattermost/types
webapp/platform/client/lib
webapp/platform/client/node_modules
webapp/platform/types/lib
webapp/platform/types/node_modules
key: e2e-platform-pkgs-${{ runner.os }}-${{ hashFiles('webapp/package-lock.json', 'webapp/platform/client/src/**', 'webapp/platform/client/tsconfig*.json', 'webapp/platform/types/src/**', 'webapp/platform/types/tsconfig*.json') }}
fail-on-cache-miss: true
- name: ci/restore-playwright-deps
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: |
e2e-tests/playwright/node_modules
e2e-tests/playwright/lib/dist
e2e-tests/playwright/lib/node_modules
key: e2e-playwright-deps-${{ runner.os }}-${{ hashFiles('e2e-tests/playwright/package-lock.json', 'e2e-tests/playwright/lib/src/**', 'e2e-tests/playwright/lib/package.json', 'e2e-tests/playwright/lib/rollup.config.js', 'e2e-tests/playwright/lib/tsconfig.json') }}
fail-on-cache-miss: true
- name: ci/restore-playwright-browsers
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('e2e-tests/playwright/package-lock.json') }}
fail-on-cache-miss: true
- name: ci/cloud-init
working-directory: e2e-tests
run: make cloud-init
- name: ci/start-server
working-directory: e2e-tests
run: make start-server
# Build once + run the `setup` project so per-spec dispatches can
# pass --no-deps and skip plugin-load + server-deployment checks.
# Run the `setup` project so per-spec dispatches can pass --no-deps
# and skip plugin-load + server-deployment checks. node_modules,
# lib/dist, and chromium are all restored from cache.
- name: ci/prepare-playwright
working-directory: e2e-tests/playwright
run: |
npm ci
npm run build
npx playwright test --project=setup
run: npx playwright test --project=setup
- name: ci/dispatch-run
uses: mattermost/mattermost-test-system-io/.github/actions/test-system-io-dispatch-run@a2ea7f005484c28fedf51e16645f6d3bd683fd63 # 2026-05-16
with:
use-staging: ${{ vars.E2E_USE_STAGING_TEST_IO_URL != 'false' }}
framework: playwright
composite-identity: ${{ needs.dispatch-begin.outputs.composite-identity-json }}
composite-identity: ${{ needs.prepare-run.outputs.composite-identity-json }}
repo-dir: ${{ github.workspace }}
artifacts-root: ${{ github.workspace }}/worker-artifacts
github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -263,7 +376,7 @@ jobs:
report:
runs-on: ubuntu-24.04
needs: [dispatch-begin, workers]
needs: [prepare-run, dispatch-begin, workers]
if: always()
permissions:
contents: read
@@ -281,7 +394,7 @@ jobs:
uses: mattermost/mattermost-test-system-io/.github/actions/test-system-io-summary@a2ea7f005484c28fedf51e16645f6d3bd683fd63 # 2026-05-16
with:
use-staging: ${{ vars.E2E_USE_STAGING_TEST_IO_URL != 'false' }}
composite-identity: ${{ needs.dispatch-begin.outputs.composite-identity-json }}
composite-identity: ${{ needs.prepare-run.outputs.composite-identity-json }}
framework: playwright
report-type: ${{ inputs.report_type }}
image-tag: ${{ inputs.server_image_tag }}
@@ -179,7 +179,14 @@ jobs:
with:
node-version-file: ".nvmrc"
cache: npm
cache-dependency-path: "e2e-tests/playwright/package-lock.json"
cache-dependency-path: |
e2e-tests/playwright/package-lock.json
webapp/package-lock.json
- name: ci/npm-cache-verify
# Heal any partial/dangling entries left in the restored ~/.npm cache
# before running `npm ci`. Avoids the intermittent EEXIST/ENOENT
# failures in npm's cacache writer.
run: npm cache verify
- name: ci/get-webapp-node-modules
working-directory: webapp
run: make node_modules