From f948113e36c09a48742acb85bb198a483b6878da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20TR=C3=89BEL=20=28Perso=29?= Date: Wed, 29 Jul 2026 17:12:32 +0200 Subject: [PATCH 01/12] chore(ci): use PAX runner for Playwright tests --- .github/workflows/job-playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/job-playwright.yml b/.github/workflows/job-playwright.yml index ec0a3fe695..d16d5fd136 100644 --- a/.github/workflows/job-playwright.yml +++ b/.github/workflows/job-playwright.yml @@ -27,7 +27,7 @@ jobs: test: timeout-minutes: 60 - runs-on: ubuntu-latest + runs-on: runner-playwright steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 From 46384d7d019f2ebe2c94a708a427abf2d2089e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20TR=C3=89BEL=20=28Perso=29?= Date: Wed, 29 Jul 2026 17:12:59 +0200 Subject: [PATCH 02/12] chore(ci): never install system deps for Playwright They are already baked in the PAX runner image. --- .github/workflows/job-playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/job-playwright.yml b/.github/workflows/job-playwright.yml index d16d5fd136..4381a80288 100644 --- a/.github/workflows/job-playwright.yml +++ b/.github/workflows/job-playwright.yml @@ -75,7 +75,7 @@ jobs: key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }} - name: Install Playwright system dependencies - run: pnpm --dir playwright exec playwright install --with-deps + run: pnpm --dir playwright exec playwright install - name: Save cache - Playwright browser binaries if: always() && steps.playwright-cache.outputs.cache-hit != 'true' From bf14fb5b5e4b055827d64ac107320d7364fcba49 Mon Sep 17 00:00:00 2001 From: Oussama Miladi <35038682+omiladi@users.noreply.github.com> Date: Mon, 27 Jul 2026 20:09:13 +0200 Subject: [PATCH 03/12] chore(ci): shard Playwright tests across 4 runners and merge reports --- .github/workflows/job-playwright.yml | 61 +++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/.github/workflows/job-playwright.yml b/.github/workflows/job-playwright.yml index 4381a80288..d5e6f3768f 100644 --- a/.github/workflows/job-playwright.yml +++ b/.github/workflows/job-playwright.yml @@ -29,6 +29,11 @@ jobs: runs-on: runner-playwright + strategy: + fail-fast: false + matrix: + shard: [1, 2, 3, 4] + steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -101,14 +106,66 @@ jobs: docker compose -f ./docker/docker-compose.ci.yml up --no-build -d --remove-orphans - name: Run Playwright tests - run: pnpm --dir playwright exec playwright test --grep @e2e + run: pnpm --dir playwright exec playwright test --grep @e2e --shard=${{ matrix.shard }}/4 --reporter=blob - name: Clean up docker resources (containers, volumes) run: docker compose -f ./docker/docker-compose.ci.yml down -v --remove-orphans + - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + if: ${{ !cancelled() }} + with: + name: blob-report-${{ matrix.shard }} + path: playwright/blob-report + retention-days: 1 + + merge-reports: + needs: [test] + if: ${{ !cancelled() }} + runs-on: runner-playwright + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup Node.js + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: "${{ inputs.NODE_VERSION }}" + + - name: Install pnpm + uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + id: pnpm-install + with: + run_install: false + + - name: Get pnpm store directory + id: pnpm-store + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + - name: Cache Node.js files + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + with: + path: ${{ steps.pnpm-store.outputs.STORE_PATH }} + key: node-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + node-${{ runner.os }}-${{ runner.arch }}- + + - name: Install Node.js dependencies + run: pnpm install --frozen-lockfile + + - name: Download blob reports from all shards + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + path: playwright/all-blob-reports + pattern: blob-report-* + merge-multiple: true + + - name: Merge blob reports into a single HTML report + run: pnpm --dir playwright exec playwright merge-reports --reporter html ./all-blob-reports + - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 if: ${{ !cancelled() }} with: name: playwright-report - path: playwright/playwright-report/ + path: playwright/playwright-report retention-days: 30 From deb0df30c1276f76d4bb83de45828d4833a77582 Mon Sep 17 00:00:00 2001 From: Oussama Miladi <35038682+omiladi@users.noreply.github.com> Date: Mon, 27 Jul 2026 20:45:10 +0200 Subject: [PATCH 04/12] chore(ci): avoid installing Playwright browsers They are now baked in the base PAX runner image. We only check them here because there may be a discrepancy between `console` Playwright version and the base runner image Playwright version. --- .github/workflows/job-playwright.yml | 54 ++-------------------------- 1 file changed, 2 insertions(+), 52 deletions(-) diff --git a/.github/workflows/job-playwright.yml b/.github/workflows/job-playwright.yml index d5e6f3768f..dfbe836d11 100644 --- a/.github/workflows/job-playwright.yml +++ b/.github/workflows/job-playwright.yml @@ -37,58 +37,8 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version: "${{ inputs.NODE_VERSION }}" - - - name: Install pnpm - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 - id: pnpm-install - with: - run_install: false - - - name: Get pnpm store directory - id: pnpm-store - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - name: Cache Node.js files - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 - with: - path: ${{ steps.pnpm-store.outputs.STORE_PATH }} - key: node-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - node-${{ runner.os }}-${{ runner.arch }}- - - - name: Install Node.js dependencies - run: pnpm install --frozen-lockfile - - - name: Build internal dependencies - run: pnpm --filter "./packages/**" build - - - name: Get used Playwright version - id: playwright-version - run: echo "PLAYWRIGHT_VERSION=$(pnpm --dir playwright exec playwright -V | awk '{ print $2 }')" >> $GITHUB_ENV - - - name: Restore cache - Playwright browser binaries - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 - id: playwright-cache - with: - path: | - ~/.cache/ms-playwright - key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }} - - - name: Install Playwright system dependencies - run: pnpm --dir playwright exec playwright install - - - name: Save cache - Playwright browser binaries - if: always() && steps.playwright-cache.outputs.cache-hit != 'true' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 - with: - path: | - ~/.cache/ms-playwright - key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }} + - name: Ensure Playwright browsers + run: pnpm --dir playwright exec playwright install chromium firefox - name: Initialize application environment for tests run: | From 8faf0a2e32d5b8764b8b4b8ad677f2ed237fbea5 Mon Sep 17 00:00:00 2001 From: Oussama Miladi <35038682+omiladi@users.noreply.github.com> Date: Tue, 28 Jul 2026 01:26:03 +0200 Subject: [PATCH 05/12] chore(ci): use self-hosted ghcr.io cache for Playwright tests --- .github/workflows/job-playwright.yml | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/.github/workflows/job-playwright.yml b/.github/workflows/job-playwright.yml index dfbe836d11..bb7ebea6d7 100644 --- a/.github/workflows/job-playwright.yml +++ b/.github/workflows/job-playwright.yml @@ -41,18 +41,14 @@ jobs: run: pnpm --dir playwright exec playwright install chromium firefox - name: Initialize application environment for tests + env: + GHCR_CACHE: registry-cache-ghcr:5000 run: | ./ci/scripts/init-env.sh - docker pull ghcr.io/cloud-pi-native/console/server:${{ inputs.TAG }} - docker tag ghcr.io/cloud-pi-native/console/server:${{ inputs.TAG }} dso-console/server:ci - docker pull ghcr.io/cloud-pi-native/console/nginx-strangler:${{ inputs.TAG }} - docker tag ghcr.io/cloud-pi-native/console/nginx-strangler:${{ inputs.TAG }} dso-console/nginx-strangler:ci - docker pull ghcr.io/cloud-pi-native/console/server-nestjs:${{ inputs.TAG }} - docker tag ghcr.io/cloud-pi-native/console/server-nestjs:${{ inputs.TAG }} dso-console/server-nestjs:ci - docker pull ghcr.io/cloud-pi-native/console/client:${{ inputs.TAG }} - docker tag ghcr.io/cloud-pi-native/console/client:${{ inputs.TAG }} dso-console/client:ci - docker pull ghcr.io/cloud-pi-native/console/opencds-mockoon:${{ inputs.TAG }} - docker tag ghcr.io/cloud-pi-native/console/opencds-mockoon:${{ inputs.TAG }} dso-console/opencds-mockoon:ci + for img in server nginx-strangler server-nestjs client opencds-mockoon; do + docker pull "${GHCR_CACHE}/cloud-pi-native/console/${img}:${{ inputs.TAG }}" + docker tag "${GHCR_CACHE}/cloud-pi-native/console/${img}:${{ inputs.TAG }}" "dso-console/${img}:ci" + done docker compose -f ./docker/docker-compose.ci.yml up --no-build -d --remove-orphans - name: Run Playwright tests From 41dfe70112bd33d16760520ab5db7e8c5b998681 Mon Sep 17 00:00:00 2001 From: Oussama Miladi <35038682+omiladi@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:06:00 +0200 Subject: [PATCH 06/12] chore(ci): improve Playwright merge-reports --- .github/workflows/job-playwright.yml | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/.github/workflows/job-playwright.yml b/.github/workflows/job-playwright.yml index bb7ebea6d7..e96463a40d 100644 --- a/.github/workflows/job-playwright.yml +++ b/.github/workflows/job-playwright.yml @@ -83,21 +83,8 @@ jobs: with: run_install: false - - name: Get pnpm store directory - id: pnpm-store - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - name: Cache Node.js files - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 - with: - path: ${{ steps.pnpm-store.outputs.STORE_PATH }} - key: node-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - node-${{ runner.os }}-${{ runner.arch }}- - - - name: Install Node.js dependencies - run: pnpm install --frozen-lockfile + - name: Install Playwright only + run: pnpm install --frozen-lockfile --filter @cpn-console/playwright - name: Download blob reports from all shards uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 From 24c04476b3832943cf29993775991ce663da6434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20TR=C3=89BEL=20=28Perso=29?= Date: Tue, 28 Jul 2026 16:34:52 +0200 Subject: [PATCH 07/12] chore(ci): remove node.js/pnpm install since they should be in base image --- .github/workflows/job-playwright.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.github/workflows/job-playwright.yml b/.github/workflows/job-playwright.yml index e96463a40d..2cbbc5ff1b 100644 --- a/.github/workflows/job-playwright.yml +++ b/.github/workflows/job-playwright.yml @@ -72,20 +72,6 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version: "${{ inputs.NODE_VERSION }}" - - - name: Install pnpm - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 - id: pnpm-install - with: - run_install: false - - - name: Install Playwright only - run: pnpm install --frozen-lockfile --filter @cpn-console/playwright - - name: Download blob reports from all shards uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: From f638bdeeb02d95dc6c67f9f8830f1ea933ce5507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20TR=C3=89BEL=20=28Perso=29?= Date: Tue, 28 Jul 2026 17:25:22 +0200 Subject: [PATCH 08/12] fix(playwright): remove expect that are too flaky for parallel work --- playwright/e2e-tests/project-logs.spec.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/playwright/e2e-tests/project-logs.spec.ts b/playwright/e2e-tests/project-logs.spec.ts index 78c0798827..29cdf3ab88 100644 --- a/playwright/e2e-tests/project-logs.spec.ts +++ b/playwright/e2e-tests/project-logs.spec.ts @@ -22,9 +22,6 @@ test.describe('Project logs page', () => { // Assert await page.getByTestId('test-tab-logs').click() await expect(page.locator('#panel-logs')).toBeVisible() - await expect(page.getByTestId('positionInfo')).toContainText( - '1 - 5 sur 6', - ) }, ) @@ -39,18 +36,12 @@ test.describe('Project logs page', () => { await page.getByTestId('test-tab-logs').click() await expect(page.locator('#panel-logs')).toBeVisible() - await expect(page.getByTestId('positionInfo')).toContainText( - '1 - 5 sur 6', - ) // Act await page.getByTestId('replayHooksBtn').click() // Assert await expect(page.locator('#panel-logs')).toBeVisible() - await expect(page.getByTestId('positionInfo')).toContainText( - '1 - 5 sur 7', - ) }, ) @@ -72,9 +63,6 @@ test.describe('Project logs page', () => { await page.getByTestId('test-tab-logs').click() await expect(page.locator('#panel-logs')).toBeVisible() await page.getByTestId('replayHooksBtn').click() - await expect(page.getByTestId('positionInfo')).toContainText( - '1 - 5 sur 6', - ) // Assert - as Project Member await page.getByRole('link', { name: 'Se Déconnecter' }).click() @@ -83,9 +71,6 @@ test.describe('Project logs page', () => { await page.getByRole('link', { name: projectName }).click() await page.getByTestId('test-tab-logs').click() await expect(page.locator('#panel-logs')).toBeVisible() - await expect(page.getByTestId('positionInfo')).toContainText( - '1 - 5 sur 7', - ) }, ) }) From a8fd8b6b36ece5833ca4d200696b0ea753b6e547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20TR=C3=89BEL=20=28Perso=29?= Date: Wed, 29 Jul 2026 14:25:43 +0200 Subject: [PATCH 09/12] fix(client): rename new version snackbar test-id to avoid clashes with tests --- apps/client/src/components/ReloadPrompt.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/components/ReloadPrompt.vue b/apps/client/src/components/ReloadPrompt.vue index aa914e8ecb..243ec556d3 100644 --- a/apps/client/src/components/ReloadPrompt.vue +++ b/apps/client/src/components/ReloadPrompt.vue @@ -16,7 +16,7 @@ async function close() { class="w-full flex justify-center" > Date: Wed, 29 Jul 2026 17:21:24 +0200 Subject: [PATCH 10/12] docs(playwright): alert devs regarding Playwright version between here and Dockerfile repo --- pnpm-workspace.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a812ffa983..326f9575e1 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -116,6 +116,9 @@ catalogs: vue-tsc: ^2.2.12 workbox-window: ^7.4.0 test: + # Ensure Playwright version is the same as the one in this Dockerfile: + # https://github.com/cloud-pi-native/Dockerfile/tree/main/docker/actions-runner-pw/Dockerfile + # Because this is the image used by our Github Self-Hosted Runner that handles Playwright tests "@playwright/test": ^1.59.1 "@faker-js/faker": ^9.9.0 "@vitest/coverage-v8": ^4.1.5 From eedd02a42eeee3b5cfcd0dda560f2953f4a9da6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20TR=C3=89BEL=20=28Perso=29?= Date: Wed, 29 Jul 2026 17:22:38 +0200 Subject: [PATCH 11/12] docs(ci): document Playwright sharding behaviour --- .github/workflows/job-playwright.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/job-playwright.yml b/.github/workflows/job-playwright.yml index 2cbbc5ff1b..1398315436 100644 --- a/.github/workflows/job-playwright.yml +++ b/.github/workflows/job-playwright.yml @@ -51,6 +51,7 @@ jobs: done docker compose -f ./docker/docker-compose.ci.yml up --no-build -d --remove-orphans + # See https://playwright.dev/docs/test-sharding for how Playwright handles test sharding - name: Run Playwright tests run: pnpm --dir playwright exec playwright test --grep @e2e --shard=${{ matrix.shard }}/4 --reporter=blob From 4678fea2e3a954ae7469c5c4b4ac1981b6ffdafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20TR=C3=89BEL=20=28Perso=29?= Date: Tue, 28 Jul 2026 16:55:43 +0200 Subject: [PATCH 12/12] chore(ci): force 2 Playwright workers --- playwright/playwright.config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/playwright/playwright.config.ts b/playwright/playwright.config.ts index 06a9545f6a..ec4838c6da 100644 --- a/playwright/playwright.config.ts +++ b/playwright/playwright.config.ts @@ -19,7 +19,8 @@ export default defineConfig({ retries: 3, - workers: process.env.CI ? 1 : undefined, // Default is 50% logical cores + // Let Playwright automatically handle parallelism + workers: process.env.CI ? 2 : undefined, // Default is 50% logical cores // The maximum number of test failures forthe whole test suite run. // After reaching this number, testing will stop and exit with an error.