This is an automated email from the ASF dual-hosted git repository.
sadpandajoe pushed a commit to branch chore-reduce-playwright-calls
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/chore-reduce-playwright-calls
by this push:
new 65bc3bbbedd chore(ci): collapse Playwright experimental workflow into
E2E playwright-tests
65bc3bbbedd is described below
commit 65bc3bbbedd004bfe95243fc640be3260e3da0de
Author: Joe Li <[email protected]>
AuthorDate: Fri Sep 25 10:04:39 2026 -0700
chore(ci): collapse Playwright experimental workflow into E2E
playwright-tests
Run the mobile Playwright specs as a step of the E2E playwright-tests job
and delete the separate "Playwright Experimental Tests" workflow, so each
PR runs a single Playwright job per app_root instead of two.
The experimental tier is removed: the only spec under tests/experimental
(Explore results-tab reuse) moves to tests/explore and runs with the
default project, and the INCLUDE_EXPERIMENTAL plumbing in
playwright.config.ts and bashlib.sh is dropped.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
---
.github/workflows/bashlib.sh | 6 +-
.github/workflows/superset-e2e.yml | 22 +-
.github/workflows/superset-playwright.yml | 222 ---------------------
superset-frontend/playwright.config.ts | 9 -
.../playwright/tests/experimental/README.md | 123 ------------
.../explore/results-tab-reuse.spec.ts | 14 +-
6 files changed, 25 insertions(+), 371 deletions(-)
diff --git a/.github/workflows/bashlib.sh b/.github/workflows/bashlib.sh
index 43f7d7a6505..332713e9b31 100644
--- a/.github/workflows/bashlib.sh
+++ b/.github/workflows/bashlib.sh
@@ -352,14 +352,10 @@ playwright-run() {
return 0
fi
echo "Running tests: ${TEST_PATH}"
- # Set INCLUDE_EXPERIMENTAL=true to allow experimental tests to run
- export INCLUDE_EXPERIMENTAL=true
npx playwright test "${TEST_PATH}" --output=playwright-results
local status=$?
- # Unset to prevent leaking into subsequent commands
- unset INCLUDE_EXPERIMENTAL
else
- echo "Running all required tests (experimental/ excluded via
playwright.config.ts)"
+ echo "Running all default-project tests"
npx playwright test --output=playwright-results
local status=$?
fi
diff --git a/.github/workflows/superset-e2e.yml
b/.github/workflows/superset-e2e.yml
index aa5826e17cb..d7a7336374c 100644
--- a/.github/workflows/superset-e2e.yml
+++ b/.github/workflows/superset-e2e.yml
@@ -204,9 +204,8 @@ jobs:
needs: changes
if: needs.changes.outputs.python == 'true' ||
needs.changes.outputs.frontend == 'true'
runs-on: ubuntu-26.04
- # Embedded Tests below adds its own gunicorn boot + spec run on top of
- # Required and Soft-delete; 30m was tight even for the two-step shadow
- # job this replaced.
+ # Soft-delete, Embedded and Mobile each add their own gunicorn boot +
+ # spec run on top of the Required step.
timeout-minutes: 40
permissions:
contents: read
@@ -381,6 +380,23 @@ jobs:
INCLUDE_EMBEDDED: "true"
with:
run: playwright-run "${{ matrix.app_root }}" embedded
+ - name: Run Playwright (Mobile Tests)
+ # cached-dependencies is a submodule (not a plain directory), and
+ # the $/ self-repository syntax resolves action files directly from
+ # the repository without performing a real (submodule-aware)
+ # checkout, so it can't see into a submodule's link. Keep this one
+ # on the workspace-relative ./ form, consistent with every other
+ # workflow in the repo that references this action.
+ uses: ./.github/actions/cached-dependencies # zizmor:
ignore[self-repository] - $/ cannot resolve an action that lives in a
submodule; ./ is required here
+ env:
+ NODE_OPTIONS: "--max-old-space-size=4096"
+ # Scoped to this step for the same reason as Soft-delete and
+ # Embedded above: the mobile consumption mode flag must not alter
+ # Flask's configuration for the other steps' servers.
+ SUPERSET_FEATURE_MOBILE_CONSUMPTION_MODE: "true"
+ INCLUDE_MOBILE: "true"
+ with:
+ run: playwright-run "${{ matrix.app_root }}" mobile/
- name: Set safe app root
if: failure()
id: set-safe-app-root
diff --git a/.github/workflows/superset-playwright.yml
b/.github/workflows/superset-playwright.yml
deleted file mode 100644
index bc0d31b522c..00000000000
--- a/.github/workflows/superset-playwright.yml
+++ /dev/null
@@ -1,222 +0,0 @@
-name: Playwright Experimental Tests
-
-on:
- push:
- branches:
- - "master"
- - "[0-9].[0-9]*"
- pull_request:
- types: [synchronize, opened, reopened, ready_for_review]
- workflow_dispatch:
- inputs:
- ref:
- description: "The branch or tag to checkout"
- required: false
- default: ""
- pr_id:
- description: "The pull request ID to checkout"
- required: false
- default: ""
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number ||
github.run_id }}
- cancel-in-progress: true
-
-permissions:
- contents: read
-
-jobs:
- changes:
- runs-on: ubuntu-26.04
- timeout-minutes: 10
- permissions:
- contents: read
- pull-requests: read
- outputs:
- python: ${{ steps.check.outputs.python }}
- frontend: ${{ steps.check.outputs.frontend }}
- steps:
- - name: Checkout
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #
v7.0.1
- with:
- persist-credentials: false
- - name: Check for file changes
- id: check
- uses: $/.github/actions/change-detector/
- with:
- token: ${{ secrets.GITHUB_TOKEN }}
-
- # NOTE: Required Playwright tests are in superset-e2e.yml (E2E /
playwright-tests),
- # including Embedded — it moved out of this workflow because embedding is a
- # required feature, not an experimental one. This workflow now contains
- # only experimental and mobile tests, which run in shadow mode.
- playwright-tests-experimental:
- needs: changes
- if: needs.changes.outputs.python == 'true' ||
needs.changes.outputs.frontend == 'true'
- runs-on: ubuntu-26.04
- timeout-minutes: 30
- continue-on-error: true
- permissions:
- contents: read
- pull-requests: read
- strategy:
- fail-fast: false
- matrix:
- browser: ["chromium"]
- app_root: ["", "/app/prefix"]
- env:
- SUPERSET_ENV: development
- SUPERSET_CONFIG: tests.integration_tests.superset_test_config
- SUPERSET__SQLALCHEMY_DATABASE_URI:
postgresql+psycopg2://superset:[email protected]:15432/superset
- PYTHONPATH: ${{ github.workspace }}
- REDIS_PORT: 16379
- GITHUB_TOKEN: ${{ github.token }}
- services:
- postgres:
- image: postgres:17-alpine
- env:
- POSTGRES_USER: superset
- POSTGRES_PASSWORD: superset
- ports:
- - 15432:5432
- redis:
- image: redis:7-alpine
- ports:
- - 16379:6379
- steps:
- # -------------------------------------------------------
- # Conditional checkout based on context (same as Cypress workflow)
- - name: Checkout for push or pull_request event
- if: github.event_name == 'push' || github.event_name == 'pull_request'
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #
v7.0.1
- with:
- persist-credentials: false
- submodules: recursive
- ref: ${{ github.event_name == 'pull_request' &&
github.event.pull_request.head.sha || github.sha }}
- - name: Checkout using ref (workflow_dispatch)
- if: github.event_name == 'workflow_dispatch' &&
github.event.inputs.ref != ''
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #
v7.0.1
- with:
- persist-credentials: false
- ref: ${{ github.event.inputs.ref }}
- submodules: recursive
- - name: Checkout using PR ID (workflow_dispatch)
- if: github.event_name == 'workflow_dispatch' &&
github.event.inputs.pr_id != ''
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #
v7.0.1
- with:
- persist-credentials: false
- ref: refs/pull/${{ github.event.inputs.pr_id }}/merge
- submodules: recursive
- # -------------------------------------------------------
- - name: Setup Python
- uses: $/.github/actions/setup-backend/
- - name: Setup postgres
- # cached-dependencies is a submodule (not a plain directory), and
- # the $/ self-repository syntax resolves action files directly from
- # the repository without performing a real (submodule-aware)
- # checkout, so it can't see into a submodule's link. Keep this one
- # on the workspace-relative ./ form, consistent with every other
- # workflow in the repo that references this action.
- uses: ./.github/actions/cached-dependencies # zizmor:
ignore[self-repository] - $/ cannot resolve an action that lives in a
submodule; ./ is required here
- with:
- run: setup-postgres
- - name: Import test data
- # cached-dependencies is a submodule (not a plain directory), and
- # the $/ self-repository syntax resolves action files directly from
- # the repository without performing a real (submodule-aware)
- # checkout, so it can't see into a submodule's link. Keep this one
- # on the workspace-relative ./ form, consistent with every other
- # workflow in the repo that references this action.
- uses: ./.github/actions/cached-dependencies # zizmor:
ignore[self-repository] - $/ cannot resolve an action that lives in a
submodule; ./ is required here
- with:
- run: playwright_testdata
- - name: Setup Node.js
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 #
v7.0.0
- with:
- node-version-file: "./superset-frontend/.nvmrc"
- cache: "npm"
- cache-dependency-path: "superset-frontend/package-lock.json"
- - name: Install npm dependencies
- # cached-dependencies is a submodule (not a plain directory), and
- # the $/ self-repository syntax resolves action files directly from
- # the repository without performing a real (submodule-aware)
- # checkout, so it can't see into a submodule's link. Keep this one
- # on the workspace-relative ./ form, consistent with every other
- # workflow in the repo that references this action.
- uses: ./.github/actions/cached-dependencies # zizmor:
ignore[self-repository] - $/ cannot resolve an action that lives in a
submodule; ./ is required here
- with:
- run: npm-install
- - name: Build javascript packages
- # cached-dependencies is a submodule (not a plain directory), and
- # the $/ self-repository syntax resolves action files directly from
- # the repository without performing a real (submodule-aware)
- # checkout, so it can't see into a submodule's link. Keep this one
- # on the workspace-relative ./ form, consistent with every other
- # workflow in the repo that references this action.
- uses: ./.github/actions/cached-dependencies # zizmor:
ignore[self-repository] - $/ cannot resolve an action that lives in a
submodule; ./ is required here
- with:
- run: build-instrumented-assets
- - name: Install Playwright
- # the $/ self-repository syntax resolves action files directly from
- # the repository without performing a real (submodule-aware)
- # checkout, so it can't see into a submodule's gitlink. Keep this one
- # on the workspace-relative ./ form, consistent with every other
- # workflow in the repo that references this action.
- uses: ./.github/actions/cached-dependencies # zizmor:
ignore[self-repository] - $/ cannot resolve an action that lives in a
submodule; ./ is required here
- with:
- run: playwright-install
- - name: Run Playwright (Experimental Tests)
- # cached-dependencies is a submodule (not a plain directory), and
- # the $/ self-repository syntax resolves action files directly from
- # the repository without performing a real (submodule-aware)
- # checkout, so it can't see into a submodule's link. Keep this one
- # on the workspace-relative ./ form, consistent with every other
- # workflow in the repo that references this action.
- uses: ./.github/actions/cached-dependencies # zizmor:
ignore[self-repository] - $/ cannot resolve an action that lives in a
submodule; ./ is required here
- env:
- NODE_OPTIONS: "--max-old-space-size=4096"
- with:
- run: playwright-run "${{ matrix.app_root }}" experimental/
- - name: Run Playwright (Mobile Tests)
- # cached-dependencies is a submodule (not a plain directory), and
- # the $/ self-repository syntax resolves action files directly from
- # the repository without performing a real (submodule-aware)
- # checkout, so it can't see into a submodule's link. Keep this one
- # on the workspace-relative ./ form, consistent with every other
- # workflow in the repo that references this action.
- uses: ./.github/actions/cached-dependencies # zizmor:
ignore[self-repository] - $/ cannot resolve an action that lives in a
submodule; ./ is required here
- env:
- NODE_OPTIONS: "--max-old-space-size=4096"
- # Scoped to this step: setting feature flags at the job level would
- # alter Flask's configuration for the preceding Experimental step
- # too — the mobile consumption mode should not do that.
- SUPERSET_FEATURE_MOBILE_CONSUMPTION_MODE: "true"
- INCLUDE_MOBILE: "true"
- with:
- run: playwright-run "${{ matrix.app_root }}" mobile/
- - name: Set safe app root
- if: failure()
- id: set-safe-app-root
- run: |
- APP_ROOT="${{ matrix.app_root }}"
- SAFE_APP_ROOT=${APP_ROOT//\//_}
- echo "safe_app_root=$SAFE_APP_ROOT" >> $GITHUB_OUTPUT
- - name: Upload Playwright Artifacts
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
# v7
- if: failure()
- with:
- path: |
- ${{ github.workspace }}/superset-frontend/playwright-results/
- ${{ github.workspace }}/superset-frontend/test-results/
- name: playwright-experimental-artifact-${{ github.run_id }}-${{
github.job }}-${{ matrix.browser }}--${{
steps.set-safe-app-root.outputs.safe_app_root }}
-
- actions-timeline:
- needs: playwright-tests-experimental
- if: always()
- runs-on: ubuntu-slim
- permissions:
- actions: read
- steps:
- - uses:
Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
- with:
- expand-composite-actions: true
diff --git a/superset-frontend/playwright.config.ts
b/superset-frontend/playwright.config.ts
index edbe94b326a..216336cf2a1 100644
--- a/superset-frontend/playwright.config.ts
+++ b/superset-frontend/playwright.config.ts
@@ -26,13 +26,6 @@ export default defineConfig({
// Test directory
testDir: './playwright/tests',
- // Conditionally ignore experimental tests based on env var
- // When INCLUDE_EXPERIMENTAL=true, experimental tests are included
- // Otherwise, they are excluded (default for required tests)
- testIgnore: process.env.INCLUDE_EXPERIMENTAL
- ? undefined
- : '**/experimental/**',
-
// Global setup - authenticate once before all tests
globalSetup: './playwright/global-setup.ts',
@@ -94,14 +87,12 @@ export default defineConfig({
// Default project - uses global authentication for speed
// E2E tests login once via global-setup.ts and reuse auth state
// Explicitly ignore auth tests (they run in chromium-unauth project)
- // Also respect the global experimental testIgnore setting
name: 'chromium',
testIgnore: [
'**/tests/auth/**/*.spec.ts',
'**/tests/sqllab/**/*.spec.ts',
'**/tests/embedded/**/*.spec.ts',
'**/tests/mobile/**/*.spec.ts',
- ...(process.env.INCLUDE_EXPERIMENTAL ? [] : ['**/experimental/**']),
],
use: {
browserName: 'chromium',
diff --git a/superset-frontend/playwright/tests/experimental/README.md
b/superset-frontend/playwright/tests/experimental/README.md
deleted file mode 100644
index 55a2399170a..00000000000
--- a/superset-frontend/playwright/tests/experimental/README.md
+++ /dev/null
@@ -1,123 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements. See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership. The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied. See the License for the
-specific language governing permissions and limitations
-under the License.
--->
-
-# Experimental Playwright Tests
-
-## Purpose
-
-This directory contains **experimental** Playwright E2E tests that are being
developed and stabilized before becoming part of the required test suite.
-
-## How Experimental Tests Work
-
-### Running Tests
-
-**By default (CI and local), experimental tests are EXCLUDED:**
-
-```bash
-npm run playwright:test
-# Only runs stable tests (tests/auth/*)
-```
-
-**To include experimental tests, set the environment variable:**
-
-```bash
-INCLUDE_EXPERIMENTAL=true npm run playwright:test
-# Runs all tests including experimental/
-```
-
-### CI Behavior
-
-- **Required CI jobs**: Experimental tests are excluded by default
- - Tests in `experimental/` do NOT block merges
- - Failures in `experimental/` do NOT fail the build
-
-- **Experimental CI jobs** (optional): Use `TEST_PATH=experimental/`
- - Set `INCLUDE_EXPERIMENTAL=true` in the job environment to include
experimental tests
- - These jobs can use `continue-on-error: true` for shadow mode
-
-### Configuration
-
-The experimental pattern is configured in `playwright.config.ts`:
-
-```typescript
-testIgnore: process.env.INCLUDE_EXPERIMENTAL
- ? undefined
- : '**/experimental/**',
-```
-
-This ensures:
-
-- Without `INCLUDE_EXPERIMENTAL`: Tests in `experimental/` are ignored
-- With `INCLUDE_EXPERIMENTAL=true`: All tests run, including experimental
-
-## When to Use Experimental
-
-Add tests to `experimental/` when:
-
-1. **Testing new infrastructure** - New page objects, components, or patterns
that need real-world validation
-2. **Flaky tests** - Tests that pass locally but have intermittent CI failures
that need investigation
-3. **New test types** - E2E tests for new features that need to prove
stability before becoming required
-4. **Prototyping** - Experimental approaches that may or may not become
standard patterns
-
-## Moving Tests to Stable
-
-Once an experimental test has proven stable (consistent CI passes over time):
-
-1. **Move the test file** from `experimental/` to the appropriate stable
directory:
-
- ```bash
- git mv tests/experimental/dataset/my-test.spec.ts
tests/dataset/my-test.spec.ts
- ```
-
-2. **Commit the move** with a clear message:
-
- ```bash
- git commit -m "test(playwright): promote my-test from experimental to
stable"
- ```
-
-3. **Test will now be required** - It will run by default and block merges on
failure
-
-## Current Experimental Tests
-
-### Dataset Tests
-
-- **`dataset/dataset-list.spec.ts`** - Dataset list E2E tests
- - Status: Infrastructure complete, validating stability
- - Includes: Delete dataset test with API-based test data
- - Supporting infrastructure: API helpers, Modal components, page objects
-
-## Infrastructure Location
-
-**Important**: Supporting infrastructure (components, page objects, API
helpers) should live in **stable locations**, NOT under `experimental/`:
-
-✅ **Correct locations:**
-
-- `playwright/components/` - Components used by any tests
-- `playwright/pages/` - Page objects for any features
-- `playwright/helpers/api/` - API helpers for test data setup
-
-❌ **Avoid:**
-
-- `playwright/tests/experimental/components/` - Makes it hard to share
infrastructure
-
-This keeps infrastructure reusable and avoids duplication when tests graduate
from experimental to stable.
-
-## Questions?
-
-See [Superset Testing
Documentation](https://superset.apache.org/docs/contributing/development#testing)
or ask in the `#testing` Slack channel.
diff --git
a/superset-frontend/playwright/tests/experimental/explore/results-tab-reuse.spec.ts
b/superset-frontend/playwright/tests/explore/results-tab-reuse.spec.ts
similarity index 89%
rename from
superset-frontend/playwright/tests/experimental/explore/results-tab-reuse.spec.ts
rename to superset-frontend/playwright/tests/explore/results-tab-reuse.spec.ts
index 6a08260d426..824c52a2137 100644
---
a/superset-frontend/playwright/tests/experimental/explore/results-tab-reuse.spec.ts
+++ b/superset-frontend/playwright/tests/explore/results-tab-reuse.spec.ts
@@ -24,16 +24,12 @@
* backend round-trip; the reuse-vs-fallback and row-limit slicing logic is
* unit-tested in useResultsPane.test.tsx, so this E2E asserts only the
* end-to-end win: opening Results issues no extra chart/data request.
- *
- * Lives under tests/experimental/ until proven stable in CI; run with:
- * INCLUDE_EXPERIMENTAL=true npm run playwright:test \
- * tests/experimental/explore/results-tab-reuse.spec.ts -- --headed
*/
-import { testWithAssets, expect } from '../../../helpers/fixtures';
-import { apiPostChart } from '../../../helpers/api/chart';
-import { getDatasetByName } from '../../../helpers/api/dataset';
-import { ExplorePage } from '../../../pages/ExplorePage';
-import { TIMEOUT } from '../../../utils/constants';
+import { testWithAssets, expect } from '../../helpers/fixtures';
+import { apiPostChart } from '../../helpers/api/chart';
+import { getDatasetByName } from '../../helpers/api/dataset';
+import { ExplorePage } from '../../pages/ExplorePage';
+import { TIMEOUT } from '../../utils/constants';
const DATASET_NAME = 'birth_names';
const CHART_DATA_PATH = '/api/v1/chart/data';