- nightly workflow: reformat the Topology comment block (drop the
column-aligned space padding that read as "weird spaces").
- nightly workflow: hoist the stress cohort sizes (simpleReindex
tables/topics/dashboards/pipelines, searchAvailable tables) into
workflow_dispatch inputs with the current values as defaults, so
they're tunable from the Actions UI per run.
- remove openmetadata-integration-tests/REINDEX_TEST_PLAN.md — a
planning/tracking doc that doesn't belong in the repo.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Real bugs:
- UiTestServer: external mode (OM_URL+OM_ADMIN_TOKEN) now honours the
operator token instead of minting a local one the external server
won't trust; no TokenRefresher for the static external token.
- UiSession.uiUrl(): strip the /api REST base before appending UI
paths instead of relying on URI.resolve (fragile for relative paths
/ trailing-slash bases → /api/<route> 404s).
- CpuSampler.percentile(): index off (length-1); floor(p*length)
returned the max for small n, overstating p95.
- OidcEnvBuilder: keep OM's own JWKS in AUTHENTICATION_PUBLIC_KEYS
alongside the mock IdP's — SSO mode still validates OM-minted
internal/bot tokens.
- DataQualityDashboardPage.tryClickDimensionCard: stop swallowing
click/navigation failures as "card absent"; only true absence skips.
- UiSessionExtension: don't save a trace for TestAbortedException
(a skipped assumption is not a failure).
Robustness / cleanup:
- GoogleSsoBootstrapUIIT: build expected authority from
MockOidcServer.NETWORK_ALIAS/PORT instead of a hardcoded :1080.
- EntityLoaderSmokeUIIT: log load duration instead of asserting a
wall-clock bound (flaky on shared runners).
- ReindexHelpers.stopAppAndWait: drop unused stopRequestedAt.
- nightly workflow: dedupe apt package list.
- Javadoc fixes (UiSessionExtension AuthStrategy ref, IncidentManager
seed count 18 -> 20).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Workflow:
- Split into a build-image job that bakes openmetadata-server:jpw-snapshot
via docker/build-push-action with a shared GHA layer cache, then exports
the loaded image as a workflow artifact. Both matrix entries
(elasticsearch + opensearch) download + `docker load` the same image
and set OM_TEST_IMAGE so ContainerizedServer skips its own `docker build`.
Result: one image build per workflow run (was 2x duplicated dist build
+ per-launch in-test builds) and stable cross-matrix correctness — the
binary both shards run against comes from the exact same source SHA.
- workflow_dispatch input `includeSsoBootstrap` toggles whether the
@Tag("sso-bootstrap") SSO bootstrap UIITs run; default off because they
spin up their own ContainerizedServer (second OM lifecycle) for an env
wiring check that doesn't change between most runs.
- Slack notification migrated to slackapi/slack-github-action@v2 with the
incoming-webhook payload shape it now requires, and guarded behind
`env.SLACK_WEBHOOK_URL != ''` so a missing secret no-ops instead of
failing the post-step.
- Publish Test Report step set fail_on_test_failures=false — mvn verify
already gates the job conclusion, and a flake in the report action
shouldn't cascade into the Slack step.
Test fixes:
- SearchAvailableDuringReindexUIIT: baseline probe now asserts
`>= seeded.countOf(TABLE)` instead of strict equality. The OM container
is shared across the suite so the index can legitimately have residual
entities from earlier tests; assertEventualConsistency already checks
that none of *our* baseline entities go missing across the recreate.
- SimpleReindexTriggerUIIT: assertExploreCount now polls via Awaitility
with a 2-minute budget, re-opening the Explore page on every tick.
Playwright's `hasText` polled only the DOM, which wedges against a
stale aggregation cache; re-issuing the search aggregation on each
retry lets ES catch up after the alias swap.
Tagging:
- @Tag("sso-bootstrap") on GoogleSsoBootstrapUIIT + MockIdpSmokeUIIT, and
the `ui-it` profile now reads `ui.it.excludedGroups` (default
`sso-bootstrap`) so default `mvn verify -P ui-it` skips them. Pass
`-Dui.it.excludedGroups=` to include them.
Bugs
- IndexFieldExplosionIT: SCHEMA_ALIAS was `databaseSchema_search_index`; the
canonical indexMapping.json name is `database_schema_search_index`.
- ExplorePage:
- `tabTestId(GLOSSARY_TERMS)` produced `glossaries-tab`, but the UI builds
the testid from the i18n label (`Glossary Terms` → `glossary terms-tab`).
- `Tab.DASHBOARD_DATA_MODELS` path was `dashboardDataModels`; the Explore
route segment is singular (`dashboardDataModel`).
- Javadoc {@link} now points at the correct `openWithSearch` overload.
- UiSessionExtension: split video lifecycle so the `Video` handles are
snapshotted before `context.close()` (pages() is empty after close) but
`video.path()` is resolved AFTER close (Playwright finalises the file on
close — calling .path() earlier blocks/fails).
- GoogleSsoSignInUIIT: removed the empty alternative from the
`(my-data|explore|)` regex; it matched almost any post-auth URL and
weakened the assertion.
- MockOidcServer: still requires a single fixed port (token `iss` claim has
to match across container/host/browser), but the port is now overridable
via `-Dom.mockOidc.port=NNNN` and a fast pre-flight `ServerSocket` probe
fails clearly when the chosen port is busy. GoogleSsoSignInUIIT now reads
the port from `MockOidcServer.PORT` instead of hard-coding 1080.
Test hygiene
- SearchAvailableDuringReindexUIIT: replaced `Thread.sleep` polling with
Awaitility (`.atMost(REINDEX_TIMEOUT).pollInterval(PROBE_INTERVAL)`),
giving the loop a real deadline and removing the antipattern.
- ClipboardHelper: replaced the fixed `waitForTimeout(300)` with bounded
paste-retries until the hidden textarea has a non-empty value; textarea
cleanup moved to a `finally` block.
- SimpleReindexTriggerUIIT / SearchAvailableDuringReindexUIIT: defaults are
now PR-friendly (200/100/100/100 tables/topics/dashboards/pipelines and
500 tables respectively) overridable via system properties; the nightly
workflow sets the historical 5k stress numbers.
Quality
- DistributedAutoTuneReindexUIIT.distributedAutoTuneConfig now returns
`Map.of(...)` instead of a mutable `HashMap`.
- SearchQueryHelper.SearchProbe defensively copies `ids` / `uniqueIds` to
immutable collections in the canonical constructor.
- EntityLoader: every parameter and local that doesn't change is now
`final`.
- AuthAssumptions: `toLowerCase` calls now pin `Locale.ROOT` to stay stable
under Turkish / other surprising locales.
Docs
- PageObject javadoc: list of rules updated to reflect actual contract
(Page Objects may expose `Locator`-returning accessors, `rawPage()` is a
documented escape hatch).
- UI_TEST_CONVENTIONS.md: layering diagram now lists the real packages
(`playwright.scenarios`, `playwright.ui.pages`, `it.auth`, `it.server`).
Rule about Locator/Page softened to match the real contract. Headed-debug
recipe points at `:openmetadata-integration-tests` (the
`:openmetadata-java-playwright` module was removed). Stale references to
MIGRATION_TRACKING.md and SearchAfterReindexUIIT replaced with
REINDEX_TEST_PLAN.md and SimpleReindexTriggerUIIT.
- REINDEX_TEST_PLAN.md: helpers table now flagged as a planning shape with
an explicit list of what's shipped today vs. what's still aspirational.
- Install antlr4 CLI + native build deps in java-playwright PR and nightly
workflows (yarn install of openmetadata-ui runs the .g4 → JS codegen,
which fails with `antlr4: not found` otherwise).
- SearchClient: split combined IOException|InterruptedException catch so
only InterruptedException re-sets the interrupt flag; an IOException
shouldn't make unrelated higher-level code think the thread was
interrupted.
- SearchQueryHelper.probeIndex: URL-encode `query` and `indexAlias` before
splicing into the query string.
- OidcBackend.acquireToken: URL-encode DEFAULT_USER (contains `@`) and
DEFAULT_PASSWORD in the password-grant form body.
- openmetadata-integration-tests/pom.xml: mark Playwright dependency as
test-scoped.
Two coupled fixes for the ContainerFetchException seen in
https://github.com/open-metadata/OpenMetadata/actions/runs/26087848414:
1. ContainerizedServer.launch() now materialises the openmetadata-server
image at the very top via a new ensureServerImageAvailable() helper.
Previously runMigrations() ran first and tried to start a container
using the jpw-snapshot tag — testcontainers then attempted a registry
pull, fell over with ContainerFetchException, and the whole run failed
before newServer()/buildLocalImageContainer() had a chance to build
anything. The image build is now done once, before any container needs
the tag. Honors OM_TEST_IMAGE override (skips local build).
2. Nightly workflow gets an explicit "Build openmetadata-dist tarball"
step. The previous `mvn install -pl :openmetadata-integration-tests
-am` doesn't transitively build openmetadata-dist (not a test
dependency), so openmetadata-*.tar.gz was never produced — meaning
ensureServerImageAvailable() would still fail in CI at
locateDistTarball(). Added before the test run, after deps build.
Run the UI integration suite on demand while it stabilises; re-add the
schedule trigger once it is green on main.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Folds the UI integration test module into the canonical integration-tests
module under a `ui-it` Maven profile. One test home, one classpath, no
more test-jar reinstall dance or cross-module IntelliJ classpath quirks.
Why: most of the value the UI test module shipped was reusable backend
infra (factories, search helpers, server harness) that worked fine
without a browser. Keeping it in a separate module forced multiple
unnecessary boundaries — test-jar publication, IntelliJ test-classes-
jar-tests phantom paths, src/test placement for AuthBackend code that
should have been in src/main, "where does this test go?" friction.
Layout in integration-tests:
org/openmetadata/it/auth/ JwtAuthProvider + AuthBackend / OidcBackend
/ AuthSession / TokenRefresher / ...
org/openmetadata/it/server/ ContainerizedServer / ServerHandle /
ExternalServer / sso/ profile records
org/openmetadata/it/search/ ReindexHelpers / SearchClient /
SearchAssertions / SearchQueryHelper
org/openmetadata/it/ui/ SessionBrowser / UiSession /
UiSessionExtension / TraceRecorder /
ClipboardHelper / pages/
org/openmetadata/it/scenarios/ *UIIT.java tests
org/openmetadata/it/util/ SdkClients + UiTestServer / OssTestServer
org/openmetadata/it/factories/ existing + EntityLoader
Build:
- integration-tests pom gains com.microsoft.playwright:playwright
(test scope). Other testcontainers / jwt deps already there.
- test-jar publish-test-harness includes pattern expanded to ship
server/, search/, ui/ packages alongside auth/, util/, factories/,
bootstrap/. Downstream consumers (collate) inherit the full UI
test harness, not just backend factories.
- New `ui-it` profile runs `**/*UIIT.java` with skip.embedded.bootstrap
=true, PW_VIDEO=true, per-method parallel @ 0.5 factor. Mirrors the
failsafe execution from the old playwright module.
- Existing parallel-tests executions across all profiles gain a
`**/*UIIT.java` exclude so embedded-mode IT runs don't pick up UI
tests they can't run.
Module removal:
- openmetadata-java-playwright/ deleted.
- parent pom <modules> entry removed.
- .github/workflows/java-playwright-nightly.yml updated to build and
test `openmetadata-integration-tests -P ui-it` instead.
Docs:
- MIGRATION_TRACKING.md and CONVENTIONS.md from the old module are
UI_MIGRATION_TRACKING.md / UI_TEST_CONVENTIONS.md at the
integration-tests root.
No test code semantics changed — pure reorganization. The 4-5 backend-
flavored *UIIT.java tests we identified as misplaced (running against
SDK with vestigial UI checks) still live under scenarios/ for now; a
follow-up will rename them to *IT.java and have them target the
embedded TestSuiteBootstrap directly to drop their ~3-minute Docker boot
overhead.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First step of the SSO-flow testing initiative. Wraps navikt/mock-oauth2-server
as a testcontainer wired into the OM Docker network under alias om-mock-idp
on port 1080.
The same URL — http://om-mock-idp:1080/<issuer> — is used by:
- the OM container (via Docker network alias)
- the Playwright browser on the host (via /etc/hosts loopback entry)
- the iss claim in tokens issued by the mock IdP
so token validation, browser redirects, and OIDC discovery all line up
against one source of truth — required for the public/id_token flow where
the browser receives the token directly and iss is derived from the URL it
hit.
Setup cost: one /etc/hosts line (127.0.0.1 om-mock-idp), added once per
machine. CI workflow does it automatically. MockOidcServer.launch() throws
with a clear remediation message if the entry is missing.
MockIdpSmokeUIIT validates the network premise end-to-end: starts the
container standalone and confirms discovery + JWKS endpoints respond from
the host JVM with the expected om-mock-idp issuer URL.
Next (S1): SsoProfile sealed interface, ContainerizedServer.launch(profile)
overload, and the first Google SSO end-to-end test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>