Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions .github/actions/ensure-playwright-image/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: 'Ensure Playwright Docker Image'
description: 'Checks if the custom Playwright Docker image exists in GHCR. Builds and pushes it if missing.'

inputs:
github_token:
description: 'GitHub token with packages:write permission'
required: true

outputs:
image:
description: 'The full Docker image reference (e.g. ghcr.io/owner/repo/playwright:v1.56.0)'
value: ${{ steps.image.outputs.ref }}

runs:
using: 'composite'
steps:
- name: Get Playwright version
id: playwright
run: |
VERSION=$(node -p "
const pkg = require('./dev-packages/browser-integration-tests/package.json');
const v = (pkg.dependencies || {})['@playwright/test'] || (pkg.devDependencies || {})['@playwright/test'];
v.replace(/[~^]/, '')
")
echo "version=$VERSION" >> $GITHUB_OUTPUT
shell: bash

- name: Verify @playwright/test version consistency
shell: bash
run: |
CANONICAL=$(node -p "
const pkg = require('./dev-packages/browser-integration-tests/package.json');
(pkg.dependencies || {})['@playwright/test'] || (pkg.devDependencies || {})['@playwright/test']
")
echo "Canonical @playwright/test version: $CANONICAL"
MISMATCHES=0

check_version() {
local file="$1"
local version
version=$(node -p "
const pkg = require('./$file');
(pkg.dependencies || {})['@playwright/test'] ||
(pkg.devDependencies || {})['@playwright/test'] ||
(pkg.peerDependencies || {})['@playwright/test'] ||
'not found'
")
if [ "$version" != "not found" ] && [ "$version" != "$CANONICAL" ]; then
echo "::error file=$file::@playwright/test version mismatch: $version (expected $CANONICAL)"
MISMATCHES=$((MISMATCHES + 1))
fi
}

check_version "dev-packages/test-utils/package.json"

for pkg in dev-packages/e2e-tests/test-applications/*/package.json; do
check_version "$pkg"
done

if [ "$MISMATCHES" -gt 0 ]; then
echo "Found $MISMATCHES package(s) with mismatched @playwright/test versions."
echo "All packages must use the same version as dev-packages/browser-integration-tests ($CANONICAL)."
exit 1
fi
echo "All @playwright/test versions are consistent ($CANONICAL)"

- name: Set image reference
id: image
shell: bash
run: |
DOCKERFILE_HASH=$(sha256sum .github/docker/playwright.Dockerfile | cut -c1-8)
TAG="v${{ steps.playwright.outputs.version }}-${DOCKERFILE_HASH}"
echo "ref=ghcr.io/${{ github.repository }}/playwright:${TAG}" >> $GITHUB_OUTPUT

- name: Check if image already exists
id: check
shell: bash
run: |
if docker manifest inspect "${{ steps.image.outputs.ref }}" > /dev/null 2>&1; then
echo "exists=true" >> $GITHUB_OUTPUT
echo "Image ${{ steps.image.outputs.ref }} already exists, skipping build."
else
echo "exists=false" >> $GITHUB_OUTPUT
echo "Image ${{ steps.image.outputs.ref }} not found, will build."
fi
env:
DOCKER_CLI_EXPERIMENTAL: enabled

- name: Log in to GHCR
if: steps.check.outputs.exists == 'false'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ inputs.github_token }}

- name: Build and push
if: steps.check.outputs.exists == 'false'
uses: docker/build-push-action@v6
with:
file: .github/docker/playwright.Dockerfile
push: true
build-args: |
PLAYWRIGHT_VERSION=${{ steps.playwright.outputs.version }}
tags: |
${{ steps.image.outputs.ref }}
52 changes: 0 additions & 52 deletions .github/actions/install-playwright/action.yml

This file was deleted.

7 changes: 7 additions & 0 deletions .github/docker/playwright.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# PLAYWRIGHT_VERSION is passed as a build arg by the ensure-playwright-image action.
# The canonical source is dev-packages/browser-integration-tests/package.json.
ARG PLAYWRIGHT_VERSION
FROM mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-noble

# Install yarn (v1) for the monorepo
RUN npm install -g yarn@1.22.22
89 changes: 56 additions & 33 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,24 @@ jobs:
permissions:
pull-requests: read

job_playwright_image:
name: Ensure Playwright Image
runs-on: ubuntu-24.04
permissions:
packages: write
outputs:
image: ${{ steps.ensure.outputs.image }}
steps:
- name: Check out current commit
uses: actions/checkout@v6
with:
ref: ${{ env.HEAD_COMMIT }}
- name: Ensure Playwright image
id: ensure
uses: ./.github/actions/ensure-playwright-image
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

job_build:
name: Build
needs: job_get_metadata
Expand Down Expand Up @@ -475,9 +493,15 @@ jobs:
name:
Playwright ${{ matrix.bundle }}${{ matrix.project && matrix.project != 'chromium' && format(' {0}',
matrix.project) || ''}}${{ matrix.shard && format(' ({0}/{1})', matrix.shard, matrix.shards) || ''}} Tests
needs: [job_get_metadata, job_build]
needs: [job_get_metadata, job_build, job_playwright_image]
if: needs.job_build.outputs.changed_browser_integration == 'true' || github.event_name != 'pull_request'
runs-on: ubuntu-24.04-large-js
container:
image: ${{ needs.job_playwright_image.outputs.image }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: --ipc=host -e HOME=/root
timeout-minutes: 25
strategy:
fail-fast: false
Expand Down Expand Up @@ -540,11 +564,6 @@ jobs:
with:
dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }}

- name: Install Playwright
uses: ./.github/actions/install-playwright
with:
browsers: ${{ matrix.project }}

- name: Run Playwright tests
env:
PW_BUNDLE: ${{ matrix.bundle }}
Expand Down Expand Up @@ -578,9 +597,15 @@ jobs:

job_browser_loader_tests:
name: PW ${{ matrix.bundle }} Tests
needs: [job_get_metadata, job_build]
needs: [job_get_metadata, job_build, job_playwright_image]
if: needs.job_build.outputs.changed_browser_integration == 'true' || github.event_name != 'pull_request'
runs-on: ubuntu-24.04
container:
image: ${{ needs.job_playwright_image.outputs.image }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: --ipc=host -e HOME=/root
timeout-minutes: 15
strategy:
fail-fast: false
Expand Down Expand Up @@ -608,11 +633,6 @@ jobs:
with:
dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }}

- name: Install Playwright
uses: ./.github/actions/install-playwright
with:
browsers: chromium

- name: Run Playwright Loader tests
env:
PW_BUNDLE: ${{ matrix.bundle }}
Expand Down Expand Up @@ -771,9 +791,15 @@ jobs:

job_remix_integration_tests:
name: Remix (Node ${{ matrix.node }}) Tests
needs: [job_get_metadata, job_build]
needs: [job_get_metadata, job_build, job_playwright_image]
if: needs.job_build.outputs.changed_remix == 'true' || github.event_name != 'pull_request'
runs-on: ubuntu-24.04
container:
image: ${{ needs.job_playwright_image.outputs.image }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: --ipc=host -e HOME=/root
timeout-minutes: 15
strategy:
fail-fast: false
Expand All @@ -793,11 +819,6 @@ jobs:
with:
dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }}

- name: Install Playwright
uses: ./.github/actions/install-playwright
with:
browsers: chromium

- name: Run integration tests
env:
NODE_VERSION: ${{ matrix.node }}
Expand Down Expand Up @@ -873,8 +894,15 @@ jobs:
# See: https://github.com/actions/runner/issues/2205
if:
always() && needs.job_e2e_prepare.result == 'success' && needs.job_e2e_prepare.outputs.matrix != '{"include":[]}'
needs: [job_get_metadata, job_build, job_e2e_prepare]
&& needs.job_playwright_image.result == 'success'
needs: [job_get_metadata, job_build, job_e2e_prepare, job_playwright_image]
runs-on: ubuntu-24.04
container:
image: ${{ needs.job_playwright_image.outputs.image }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: --ipc=host -e HOME=/root
timeout-minutes: 15
env:
# We just use a dummy DSN here, only send to the tunnel anyhow
Expand Down Expand Up @@ -956,12 +984,6 @@ jobs:
env:
SENTRY_E2E_WORKSPACE_ROOT: ${{ github.workspace }}

- name: Install Playwright
uses: ./.github/actions/install-playwright
with:
browsers: chromium
cwd: ${{ runner.temp }}/test-application

- name: Run E2E test
working-directory: ${{ runner.temp }}/test-application
timeout-minutes: 10
Expand Down Expand Up @@ -1002,9 +1024,16 @@ jobs:
if:
always() && needs.job_get_metadata.outputs.is_release != 'true' && needs.job_e2e_prepare.result == 'success' &&
needs.job_e2e_prepare.outputs.matrix-optional != '{"include":[]}' && (github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
needs: [job_get_metadata, job_build, job_e2e_prepare]
github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]' &&
needs.job_playwright_image.result == 'success'
needs: [job_get_metadata, job_build, job_e2e_prepare, job_playwright_image]
runs-on: ubuntu-24.04
container:
image: ${{ needs.job_playwright_image.outputs.image }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: --ipc=host -e HOME=/root
timeout-minutes: 15
env:
E2E_TEST_AUTH_TOKEN: ${{ secrets.E2E_TEST_AUTH_TOKEN }}
Expand Down Expand Up @@ -1071,12 +1100,6 @@ jobs:
timeout-minutes: 7
run: ${{ matrix.build-command || 'pnpm test:build' }}

- name: Install Playwright
uses: ./.github/actions/install-playwright
with:
browsers: chromium
cwd: ${{ runner.temp }}/test-application

- name: Run E2E test
working-directory: ${{ runner.temp }}/test-application
timeout-minutes: 10
Expand Down
30 changes: 23 additions & 7 deletions .github/workflows/canary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,24 @@ env:
permissions:
contents: read
issues: write
packages: write

jobs:
job_playwright_image:
name: Ensure Playwright Image
runs-on: ubuntu-24.04
outputs:
image: ${{ steps.ensure.outputs.image }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ env.HEAD_COMMIT }}
- name: Ensure Playwright image
id: ensure
uses: ./.github/actions/ensure-playwright-image
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

job_e2e_prepare:
name: Prepare E2E Canary tests
runs-on: ubuntu-24.04
Expand Down Expand Up @@ -53,8 +69,14 @@ jobs:

job_e2e_tests:
name: E2E ${{ matrix.label }} Test
needs: [job_e2e_prepare]
needs: [job_e2e_prepare, job_playwright_image]
runs-on: ubuntu-24.04
container:
image: ${{ needs.job_playwright_image.outputs.image }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: --ipc=host -e HOME=/root
timeout-minutes: 20
env:
# We just use a dummy DSN here, only send to the tunnel anyhow
Expand Down Expand Up @@ -164,12 +186,6 @@ jobs:
timeout-minutes: 7
run: yarn ${{ matrix.build-command }}

- name: Install Playwright
uses: ./.github/actions/install-playwright
with:
browsers: chromium
cwd: ${{ runner.temp }}/test-application

- name: Run E2E test
working-directory: ${{ runner.temp }}/test-application
timeout-minutes: 15
Expand Down
Loading
Loading