Skip to content

perf(ci): use playwright ingestion_dependency in postgresql e2e#26893

Open
chirag-madlani wants to merge 4 commits intomainfrom
claude/inspiring-mcclintock
Open

perf(ci): use playwright ingestion_dependency in postgresql e2e#26893
chirag-madlani wants to merge 4 commits intomainfrom
claude/inspiring-mcclintock

Conversation

@chirag-madlani
Copy link
Copy Markdown
Collaborator

Changes

Updates the PostgreSQL E2E workflow to use playwright as the ingestion dependency instead of all.

File Modified:

  • .github/workflows/playwright-postgresql-e2e.yml
    • Changed ingestion_dependency from "all" to "playwright" (line 135)

Impact

This optimization reduces CI build time and resource usage by only installing playwright-specific dependencies rather than all available ingestion dependencies for this E2E test workflow.

Replaces `ingestion_dependency: "all"` with `"playwright"` which installs
only the connectors needed for E2E tests (mysql, bigquery, kafka, mlflow,
snowflake). Runs across all 6 shards so the savings compound.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 31, 2026 14:27
@chirag-madlani chirag-madlani requested a review from tutte as a code owner March 31, 2026 14:27
@github-actions github-actions bot added safe to test Add this label to run secure Github workflows on PRs UI UI specific issues labels Mar 31, 2026
- Cache Maven dependencies in shard jobs (restore from build job's cache)
- Cache Python venv keyed on setup.py/pyproject.toml hashes to skip
  repeated ingestion[playwright] installs across shards and reruns
- Cache Node modules (node_modules) keyed on yarn.lock; skip yarn install
  on cache hit
- Cache Playwright browser binaries keyed on playwright version; skip
  install on cache hit
- Bump CI workers from 3 to 4 to utilise all vCPUs on ubuntu-latest

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Optimizes the PostgreSQL Playwright E2E CI workflow by changing the ingestion container dependency set from the full all extra to the narrower playwright extra, aiming to reduce CI runtime/resources for this workflow.

Changes:

  • Update ingestion_dependency passed to the test-environment setup action from "all" to "playwright".

Comment on lines 133 to 136
python-version: "3.10"
args: "-d postgresql -s true"
ingestion_dependency: "all"
ingestion_dependency: "playwright"

Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ingestion_dependency input here only affects the Docker build arg (INGESTION_DEPENDENCY) used by docker/run_local_docker.sh (i.e., what gets installed inside the ingestion container). The composite action setup-openmetadata-test-environment still installs ingestion[all] + ingestion[test] in the runner venv unconditionally, so this change likely won’t deliver the “only install playwright-specific dependencies” CI-time reduction described unless that action is also updated (or the PR description clarifies the scope of the optimization).

Copilot uses AI. Check for mistakes.
@chirag-madlani chirag-madlani requested a review from a team as a code owner March 31, 2026 14:32
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-1.57.0
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Edge Case: Hardcoded Playwright version in cache key may drift from package.json

The Playwright browser cache key is hardcoded to playwright-1.57.0 (line 177), while the install command also hardcodes npx playwright@1.57.0. If @playwright/test is bumped in package.json, these hardcoded references will silently become stale, causing version mismatches between the test runner and cached browsers. Other workflows (e.g., playwright-mysql-e2e.yml) have the same pattern, so this is a pre-existing issue, but this PR is adding a new instance of it.

Suggested fix:

Consider deriving the version dynamically, e.g.:
  key: ${{ runner.os }}-playwright-${{ hashFiles('openmetadata-ui/src/main/resources/ui/yarn.lock') }}
Or extract the version into a workflow-level env var to reduce duplication.

Was this helpful? React with 👍 / 👎 | Reply gitar fix to apply this suggestion

The ingestion_dependency input was only passed to run_local_docker.sh
(Docker build arg) but the runner venv still installed ingestion[all]
unconditionally. Now both the Docker container and the runner venv
respect the same ingestion_dependency value.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 31, 2026 14:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

Comment on lines +138 to +151
- name: Cache Python venv
uses: actions/cache@v4
with:
path: env
key: ${{ runner.os }}-python-3.10-ingestion-playwright-${{ hashFiles('ingestion/setup.py', 'ingestion/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-python-3.10-ingestion-playwright-

- name: Setup Openmetadata Test Environment
uses: ./.github/actions/setup-openmetadata-test-environment
with:
python-version: "3.10"
args: "-d postgresql -s true"
ingestion_dependency: "all"
ingestion_dependency: "playwright"
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says the only change is switching ingestion_dependency in this workflow, but this PR also adds multiple caching steps, changes the composite action to install ingestion[${{ inputs.ingestion_dependency }}], and increases Playwright workers in playwright.config.ts. Please update the PR description (or split the PR) so reviewers understand the full scope and rationale for each change.

Copilot uses AI. Check for mistakes.
@@ -32,7 +32,7 @@ export default defineConfig({
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says “Opt out of parallel tests on CI”, but workers: process.env.CI ? 4 : undefined explicitly configures parallel workers on CI (and fullyParallel: true is enabled). Please update the comment to reflect the intended CI concurrency rationale (or adjust the config to match the comment).

Suggested change
/* Opt out of parallel tests on CI. */
/* Limit CI to a fixed number of workers to keep parallelism and resource usage predictable. */

Copilot uses AI. Check for mistakes.
Comment on lines 179 to 181
- name: Install Playwright Browsers
if: steps.cache-playwright.outputs.cache-hit != 'true'
run: npx playwright@1.57.0 install --with-deps
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the new cache/conditional, npx playwright@1.57.0 install --with-deps is skipped on cache hits. That changes the workflow semantics: --with-deps is also responsible for installing OS-level browser dependencies, which won’t happen on fresh runners if this step is skipped. Consider always running the deps installation (e.g., playwright install-deps) and only skipping the browser download, or just run install --with-deps unconditionally and rely on the cache to avoid re-downloading browsers.

Suggested change
- name: Install Playwright Browsers
if: steps.cache-playwright.outputs.cache-hit != 'true'
run: npx playwright@1.57.0 install --with-deps
- name: Install Playwright OS dependencies
run: npx playwright@1.57.0 install-deps
- name: Install Playwright Browsers
if: steps.cache-playwright.outputs.cache-hit != 'true'
run: npx playwright@1.57.0 install

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 31, 2026

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 64%
64.78% (58873/90868) 44.28% (30870/69713) 47.59% (9333/19609)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 31, 2026

🔴 Playwright Results — 2 failure(s), 18 flaky

✅ 3447 passed · ❌ 2 failed · 🟡 18 flaky · ⏭️ 223 skipped

Shard Passed Failed Flaky Skipped
🔴 Shard 1 453 1 1 2
🟡 Shard 2 616 0 3 32
🟡 Shard 3 617 0 3 27
🔴 Shard 4 616 1 7 47
🟡 Shard 5 586 0 1 67
🟡 Shard 6 559 0 3 48

Genuine Failures (failed on all attempts)

Pages/SearchIndexApplication.spec.ts › Search Index Application (shard 1)
Error: �[2mexpect(�[22m�[31mreceived�[39m�[2m).�[22mtoEqual�[2m(�[22m�[32mexpected�[39m�[2m) // deep equality�[22m

Expected: �[32mStringMatching /success|activeError/g�[39m
Received: �[31m"failed"�[39m
Pages/Entity.spec.ts › Tag Add, Update and Remove for child entities (shard 4)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeHidden�[2m(�[22m�[2m)�[22m failed

Locator:  locator('.column-detail-panel').locator('.tags-list').getByTestId('tag-PersonalData.SpecialCategory')
Expected: hidden
Received: visible
Timeout:  15000ms

Call log:
�[2m  - Expect "toBeHidden" with timeout 15000ms�[22m
�[2m  - waiting for locator('.column-detail-panel').locator('.tags-list').getByTestId('tag-PersonalData.SpecialCategory')�[22m
�[2m    18 × locator resolved to <div class="tag-item" data-testid="tag-PersonalData.SpecialCategory">…</div>�[22m
�[2m       - unexpected value "visible"�[22m

🟡 18 flaky test(s) (passed on retry)
  • Pages/UserCreationWithPersona.spec.ts › Create user with persona and verify on profile (shard 1, 1 retry)
  • Features/DataQuality/TestCaseIncidentPermissions.spec.ts › User with only VIEW cannot PATCH incidents (shard 2, 1 retry)
  • Features/DataQuality/TestCaseResultPermissions.spec.ts › User with only TEST_CASE.DELETE (no TABLE.DELETE) cannot DELETE results (shard 2, 1 retry)
  • Features/EntitySummaryPanel.spec.ts › should display summary panel for table (shard 2, 1 retry)
  • Features/Permissions/GlossaryPermissions.spec.ts › Team-based permissions work correctly (shard 3, 1 retry)
  • Flow/ExploreDiscovery.spec.ts › Should display deleted assets when showDeleted is checked and deleted is not present in queryFilter (shard 3, 1 retry)
  • Flow/ExploreDiscovery.spec.ts › Should not display soft deleted assets in search suggestions (shard 3, 1 retry)
  • Pages/Customproperties-part2.spec.ts › entityReferenceList shows item count, scrollable list, no expand toggle (shard 4, 1 retry)
  • Pages/DataContracts.spec.ts › Create Data Contract and validate for SearchIndex (shard 4, 1 retry)
  • Pages/DataContracts.spec.ts › Create Data Contract and validate for Database (shard 4, 1 retry)
  • Pages/DataContractsSemanticRules.spec.ts › Validate Owner Rule Any_In (shard 4, 1 retry)
  • Pages/Domains.spec.ts › Rename domain with tags and glossary terms preserves associations (shard 4, 1 retry)
  • Pages/Entity.spec.ts › Certification Add Remove (shard 4, 1 retry)
  • Pages/Entity.spec.ts › Inactive Announcement create & delete (shard 4, 1 retry)
  • Pages/ExplorePageRightPanel.spec.ts › Should perform CRUD and Removal operations for table (shard 5, 1 retry)
  • Features/AutoPilot.spec.ts › Agents created by AutoPilot should be deleted (shard 6, 1 retry)
  • Pages/ExploreTree.spec.ts › Verify Tags navigation via Governance tree and breadcrumb renders page correctly (shard 6, 1 retry)
  • Pages/ExploreTree.spec.ts › Verify Database and Database schema after rename (shard 6, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

@gitar-bot
Copy link
Copy Markdown

gitar-bot bot commented Apr 1, 2026

Code Review 👍 Approved with suggestions 0 resolved / 5 findings

Optimizes PostgreSQL e2e workflow runtime by leveraging Playwright ingestion dependency with caching and tuning. Consider hardcoding the Playwright version in the cache key to prevent drift from package.json, and review the five minor findings across test data handling and servlet implementations.

💡 Edge Case: Hardcoded Playwright version in cache key may drift from package.json

📄 .github/workflows/playwright-postgresql-e2e.yml:177 📄 .github/workflows/playwright-postgresql-e2e.yml:181

The Playwright browser cache key is hardcoded to playwright-1.57.0 (line 177), while the install command also hardcodes npx playwright@1.57.0. If @playwright/test is bumped in package.json, these hardcoded references will silently become stale, causing version mismatches between the test runner and cached browsers. Other workflows (e.g., playwright-mysql-e2e.yml) have the same pattern, so this is a pre-existing issue, but this PR is adding a new instance of it.

Suggested fix
Consider deriving the version dynamically, e.g.:
  key: ${{ runner.os }}-playwright-${{ hashFiles('openmetadata-ui/src/main/resources/ui/yarn.lock') }}
Or extract the version into a workflow-level env var to reduce duplication.
💡 Edge Case: FailedTestCaseSampleData uses rowKey="name" but rows lack a name field

In FailedTestCaseSampleData.component.tsx, the <Table> component uses rowKey="name" (line 274), but the rows data built by getSampleDataWithType (lines 146-153) creates objects keyed by column names from the sample data — there's no guaranteed name property on each row. If no column is literally called "name", every row gets undefined as its key, causing React duplicate-key warnings and potential rendering bugs when rows are added/removed.

Suggestion: Use the row index as the key instead, e.g., rowKey={(_, index) => index}.

Suggested fix
rowKey={(_, index) => String(index)}
💡 Bug: tableCustomSQLQuery re-executes full SQL to fetch failed row sample

In _get_custom_sql_failed_rows (line 394-405), the method calls self._run_results(sql_expression, ...) which re-executes the user's custom SQL query against the database a second time (the first execution happens during run_validation). For expensive queries this doubles execution cost. Additionally, unlike run_validation which calls is_safe_sql_query() before execution, the _get_custom_sql_failed_rows path relies on the fact that validation ran first — but fetch_failed_rows_sample is called from the mixin after validation, so this is safe in practice. The double-execution is the main concern.

💡 Edge Case: AddSqlQueryFormModal fetches table data even when testCase is undefined

In AddSqlQueryFormModal.component.tsx line 129-135, the useEffect checks if (testCase) but then calls fetchTableData(testCase?.entityFQN ?? ''). If entityFQN is undefined/empty, this calls getPartialNameFromTableFQN with an empty string, which will produce an empty FQN and make a failing API call to getTableDetailsByFQN(''). The error is caught and toasted, but it's a wasted network call and confusing UX.

Suggestion: Guard on testCase?.entityFQN being truthy before calling fetchTableData.

Suggested fix
useEffect(() => {
  if (testCase?.entityFQN) {
    fetchTableData(testCase.entityFQN);
    form.setFieldsValue({
      query: testCase.inspectionQuery,
    });
  }
}, [testCase]);
💡 Quality: McpCallbackServlet errorSink ByteArrayOutputStream is never read

In McpCallbackServlet.doGet(), a ByteArrayOutputStream errorSink is created (line 301) and wired into the response wrapper's getOutputStream() override to capture error output from the SSO handler. However, the captured bytes are never read or logged anywhere in the method — the error handling path only checks handlerWroteError.get() and capturedStatus.get() but discards the actual error body. This makes debugging SSO callback failures harder than necessary.

Suggestion: Log errorSink.toString(StandardCharsets.UTF_8) when handlerWroteError is true.

🤖 Prompt for agents
Code Review: Optimizes PostgreSQL e2e workflow runtime by leveraging Playwright ingestion dependency with caching and tuning. Consider hardcoding the Playwright version in the cache key to prevent drift from package.json, and review the five minor findings across test data handling and servlet implementations.

1. 💡 Edge Case: Hardcoded Playwright version in cache key may drift from package.json
   Files: .github/workflows/playwright-postgresql-e2e.yml:177, .github/workflows/playwright-postgresql-e2e.yml:181

   The Playwright browser cache key is hardcoded to `playwright-1.57.0` (line 177), while the install command also hardcodes `npx playwright@1.57.0`. If `@playwright/test` is bumped in `package.json`, these hardcoded references will silently become stale, causing version mismatches between the test runner and cached browsers. Other workflows (e.g., `playwright-mysql-e2e.yml`) have the same pattern, so this is a pre-existing issue, but this PR is adding a new instance of it.

   Suggested fix:
   Consider deriving the version dynamically, e.g.:
     key: ${{ runner.os }}-playwright-${{ hashFiles('openmetadata-ui/src/main/resources/ui/yarn.lock') }}
   Or extract the version into a workflow-level env var to reduce duplication.

2. 💡 Edge Case: FailedTestCaseSampleData uses rowKey="name" but rows lack a name field

   In `FailedTestCaseSampleData.component.tsx`, the `<Table>` component uses `rowKey="name"` (line 274), but the `rows` data built by `getSampleDataWithType` (lines 146-153) creates objects keyed by column names from the sample data — there's no guaranteed `name` property on each row. If no column is literally called "name", every row gets `undefined` as its key, causing React duplicate-key warnings and potential rendering bugs when rows are added/removed.
   
   Suggestion: Use the row index as the key instead, e.g., `rowKey={(_, index) => index}`.

   Suggested fix:
   rowKey={(_, index) => String(index)}

3. 💡 Bug: tableCustomSQLQuery re-executes full SQL to fetch failed row sample

   In `_get_custom_sql_failed_rows` (line 394-405), the method calls `self._run_results(sql_expression, ...)` which re-executes the user's custom SQL query against the database a second time (the first execution happens during `run_validation`). For expensive queries this doubles execution cost. Additionally, unlike `run_validation` which calls `is_safe_sql_query()` before execution, the `_get_custom_sql_failed_rows` path relies on the fact that validation ran first — but `fetch_failed_rows_sample` is called from the mixin after validation, so this is safe in practice. The double-execution is the main concern.

4. 💡 Edge Case: AddSqlQueryFormModal fetches table data even when testCase is undefined

   In `AddSqlQueryFormModal.component.tsx` line 129-135, the `useEffect` checks `if (testCase)` but then calls `fetchTableData(testCase?.entityFQN ?? '')`. If `entityFQN` is undefined/empty, this calls `getPartialNameFromTableFQN` with an empty string, which will produce an empty FQN and make a failing API call to `getTableDetailsByFQN('')`. The error is caught and toasted, but it's a wasted network call and confusing UX.
   
   Suggestion: Guard on `testCase?.entityFQN` being truthy before calling `fetchTableData`.

   Suggested fix:
   useEffect(() => {
     if (testCase?.entityFQN) {
       fetchTableData(testCase.entityFQN);
       form.setFieldsValue({
         query: testCase.inspectionQuery,
       });
     }
   }, [testCase]);

5. 💡 Quality: McpCallbackServlet errorSink ByteArrayOutputStream is never read

   In `McpCallbackServlet.doGet()`, a `ByteArrayOutputStream errorSink` is created (line 301) and wired into the response wrapper's `getOutputStream()` override to capture error output from the SSO handler. However, the captured bytes are never read or logged anywhere in the method — the error handling path only checks `handlerWroteError.get()` and `capturedStatus.get()` but discards the actual error body. This makes debugging SSO callback failures harder than necessary.
   
   Suggestion: Log `errorSink.toString(StandardCharsets.UTF_8)` when `handlerWroteError` is true.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 1, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test Add this label to run secure Github workflows on PRs UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants