From 564ef599ab4dd7eb2dd55239ebbf3df6ab91d26c Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 3 Aug 2026 11:49:47 -0700 Subject: [PATCH 01/37] fix(ci): collapse Cypress e2e matrix from 2 runners to 1 (#42715) --- .github/workflows/bashlib.sh | 2 +- .github/workflows/superset-e2e.yml | 12 ++---------- scripts/cypress_run.py | 22 ++-------------------- 3 files changed, 5 insertions(+), 31 deletions(-) diff --git a/.github/workflows/bashlib.sh b/.github/workflows/bashlib.sh index e1b622b6afa..d36369f4353 100644 --- a/.github/workflows/bashlib.sh +++ b/.github/workflows/bashlib.sh @@ -256,7 +256,7 @@ cypress-run-all() { # UNCOMMENT the next few commands to monitor memory usage # monitor_memory & # Start memory monitoring in the background # memoryMonitorPid=$! - python ../../scripts/cypress_run.py --parallelism $PARALLELISM --parallelism-id $PARALLEL_ID --group $PARALLEL_ID --retries 5 $USE_DASHBOARD_FLAG + python ../../scripts/cypress_run.py --retries 5 $USE_DASHBOARD_FLAG # kill $memoryMonitorPid } diff --git a/.github/workflows/superset-e2e.yml b/.github/workflows/superset-e2e.yml index 4df02fd0984..9d50e7866ae 100644 --- a/.github/workflows/superset-e2e.yml +++ b/.github/workflows/superset-e2e.yml @@ -57,19 +57,13 @@ jobs: pull-requests: read strategy: # when one test fails, DO NOT cancel the other - # parallel_id, because this will kill Cypress processes + # app_root variant, because this will kill Cypress processes # leaving the Dashboard hanging ... # https://github.com/cypress-io/github-action/issues/48 fail-fast: false matrix: - parallel_id: [0, 1] browser: ["chrome"] app_root: ${{ github.event_name == 'push' && fromJSON('["", "/app/prefix"]') || fromJSON('[""]') }} - # The /app/prefix variant (push events only) is smoke-tested on a single - # shard rather than the full matrix, so exclude it from the other shards. - exclude: - - parallel_id: 1 - app_root: "/app/prefix" env: SUPERSET_ENV: development SUPERSET_CONFIG: tests.integration_tests.superset_test_config @@ -148,8 +142,6 @@ jobs: uses: ./.github/actions/cached-dependencies env: CYPRESS_BROWSER: ${{ matrix.browser }} - PARALLEL_ID: ${{ matrix.parallel_id }} - PARALLELISM: 2 CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} NODE_OPTIONS: "--max-old-space-size=4096" with: @@ -167,7 +159,7 @@ jobs: if: failure() with: path: ${{ github.workspace }}/superset-frontend/cypress-base/cypress/screenshots - name: cypress-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}-${{ matrix.parallel_id }}--${{ steps.set-safe-app-root.outputs.safe_app_root }} + name: cypress-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}--${{ steps.set-safe-app-root.outputs.safe_app_root }} playwright-tests: needs: changes diff --git a/scripts/cypress_run.py b/scripts/cypress_run.py index 3cf129bb2f9..66617049b2f 100644 --- a/scripts/cypress_run.py +++ b/scripts/cypress_run.py @@ -112,12 +112,6 @@ def main() -> None: action="store_true", help="Use Cypress Dashboard for parallelization", ) - parser.add_argument( - "--parallelism", type=int, default=10, help="Number of parallel groups" - ) - parser.add_argument( - "--parallelism-id", type=int, required=True, help="ID of the parallelism group" - ) parser.add_argument( "--filter", type=str, required=False, default=None, help="Filter to test" ) @@ -153,20 +147,8 @@ def main() -> None: ) print(f"Found {file_count} test files ({skipped_count} skipped).") - # Initialize groups for round-robin distribution - groups: dict[int, list[str]] = {i: [] for i in range(args.parallelism)} - - # Sort test files to ensure deterministic distribution - sorted_test_files = sorted(test_files) - - # Distribute test files in a round-robin manner - for index, test_file in enumerate(sorted_test_files): - group_index = index % args.parallelism - groups[group_index].append(test_file) - - # Only run tests for the group that matches the parallelism ID - group_id = args.parallelism_id - spec_list = groups[group_id] + # Sort test files for deterministic, readable run order. + spec_list = sorted(test_files) # Run each test file independently with retry logic or dry-run processed_file_count: int = 0 From d0503c1b9871bd6b6b7ef1508e356ff9939e7e46 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 3 Aug 2026 12:00:39 -0700 Subject: [PATCH 02/37] fix(dashboard): keep refresh_frequency set via the Advanced JSON editor (#42116) (#42142) Co-authored-by: Claude Opus 4.8 (1M context) --- .../PropertiesModal/PropertiesModal.test.tsx | 203 ++++++++++++++++++ .../components/PropertiesModal/index.tsx | 44 +++- superset/commands/dashboard/update.py | 18 +- superset/daos/dashboard.py | 67 +++++- .../integration_tests/dashboards/api_tests.py | 98 ++++++++- .../integration_tests/dashboards/dao_tests.py | 51 +++++ 6 files changed, 461 insertions(+), 20 deletions(-) diff --git a/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.tsx b/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.tsx index 0dc7b269a23..305a8597850 100644 --- a/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.tsx +++ b/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.tsx @@ -17,6 +17,7 @@ * under the License. */ import { + fireEvent, render, screen, userEvent, @@ -41,6 +42,30 @@ jest.mock('@superset-ui/core', () => ({ })), })); +// Mock the Advanced JSON editor (Ace-based, not drivable in jsdom) with a plain +// textarea so a direct JSON edit can be simulated. Keeps the "JSON Metadata" +// label so the existing "should open advance" test still passes. +jest.mock('./sections/AdvancedSection', () => ({ + __esModule: true, + default: ({ + jsonMetadata, + onJsonMetadataChange, + }: { + jsonMetadata: string; + onJsonMetadataChange: (value: string) => void; + }) => ( +
+ JSON Metadata +