From 300b826c39803b764da479b5a6e2d6491611ea33 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Wed, 27 May 2026 12:52:38 +0200 Subject: [PATCH 01/25] IBX-11740: Added playwright-browser-tests.yml --- .../workflows/playwright-browser-tests.yml | 225 ++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 .github/workflows/playwright-browser-tests.yml diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml new file mode 100644 index 0000000..6e6dc8c --- /dev/null +++ b/.github/workflows/playwright-browser-tests.yml @@ -0,0 +1,225 @@ +name: Browser tests (Playwright) + +on: + workflow_call: + inputs: + project-edition: + description: "Project edition to set up: oss, headless, experience, commerce" + required: true + type: string + test-suite: + description: "Playwright CLI args (e.g. --project=commerce)" + required: true + type: string + project-version: + description: "Project version (e.g. 6.0.x-dev). If empty, inferred from branch alias." + required: false + type: string + default: '' + setup: + description: "Docker Compose files to use" + required: false + type: string + default: "doc/docker/base-dev.yml" + php-image: + description: "PHP Docker image to use" + required: false + type: string + default: "ghcr.io/ibexa/docker/php:8.3-node22" + node-version: + description: "Node.js version for running Playwright" + required: false + type: string + default: "20" + ci-scripts-branch: + description: "Branch from ibexa/ci-scripts to use" + required: false + type: string + default: "main" + test-setup-phase-1: + description: "Behat suite to run before Playwright tests for data seeding - phase 1" + required: false + type: string + default: "" + test-setup-phase-2: + description: "Behat suite to run before Playwright tests for data seeding - phase 2" + required: false + type: string + default: "" + send-success-notification: + description: "Send a Slack notification when tests pass" + required: false + type: boolean + default: true + timeout: + description: "Job timeout in minutes" + required: false + type: number + default: 60 + secrets: + SLACK_WEBHOOK_URL: + required: false + SATIS_NETWORK_KEY: + required: false + SATIS_NETWORK_TOKEN: + required: false + AUTOMATION_CLIENT_ID: + required: false + AUTOMATION_CLIENT_SECRET: + required: false + EZROBOT_33: + required: false + +env: + APP_ENV: behat + APP_DEBUG: 1 + APP_SECRET: '2d4218d7b6c69a9f88da7b8986e64717b3c40948a7ba2b1ca309dc292472286d' + PHP_INI_ENV_memory_limit: 1G + COMPOSER_CACHE_DIR: ~/.composer/cache + +jobs: + browser-tests: + runs-on: ubuntu-latest + timeout-minutes: ${{ inputs.timeout }} + + steps: + - uses: actions/checkout@v4 + + - name: Set up project version + id: project-version + run: | + if [[ "$version" == "" ]] ; then + echo "Input project version not set, taking the value from composer.json" + version=$(cat composer.json | jq -r '.extra | ."branch-alias" | .[]') + fi + if [[ "$version" == "3.3.x-dev" ]] ; then + version="^3.3.x-dev" + fi + echo "version=$version" >> $GITHUB_OUTPUT + env: + version: ${{ inputs.project-version }} + + - name: Setup PHP Action + uses: shivammathur/setup-php@v2 + with: + php-version: 8.3 + coverage: none + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ${{ env.COMPOSER_CACHE_DIR }} + key: ${{ inputs.project-edition }}-${{ steps.project-version.outputs.version }}-${{ inputs.php-image }}-${{ github.sha }} + restore-keys: | + ${{ inputs.project-edition }}-${{ steps.project-version.outputs.version }}-${{ inputs.php-image }} + + - name: Generate token + id: generate_token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.AUTOMATION_CLIENT_ID }} + private-key: ${{ secrets.AUTOMATION_CLIENT_SECRET }} + owner: ibexa + + - if: env.SATIS_NETWORK_KEY != '' + name: Add composer keys for private packagist + run: | + composer config http-basic.updates.ibexa.co $SATIS_NETWORK_KEY $SATIS_NETWORK_TOKEN + env: + SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }} + SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }} + + - name: Add composer key for GitHub App + if: ${{ steps.generate_token.outputs.token != '' }} + run: | + composer config github-oauth.github.com $GITHUB_TOKEN + env: + GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} + + - if: startsWith(steps.project-version.outputs.version, 'v') == false + name: Set up whole project using the tested dependency (dev version) + run: | + curl -L "https://raw.githubusercontent.com/ibexa/ci-scripts/${{ inputs.ci-scripts-branch }}/bin/${{ steps.project-version.outputs.version }}/prepare_project_edition.sh" > prepare_project_edition.sh + chmod +x prepare_project_edition.sh + ./prepare_project_edition.sh ${{ inputs.project-edition }} ${{ steps.project-version.outputs.version }} ${{ inputs.setup }} ${{ inputs.php-image }} + + - if: startsWith(steps.project-version.outputs.version, 'v') + name: Set up whole project using a stable release + run: | + curl -L "https://raw.githubusercontent.com/ibexa/ci-scripts/${{ inputs.ci-scripts-branch }}/bin/stable/prepare_project_edition.sh" > prepare_project_edition.sh + chmod +x prepare_project_edition.sh + ./prepare_project_edition.sh ${{ inputs.project-edition }} ${{ steps.project-version.outputs.version }} ${{ inputs.setup }} ${{ inputs.php-image }} + + - name: Add ibexa_integrated_help config + if: inputs.project-edition != 'oss' + run: | + cd ${HOME}/build/project + docker compose --env-file=.env exec -T --user www-data app sh -c "printf 'ibexa_integrated_help:\n enabled: false\n' > config/packages/ibexa_integrated_help.yaml" + + - if: inputs.test-setup-phase-1 != '' + name: Run first phase of tests setup + run: | + cd ${HOME}/build/project + docker compose --env-file=.env exec -T --user www-data app sh -c "vendor/bin/ibexabehat ${{ inputs.test-setup-phase-1 }}" + docker compose --env-file=.env exec -T --user www-data app sh -c "composer run post-install-cmd" + + - if: inputs.test-setup-phase-2 != '' + name: Run second phase of tests setup + run: | + cd ${HOME}/build/project + docker compose --env-file=.env exec -T --user www-data app sh -c "vendor/bin/ibexabehat ${{ inputs.test-setup-phase-2 }}" + docker compose --env-file=.env exec -T --user www-data app sh -c "composer run post-install-cmd" + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + cache: 'npm' + + - name: Install Node.js dependencies + run: npm ci + + - name: Install Playwright browsers + run: npx playwright install --with-deps chromium + + - name: Run Playwright tests + run: npx playwright test ${{ inputs.test-suite }} + env: + APP_URL: http://localhost:8080 + CI: true + + - name: Upload Playwright report + if: always() + uses: actions/upload-artifact@v4 + with: + name: playwright-report-${{ inputs.project-edition }} + path: playwright-report/ + retention-days: 14 + + - if: always() && github.event_name != 'pull_request' + name: Create Slack message variables + run: | + echo "RESULT_EMOJI=:x:" >> $GITHUB_ENV + + - if: always() && job.status == 'success' && github.event_name != 'pull_request' + name: Create Slack message success variables + run: | + echo "RESULT_EMOJI=:white_check_mark:" >> $GITHUB_ENV + + - if: always() && github.event_name != 'pull_request' + name: Create Slack message + run: > + echo "SLACK_PAYLOAD= + {\"blocks\": [{\"type\": \"section\",\"text\": {\"type\": \"mrkdwn\",\"text\": \" + $RESULT_EMOJI *$GITHUB_REPOSITORY*:*$GITHUB_REF_NAME* ($GITHUB_ACTOR) | + <$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID|Details> + \"}}]}" >> $GITHUB_ENV + + - if: always() && github.event_name != 'pull_request' && (job.status != 'success' || inputs.send-success-notification) + name: Send notification about workflow result + uses: slackapi/slack-github-action@v1.23.0 + with: + payload: ${{ env.SLACK_PAYLOAD }} + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK From a44e9214f6fd55bb6108f847c929e1cb8c92a1d3 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Wed, 27 May 2026 16:05:33 +0200 Subject: [PATCH 02/25] IBX-11740: refactor playwright-browser-tests.yml --- .../workflows/playwright-browser-tests.yml | 133 +++++++++++++++++- 1 file changed, 126 insertions(+), 7 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 6e6dc8c..4629276 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -30,7 +30,7 @@ on: description: "Node.js version for running Playwright" required: false type: string - default: "20" + default: "22" ci-scripts-branch: description: "Branch from ibexa/ci-scripts to use" required: false @@ -174,18 +174,137 @@ jobs: uses: actions/setup-node@v4 with: node-version: ${{ inputs.node-version }} - cache: 'npm' - - name: Install Node.js dependencies - run: npm ci + # Inject playwright.config.ts and playwright-global-setup.ts into the installed project. + # testMatch discovers tests shipped by all installed Ibexa packages + # under vendor/ibexa/*/tests/playwright_ts/tests/**/*.spec.ts + - name: Inject Playwright config into installed project + run: | + cd ${HOME}/build/project + cat > playwright-global-setup.ts << 'EOF' + import { chromium } from '@playwright/test'; + import { execSync } from 'child_process'; + import { globSync } from 'fs'; + import path from 'path'; + + export default async function globalSetup(): Promise { + const projectRoot = process.cwd(); + const dockerEnvFile = process.env.DOCKER_COMPOSE_ENV_FILE; + + // Run migration YAML files from all installed Ibexa packages + const migrationFiles = globSync('vendor/ibexa/*/tests/playwright_ts/migrations/*.yaml'); + for (const migrationFile of migrationFiles) { + const absPath = path.resolve(projectRoot, migrationFile); + try { + if (dockerEnvFile) { + const containerPath = absPath.replace(projectRoot, '/var/www'); + execSync( + `docker compose --env-file="${dockerEnvFile}" exec -T --user www-data app sh -c "php bin/console ibexa:migrations:import '${containerPath}' --no-interaction && php bin/console ibexa:migrations:migrate --no-interaction"`, + { cwd: projectRoot, stdio: 'inherit' }, + ); + } else { + execSync( + `php bin/console ibexa:migrations:import "${absPath}" --no-interaction && php bin/console ibexa:migrations:migrate --no-interaction`, + { cwd: projectRoot, stdio: 'inherit' }, + ); + } + } catch { + // migration already executed or non-fatal — continue + } + } + + // One-time browser login — saves session to playwright-auth.json + const baseURL = process.env.APP_URL ?? 'http://localhost:8080'; + const adminUser = process.env.ADMIN_LOGIN ?? 'admin'; + const adminPassword = process.env.ADMIN_PASSWORD ?? 'publish'; + + const browser = await chromium.launch({ headless: true }); + const context = await browser.newContext({ baseURL, locale: 'en-GB' }); + const page = await context.newPage(); + + try { + await page.goto('/admin/login'); + await page.waitForLoadState('domcontentloaded'); + await page.locator('#username').waitFor({ state: 'visible', timeout: 30_000 }); + await page.locator('#username').pressSequentially(adminUser); + await page.keyboard.press('Tab'); + await page.locator('#password').pressSequentially(adminPassword); + await page.keyboard.press('Tab'); + await page.locator('button[type="submit"].ibexa-login__btn--sign-in').waitFor({ state: 'visible', timeout: 10_000 }); + await page.locator('button[type="submit"].ibexa-login__btn--sign-in').click(); + await page.waitForLoadState('networkidle'); + await context.storageState({ path: './playwright-auth.json' }); + } finally { + await context.close(); + await browser.close(); + } + } + EOF + + cat > playwright.config.ts << 'EOF' + import { defineConfig, devices } from '@playwright/test'; + + const baseURL = process.env.APP_URL ?? 'http://localhost:8080'; + const vendorTests = 'vendor/ibexa/*/tests/playwright_ts/tests/**/*.spec.ts'; + + export default defineConfig({ + testMatch: vendorTests, + globalSetup: './playwright-global-setup.ts', + fullyParallel: false, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 1 : 0, + workers: process.env.CI ? 1 : undefined, + reporter: process.env.CI ? 'github' : 'html', + use: { + baseURL, + storageState: './playwright-auth.json', + locale: 'en-GB', + ignoreHTTPSErrors: true, + trace: 'retain-on-failure', + screenshot: 'only-on-failure', + video: 'on-first-retry', + viewport: { width: 1920, height: 1080 }, + }, + projects: [ + { + name: 'oss', + grep: /@IbexaOSS/, + use: { ...devices['Desktop Chrome'] }, + }, + { + name: 'headless', + grep: /@IbexaHeadless/, + use: { ...devices['Desktop Chrome'] }, + }, + { + name: 'experience', + grep: /@IbexaExperience/, + use: { ...devices['Desktop Chrome'] }, + }, + { + name: 'commerce', + grep: /@IbexaCommerce/, + use: { ...devices['Desktop Chrome'] }, + }, + ], + }); + EOF + npm install --no-save @playwright/test@^1.44.0 @ibexa/cohesivo-playwright@github:ibexa/cohesivo-playwright#main - name: Install Playwright browsers - run: npx playwright install --with-deps chromium + run: | + cd ${HOME}/build/project + npx playwright install --with-deps chromium - name: Run Playwright tests - run: npx playwright test ${{ inputs.test-suite }} + run: | + cd ${HOME}/build/project + npx playwright test ${{ inputs.test-suite }} env: APP_URL: http://localhost:8080 + DOCKER_COMPOSE_ENV_FILE: ${{ env.HOME }}/build/project/.env + ADMIN_LOGIN: admin + ADMIN_PASSWORD: publish CI: true - name: Upload Playwright report @@ -193,7 +312,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: playwright-report-${{ inputs.project-edition }} - path: playwright-report/ + path: ${{ env.HOME }}/build/project/playwright-report/ retention-days: 14 - if: always() && github.event_name != 'pull_request' From 858d7c99226e748e9688c2ab402cbb00d4bd43c3 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Wed, 27 May 2026 16:53:02 +0200 Subject: [PATCH 03/25] IBX-11740: refactor playwright-browser-tests.yml --- .../workflows/playwright-browser-tests.yml | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 4629276..51fa6df 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -175,6 +175,14 @@ jobs: with: node-version: ${{ inputs.node-version }} + - name: Configure npm to use HTTPS for GitHub packages + if: ${{ steps.generate_token.outputs.token != '' }} + run: | + git config --global url."https://x-access-token:${GITHUB_TOKEN}@github.com/".insteadOf "git@github.com:" + git config --global url."https://x-access-token:${GITHUB_TOKEN}@github.com/".insteadOf "ssh://git@github.com/" + env: + GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} + # Inject playwright.config.ts and playwright-global-setup.ts into the installed project. # testMatch discovers tests shipped by all installed Ibexa packages # under vendor/ibexa/*/tests/playwright_ts/tests/**/*.spec.ts @@ -183,18 +191,31 @@ jobs: cd ${HOME}/build/project cat > playwright-global-setup.ts << 'EOF' import { chromium } from '@playwright/test'; - import { execSync } from 'child_process'; - import { globSync } from 'fs'; + import { execSync, execFileSync } from 'child_process'; import path from 'path'; + import fs from 'fs'; export default async function globalSetup(): Promise { const projectRoot = process.cwd(); const dockerEnvFile = process.env.DOCKER_COMPOSE_ENV_FILE; - // Run migration YAML files from all installed Ibexa packages - const migrationFiles = globSync('vendor/ibexa/*/tests/playwright_ts/migrations/*.yaml'); - for (const migrationFile of migrationFiles) { - const absPath = path.resolve(projectRoot, migrationFile); + // Discover migration YAML files from all installed Ibexa packages + const migrationFiles: string[] = []; + const vendorIbexa = path.join(projectRoot, 'vendor', 'ibexa'); + if (fs.existsSync(vendorIbexa)) { + for (const pkg of fs.readdirSync(vendorIbexa)) { + const migrationsDir = path.join(vendorIbexa, pkg, 'tests', 'playwright_ts', 'migrations'); + if (fs.existsSync(migrationsDir)) { + for (const file of fs.readdirSync(migrationsDir)) { + if (file.endsWith('.yaml') || file.endsWith('.yml')) { + migrationFiles.push(path.join(migrationsDir, file)); + } + } + } + } + } + + for (const absPath of migrationFiles) { try { if (dockerEnvFile) { const containerPath = absPath.replace(projectRoot, '/var/www'); From 690fbe9a24c6a42e3063ec75bd71dae64e6b85d6 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Wed, 27 May 2026 18:06:40 +0200 Subject: [PATCH 04/25] IBX-11740: Fixed write permissions --- .github/workflows/playwright-browser-tests.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 51fa6df..7410cca 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -180,9 +180,13 @@ jobs: run: | git config --global url."https://x-access-token:${GITHUB_TOKEN}@github.com/".insteadOf "git@github.com:" git config --global url."https://x-access-token:${GITHUB_TOKEN}@github.com/".insteadOf "ssh://git@github.com/" + git config --global url."https://x-access-token:${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/" env: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} + - name: Fix write permissions on project directory + run: sudo chmod -R a+w ${HOME}/build/project + # Inject playwright.config.ts and playwright-global-setup.ts into the installed project. # testMatch discovers tests shipped by all installed Ibexa packages # under vendor/ibexa/*/tests/playwright_ts/tests/**/*.spec.ts @@ -310,7 +314,7 @@ jobs: ], }); EOF - npm install --no-save @playwright/test@^1.44.0 @ibexa/cohesivo-playwright@github:ibexa/cohesivo-playwright#main + npm install --no-save @playwright/test@^1.44.0 @ibexa/cohesivo-playwright@git+https://github.com/ibexa/cohesivo-playwright.git - name: Install Playwright browsers run: | From 1f7e488abcf3099d9e226a5fc75133e086c1b685 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Wed, 27 May 2026 18:16:00 +0200 Subject: [PATCH 05/25] IBX-11740: Fixed workflows --- .github/workflows/playwright-browser-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 7410cca..df5c1c5 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -314,7 +314,7 @@ jobs: ], }); EOF - npm install --no-save @playwright/test@^1.44.0 @ibexa/cohesivo-playwright@git+https://github.com/ibexa/cohesivo-playwright.git + npm install --no-save --legacy-peer-deps @playwright/test@^1.44.0 @ibexa/cohesivo-playwright@git+https://github.com/ibexa/cohesivo-playwright.git - name: Install Playwright browsers run: | From ae634c9284f323a9807e0ad70a37826219272762 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Thu, 28 May 2026 09:32:32 +0200 Subject: [PATCH 06/25] IBX-11740: Fixed workflows --- .github/workflows/playwright-browser-tests.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index df5c1c5..b0461d9 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -314,17 +314,19 @@ jobs: ], }); EOF - npm install --no-save --legacy-peer-deps @playwright/test@^1.44.0 @ibexa/cohesivo-playwright@git+https://github.com/ibexa/cohesivo-playwright.git + npm install --prefix /tmp/playwright-tools --legacy-peer-deps @playwright/test@^1.44.0 @ibexa/cohesivo-playwright@git+https://github.com/ibexa/cohesivo-playwright.git - name: Install Playwright browsers run: | - cd ${HOME}/build/project - npx playwright install --with-deps chromium + export PATH="/tmp/playwright-tools/node_modules/.bin:$PATH" + playwright install --with-deps chromium - name: Run Playwright tests run: | cd ${HOME}/build/project - npx playwright test ${{ inputs.test-suite }} + export PATH="/tmp/playwright-tools/node_modules/.bin:$PATH" + export NODE_PATH="/tmp/playwright-tools/node_modules" + playwright test ${{ inputs.test-suite }} env: APP_URL: http://localhost:8080 DOCKER_COMPOSE_ENV_FILE: ${{ env.HOME }}/build/project/.env From 16dc35c95d3aaab199deccb861b00c2e270c6cac Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Thu, 28 May 2026 09:53:07 +0200 Subject: [PATCH 07/25] IBX-11740: Fixed workflows --- .github/workflows/playwright-browser-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index b0461d9..b6fe781 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -185,7 +185,7 @@ jobs: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} - name: Fix write permissions on project directory - run: sudo chmod -R a+w ${HOME}/build/project + run: sudo chmod -R a+rwX ${HOME}/build/project # Inject playwright.config.ts and playwright-global-setup.ts into the installed project. # testMatch discovers tests shipped by all installed Ibexa packages From aa47989c5bb346d3caefe7a5cec5d2464cc116ca Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Thu, 28 May 2026 11:00:58 +0200 Subject: [PATCH 08/25] IBX-11740: Fixed workflows --- .github/workflows/playwright-browser-tests.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index b6fe781..68dec14 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -315,18 +315,22 @@ jobs: }); EOF npm install --prefix /tmp/playwright-tools --legacy-peer-deps @playwright/test@^1.44.0 @ibexa/cohesivo-playwright@git+https://github.com/ibexa/cohesivo-playwright.git + # Symlink Playwright packages into project root node_modules so esbuild can resolve them + # when transforming spec files in vendor/ibexa/*/tests/playwright_ts/tests/ + TOOLS="/tmp/playwright-tools/node_modules" + mkdir -p node_modules/@playwright node_modules/@ibexa + ln -sf "$TOOLS/@playwright/test" node_modules/@playwright/test + ln -sf "$TOOLS/playwright" node_modules/playwright + ln -sf "$TOOLS/@ibexa/cohesivo-playwright" node_modules/@ibexa/cohesivo-playwright - name: Install Playwright browsers run: | - export PATH="/tmp/playwright-tools/node_modules/.bin:$PATH" - playwright install --with-deps chromium + /tmp/playwright-tools/node_modules/.bin/playwright install --with-deps chromium - name: Run Playwright tests run: | cd ${HOME}/build/project - export PATH="/tmp/playwright-tools/node_modules/.bin:$PATH" - export NODE_PATH="/tmp/playwright-tools/node_modules" - playwright test ${{ inputs.test-suite }} + /tmp/playwright-tools/node_modules/.bin/playwright test ${{ inputs.test-suite }} env: APP_URL: http://localhost:8080 DOCKER_COMPOSE_ENV_FILE: ${{ env.HOME }}/build/project/.env From 2c47d618c768840518fccb7c2fdd9a24e6a7e676 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Thu, 28 May 2026 11:44:17 +0200 Subject: [PATCH 09/25] IBX-11740: Fixed workflows --- .github/workflows/playwright-browser-tests.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 68dec14..9818200 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -270,7 +270,7 @@ jobs: import { defineConfig, devices } from '@playwright/test'; const baseURL = process.env.APP_URL ?? 'http://localhost:8080'; - const vendorTests = 'vendor/ibexa/*/tests/playwright_ts/tests/**/*.spec.ts'; + const vendorTests = '**/vendor/ibexa/*/tests/playwright_ts/tests/**/*.spec.ts'; export default defineConfig({ testMatch: vendorTests, @@ -319,9 +319,10 @@ jobs: # when transforming spec files in vendor/ibexa/*/tests/playwright_ts/tests/ TOOLS="/tmp/playwright-tools/node_modules" mkdir -p node_modules/@playwright node_modules/@ibexa - ln -sf "$TOOLS/@playwright/test" node_modules/@playwright/test - ln -sf "$TOOLS/playwright" node_modules/playwright - ln -sf "$TOOLS/@ibexa/cohesivo-playwright" node_modules/@ibexa/cohesivo-playwright + rm -rf node_modules/@playwright/test node_modules/playwright node_modules/@ibexa/cohesivo-playwright + ln -s "$TOOLS/@playwright/test" node_modules/@playwright/test + ln -s "$TOOLS/playwright" node_modules/playwright + ln -s "$TOOLS/@ibexa/cohesivo-playwright" node_modules/@ibexa/cohesivo-playwright - name: Install Playwright browsers run: | @@ -333,7 +334,7 @@ jobs: /tmp/playwright-tools/node_modules/.bin/playwright test ${{ inputs.test-suite }} env: APP_URL: http://localhost:8080 - DOCKER_COMPOSE_ENV_FILE: ${{ env.HOME }}/build/project/.env + DOCKER_COMPOSE_ENV_FILE: /home/runner/build/project/.env ADMIN_LOGIN: admin ADMIN_PASSWORD: publish CI: true @@ -343,7 +344,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: playwright-report-${{ inputs.project-edition }} - path: ${{ env.HOME }}/build/project/playwright-report/ + path: /home/runner/build/project/playwright-report/ retention-days: 14 - if: always() && github.event_name != 'pull_request' From d94ac4c857dfdeebf69cbdbe7eb8d6d97db4cf42 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Thu, 28 May 2026 12:29:38 +0200 Subject: [PATCH 10/25] IBX-11740: Fixed workflows --- .github/workflows/playwright-browser-tests.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 9818200..279b4dc 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -187,6 +187,15 @@ jobs: - name: Fix write permissions on project directory run: sudo chmod -R a+rwX ${HOME}/build/project + - name: Install npm dependencies in Playwright test directories + run: | + for dir in ${HOME}/build/project/vendor/ibexa/*/tests/playwright_ts; do + if [ -f "$dir/package.json" ]; then + echo "→ npm ci in $dir" + cd "$dir" && npm ci + fi + done + # Inject playwright.config.ts and playwright-global-setup.ts into the installed project. # testMatch discovers tests shipped by all installed Ibexa packages # under vendor/ibexa/*/tests/playwright_ts/tests/**/*.spec.ts @@ -315,14 +324,6 @@ jobs: }); EOF npm install --prefix /tmp/playwright-tools --legacy-peer-deps @playwright/test@^1.44.0 @ibexa/cohesivo-playwright@git+https://github.com/ibexa/cohesivo-playwright.git - # Symlink Playwright packages into project root node_modules so esbuild can resolve them - # when transforming spec files in vendor/ibexa/*/tests/playwright_ts/tests/ - TOOLS="/tmp/playwright-tools/node_modules" - mkdir -p node_modules/@playwright node_modules/@ibexa - rm -rf node_modules/@playwright/test node_modules/playwright node_modules/@ibexa/cohesivo-playwright - ln -s "$TOOLS/@playwright/test" node_modules/@playwright/test - ln -s "$TOOLS/playwright" node_modules/playwright - ln -s "$TOOLS/@ibexa/cohesivo-playwright" node_modules/@ibexa/cohesivo-playwright - name: Install Playwright browsers run: | From 0e357055eb66a1fe8d3699c3af3ed56fd6a885b9 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Thu, 28 May 2026 13:14:08 +0200 Subject: [PATCH 11/25] IBX-11740: debug --- .github/workflows/playwright-browser-tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 279b4dc..625729c 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -332,6 +332,9 @@ jobs: - name: Run Playwright tests run: | cd ${HOME}/build/project + echo "=== Playwright spec files found in vendor ===" + find vendor/ibexa -name "*.spec.ts" -path "*/playwright_ts/tests/*" 2>/dev/null || echo "None found" + echo "=== Running Playwright ===" /tmp/playwright-tools/node_modules/.bin/playwright test ${{ inputs.test-suite }} env: APP_URL: http://localhost:8080 From d309696985e148dec90021a5609cf59bddc67a8c Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Thu, 28 May 2026 13:59:40 +0200 Subject: [PATCH 12/25] IBX-11740: debug --- .github/workflows/playwright-browser-tests.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 625729c..4d02dca 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -191,8 +191,14 @@ jobs: run: | for dir in ${HOME}/build/project/vendor/ibexa/*/tests/playwright_ts; do if [ -f "$dir/package.json" ]; then - echo "→ npm ci in $dir" - cd "$dir" && npm ci + cd "$dir" + if [ -f "package-lock.json" ]; then + echo "→ npm ci in $dir" + npm ci + else + echo "→ npm install in $dir (no lock file)" + npm install + fi fi done @@ -335,7 +341,7 @@ jobs: echo "=== Playwright spec files found in vendor ===" find vendor/ibexa -name "*.spec.ts" -path "*/playwright_ts/tests/*" 2>/dev/null || echo "None found" echo "=== Running Playwright ===" - /tmp/playwright-tools/node_modules/.bin/playwright test ${{ inputs.test-suite }} + NODE_PATH=/tmp/playwright-tools/node_modules /tmp/playwright-tools/node_modules/.bin/playwright test ${{ inputs.test-suite }} env: APP_URL: http://localhost:8080 DOCKER_COMPOSE_ENV_FILE: /home/runner/build/project/.env From 354186c531d9685bf88ceef18b35897fdf60c979 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Thu, 28 May 2026 14:27:03 +0200 Subject: [PATCH 13/25] IBX-11740: debug --- .github/workflows/playwright-browser-tests.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 4d02dca..1ee9a38 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -308,22 +308,18 @@ jobs: projects: [ { name: 'oss', - grep: /@IbexaOSS/, use: { ...devices['Desktop Chrome'] }, }, { name: 'headless', - grep: /@IbexaHeadless/, use: { ...devices['Desktop Chrome'] }, }, { name: 'experience', - grep: /@IbexaExperience/, use: { ...devices['Desktop Chrome'] }, }, { name: 'commerce', - grep: /@IbexaCommerce/, use: { ...devices['Desktop Chrome'] }, }, ], From 2a3b56ce1f1009d3363af3b6512493bd9c1fd9d4 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Thu, 28 May 2026 14:46:24 +0200 Subject: [PATCH 14/25] IBX-11740: debug --- .github/workflows/playwright-browser-tests.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 1ee9a38..73e7dd6 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -336,6 +336,16 @@ jobs: cd ${HOME}/build/project echo "=== Playwright spec files found in vendor ===" find vendor/ibexa -name "*.spec.ts" -path "*/playwright_ts/tests/*" 2>/dev/null || echo "None found" + echo "=== node_modules check ===" + for dir in vendor/ibexa/*/tests/playwright_ts; do + if [ -d "$dir/node_modules/@ibexa/cohesivo-playwright" ]; then + echo "✓ $dir has @ibexa/cohesivo-playwright" + else + echo "✗ $dir MISSING @ibexa/cohesivo-playwright" + fi + done + echo "=== Listing tests (no run) ===" + NODE_PATH=/tmp/playwright-tools/node_modules /tmp/playwright-tools/node_modules/.bin/playwright test --list ${{ inputs.test-suite }} 2>&1 || true echo "=== Running Playwright ===" NODE_PATH=/tmp/playwright-tools/node_modules /tmp/playwright-tools/node_modules/.bin/playwright test ${{ inputs.test-suite }} env: From c57453da4ecad2ca8cb963e89b6fe345a1e4e04f Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Thu, 28 May 2026 15:24:22 +0200 Subject: [PATCH 15/25] IBX-11740: debug --- .github/workflows/playwright-browser-tests.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 73e7dd6..c654381 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -285,10 +285,10 @@ jobs: import { defineConfig, devices } from '@playwright/test'; const baseURL = process.env.APP_URL ?? 'http://localhost:8080'; - const vendorTests = '**/vendor/ibexa/*/tests/playwright_ts/tests/**/*.spec.ts'; export default defineConfig({ - testMatch: vendorTests, + testDir: './vendor/ibexa', + testMatch: /playwright_ts\/tests\/.*\.spec\.ts/, globalSetup: './playwright-global-setup.ts', fullyParallel: false, forbidOnly: !!process.env.CI, @@ -325,6 +325,8 @@ jobs: ], }); EOF + echo "=== playwright.config.ts content ===" + cat playwright.config.ts npm install --prefix /tmp/playwright-tools --legacy-peer-deps @playwright/test@^1.44.0 @ibexa/cohesivo-playwright@git+https://github.com/ibexa/cohesivo-playwright.git - name: Install Playwright browsers From 0e64594877ef8827ac267f216165bb39bb9dd99d Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Thu, 28 May 2026 15:52:13 +0200 Subject: [PATCH 16/25] IBX-11740: debug --- .github/workflows/playwright-browser-tests.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index c654381..2162755 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -325,9 +325,13 @@ jobs: ], }); EOF - echo "=== playwright.config.ts content ===" - cat playwright.config.ts npm install --prefix /tmp/playwright-tools --legacy-peer-deps @playwright/test@^1.44.0 @ibexa/cohesivo-playwright@git+https://github.com/ibexa/cohesivo-playwright.git + mkdir -p node_modules/@playwright + ln -sf /tmp/playwright-tools/node_modules/@playwright/test node_modules/@playwright/test + ln -sf /tmp/playwright-tools/node_modules/playwright node_modules/playwright + for dir in vendor/ibexa/*/tests/playwright_ts/node_modules; do + [ -d "$dir" ] && rm -rf "$dir/playwright" "$dir/@playwright" 2>/dev/null || true + done - name: Install Playwright browsers run: | From cbf9486833112d8bc04488dd696f343db10e458c Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Fri, 29 May 2026 08:08:52 +0200 Subject: [PATCH 17/25] IBX-11740: debug --- .github/workflows/playwright-browser-tests.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 2162755..e0ab0fd 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -272,8 +272,11 @@ jobs: await page.keyboard.press('Tab'); await page.locator('button[type="submit"].ibexa-login__btn--sign-in').waitFor({ state: 'visible', timeout: 10_000 }); await page.locator('button[type="submit"].ibexa-login__btn--sign-in').click(); + await page.waitForURL('**/admin/**', { timeout: 60_000 }); await page.waitForLoadState('networkidle'); + console.log('Login successful, current URL:', page.url()); await context.storageState({ path: './playwright-auth.json' }); + console.log('Auth state saved to playwright-auth.json'); } finally { await context.close(); await browser.close(); @@ -294,7 +297,10 @@ jobs: forbidOnly: !!process.env.CI, retries: process.env.CI ? 1 : 0, workers: process.env.CI ? 1 : undefined, - reporter: process.env.CI ? 'github' : 'html', + timeout: 10_000, + reporter: process.env.CI + ? [['github'], ['html', { open: 'never', outputFolder: './playwright-report' }]] + : [['html']], use: { baseURL, storageState: './playwright-auth.json', From 51f91644442af261a8eb2149b1c23dc3b9fb5f32 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Tue, 23 Jun 2026 15:07:05 +0200 Subject: [PATCH 18/25] IBX-11740: refactor playwright-browser-tests.yml --- .../workflows/playwright-browser-tests.yml | 197 +++--------------- 1 file changed, 27 insertions(+), 170 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index e0ab0fd..5b6b2c3 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -8,9 +8,10 @@ on: required: true type: string test-suite: - description: "Playwright CLI args (e.g. --project=commerce)" - required: true + description: "Extra Playwright CLI args passed to test:all (e.g. --grep Trash)" + required: false type: string + default: '' project-version: description: "Project version (e.g. 6.0.x-dev). If empty, inferred from branch alias." required: false @@ -69,6 +70,10 @@ on: required: false EZROBOT_33: required: false + ADMIN_LOGIN: + required: false + ADMIN_PASSWORD: + required: false env: APP_ENV: behat @@ -187,184 +192,34 @@ jobs: - name: Fix write permissions on project directory run: sudo chmod -R a+rwX ${HOME}/build/project - - name: Install npm dependencies in Playwright test directories + - name: Install cohesivo-playwright dependencies and build + run: | + npm ci + npm run build + working-directory: ${HOME}/build/project/vendor/ibexa/cohesivo-playwright + + - name: Install per-package Playwright test dependencies run: | - for dir in ${HOME}/build/project/vendor/ibexa/*/tests/playwright_ts; do + for dir in ${HOME}/build/project/vendor/ibexa/*/tests/playwright-tests; do if [ -f "$dir/package.json" ]; then cd "$dir" - if [ -f "package-lock.json" ]; then - echo "→ npm ci in $dir" - npm ci - else - echo "→ npm install in $dir (no lock file)" - npm install - fi + echo "→ npm ci in $dir" + npm ci fi done - # Inject playwright.config.ts and playwright-global-setup.ts into the installed project. - # testMatch discovers tests shipped by all installed Ibexa packages - # under vendor/ibexa/*/tests/playwright_ts/tests/**/*.spec.ts - - name: Inject Playwright config into installed project - run: | - cd ${HOME}/build/project - cat > playwright-global-setup.ts << 'EOF' - import { chromium } from '@playwright/test'; - import { execSync, execFileSync } from 'child_process'; - import path from 'path'; - import fs from 'fs'; - - export default async function globalSetup(): Promise { - const projectRoot = process.cwd(); - const dockerEnvFile = process.env.DOCKER_COMPOSE_ENV_FILE; - - // Discover migration YAML files from all installed Ibexa packages - const migrationFiles: string[] = []; - const vendorIbexa = path.join(projectRoot, 'vendor', 'ibexa'); - if (fs.existsSync(vendorIbexa)) { - for (const pkg of fs.readdirSync(vendorIbexa)) { - const migrationsDir = path.join(vendorIbexa, pkg, 'tests', 'playwright_ts', 'migrations'); - if (fs.existsSync(migrationsDir)) { - for (const file of fs.readdirSync(migrationsDir)) { - if (file.endsWith('.yaml') || file.endsWith('.yml')) { - migrationFiles.push(path.join(migrationsDir, file)); - } - } - } - } - } - - for (const absPath of migrationFiles) { - try { - if (dockerEnvFile) { - const containerPath = absPath.replace(projectRoot, '/var/www'); - execSync( - `docker compose --env-file="${dockerEnvFile}" exec -T --user www-data app sh -c "php bin/console ibexa:migrations:import '${containerPath}' --no-interaction && php bin/console ibexa:migrations:migrate --no-interaction"`, - { cwd: projectRoot, stdio: 'inherit' }, - ); - } else { - execSync( - `php bin/console ibexa:migrations:import "${absPath}" --no-interaction && php bin/console ibexa:migrations:migrate --no-interaction`, - { cwd: projectRoot, stdio: 'inherit' }, - ); - } - } catch { - // migration already executed or non-fatal — continue - } - } - - // One-time browser login — saves session to playwright-auth.json - const baseURL = process.env.APP_URL ?? 'http://localhost:8080'; - const adminUser = process.env.ADMIN_LOGIN ?? 'admin'; - const adminPassword = process.env.ADMIN_PASSWORD ?? 'publish'; - - const browser = await chromium.launch({ headless: true }); - const context = await browser.newContext({ baseURL, locale: 'en-GB' }); - const page = await context.newPage(); - - try { - await page.goto('/admin/login'); - await page.waitForLoadState('domcontentloaded'); - await page.locator('#username').waitFor({ state: 'visible', timeout: 30_000 }); - await page.locator('#username').pressSequentially(adminUser); - await page.keyboard.press('Tab'); - await page.locator('#password').pressSequentially(adminPassword); - await page.keyboard.press('Tab'); - await page.locator('button[type="submit"].ibexa-login__btn--sign-in').waitFor({ state: 'visible', timeout: 10_000 }); - await page.locator('button[type="submit"].ibexa-login__btn--sign-in').click(); - await page.waitForURL('**/admin/**', { timeout: 60_000 }); - await page.waitForLoadState('networkidle'); - console.log('Login successful, current URL:', page.url()); - await context.storageState({ path: './playwright-auth.json' }); - console.log('Auth state saved to playwright-auth.json'); - } finally { - await context.close(); - await browser.close(); - } - } - EOF - - cat > playwright.config.ts << 'EOF' - import { defineConfig, devices } from '@playwright/test'; - - const baseURL = process.env.APP_URL ?? 'http://localhost:8080'; - - export default defineConfig({ - testDir: './vendor/ibexa', - testMatch: /playwright_ts\/tests\/.*\.spec\.ts/, - globalSetup: './playwright-global-setup.ts', - fullyParallel: false, - forbidOnly: !!process.env.CI, - retries: process.env.CI ? 1 : 0, - workers: process.env.CI ? 1 : undefined, - timeout: 10_000, - reporter: process.env.CI - ? [['github'], ['html', { open: 'never', outputFolder: './playwright-report' }]] - : [['html']], - use: { - baseURL, - storageState: './playwright-auth.json', - locale: 'en-GB', - ignoreHTTPSErrors: true, - trace: 'retain-on-failure', - screenshot: 'only-on-failure', - video: 'on-first-retry', - viewport: { width: 1920, height: 1080 }, - }, - projects: [ - { - name: 'oss', - use: { ...devices['Desktop Chrome'] }, - }, - { - name: 'headless', - use: { ...devices['Desktop Chrome'] }, - }, - { - name: 'experience', - use: { ...devices['Desktop Chrome'] }, - }, - { - name: 'commerce', - use: { ...devices['Desktop Chrome'] }, - }, - ], - }); - EOF - npm install --prefix /tmp/playwright-tools --legacy-peer-deps @playwright/test@^1.44.0 @ibexa/cohesivo-playwright@git+https://github.com/ibexa/cohesivo-playwright.git - mkdir -p node_modules/@playwright - ln -sf /tmp/playwright-tools/node_modules/@playwright/test node_modules/@playwright/test - ln -sf /tmp/playwright-tools/node_modules/playwright node_modules/playwright - for dir in vendor/ibexa/*/tests/playwright_ts/node_modules; do - [ -d "$dir" ] && rm -rf "$dir/playwright" "$dir/@playwright" 2>/dev/null || true - done - - name: Install Playwright browsers - run: | - /tmp/playwright-tools/node_modules/.bin/playwright install --with-deps chromium + run: npx playwright install --with-deps chromium + working-directory: ${HOME}/build/project/vendor/ibexa/cohesivo-playwright - name: Run Playwright tests - run: | - cd ${HOME}/build/project - echo "=== Playwright spec files found in vendor ===" - find vendor/ibexa -name "*.spec.ts" -path "*/playwright_ts/tests/*" 2>/dev/null || echo "None found" - echo "=== node_modules check ===" - for dir in vendor/ibexa/*/tests/playwright_ts; do - if [ -d "$dir/node_modules/@ibexa/cohesivo-playwright" ]; then - echo "✓ $dir has @ibexa/cohesivo-playwright" - else - echo "✗ $dir MISSING @ibexa/cohesivo-playwright" - fi - done - echo "=== Listing tests (no run) ===" - NODE_PATH=/tmp/playwright-tools/node_modules /tmp/playwright-tools/node_modules/.bin/playwright test --list ${{ inputs.test-suite }} 2>&1 || true - echo "=== Running Playwright ===" - NODE_PATH=/tmp/playwright-tools/node_modules /tmp/playwright-tools/node_modules/.bin/playwright test ${{ inputs.test-suite }} + run: npm run test:all -- ${{ inputs.test-suite }} + working-directory: ${HOME}/build/project/vendor/ibexa/cohesivo-playwright env: APP_URL: http://localhost:8080 - DOCKER_COMPOSE_ENV_FILE: /home/runner/build/project/.env - ADMIN_LOGIN: admin - ADMIN_PASSWORD: publish + APP_EDITION: ${{ inputs.project-edition }} + ADMIN_LOGIN: ${{ secrets.ADMIN_LOGIN || 'admin' }} + ADMIN_PASSWORD: ${{ secrets.ADMIN_PASSWORD || 'publish' }} CI: true - name: Upload Playwright report @@ -372,7 +227,9 @@ jobs: uses: actions/upload-artifact@v4 with: name: playwright-report-${{ inputs.project-edition }} - path: /home/runner/build/project/playwright-report/ + path: | + /home/runner/build/project/vendor/ibexa/**/playwright-tests/playwright-report/ + /home/runner/build/project/vendor/ibexa/**/playwright-tests/test-results/ retention-days: 14 - if: always() && github.event_name != 'pull_request' From 4ae64328c8ab5c923fd70f9579a743d1a91fa59f Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Wed, 24 Jun 2026 12:25:05 +0200 Subject: [PATCH 19/25] IBX-11740: Fixed CI --- .github/workflows/playwright-browser-tests.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 5b6b2c3..564410e 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -194,9 +194,9 @@ jobs: - name: Install cohesivo-playwright dependencies and build run: | + cd ${HOME}/build/project/vendor/ibexa/cohesivo-playwright npm ci npm run build - working-directory: ${HOME}/build/project/vendor/ibexa/cohesivo-playwright - name: Install per-package Playwright test dependencies run: | @@ -209,12 +209,14 @@ jobs: done - name: Install Playwright browsers - run: npx playwright install --with-deps chromium - working-directory: ${HOME}/build/project/vendor/ibexa/cohesivo-playwright + run: | + cd ${HOME}/build/project/vendor/ibexa/cohesivo-playwright + npx playwright install --with-deps chromium - name: Run Playwright tests - run: npm run test:all -- ${{ inputs.test-suite }} - working-directory: ${HOME}/build/project/vendor/ibexa/cohesivo-playwright + run: | + cd ${HOME}/build/project/vendor/ibexa/cohesivo-playwright + npm run test:all -- ${{ inputs.test-suite }} env: APP_URL: http://localhost:8080 APP_EDITION: ${{ inputs.project-edition }} From 0526e13ef878abf6068212af53a6f7b985a3633f Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Wed, 24 Jun 2026 13:19:52 +0200 Subject: [PATCH 20/25] IBX-11740: Fixed CI --- .../workflows/playwright-browser-tests.yml | 63 ++++++++++--------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 564410e..e765bdf 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -83,7 +83,33 @@ env: COMPOSER_CACHE_DIR: ~/.composer/cache jobs: - browser-tests: + setup-tests: + runs-on: ubuntu-latest + timeout-minutes: 1 + steps: + - if: always() && github.event_name != 'pull_request' + name: Create Slack message variables + run: | + echo "RESULT_EMOJI=:x:" >> $GITHUB_ENV + - if: always() && github.event_name != 'pull_request' + name: Create Slack message + run: > + echo "SLACK_PAYLOAD= + {\"blocks\": [{\"type\": \"section\",\"text\": {\"type\": \"mrkdwn\",\"text\": \" + $RESULT_EMOJI *$GITHUB_REPOSITORY*:*$GITHUB_REF_NAME* ($GITHUB_ACTOR) | + <$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID|Details> + \"}}]}" >> $GITHUB_ENV + - if: always() && github.event_name != 'pull_request' && job.status != 'success' && job.status != 'skipped' + name: Send notification about workflow result + uses: slackapi/slack-github-action@v1.23.0 + with: + payload: ${{ env.SLACK_PAYLOAD }} + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + + playwright-tests: + needs: setup-tests runs-on: ubuntu-latest timeout-minutes: ${{ inputs.timeout }} @@ -192,6 +218,13 @@ jobs: - name: Fix write permissions on project directory run: sudo chmod -R a+rwX ${HOME}/build/project + - name: Check cohesivo-playwright presence + run: | + echo "=== Checking vendor structure ===" + ls ${HOME}/build/project/vendor/ibexa/ | grep -E "cohesivo|admin" || echo "WARNING: expected packages not found" + echo "=== cohesivo-playwright contents ===" + ls ${HOME}/build/project/vendor/ibexa/cohesivo-playwright/ 2>/dev/null || echo "ERROR: cohesivo-playwright not found in vendor" + - name: Install cohesivo-playwright dependencies and build run: | cd ${HOME}/build/project/vendor/ibexa/cohesivo-playwright @@ -233,31 +266,3 @@ jobs: /home/runner/build/project/vendor/ibexa/**/playwright-tests/playwright-report/ /home/runner/build/project/vendor/ibexa/**/playwright-tests/test-results/ retention-days: 14 - - - if: always() && github.event_name != 'pull_request' - name: Create Slack message variables - run: | - echo "RESULT_EMOJI=:x:" >> $GITHUB_ENV - - - if: always() && job.status == 'success' && github.event_name != 'pull_request' - name: Create Slack message success variables - run: | - echo "RESULT_EMOJI=:white_check_mark:" >> $GITHUB_ENV - - - if: always() && github.event_name != 'pull_request' - name: Create Slack message - run: > - echo "SLACK_PAYLOAD= - {\"blocks\": [{\"type\": \"section\",\"text\": {\"type\": \"mrkdwn\",\"text\": \" - $RESULT_EMOJI *$GITHUB_REPOSITORY*:*$GITHUB_REF_NAME* ($GITHUB_ACTOR) | - <$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID|Details> - \"}}]}" >> $GITHUB_ENV - - - if: always() && github.event_name != 'pull_request' && (job.status != 'success' || inputs.send-success-notification) - name: Send notification about workflow result - uses: slackapi/slack-github-action@v1.23.0 - with: - payload: ${{ env.SLACK_PAYLOAD }} - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK From c85c41a4455460bca91b4912e6132e5fcd6211a4 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Mon, 13 Jul 2026 16:22:22 +0200 Subject: [PATCH 21/25] IBX-11740: Fixed CI --- .../workflows/playwright-browser-tests.yml | 129 +++++++++++++++--- 1 file changed, 111 insertions(+), 18 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index e765bdf..600454e 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -7,8 +7,13 @@ on: description: "Project edition to set up: oss, headless, experience, commerce" required: true type: string + test-package: + description: "Run tests of a single package (e.g. admin-ui). Empty = all packages with tests (edition mode)." + required: false + type: string + default: '' test-suite: - description: "Extra Playwright CLI args passed to test:all (e.g. --grep Trash)" + description: "Extra Playwright CLI args (e.g. --grep Trash)" required: false type: string default: '' @@ -37,6 +42,16 @@ on: required: false type: string default: "main" + cohesivo-version: + description: "Composer version constraint for ibexa/cohesivo-playwright. Empty = same as the project version (branch alias), so 4.6/5.0/6.0 branches get the matching library version." + required: false + type: string + default: "" + app-url: + description: "URL under which the app is reachable from the runner host" + required: false + type: string + default: "http://localhost:8080" test-setup-phase-1: description: "Behat suite to run before Playwright tests for data seeding - phase 1" required: false @@ -47,6 +62,11 @@ on: required: false type: string default: "" + job-count: + description: "Number of jobs that will run the tests in parallel (Playwright --shard)" + required: false + type: number + default: 1 send-success-notification: description: "Send a Slack notification when tests pass" required: false @@ -83,10 +103,30 @@ env: COMPOSER_CACHE_DIR: ~/.composer/cache jobs: - setup-tests: + setup-jobs: runs-on: ubuntu-latest timeout-minutes: 1 + outputs: + matrix: ${{ steps.generate-matrix.outputs.matrix }} + job-count: ${{ steps.generate-matrix.outputs.job-count }} steps: + - name: Set job count for builds + run: echo "job_count=${{ inputs.job-count }}" >> $GITHUB_ENV + - name: Limit job-count to max 3 for PRs + if: github.event_name == 'pull_request' + run: | + if [[ "$job_count" -gt 3 ]] ; then + job_count=3 + fi + echo "job_count=$job_count" >> $GITHUB_ENV + env: + job_count: ${{ env.job_count }} + - name: Generate matrix + id: generate-matrix + run: | + matrix=$(jq -cn --argjson n "$job_count" '{offset: [range(0; $n)]}') + echo "matrix=$matrix" >> $GITHUB_OUTPUT + echo "job-count=$job_count" >> $GITHUB_OUTPUT - if: always() && github.event_name != 'pull_request' name: Create Slack message variables run: | @@ -109,9 +149,12 @@ jobs: SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK playwright-tests: - needs: setup-tests + needs: setup-jobs runs-on: ubuntu-latest timeout-minutes: ${{ inputs.timeout }} + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.setup-jobs.outputs.matrix) }} steps: - uses: actions/checkout@v4 @@ -123,9 +166,6 @@ jobs: echo "Input project version not set, taking the value from composer.json" version=$(cat composer.json | jq -r '.extra | ."branch-alias" | .[]') fi - if [[ "$version" == "3.3.x-dev" ]] ; then - version="^3.3.x-dev" - fi echo "version=$version" >> $GITHUB_OUTPUT env: version: ${{ inputs.project-version }} @@ -146,11 +186,14 @@ jobs: - name: Generate token id: generate_token + if: env.AUTOMATION_CLIENT_ID != '' uses: actions/create-github-app-token@v2 with: app-id: ${{ secrets.AUTOMATION_CLIENT_ID }} private-key: ${{ secrets.AUTOMATION_CLIENT_SECRET }} owner: ibexa + env: + AUTOMATION_CLIENT_ID: ${{ secrets.AUTOMATION_CLIENT_ID }} - if: env.SATIS_NETWORK_KEY != '' name: Add composer keys for private packagist @@ -192,14 +235,30 @@ jobs: run: | cd ${HOME}/build/project docker compose --env-file=.env exec -T --user www-data app sh -c "vendor/bin/ibexabehat ${{ inputs.test-setup-phase-1 }}" - docker compose --env-file=.env exec -T --user www-data app sh -c "composer run post-install-cmd" + docker compose --env-file=.env exec -T --user www-data app sh -c "NODE_OPTIONS='--max-old-space-size=3072' composer run post-install-cmd" - if: inputs.test-setup-phase-2 != '' name: Run second phase of tests setup run: | cd ${HOME}/build/project docker compose --env-file=.env exec -T --user www-data app sh -c "vendor/bin/ibexabehat ${{ inputs.test-setup-phase-2 }}" - docker compose --env-file=.env exec -T --user www-data app sh -c "composer run post-install-cmd" + docker compose --env-file=.env exec -T --user www-data app sh -c "NODE_OPTIONS='--max-old-space-size=3072' composer run post-install-cmd" + + - name: Install ibexa/cohesivo-playwright + run: | + cd ${HOME}/build/project + COHESIVO_VERSION="${{ inputs.cohesivo-version }}" + if [ -z "$COHESIVO_VERSION" ]; then + COHESIVO_VERSION="${{ steps.project-version.outputs.version }}" + fi + echo "Installing ibexa/cohesivo-playwright:$COHESIVO_VERSION" + # TODO: drop the vcs repository once ibexa/cohesivo-playwright is published on updates.ibexa.co + docker compose --env-file=.env exec -T --user www-data -e GITHUB_TOKEN -e COHESIVO_VERSION app sh -c ' + composer config repositories.cohesivo-playwright vcs https://github.com/ibexa/cohesivo-playwright && + if [ -n "$GITHUB_TOKEN" ]; then composer config github-oauth.github.com "$GITHUB_TOKEN"; fi && + composer require --dev "ibexa/cohesivo-playwright:$COHESIVO_VERSION" --no-scripts --no-plugins' + env: + GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} - name: Setup Node.js uses: actions/setup-node@v4 @@ -218,13 +277,6 @@ jobs: - name: Fix write permissions on project directory run: sudo chmod -R a+rwX ${HOME}/build/project - - name: Check cohesivo-playwright presence - run: | - echo "=== Checking vendor structure ===" - ls ${HOME}/build/project/vendor/ibexa/ | grep -E "cohesivo|admin" || echo "WARNING: expected packages not found" - echo "=== cohesivo-playwright contents ===" - ls ${HOME}/build/project/vendor/ibexa/cohesivo-playwright/ 2>/dev/null || echo "ERROR: cohesivo-playwright not found in vendor" - - name: Install cohesivo-playwright dependencies and build run: | cd ${HOME}/build/project/vendor/ibexa/cohesivo-playwright @@ -249,9 +301,17 @@ jobs: - name: Run Playwright tests run: | cd ${HOME}/build/project/vendor/ibexa/cohesivo-playwright - npm run test:all -- ${{ inputs.test-suite }} + EXTRA_ARGS="${{ inputs.test-suite }}" + if [ "${{ needs.setup-jobs.outputs.job-count }}" -gt 1 ]; then + EXTRA_ARGS="$EXTRA_ARGS --shard=$(( ${{ matrix.offset }} + 1 ))/${{ needs.setup-jobs.outputs.job-count }} --pass-with-no-tests" + fi + if [ -n "${{ inputs.test-package }}" ]; then + npm run test:package -- ${{ inputs.test-package }} $EXTRA_ARGS + else + npm run test:all -- $EXTRA_ARGS + fi env: - APP_URL: http://localhost:8080 + APP_URL: ${{ inputs.app-url }} APP_EDITION: ${{ inputs.project-edition }} ADMIN_LOGIN: ${{ secrets.ADMIN_LOGIN || 'admin' }} ADMIN_PASSWORD: ${{ secrets.ADMIN_PASSWORD || 'publish' }} @@ -261,8 +321,41 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: playwright-report-${{ inputs.project-edition }} + name: playwright-report-${{ inputs.project-edition }}-${{ matrix.offset }} path: | /home/runner/build/project/vendor/ibexa/**/playwright-tests/playwright-report/ /home/runner/build/project/vendor/ibexa/**/playwright-tests/test-results/ + /home/runner/build/project/vendor/ibexa/cohesivo-playwright/playwright-report/ + /home/runner/build/project/vendor/ibexa/cohesivo-playwright/test-results/ retention-days: 14 + + - if: always() && github.event_name != 'pull_request' + name: Create Slack message variables + run: | + echo "RESULT_EMOJI=:x:" >> $GITHUB_ENV + JOB_NUMBER=$(expr ${{ matrix.offset }} + 1) + echo "JOB_NUMBER=$JOB_NUMBER" >> $GITHUB_ENV + + - if: always() && job.status == 'success' && github.event_name != 'pull_request' + name: Create Slack message success variables + run: | + echo "RESULT_EMOJI=:white_check_mark:" >> $GITHUB_ENV + + - if: always() && github.event_name != 'pull_request' + name: Create Slack message + run: > + echo "SLACK_PAYLOAD= + {\"blocks\": [{\"type\": \"section\",\"text\": {\"type\": \"mrkdwn\",\"text\": \" + $RESULT_EMOJI *$GITHUB_REPOSITORY*:*$GITHUB_REF_NAME* ($GITHUB_ACTOR) | Playwright | + <$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID|Details> | + $JOB_NUMBER/${{ needs.setup-jobs.outputs.job-count }} + \"}}]}" >> $GITHUB_ENV + + - if: always() && github.event_name != 'pull_request' && (job.status != 'success' || inputs.send-success-notification) + name: Send notification about workflow result + uses: slackapi/slack-github-action@v1.23.0 + with: + payload: ${{ env.SLACK_PAYLOAD }} + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK From 95abdfb2bf9dd8ac38e9cf48c13c563250a027ac Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Mon, 13 Jul 2026 17:05:44 +0200 Subject: [PATCH 22/25] IBX-11740: Added missing export for cohesivo_version --- .github/workflows/playwright-browser-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 600454e..6f6fc9d 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -247,9 +247,9 @@ jobs: - name: Install ibexa/cohesivo-playwright run: | cd ${HOME}/build/project - COHESIVO_VERSION="${{ inputs.cohesivo-version }}" + export COHESIVO_VERSION="${{ inputs.cohesivo-version }}" if [ -z "$COHESIVO_VERSION" ]; then - COHESIVO_VERSION="${{ steps.project-version.outputs.version }}" + export COHESIVO_VERSION="${{ steps.project-version.outputs.version }}" fi echo "Installing ibexa/cohesivo-playwright:$COHESIVO_VERSION" # TODO: drop the vcs repository once ibexa/cohesivo-playwright is published on updates.ibexa.co From 1fc8a3af558e92a276c6a6bbe5075f3b4b4a17de Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Fri, 24 Jul 2026 12:21:57 +0200 Subject: [PATCH 23/25] Changed slack integration from v1.23 to v3.03 --- .github/workflows/playwright-browser-tests.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 6f6fc9d..27828ff 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -141,12 +141,11 @@ jobs: \"}}]}" >> $GITHUB_ENV - if: always() && github.event_name != 'pull_request' && job.status != 'success' && job.status != 'skipped' name: Send notification about workflow result - uses: slackapi/slack-github-action@v1.23.0 + uses: slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c # v3.0.3 with: + webhook: ${{ secrets.SLACK_WEBHOOK_URL }} + webhook-type: incoming-webhook payload: ${{ env.SLACK_PAYLOAD }} - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK playwright-tests: needs: setup-jobs @@ -353,9 +352,8 @@ jobs: - if: always() && github.event_name != 'pull_request' && (job.status != 'success' || inputs.send-success-notification) name: Send notification about workflow result - uses: slackapi/slack-github-action@v1.23.0 + uses: slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c # v3.0.3 with: + webhook: ${{ secrets.SLACK_WEBHOOK_URL }} + webhook-type: incoming-webhook payload: ${{ env.SLACK_PAYLOAD }} - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK From fba4fa46b6fe4be356ffdb3d5e015a65b987e3f3 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Fri, 24 Jul 2026 15:30:39 +0200 Subject: [PATCH 24/25] Removed 2 paths for reports, added timestamp and removed behat phases --- .../workflows/playwright-browser-tests.yml | 69 +++++++++---------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index 27828ff..ae435bb 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -43,7 +43,7 @@ on: type: string default: "main" cohesivo-version: - description: "Composer version constraint for ibexa/cohesivo-playwright. Empty = same as the project version (branch alias), so 4.6/5.0/6.0 branches get the matching library version." + description: "Composer version constraint for ibexa/cohesivo-playwright. Empty = match the project version (branch alias). Playwright is 5.0+ only — there is no 4.6 branch of the library, so 4.6 projects must not call this workflow." required: false type: string default: "" @@ -52,16 +52,6 @@ on: required: false type: string default: "http://localhost:8080" - test-setup-phase-1: - description: "Behat suite to run before Playwright tests for data seeding - phase 1" - required: false - type: string - default: "" - test-setup-phase-2: - description: "Behat suite to run before Playwright tests for data seeding - phase 2" - required: false - type: string - default: "" job-count: description: "Number of jobs that will run the tests in parallel (Playwright --shard)" required: false @@ -96,6 +86,10 @@ on: required: false env: + # Symfony env the app boots in — the established platform test env (provided by ibexa/behat), + # same as the Behat pipeline and expected by the shared project-setup script. It configures + # the app, not Playwright (the tests just hit it over HTTP). There is no dedicated "playwright" + # env; dropping this would fall back to "dev", so it stays as-is. APP_ENV: behat APP_DEBUG: 1 APP_SECRET: '2d4218d7b6c69a9f88da7b8986e64717b3c40948a7ba2b1ca309dc292472286d' @@ -229,26 +223,16 @@ jobs: cd ${HOME}/build/project docker compose --env-file=.env exec -T --user www-data app sh -c "printf 'ibexa_integrated_help:\n enabled: false\n' > config/packages/ibexa_integrated_help.yaml" - - if: inputs.test-setup-phase-1 != '' - name: Run first phase of tests setup - run: | - cd ${HOME}/build/project - docker compose --env-file=.env exec -T --user www-data app sh -c "vendor/bin/ibexabehat ${{ inputs.test-setup-phase-1 }}" - docker compose --env-file=.env exec -T --user www-data app sh -c "NODE_OPTIONS='--max-old-space-size=3072' composer run post-install-cmd" - - - if: inputs.test-setup-phase-2 != '' - name: Run second phase of tests setup - run: | - cd ${HOME}/build/project - docker compose --env-file=.env exec -T --user www-data app sh -c "vendor/bin/ibexabehat ${{ inputs.test-setup-phase-2 }}" - docker compose --env-file=.env exec -T --user www-data app sh -c "NODE_OPTIONS='--max-old-space-size=3072' composer run post-install-cmd" + # Data seeding is done per-test through IbexaApiClient (REST) in the packages' + # beforeAll hooks — no Behat setup phase here, so this workflow has no Behat dependency. - name: Install ibexa/cohesivo-playwright run: | cd ${HOME}/build/project - export COHESIVO_VERSION="${{ inputs.cohesivo-version }}" + # empty cohesivo-version → match the project version (branch alias), so a 5.0/6.0 + # branch installs the matching library version. (No 4.6 branch of the library exists.) if [ -z "$COHESIVO_VERSION" ]; then - export COHESIVO_VERSION="${{ steps.project-version.outputs.version }}" + COHESIVO_VERSION="$PROJECT_VERSION" fi echo "Installing ibexa/cohesivo-playwright:$COHESIVO_VERSION" # TODO: drop the vcs repository once ibexa/cohesivo-playwright is published on updates.ibexa.co @@ -258,6 +242,8 @@ jobs: composer require --dev "ibexa/cohesivo-playwright:$COHESIVO_VERSION" --no-scripts --no-plugins' env: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} + COHESIVO_VERSION: ${{ inputs.cohesivo-version }} + PROJECT_VERSION: ${{ steps.project-version.outputs.version }} - name: Setup Node.js uses: actions/setup-node@v4 @@ -298,34 +284,45 @@ jobs: npx playwright install --with-deps chromium - name: Run Playwright tests + # inputs are passed via env (not interpolated into the script) to avoid shell injection run: | cd ${HOME}/build/project/vendor/ibexa/cohesivo-playwright - EXTRA_ARGS="${{ inputs.test-suite }}" - if [ "${{ needs.setup-jobs.outputs.job-count }}" -gt 1 ]; then - EXTRA_ARGS="$EXTRA_ARGS --shard=$(( ${{ matrix.offset }} + 1 ))/${{ needs.setup-jobs.outputs.job-count }} --pass-with-no-tests" + EXTRA_ARGS="$TEST_SUITE" + if [ "$JOB_COUNT" -gt 1 ]; then + EXTRA_ARGS="$EXTRA_ARGS --shard=$(( SHARD_OFFSET + 1 ))/$JOB_COUNT --pass-with-no-tests" fi - if [ -n "${{ inputs.test-package }}" ]; then - npm run test:package -- ${{ inputs.test-package }} $EXTRA_ARGS + if [ -n "$TEST_PACKAGE" ]; then + npm run test:package -- "$TEST_PACKAGE" $EXTRA_ARGS else npm run test:all -- $EXTRA_ARGS fi env: + TEST_SUITE: ${{ inputs.test-suite }} + TEST_PACKAGE: ${{ inputs.test-package }} + JOB_COUNT: ${{ needs.setup-jobs.outputs.job-count }} + SHARD_OFFSET: ${{ matrix.offset }} APP_URL: ${{ inputs.app-url }} APP_EDITION: ${{ inputs.project-edition }} ADMIN_LOGIN: ${{ secrets.ADMIN_LOGIN || 'admin' }} ADMIN_PASSWORD: ${{ secrets.ADMIN_PASSWORD || 'publish' }} CI: true + - name: Report timestamp + if: always() + id: report-ts + run: echo "value=$(date -u +'%Y%m%d-%H%M%S')" >> "$GITHUB_OUTPUT" + - name: Upload Playwright report if: always() uses: actions/upload-artifact@v4 with: - name: playwright-report-${{ inputs.project-edition }}-${{ matrix.offset }} + # edition + shard make it unique within a run; UTC timestamp tells runs apart + name: playwright-report-${{ inputs.project-edition }}-shard${{ matrix.offset }}-${{ steps.report-ts.outputs.value }} + # `**` matches any depth, so one pair of globs covers both the package suites + # (/tests/playwright-tests/) and cohesivo's own tests (cohesivo-playwright/) path: | - /home/runner/build/project/vendor/ibexa/**/playwright-tests/playwright-report/ - /home/runner/build/project/vendor/ibexa/**/playwright-tests/test-results/ - /home/runner/build/project/vendor/ibexa/cohesivo-playwright/playwright-report/ - /home/runner/build/project/vendor/ibexa/cohesivo-playwright/test-results/ + /home/runner/build/project/vendor/ibexa/**/playwright-report/ + /home/runner/build/project/vendor/ibexa/**/test-results/ retention-days: 14 - if: always() && github.event_name != 'pull_request' From 497f45ab9509ef026b2447512113109ebc9e54e2 Mon Sep 17 00:00:00 2001 From: adrianpawlak Date: Thu, 10 Sep 2026 12:12:44 +0200 Subject: [PATCH 25/25] After review --- .../workflows/playwright-browser-tests.yml | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/.github/workflows/playwright-browser-tests.yml b/.github/workflows/playwright-browser-tests.yml index ae435bb..e95aff0 100644 --- a/.github/workflows/playwright-browser-tests.yml +++ b/.github/workflows/playwright-browser-tests.yml @@ -48,10 +48,15 @@ on: type: string default: "" app-url: - description: "URL under which the app is reachable from the runner host" + description: "URL under which the app is reachable from the runner host. Empty = derived from setup." required: false type: string - default: "http://localhost:8080" + default: "" + artifact-suffix: + description: "Discriminator when one run calls this workflow several times for the same edition (e.g. 'pgsql18-varnish')" + required: false + type: string + default: '' job-count: description: "Number of jobs that will run the tests in parallel (Playwright --shard)" required: false @@ -150,7 +155,20 @@ jobs: matrix: ${{ fromJson(needs.setup-jobs.outputs.matrix) }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Derive app URL from setup + run: | + if [ -n "$APP_URL" ]; then + echo "APP_URL=$APP_URL" >> $GITHUB_ENV + elif echo "$SETUP" | grep -q varnish; then + echo "APP_URL=http://localhost:8081" >> $GITHUB_ENV + else + echo "APP_URL=http://localhost:8080" >> $GITHUB_ENV + fi + env: + APP_URL: ${{ inputs.app-url }} + SETUP: ${{ inputs.setup }} - name: Set up project version id: project-version @@ -164,13 +182,13 @@ jobs: version: ${{ inputs.project-version }} - name: Setup PHP Action - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2 with: php-version: 8.3 coverage: none - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ${{ env.COMPOSER_CACHE_DIR }} key: ${{ inputs.project-edition }}-${{ steps.project-version.outputs.version }}-${{ inputs.php-image }}-${{ github.sha }} @@ -180,7 +198,7 @@ jobs: - name: Generate token id: generate_token if: env.AUTOMATION_CLIENT_ID != '' - uses: actions/create-github-app-token@v2 + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: app-id: ${{ secrets.AUTOMATION_CLIENT_ID }} private-key: ${{ secrets.AUTOMATION_CLIENT_SECRET }} @@ -288,6 +306,8 @@ jobs: run: | cd ${HOME}/build/project/vendor/ibexa/cohesivo-playwright EXTRA_ARGS="$TEST_SUITE" + # --pass-with-no-tests only under sharding: an empty shard is expected, an empty + # unsharded run means the edition grep matched nothing and should fail loudly. if [ "$JOB_COUNT" -gt 1 ]; then EXTRA_ARGS="$EXTRA_ARGS --shard=$(( SHARD_OFFSET + 1 ))/$JOB_COUNT --pass-with-no-tests" fi @@ -301,23 +321,17 @@ jobs: TEST_PACKAGE: ${{ inputs.test-package }} JOB_COUNT: ${{ needs.setup-jobs.outputs.job-count }} SHARD_OFFSET: ${{ matrix.offset }} - APP_URL: ${{ inputs.app-url }} + APP_URL: ${{ env.APP_URL }} APP_EDITION: ${{ inputs.project-edition }} ADMIN_LOGIN: ${{ secrets.ADMIN_LOGIN || 'admin' }} ADMIN_PASSWORD: ${{ secrets.ADMIN_PASSWORD || 'publish' }} CI: true - - name: Report timestamp - if: always() - id: report-ts - run: echo "value=$(date -u +'%Y%m%d-%H%M%S')" >> "$GITHUB_OUTPUT" - - name: Upload Playwright report if: always() uses: actions/upload-artifact@v4 with: - # edition + shard make it unique within a run; UTC timestamp tells runs apart - name: playwright-report-${{ inputs.project-edition }}-shard${{ matrix.offset }}-${{ steps.report-ts.outputs.value }} + name: playwright-report-${{ inputs.project-edition }}-${{ inputs.artifact-suffix || inputs.test-package || 'all' }}-shard${{ matrix.offset }}-${{ github.run_id }}-${{ github.run_attempt }} # `**` matches any depth, so one pair of globs covers both the package suites # (/tests/playwright-tests/) and cohesivo's own tests (cohesivo-playwright/) path: |