mirror of
https://github.com/open-metadata/OpenMetadata
synced 2026-05-24 09:39:11 +00:00
16392 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d3bbbefe37
|
fix(rdf): dedupe lineage edges, surface Fuseki failures, port distributed-mode improvements (#27999)
* fix(rdf): dedupe lineage edges and broaden PROV-O coverage
The RDF Knowledge Graph endpoint was emitting two edges per lineage
relationship — once as `om:UPSTREAM` (forward) and once as
`prov:wasDerivedFrom` (reverse) — because the parser preserved each
predicate's native subject/object orientation instead of canonicalizing
both into a single `(upstream, downstream)` edge.
Also extend PROV-O coverage so external SPARQL clients can use the W3C
Provenance vocabulary directly:
- `prov:Entity` / `prov:Activity` / `prov:Agent` class typing on
datasets / pipelines / users
- `prov:wasAttributedTo` mirror of `om:owners`
- `prov:generated` (inverse of existing `wasGeneratedBy`) and `prov:used`
on lineageDetails so the Entity → Activity → Entity chain is complete
- `prov:hadPlan` + `prov:Plan` for SQL transformation recipes
- `prov:startedAtTime` / `prov:endedAtTime` on Activity instances
- `prov:wasAssociatedWith` Activity → Agent linking
- `prov:invalidatedAtTime` on soft-deleted entities
Other RDF cleanups in the same area:
- LineageDetails URIs are now deterministic (driven by from/to ids
instead of a timestamp), so re-indexing collapses duplicate Activity
resources via the existing DELETE+INSERT idempotency
- Skip emitting the redundant `om:owners` JSON-string literal — the
mapped path already produces clean `om:hasOwner <agent>` triples
- Skip empty `[]` array literals in the unmapped path
- Propagate failures from `RdfRepository.{addRelationship,
addLineageWithDetails, bulkAddRelationships,
bulkAddGlossaryTermRelations}` instead of silently swallowing them,
so downstream callers can surface the failure
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(rdf-index-app): surface Fuseki failures in app run record
Per-entity and per-batch failures from the RDF index app used to be
logged via SLF4J only — they never made it into the AppRunRecord, so
the UI/run history showed "completed" even when every entity had
silently failed to write to Fuseki.
- `RdfBatchProcessor.processEntities` now captures the last error per
entity, returns it in `BatchProcessingResult.lastError`, and
accumulates relationship-processing failures into the same result.
- Relationship and lineage processing methods (`processBatchRelationships`,
`processLineageRelationship`, `processGlossaryTermRelations`) return
structured results with failure counts and last-error messages instead
of `void`, so failures are visible to the partition worker.
- `RdfIndexApp` records the failure on `jobData` for both the
distributed and non-distributed code paths, so users see a real
error message in the run history (e.g.
"Failed to write entity X to Fuseki: ConnectException").
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* perf(rdf-index-app): port distributed-mode improvements from SearchIndex
The RDF distributed-indexing fork was lagging behind several SearchIndex
improvements that addressed concrete reliability and throughput issues.
Port them across:
Core perf / reliability
- Precomputed partition start cursors: coordinator walks each entity
once via keyset pagination at job init and caches the boundary cursor
per (jobId, entityType, rangeStart). Workers consult the cache before
falling back to the OFFSET-based path. Eliminates the previous O(N²)
per-partition cursor lookup.
- `cancelInFlightPartitions` + `requestStop` + `checkAndUpdateJobCompletion`
on the coordinator. Stop now cancels both PENDING and PROCESSING
partitions in a single SQL update and immediately drives the job
status from STOPPING → STOPPED, so the UI status no longer hangs
while workers drain.
- Selective field hydration: `RdfPartitionWorker.readEntitiesKeyset`
uses `ReindexingUtil.getSearchIndexFields(entityType)` instead of
`List.of("*")`, avoiding expensive fetchers (e.g. fetchAndSetOwns)
per batch.
- Partition heartbeat thread: virtual thread refreshes
`lastUpdateAt` every 30s for partitions actively being processed by
this server, so the stale reclaimer no longer interrupts active work.
- `MAX_IN_FLIGHT_PARTITIONS_PER_SERVER = 5` backpressure: claim path
rejects when the server already holds 5 PROCESSING partitions, giving
fair distribution across pods. Verified the existing claim DAO uses
`FOR UPDATE SKIP LOCKED` for both MySQL and Postgres.
- Gate WebSocket stat broadcasts during the STOPPING phase so the
Quartz-scheduler-driven STOPPED status push isn't overwritten.
Multi-server scaffolding (single-pod is unaffected)
- `RdfPollingJobNotifier`: DB-polling discovery for other server pods
to find an in-flight RDF reindex they can join.
- `RdfEntityCompletionTracker`: per-entity-type partition tracking with
callback firing once all partitions for an entity complete, foundation
for early per-entity index promotion.
Tests: precomputed-cursor cache lookup, in-flight backpressure,
cancelInFlight delegation, completion tracker callback semantics,
notifier start/stop.
DAO additions on `rdf_index_partition`:
- `cancelInFlightPartitions(jobId, now)` — covers both PENDING and
PROCESSING in one statement
- `countInFlightPartitionsForServer(jobId, serverId)` — backpressure
- `countPartitionsByStatus(jobId, status)` — used by completion check
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ui-apps): hide misleading data on synthetic 'CurrentConfig' row
When an app has no run history, AppRunsHistory fabricated a synthetic
placeholder row that looked like a real run — `runType: "CurrentConfig"`,
a fake `Run At` timestamp pulled from `appData.updatedAt`, an
ever-growing `Duration` (`now − updatedAt`), and an active `Stop` button
that targeted nothing.
Render `--` for `Run At`, `Run Type`, and `Duration` on synthetic rows,
and hide the `Stop` button so users no longer see "Run now → 19-minute
Running with Stop button" when the actual job never registered. Real
app runs are unaffected — they still display `runType` from the
backend (OnDemandJob, Hourly, Daily, Custom, etc.).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(rdf): address PR review findings
Four issues raised in PR #27999 review:
- **Cursor format consistency in walkAndRecord** (bug):
The defensive branch produced cursors via a custom `{name, id}` map
while the regular path used `repo.getCursorValue()`. For entities
with quoted names these encodings diverge — a quoted-name entity
could land in the cache with a cursor incompatible with what the
worker fetches via keyset pagination. Track the last seen entity
reference and run it through `repo.getCursorValue()` in both paths.
`encodeBoundaryCursor` is removed.
- **Adaptive scheduling in RdfPollingJobNotifier** (perf):
The previous implementation woke the scheduler thread every 1s and
short-circuited inside the poll method when idle. Reschedule the
task at the appropriate interval (1s active / 30s idle) when
`setParticipating` flips, so the thread genuinely sleeps when idle.
- **Cursor cache cleanup on startup recovery** (edge case):
`partitionStartCursors` was only evicted by `refreshAggregatedJob`
/ `checkAndUpdateJobCompletion`. If a coordinator crashed mid-job
and never reached either, the cache entry leaked until process
restart. Add `evictStaleCursorCacheEntries()` invoked by
`performStartupRecovery` that drops entries for jobs that no longer
exist in the DB or are already terminal.
- **Consolidate describeError helpers** (quality):
`describeError`, `describeBulkError`, and `describeLineageError` in
`RdfBatchProcessor` all walked the cause chain and formatted a
prefixed message with the same logic. Reduced to a single
`describeError(prefix, error)` plus a thin `describeEntityError`
adapter for the per-entity call site.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(rdf-index-app): avoid double workerExecutor.shutdownNow() in stop()
stop() called workerExecutor.shutdownNow() inline AND through
cleanupLocalExecution -> shutdownWorkerExecutor, which broke the
DistributedRdfIndexExecutorTest.stopAndCoordinatorCleanupOnlyTearDownLocalExecutionOnce
verify(workerExecutor, times(1)).shutdownNow() expectation. Drop the
inline call — cleanupLocalExecution is the single owner of the
shutdown path.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* ci: drop redundant DB matrix from openmetadata-service unit tests
The {mysql, postgresql} strategy matrix on openmetadata-service unit
tests doubled CI cost without adding signal: both jobs ran the same
surefire suite. The `-Pmysql` / `-Ppostgresql` profiles are defined
only in `openmetadata-sdk/pom.xml` (lines 190-206), set a single
`test.database` property, and that property is consumed exclusively by
the failsafe plugin (integration tests `*IT.java` / `*IntegrationTest.java`),
which only runs under `-Pintegration-tests` — not enabled here.
`openmetadata-service` itself has zero tests that read `test.database`
or use `MySQLContainer`/`PostgreSQLContainer` (verified by grep). The
only testcontainer-based DB code in the repo lives in
`openmetadata-integration-tests`, a different module that this workflow
doesn't build.
Run the unit suite once. The `openmetadata-service-unit-tests-status`
required-check aggregator is unaffected (it depends on the renamed job
which still has the same name).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(rdf): address Copilot PR review findings
Six correctness issues raised on PR #27999:
- **Lineage-details DELETE was too broad** (RdfRepository): the cleanup
step deleted *all* `<fromUri> om:hasLineageDetails ?d` triples,
so reindexing one (fromId, toId) edge wiped lineage-details links
for every other downstream of the same source entity. Pin the
delete to the specific `<fromUri> om:hasLineageDetails <detailsUri>`
triple. Same with prov:generated cleanup — anchor it to the
specific detailsUri instead of any details resource.
- **Predicate not flipped during canonicalization** (RdfRepository):
`parseEntityGraphEdgesFromResults` swapped subject/object for
reverse-direction predicates (`prov:wasDerivedFrom`,
`prov:wasInfluencedBy`) but kept the original predicate URI on the
resulting EdgeInfo. Exported graphs could carry semantically
invalid triples like `<upstream> prov:wasDerivedFrom <downstream>`.
Add `forwardEquivalentPredicate` to substitute the OM-native
forward predicate when the direction flips.
- **`dct:modified` was an invalid xsd:dateTime** (RdfPropertyMapper):
`entity.getUpdatedAt().toString()` returns the epoch-millis Long as
a string, but the literal was tagged `xsd:dateTime`. Convert via
`Instant.ofEpochMilli(...).toString()` so the lexical form matches
the type — same fix already in place for prov:invalidatedAtTime.
- **Unmapped EntityReference arrays were dropped entirely**
(RdfPropertyMapper): the previous fix to skip noisy JSON-string
literals also dropped fields like `domains`, `reviewers`, `voters`
for entity contexts that don't have a JSON-LD mapping for them —
the unmapped path was the only path emitting them, so nothing
landed in RDF. Expand each array element through
`addEntityReference` so the data still produces proper
`om:<fieldName> <ref>` triples; mapped-path duplicates are
collapsed by Jena's Model dedupe.
- **Partition failure detection missed reader errors**
(DistributedRdfIndexExecutor): the EntityCompletionTracker was fed
`result.errorMessage() != null`, but `RdfPartitionWorker` can
increment `failedCount` from `readerErrors` without ever setting
`lastError`. Use `result.failedCount() > 0` so partitions whose
failures came from `ResultList.getErrors()` are also marked as
failed when promoting an entity.
- **`COMPLETED_WITH_ERRORS` was hidden when failedRecords == 0**
(RdfIndexApp): the coordinator marks a job COMPLETED_WITH_ERRORS
whenever any partition is FAILED or CANCELLED, including for
user-initiated stops where no record-level failures accrued. The
monitor's `completedWithErrors` gate required `failedRecords > 0`,
so those terminal states never hit `jobData.setFailure(...)` and
the run record showed success. Drop the failedRecords precondition
and tailor the fallback message based on whether there are
record-level failures or partition-level only.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(rdf): separate relationship failures + type lineage as prov:Activity
Two more PR review findings on #27999:
- **Relationship failures inflated failedRecords stat**: `processEntities`
was folding relationship/lineage edge failures into `failedCount`,
which becomes `failedRecords` in the index stats. Records there mean
entities, computed from entity counts in `totalRecords`. Counting
per-edge relationship failures could push `failedRecords` above
`processedRecords`/`totalRecords` and produce nonsensical
per-entity stats.
Track them separately: add `relationshipFailureCount` to
`BatchProcessingResult` and `PartitionResult`. `failedCount` now stays
entity-level. The completion tracker is fed the broader
`result.hasAnyFailure()` so partitions where relationship triples
failed don't get prematurely promoted as success even though their
entity writes succeeded.
- **`detailsResource` wasn't typed as prov:Activity**: the resource
carries Activity-shaped predicates (prov:startedAtTime,
prov:endedAtTime, prov:used, prov:hadPlan, prov:wasGeneratedBy,
prov:wasAssociatedWith) but only the OM-specific
`om:LineageDetails` rdf:type. Add an explicit
`rdf:type prov:Activity` so PROV-O reasoners and federated SPARQL
clients recognize it as an Activity without having to learn the
OM type.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(rdf): label lineage edges relative to focal node
The Knowledge Graph view was labeling every edge with relation
type "upstream" as "Upstream" regardless of direction relative to the
focal node. For a focal node F, the raw stored relation `(F, X, upstream)`
means "F is upstream of X" — i.e. X is *downstream* of F. The previous
output labeled both `F → X` and `X → F` edges as "Upstream", which made
bidirectional lineage look like a duplicated relation.
Re-orient the label in `convertEdgesToGraphData` based on whether the
focal is the edge's source or target:
- focal → X → "Downstream"
- X → focal → "Upstream"
- non-focal-touching edges keep the raw relation label.
Reported on a sample-data table with a circular lineage cycle
(`dim_customer ↔ fact_orders`) where both directions showed "Upstream".
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(rdf): close remaining Copilot review gaps
Three findings from PR #27999's third review pass — all about failure
signals being silently dropped between layers:
- **`RdfIndexApp.processTask` ignored relationship failures**: only
`result.failedCount() > 0` was treated as a failure, so partitions
whose Fuseki relationship/lineage writes failed (incrementing
`relationshipFailureCount` but not `failedCount`) never wrote
`jobData.failure`. Switch to `result.hasAnyFailure()` and report the
combined count.
- **`checkAndUpdateJobCompletion` ignored partition `lastError`**: a
partition can finish COMPLETED with `lastError` set when a relationship
bulk write was caught and recorded but didn't bump `failedRecords` or
flip the partition to FAILED. The job would then go to COMPLETED even
though there were real failures. Treat the presence of any
`rdf_index_partition.lastError` as an error signal — promote to
COMPLETED_WITH_ERRORS and aggregate sample errors into the job's
errorMessage if it was blank.
- **`forwardEquivalentPredicate` mapped to a non-existent
`om:DOWNSTREAM` URI**: OpenMetadata only stores lineage with
`om:UPSTREAM` (forward) and `prov:wasDerivedFrom` (reverse PROV-O
pair); there is no `om:DOWNSTREAM` predicate written anywhere — the
downstream view is derived by reading the same UPSTREAM edge from the
other side. Map both `prov:wasDerivedFrom` and `prov:wasInfluencedBy`
to `om:UPSTREAM` (both are reverse-direction causation predicates: in
`B wasDerivedFrom A` / `B wasInfluencedBy A` the source is A and
effect is B, so the canonical forward predicate is the same).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Fix RDF tag mapper
* Fix all the comments
Cherry-picked from #27562 (without bin/ autogenerated noise).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Align RdfPropertyMapper tests with refactor and isolate ontology export IT
RdfPropertyMapperTest still referenced the removed addVotes helper and
expected addStructuredProperty to dispatch votes — both gone after votes
was added to IGNORED_PROPERTIES. Update the assertions accordingly.
GlossaryOntologyExportIT timed out on the full suite because it flips a
global RDF singleton in @BeforeAll and each test blocks a server thread on
synchronous Fuseki writes. SAME_THREAD only serialized methods within the
class — concurrent classes still raced for server threads. Adding @Isolated
matches the pattern already used by RdfResourceIT for the same reason.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(rdf): align addCertification typing + relationType after predicate flip
Two findings on PR #27999 from the post-cherry-pick review pass:
- **`addCertification` mis-typed glossary-source certifications and
skipped skos:Concept**: it always emitted `om:Tag` regardless of
source, even though `resolveTagResource` returns a glossaryTerm URI
when the certification points at a glossary term. It also didn't add
`skos:Concept` (or the `createTypeResource("tag")` `skos:Concept` for
classification tags), so SPARQL queries filtering certification
targets by `a skos:Concept` missed them while `addTagLabel`-emitted
tags were findable. Mirror `addTagLabel`: branch on source
(`Glossary` vs `Classification`), emit the right primary type plus
`skos:Concept` (glossary) or `om:Tag` (classification), and include
`om:tagSource`.
- **`relationType` left stale after predicate flip**: when
`parseEntityGraphEdgesFromResults` flipped subject/object for a
reverse-direction predicate and rewrote `canonicalPredicate` to
`om:UPSTREAM`, it kept the original `relationType` derived from the
reverse predicate. So `prov:wasInfluencedBy` produced an EdgeInfo
with `relationType=downstream` + `predicate=om:UPSTREAM` —
internally inconsistent, and the mismatched `edgeKey` prevented
dedup against an existing UPSTREAM edge with the same endpoints.
Re-derive `relationType` from the canonical predicate after the
flip.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(rdf): close 2 review findings + add parser-helper unit tests
Two outstanding Copilot findings on PR #27999 plus targeted unit
coverage for the helpers that drive lineage canonicalization.
Findings:
- **`colLineageUri` collision risk** (RdfRepository): the deterministic
key replaced non-alphanumerics in `toColumn` with `_`, so distinct
column names (e.g. `a-b` vs `a_b`) collapsed onto the same URI, which
would lose / overwrite column-lineage resources during reindex.
Append the loop index as a tiebreaker so distinct columns keep
distinct URIs.
- **`createTypeResource` missing dprod prefix** (RdfPropertyMapper):
the `getNamespace` switch didn't recognize `dprod`, so
`RdfUtils.getRdfType("dataProduct")` (returns `dprod:DataProduct`)
produced an invalid `dprod:DataProduct` URI on the wire. Added the
`DPROD_NS = https://ekgf.github.io/dprod/` constant and a `dprod`
case in the switch.
Coverage:
- New `RdfParserHelpersTest` exercises the canonicalization helpers
via reflection: `isReverseDirectionPredicate` (recognizes
PROV-O causation predicates, ignores forward predicates),
`forwardEquivalentPredicate` (both `wasDerivedFrom` and
`wasInfluencedBy` collapse to `om:UPSTREAM` so dedup works),
`relativeRelationLabel` (focal-relative Upstream/Downstream
flipping with all the boundary cases — non-focal edges,
non-lineage relations, null focal).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(rdf): merge array contexts before per-field resolution
The third (low-confidence "suppressed") finding on review 4256830399
turned out to be a real duplication: when a field is mapped in one
context map of an array context but absent from another, the previous
processArrayContext ran processContextMappings once per map. The pass
where the field IS mapped emits the proper `om:hasOwner <ref>` triples
(plus `prov:wasAttributedTo`); the pass where the field is absent
falls through to processUnmappedField and emits an additional
`om:owners <ref>` triple. Net: two predicates for the same logical
relationship.
Verified on the live Fuseki: 113 `om:hasOwner` triples vs 112
`om:owners` triples — one set per pass.
Fix: flatten all context maps in the array into a single merged map
once, then iterate entity fields exactly once against that combined
view (later contexts win on key conflicts, matching JSON-LD context
merge semantics). Each field is resolved against the union of
mappings, so the unmapped fallback only fires for fields truly absent
from every context. Net effect: `prov:wasAttributedTo` count is
unchanged, `om:hasOwner` is unchanged, and the redundant `om:owners`
triples disappear.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(rdf): close 2 review findings on coordinator finalization race
Two findings from PR #27999 review 4259628860:
- **`checkAndUpdateJobCompletion` early-returned before lastError check
could promote**: `refreshAggregatedJob` already marks the job COMPLETED
when partitions all finish without `failedRecords`/`failedPartitions`,
so `checkAndUpdateJobCompletion`'s subsequent `if (job.isTerminal())`
short-circuit silently dropped the lastError signal. Move the
partition-lastError check INTO `refreshAggregatedJob` so both code
paths produce consistent terminal status — a partition that finished
COMPLETED but carries a non-null lastError now correctly promotes the
job to COMPLETED_WITH_ERRORS regardless of which finalizer wins the
race.
- **`completePartition` / `failPartition` overwrote CANCELLED state**:
the unconditional partition row update lost a concurrent Stop's
CANCELLED status if a worker finished its batch after the Stop
request landed but before noticing it. Add a status-guarded
`updateIfProcessing` DAO method (UPDATE ... WHERE id = :id AND
status = 'PROCESSING') and have both completion paths use it; if 0
rows update, log and skip the side effects (no server-stat increment,
no refreshAggregatedJob call) so the authoritative CANCELLED status
stays. Mirrors the pattern SearchIndex's coordinator uses for the
same race.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Pere Miquel Brull <peremiquelbrull@gmail.com>
|
||
|
|
3d6fd71de3
|
Fixes #27950: [Datalake] JSON columns incorrectly typed as STRING for empty dict values (#27951)
* fix: datalake JSON columns incorrectly typed as STRING for empty dict values * fix: wrap df_row_val with str() for strptime and parse calls to satisfy type checker * fix: address static check type errors and review comments in datalake utils * Restore debug logging, fix dead-code fallback, strengthen tests * Replace lexicographic max() with explicit type precedence in fetch_col_types |
||
|
|
a00a8dcdb4
|
test: enhance FailedTestCaseSampleData tests with mock Table component (#28028) | ||
|
|
97e3ae52db
|
Fixes #22916: Add chart-level lineage for Metabase connector (#26778)
Some checks are pending
Integration Tests - MySQL + Elasticsearch / Detect Changes (push) Waiting to run
Integration Tests - MySQL + Elasticsearch / integration-tests-mysql-elasticsearch (push) Blocked by required conditions
Integration Tests - PostgreSQL + OpenSearch / Detect Changes (push) Waiting to run
Maven Collate Tests / maven-collate-ci (push) Waiting to run
Integration Tests - PostgreSQL + OpenSearch / integration-tests-postgres-opensearch (push) Blocked by required conditions
Java Checkstyle / java-checkstyle (push) Waiting to run
Publish Package to Maven Central Repository / publish-maven-packages (push) Waiting to run
OpenMetadata Service Unit Tests / Detect Changes (push) Waiting to run
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (mysql) (push) Blocked by required conditions
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (postgresql) (push) Blocked by required conditions
OpenMetadata Service Unit Tests / k8s_operator-unit-tests (push) Blocked by required conditions
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests-status (push) Blocked by required conditions
* fix: add chart-level lineage for Metabase connector * refactor: extract _get_chart_entity helper and move lookups outside source_tables loop Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: update test_yield_lineage to assert chart-level lineage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: add type guards for chart-level lineage to satisfy basedpyright Guard chart lineage yields with isinstance(from_entity, Table) and None-check on chart_entity to produce type-safe generator yields, eliminating reportArgumentType and reportReturnType errors from the static-checks CI step. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: guard optional metabase lineage lookups * fix: normalize metabase lineage search results * test: cover metabase lineage fallback cases * build: use canonical Maven Central URL --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Sriharsha Chintalapani <harshach@users.noreply.github.com> |
||
|
|
6c30d82f4c
|
fix(security): pin libthrift, provided jsonschema2pojo, bump azure-kv/sjm/reactor-netty, exclude netty-epoll (#28010)
* fix(security): pin libthrift 0.23.0 and exclude Jackson 3.x from jsonschema2pojo-core
- Pin org.apache.thrift:libthrift to 0.23.0 in dependencyManagement.
apache-jena-libs:4.10.0 transitively pulls libthrift:0.19.0 which is
vulnerable to CVE-2026-43869 (fixed in 0.23.0).
- Exclude tools.jackson.core:jackson-core and jackson-databind from
jsonschema2pojo-core in common/pom.xml. jsonschema2pojo-core 1.3.x
switched its internal Jackson to 3.x; the existing exclusion only
covered the legacy com.fasterxml.jackson.core groupId, so 3.0.2 jars
were leaking into the runtime classpath despite our annotator code
using Jackson 2.x exclusively. Removes exposure to:
- GHSA-2m67-wjpj-xhg9
- CVE-2026-29062
- GHSA-72hv-8253-57qq (3.x line)
* chore(security): bump azure-security-keyvault-secrets and simple-java-mail to fix transitive CVEs
- com.azure:azure-security-keyvault-secrets 4.10.0 → 4.10.7
4.10.7 declares azure-core-http-netty 1.16.4, which uses
reactor-netty-http 1.2.16. Replaces the second source path of
reactor-netty-http 1.0.48 in the OM standalone dist.
Fixes CVE-2025-22227 (the azure-kv path).
- org.simplejavamail:simple-java-mail 8.12.2 → 8.12.6
Hygiene bump (4 patch versions). Note: simple-java-mail 8.12.6's
master pom still pins angus-mail to 2.0.3, so the actual angus-mail
fix for CVE-2025-7962 still relies on OM's existing
<angus-mail.version>2.0.4</angus-mail.version> dep-management entry,
which already wins for OM standalone (verified: openmetadata-1.12.7
dist already ships angus-mail-2.0.4.jar).
* fix(security): switch libthrift fix from version-pin to exclusion; expand reasoning comments
libthrift (CVE-2026-43869):
Replace the dependencyManagement pin to 0.23.0 with an explicit <exclusion>
on apache-jena-libs. OM's source tree has zero org.apache.thrift imports and
no references to RDF Thrift binary serialization (RDF_THRIFT, ThriftConvert,
RDFFormat.*THRIFT) — the only consumer of libthrift in our dep tree is Jena's
optional RDF Thrift I/O code path, which OM never exercises.
libthrift 0.23.0 was published 2026-05-08 and no Jena release yet ships it
(Jena 6.0.0 and 5.6.0 still ship libthrift 0.22.0, also vulnerable). Pinning
would force a Jena-uncertified libthrift onto code Jena tests with 0.22.0;
excluding the unused JAR is cleaner and self-cleaning when Jena bumps.
Lucene/Solr (also in this dep tree) already excludes libthrift for the same
reason — confirmed via lucene-solr-grandparent pom.
Jackson 3.x exclusion: expanded the comment in common/pom.xml to record the
upstream state (jsonschema2pojo-core 1.3.3 still pins jackson3.version=3.0.2)
and the verification that build succeeds with the exclusion.
* fix(security): mark jsonschema2pojo-core as <optional> instead of maintaining per-dep exclusion list
Per Copilot review on PR #28010 (line 66 of common/pom.xml): jsonschema2pojo-core
is build-time only — the annotator classes that reference it (PasswordAnnotator,
MaskedAnnotator, etc.) are invoked exclusively by the jsonschema2pojo-maven-plugin
at code-gen time, never on the runtime classpath of any deployed service.
Switch from a growing list of <exclusion> entries (which only caught the deps
known at the time each entry was added) to <optional>true</optional>. This stops
jsonschema2pojo-core AND every transitive dep it pulls — current and future —
from propagating to downstream consumers' runtime classpath.
Effect on the GHSA-2m67-wjpj-xhg9 / CVE-2026-29062 / GHSA-72hv-8253-57qq fix:
the jackson-core-3.0.2 / jackson-databind-3.0.2 jars (groupId tools.jackson.core)
no longer leak into the dist via this path. Verified:
$ mvn -pl openmetadata-service dependency:tree -Dincludes='tools.jackson.core:*,org.jsonschema2pojo:*'
(empty)
$ mvn -pl openmetadata-spec -am install -DskipTests
BUILD SUCCESS (annotator code-gen still works — jsonschema2pojo-maven-plugin
pulls jsonschema2pojo-core via its own <dependencies> block,
and adds common.jar there too via openmetadata-spec/pom.xml)
* fix(security): revert libthrift exclusion → pin to 0.23.0; Jena statically references TException
The exclusion broke RDF tests:
RdfInferenceConfigurationTest, RdfPropertyMapperTest,
SparqlBuilderNestedFieldsTest, SqlToSparqlTranslatorTest
fail with `Could not initialize class org.apache.jena.rdf.model.ModelFactory`
and `org/apache/thrift/TException` (NoClassDefFoundError).
Even though OM never calls RDF Thrift I/O directly, several Jena classes
(ModelFactory, PrefixMappingImpl, etc.) statically reference
org.apache.thrift.TException at class-init time. Removing libthrift fails
class loading on the very first use of any Jena Model.
The grep for `org.apache.thrift` in OM source missed this because the
references are in Jena's own bytecode, not OM's source.
Reverting the exclusion. Pinning libthrift to 0.23.0 in dependencyManagement
remains the only available fix:
- No Jena release ships the fix (latest 6.0.0 still uses 0.22.0;
libthrift 0.23.0 was published 2026-05-08).
- Exclusion breaks the build (above).
- Pinning forces the fixed version onto Jena's classpath; libthrift
maintains backwards-compatible binary protocol semantics, so Jena's
runtime usage continues to work. CI will validate.
In-pom comment expanded to record this discovery so the trade-off doesn't
get re-litigated next round.
* chore: shorten security comments in poms
* fix(security): exclude netty-transport-native-epoll from azure-core-http-netty
GHSA-rwm7-x88c-3g2p / CVE-2026-42577 (AWS Inspector reports HIGH). The bug is
in netty 4.2.x epoll; we ship 4.1.x. The advisory's machine-readable
vulnerable_version_range is < 4.2.13.Final (overly broad), which causes
scanners to flag 4.1.x even though the buggy code path was never in 4.1.
Bumping our netty to 4.2.13.Final is blocked by Azure SDK / gRPC / AWS SDK /
reactor-netty all targeting 4.1.x. Instead, exclude the Linux native binding
JAR (the only thing in our tree that is named io.netty:netty-transport-native-epoll)
so the flagged artifact stops shipping in the dist. Netty's standard pattern is
to call Epoll.isAvailable() and fall back to NioEventLoopGroup when the native
binding is absent — the exact same code path already used on macOS/Windows
deployments. netty-transport-classes-epoll (the Java classes, required by
reactor-netty/lettuce/AWS-netty-nio-client bytecode references) stays.
Verified:
mvn -pl openmetadata-service -am dependency:tree \
-Dincludes='io.netty:netty-transport-native-epoll'
-> empty (was: 4.1.133.Final-linux-x86_64)
* fix(security): align reactor-netty-http dep-mgmt pin to 1.2.16
Per Copilot review on PR #28010 (line 19): the bump of azure-kv to 4.10.7 was
described as bringing reactor-netty-http 1.2.16, but the existing dep-mgmt pin
to 1.2.14 was overriding the transitive (mvn dependency:tree confirmed 1.2.14
was the actual resolved version).
Bump the pin 1.2.14 → 1.2.16 to match what azure-core-http-netty 1.16.4 ships
transitively. Both are above the CVE-2025-22227 fix line (≥ 1.2.8), so this is
a pin-alignment cleanup, not a security delta.
* fix(security): switch jsonschema2pojo-core from <optional> to <scope>provided</scope>
Semantically more correct for a build-time-only dep. The annotator classes
(PasswordAnnotator, MaskedAnnotator, etc.) are invoked only by
jsonschema2pojo-maven-plugin at code-gen time in its own classloader; the
runtime classpath of any deployed service never needs jsonschema2pojo-core.
<scope>provided</scope> says exactly that:
- on compile + test classpath (so annotators compile)
- excluded from runtime / dist packaging by default
- not propagated to downstream consumers
Same scanner outcome as <optional>true</optional> — Jackson 3.x JARs still
don't ship in the dist — but cleaner expression of intent. CVE coverage
unchanged: GHSA-2m67-wjpj-xhg9, CVE-2026-29062, GHSA-72hv-8253-57qq.
Verified:
mvn -pl openmetadata-spec -am install -DskipTests → BUILD SUCCESS
mvn -pl openmetadata-service dependency:tree -Dincludes='tools.jackson.core:*,org.jsonschema2pojo:*' → empty
* fix(security): switch netty-epoll exclusion from dep-mgmt to per-direct-dep
Per Copilot review on PR #28010: the previous parent-pom dep-management entry
for azure-core-http-netty with <exclusion> on netty-transport-native-epoll
did work (verified via mvn dependency:tree — exclusion DOES propagate to
transitive resolution in dep-mgmt), but Copilot raised a concern that pinning
azure-core-http-netty to 1.16.4 would block future Azure SDK bumps if a newer
SDK requires a higher azure-core-http-netty.
Same refactor as already applied to ai-platform PR #669. Remove the parent
dep-mgmt entry; apply per-direct-dep <exclusions> on the 3 azure-* deps that
transitively bring azure-core-http-netty in openmetadata-service:
- azure-security-keyvault-secrets
- azure-identity
- azure-storage-blob
Exclusion now travels with whatever azure-core-http-netty version each SDK
chooses; SDK bumps are no longer blocked by a hardcoded version.
Verified: mvn -pl openmetadata-service dependency:tree -Dincludes='io.netty:netty-transport-native-epoll'
returns empty.
* fix(security): extend netty-epoll exclusion to azure-identity-extensions
Per gitar-bot review on PR #28010: add the netty-transport-native-epoll
<exclusion> to azure-identity-extensions for consistency with the 3 other
azure-* direct deps in openmetadata-service/pom.xml that already have it
(azure-security-keyvault-secrets, azure-identity, azure-storage-blob).
Defensive: today's resolution is already clean because Maven's
nearest-definition rule picks the directly-declared azure-identity:1.15.2
(with our exclusion) over the transitive azure-identity:1.7.1 brought by
azure-identity-extensions:1.0.0. Adding the exclusion here protects against
a future refactor that removes the direct azure-identity declaration.
Verified: mvn -pl openmetadata-service dependency:tree -Dincludes='io.netty:netty-transport-native-epoll'
still returns empty.
---------
Co-authored-by: Shailesh Parmar <shailesh.parmar.webdev@gmail.com>
|
||
|
|
7c844d77d2
|
Fix fast-uri Dependabot vulnerabilities in UI core components (#28020) | ||
|
|
f4cb7d0f14
|
feat(ingestion): add QuestDB database connector (#27604)
* feat(ingestion): add QuestDB database connector QuestDB speaks the PostgreSQL wire protocol but implements a minimal pg_catalog, so the default PG dialect queries fail on the CHAR->DOUBLE cast in pg_class.relkind. This connector routes SQLAlchemy inspection through information_schema and short-circuits constraint/index lookups (QuestDB has no PK/FK/unique/indexes), letting CommonDbSourceService handle the rest of the topology unchanged. - Fixed /qdb target in the psycopg2 URL regardless of databaseName (which remains the OpenMetadata display name) - get_database_names defaults to 'qdb' instead of 'default' - 12 unit tests + live-verified against QuestDB 9.3.5 on localhost:8812 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(questdb): address review feedback — rename to QuestDB, wire UI Code review fixes for PR #27604: Blockers resolved: - Rename Questdb -> QuestDB across schema, enum, Python classes, and all generated TS files. Matches peer connectors (PinotDB, DynamoDB) and the product's actual brand. Changing post-merge would be a breaking migration. - Remove sslConfig from schema. QuestDB's sslConfig was declared but never wired — ssl_manager.check_ssl_and_init is @singledispatch and has no QuestDBConnection registration, so enabling SSL in the UI was a silent no-op. Can be added in a follow-up with an explicit psycopg2 wiring. Warnings resolved: - authType now in schema's required array — was failing with opaque 401. - Delete dead queries.py (QUESTDB_TEST_GET_TABLES was defined but never imported). - Add bytea -> LargeBinary to the type map (verified via live information_schema probe against QuestDB 9.3.5 — all other native types normalize to standard PG names that were already mapped). - Complete type annotations on utils._get_table_names, _get_columns, _information_schema_type. - Dialect patch test now uses a real PGDialect_psycopg2 instance instead of a MagicMock dialect, so it catches signature drift against the real SQLAlchemy Inspector contract. Added a separate test that verifies get_table_names emits a query against information_schema.tables (not pg_catalog). - Add ingestion_logger() to utils.py with a debug log on dialect patching. - _empty_view_definition now returns None instead of "" to match how other dialects signal the absence of a DDL. Also fixes UI visibility (QuestDB was missing from the service picker): - Regenerate 15 TS enum files via json2ts.sh -> quicktype so the new DatabaseServiceType.QuestDB value flows through the UI. - Register service-icon-questdb.png in ServiceIconUtils.ts. - Add locales/en-US/Database/QuestDB.md connector form docs. - Add quicktype as a devDependency — json2ts.sh needs it and it wasn't installed. Docs: update skills/connector-building and skills/standards/registration to reflect reality — i18n locale files are not needed, icon + locale MD registration steps are, and Services.constant.ts is deprecated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * skill * fix(questdb): restore databaseSchema field for test connection test_connection_db_schema_sources reads service_connection.databaseSchema directly with no hasattr guard. Removing it from the schema in the prior review fix broke GetTables and GetViews steps: 'QuestDBConnection' object has no attribute 'databaseSchema' Restored as an optional string with a clearer description (defaults to public when unset). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix owners * add yaml * Update generated TypeScript types * Sync package.json and yarn.lock with main * Fix: ingestion files , Added Lineage for questdb tests and UI changes, Refactored code * FIX: python_checkstyle * Fix: test and unused param * Fix: yield_table enforcing tabletype to partition, Refactored lineage * Fix: Failing test and remove print statement * FIX: python_checkstyle and added error handling * FIX: Resolved comments * FIX: failing tests and schema cleaning * Minor change * Fix: Failing unit tests * Fix: Unit test unrelated changes ignored * FIX: tests * Fix: Failing test due to extra parameter in yaml --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Akash Verma <akashverma@Akashs-MacBook-Pro-2.local> Co-authored-by: Akash Verma <138790903+akashverma0786@users.noreply.github.com> |
||
|
|
6ac135dc7e
|
Fixes 21329: exclude temporal table period columns from autoClassification sampling (#27960)
* fix(azuresql): exclude temporal table period columns from sampling Query sys.columns for generated_always_type to detect SYSTEM_TIME period columns (ValidFrom/ValidTo) and skip them in both schema reflection (mssql/utils.py) and sample data fetching (AzureSQLSampler). Also moves the catalog round-trip inside the `if columns` guard to avoid the query when column filtering is not in use. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(azuresql): add unit tests for temporal column exclusion Adds sampler unit tests covering period-column filtering and NOT_COMPUTE_PYODBC exclusion. Adds a PII processor test case for temporal tables using single first-names to avoid non-deterministic NER matches. Corrects customers_sensitive expected tags to include address→PII.NonSensitive, which the classifier now correctly detects. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(azuresql): add full workflow integration test for temporal tables Replaces the isolated sampler unit test with an end-to-end integration test that registers the AzureSQL service, creates a system-versioned table, runs MetadataWorkflow then AutoClassificationWorkflow, and asserts that sample data excludes ValidFrom/ValidTo. Includes SQL permission prerequisites and troubleshooting guide in the module docstring. Teardown controlled by AZURE_SQL_CLEANUP env var (default: true). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix `spacy<3.8` for `ingestion/[dev]` --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
6068a10dbe
|
(feat)ui: migrate form builder in connection form (#27812)
* (feat)ui: migrate form builder in connection form * add core field support * fix failing test & fix checkstyle * fix failing test * improvise fields visibility * fix failing test * improve spacing * add password hint support * fix ui checkstyle * address gitar * fix oneOfField stale issues * address gitar along with test * fix failing sonar * array field type to ui-core and advanced config to accordion usage * address gitar * remove form bg, handle breadcrumb navigation * fix mocks * handle layout, spacing , bg color * handle bg colors * use core-components * fix checkstyle * radio buttons bg color and spacing * remove hideBgGrey prop * nit * add dedicated EmbeddedAddServicePage for askcollate route & fix checkstyle * add unit tests |
||
|
|
86e1d88386
|
security: Include branch name in security scan Slack alerts and fail only on high vulnerabilities (#27977)
* Add branch context to security scan Slack alerts and upload CSV findings summary * change failing severity from medium to high & address gitar * fix csv formatting * revert flattening changes |
||
|
|
7e0ee80c28
|
feat(search): add Google Gemini embedding provider (#27974)
Some checks are pending
Integration Tests - MySQL + Elasticsearch / Detect Changes (push) Waiting to run
Integration Tests - MySQL + Elasticsearch / integration-tests-mysql-elasticsearch (push) Blocked by required conditions
Integration Tests - PostgreSQL + OpenSearch / integration-tests-postgres-opensearch (push) Blocked by required conditions
Integration Tests - PostgreSQL + OpenSearch / Detect Changes (push) Waiting to run
Java Checkstyle / java-checkstyle (push) Waiting to run
Maven Collate Tests / maven-collate-ci (push) Waiting to run
OpenMetadata Service Unit Tests / Detect Changes (push) Waiting to run
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (mysql) (push) Blocked by required conditions
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (postgresql) (push) Blocked by required conditions
OpenMetadata Service Unit Tests / k8s_operator-unit-tests (push) Blocked by required conditions
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests-status (push) Blocked by required conditions
Publish Package to Maven Central Repository / publish-maven-packages (push) Waiting to run
* Add design: Google Gemini embedding client Adds a fourth embedding provider (google) alongside openai/bedrock/djl, using the Generative Language API with a single API key. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Add implementation plan: Google Gemini embedding client 7 tasks covering schema change + regen, client implementation, validation tests, error path tests, request shape tests, switch wiring, and final verification. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(spec): add google embedding provider config block Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(search): add GoogleEmbeddingClient with happy-path test Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(search): extract MODELS_PREFIX constant in GoogleEmbeddingClient The string "models/" appeared in both DEFAULT_BASE_URL and the buildRequestBody method. Extract it as a named constant per project standards. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(search): add constructor validation tests for GoogleEmbeddingClient Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(search): add blank model id test and clarify null-modelId workaround Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(search): add HTTP error and malformed response tests for GoogleEmbeddingClient * test(search): tighten empty values array assertion to check message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(search): verify Google embedding request URL, headers, and body shape Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(search): extract endpoint constant and harden extractBody helper Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(search): wire google embedding provider into SearchRepository switch * test(search): cover null dimension and custom endpoint, drop redundant comment Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Update generated TypeScript types * Remove internal planning docs from PR These were workflow scaffolding (design spec + implementation plan) generated by the superpowers brainstorming/planning flow; they belong in the local development trail, not the PR. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Address PR review comments - GoogleEmbeddingClient.buildRequest: handle endpoint with existing query string by switching the key separator from '?' to '&' as needed; document why the API key travels in the URL (Google Generative Language API requirement, not Bearer-header). - GoogleEmbeddingClient.extractErrorMessage: replace empty catch block with a trace-level log to comply with the 'no empty catch' standard. - elasticSearchConfiguration.json: clarify google.endpoint description so operators know it must be the full ':embedContent' URL, not a base URL. - GoogleEmbeddingClientTest.extractBody: await onComplete via CompletableFuture.get(5s) instead of relying on synchronous publisher delivery; surface onError properly. - New test: testEndpointWithExistingQueryStringUsesAmpersand verifies the '?' / '&' separator logic. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Update generated TypeScript types * Wire google embedding provider into openmetadata.yaml defaults - Add `google:` block under naturalLanguageSearch with env-var fallbacks (GOOGLE_API_KEY, GOOGLE_EMBEDDING_MODEL_ID, GOOGLE_EMBEDDING_DIMENSION, GOOGLE_API_ENDPOINT). - Update embeddingProvider option list comment to include "google". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Use gemini-embedding-001 default and pass outputDimensionality The previous default (text-embedding-004) is rejected on some Google projects with `404: not found for API version v1beta, or is not supported for embedContent`. Switch to gemini-embedding-001 — the current GA model, available at v1beta and broadly accessible. - GoogleEmbeddingClient.buildRequestBody: include outputDimensionality from the configured embeddingDimension. Required for gemini-embedding-001 (defaults to 3072 dims otherwise) and supported as a truncation hint by text-embedding-004. - elasticSearchConfiguration.json + openmetadata.yaml: change default embeddingModelId to gemini-embedding-001 and document the outputDimensionality semantics on the embeddingDimension field. - GoogleEmbeddingClientTest.testRequestBodyShape: assert outputDimensionality=768 in the captured body and use gemini-embedding-001 as the test fixture model. - SystemRepository.getEmbeddingConfigurationMessage: add a `google` case so /api/v1/system/status surfaces the configured model/endpoint instead of "Unknown provider 'google'". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Update generated TypeScript types * Guard against missing google config in SystemRepository diagnostic If `embeddingProvider=google` but the `google` config block is absent, calling `nlpConfig.getGoogle().getEndpoint()` would NPE and produce a misleading "Unable to determine embedding configuration" message. Add an explicit null check that yields a clear diagnostic instead. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Validate google.endpoint contains :embedContent at construction A custom endpoint missing the `:embedContent` action used to silently produce 404s at runtime. Fail fast at startup with a clear message showing the expected URL form, so misconfiguration surfaces in logs instead of in vector-search failures. - Update testCustomEndpointConstruction to use a valid full URL. - Add testCustomEndpointWithoutEmbedContentThrows. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(spec): add modelId chat field to google block Adds a `modelId` property to the natural-language-search `google` block, parallel to how the `openai` block exposes both `modelId` (chat) and `embeddingModelId` (embedding). This enables Gemini-based NLQ filter extraction (chat completions via :generateContent) on top of the existing embedding support. Default: gemini-2.5-flash. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Update generated TypeScript types * Update generated TypeScript types * trigger --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> |
||
|
|
2967a7f0a8
|
refactor: replace RouterUtils with ObservabilityRouterClassBase for navigation paths (#27956)
* refactor: replace RouterUtils with ObservabilityRouterClassBase for navigation paths * feat: migrate navigation to observabilityRouterClassBase in DataQuality and IncidentManager components * refactor: format navigation calls and imports for consistency across components * test: mark 'Pipeline Alert' and permission tests as slow |
||
|
|
41cfcf995e
|
chore(deps): bump fast-uri in /openmetadata-ui/src/main/resources/ui (#28004)
Some checks are pending
Integration Tests - MySQL + Elasticsearch / Detect Changes (push) Waiting to run
Integration Tests - MySQL + Elasticsearch / integration-tests-mysql-elasticsearch (push) Blocked by required conditions
Integration Tests - PostgreSQL + OpenSearch / Detect Changes (push) Waiting to run
Integration Tests - PostgreSQL + OpenSearch / integration-tests-postgres-opensearch (push) Blocked by required conditions
Java Checkstyle / java-checkstyle (push) Waiting to run
Maven Collate Tests / maven-collate-ci (push) Waiting to run
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests-status (push) Blocked by required conditions
OpenMetadata Service Unit Tests / Detect Changes (push) Waiting to run
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (mysql) (push) Blocked by required conditions
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (postgresql) (push) Blocked by required conditions
OpenMetadata Service Unit Tests / k8s_operator-unit-tests (push) Blocked by required conditions
Publish Package to Maven Central Repository / publish-maven-packages (push) Waiting to run
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.0 to 3.1.2. - [Release notes](https://github.com/fastify/fast-uri/releases) - [Commits](https://github.com/fastify/fast-uri/compare/v3.1.0...v3.1.2) --- updated-dependencies: - dependency-name: fast-uri dependency-version: 3.1.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
882ef3f8c5
|
add nlq to OpenMetadataApplicationConfig (#27988)
* add nlq to OpenMetadataApplicationConfig * move config under naturalLanguageSearch * openai client * Update generated TypeScript types --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Pere Miquel Brull <peremiquelbrull@gmail.com> |
||
|
|
0ff09b4915
|
Migrate FailedTestCaseSampleData table to core-ui Table component (#27985)
Some checks are pending
Java Checkstyle / java-checkstyle (push) Waiting to run
Maven Collate Tests / maven-collate-ci (push) Waiting to run
OpenMetadata Service Unit Tests / k8s_operator-unit-tests (push) Blocked by required conditions
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests-status (push) Blocked by required conditions
OpenMetadata Service Unit Tests / Detect Changes (push) Waiting to run
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (mysql) (push) Blocked by required conditions
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (postgresql) (push) Blocked by required conditions
* refactor(FailedTestCaseSampleData): migrate table to core-ui Table component - Replace Ant Design Table with core-ui Table (react-aria-components) - Add border wrapper tw:border tw:border-border-secondary tw:rounded-[10px] - Add 210px min-width on data cells with horizontal scroll - Add 8px padding on header and data cells - Center diff-type column content vertically and horizontally - Move all styles from .less file to tw: classes using theme tokens - Delete failed-test-case-sample-data.less Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix checkstyle --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
8570d36830
|
Migrate IncidentManager table to core-ui Table component (#27972)
* refactor(IncidentManager): migrate table to core-ui Table component - Replace Ant Design Table with core-ui Table (react-aria-components) - Use plain renderRow function (matching DataQualityTab pattern) with static Table.Cell children and Table.Body dependencies to fix status/ severity/assignee columns stuck at loading skeleton - Fix popover max-height distortion by adding popoverClassName prop to IncidentStatusPopoverShell and applying tw:!max-h-none via react-aria className override - Update unit test mock for @openmetadata/ui-core-components to include Table component - Update e2e selector from Ant Design .ant-table-tbody to data-testid based tbody tr selector Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix checkstyle * address gitar-bot comments * address comments --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
f3ef11cf50
|
fix: use useClipboard hook in CodeBlockComponent to fix clipboard on non-secure contexts (#28003) | ||
|
|
22a6c10072
|
Context center (#27558)
Some checks are pending
Integration Tests - MySQL + Elasticsearch / Detect Changes (push) Waiting to run
Integration Tests - MySQL + Elasticsearch / integration-tests-mysql-elasticsearch (push) Blocked by required conditions
Integration Tests - PostgreSQL + OpenSearch / Detect Changes (push) Waiting to run
Integration Tests - PostgreSQL + OpenSearch / integration-tests-postgres-opensearch (push) Blocked by required conditions
Java Checkstyle / java-checkstyle (push) Waiting to run
Maven Collate Tests / maven-collate-ci (push) Waiting to run
OpenMetadata Service Unit Tests / Detect Changes (push) Waiting to run
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (mysql) (push) Blocked by required conditions
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (postgresql) (push) Blocked by required conditions
OpenMetadata Service Unit Tests / k8s_operator-unit-tests (push) Blocked by required conditions
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests-status (push) Blocked by required conditions
Publish Package to Maven Central Repository / publish-maven-packages (push) Waiting to run
* Add Context Center: Migrate Knowledge Center , Images/ PDFs document support * Add Context Center: Migrate Knowledge Center , Images/ PDFs document support * Address PR #27558 review comments - KnowledgePageRepository: null-safe pageType in getHierarchyWithSearch and getHierarchyWithSearchForActivePage so the /search/hierarchy endpoint no longer NPEs when the pageType query param is omitted. The ES/OS client helpers already skip the pageType term when the value is null or empty, so this is a pure null-guard. - ContextFileResource.uploadFile: when a failure happens after the ContextFileContent row is created (e.g. inside extractionService.submit), the cleanup path now hard-deletes that content row so the DB is not left with an orphaned record. - ContextFileResource: replace the raw Content-Disposition string with a buildContentDisposition helper that emits both the legacy quoted filename= and the RFC 5987 filename*=UTF-8'' parameter with percent-encoded bytes, so international filenames round-trip while staying header-injection safe. sanitizeFileName also falls back to "download" on null/blank input. - ContextFileResourceTest: new cases for sanitizeFileName null/blank fallbacks and for buildContentDisposition ASCII/unicode/space/injection behaviour (18 tests, all passing). * Address copilot review comments on PR #27558 - AssetRepository.getByFqnPrefix: swap arguments so (assetType, fqnPrefix) matches the DAO signature — previous ordering always missed the index. - FolderResource / ContextFileResource getEntitySpecificOperations: return List.of() instead of null so callers iterating the returned list cannot NPE. - SearchUtils.getPageHierarchy: replace UUID.fromString with a parseUuid helper that returns null for missing/malformed values and logs a warning instead of failing the whole hierarchy response. - DaoListFilter: qualify the pageType column with the caller-provided tableName, rename getArticleCondition to getPageTypeCondition (legacy no-arg method kept as @Deprecated wrapper for compatibility). - Elastic/OpenSearch client processPageHierarchyHits: replace the per-hit getChildrenCountForPage search (N+1) with a single pass over the batch that derives childrenCount from pages whose parent is in the same result set. Also drops the now-unused helper and its throws clause. - openmetadata-sdk/pom.xml: mark JWT, JAX-RS client, Apache HttpClient, jakarta.json, parsson, and JUnit Jupiter as <optional>true</optional> so they don't leak into SDK consumers that only use the core client. - InMemoryAssetService: use the shared AsyncService executor for upload /read/delete instead of the JVM common ForkJoinPool. - sample-pricing.xlsx: replace the plain-text placeholder with a real minimal XLSX workbook so detection-based and extraction-based code paths see a valid Microsoft Excel 2007+ file. * Use one filters aggregation for page hierarchy childrenCount Follow-up to |
||
|
|
9956592b00
|
chore(security): bump deps to address reported CVEs (#27994)
* chore(security): bump deps to address reported CVEs - log4j 2.25.3 -> 2.25.4 (CVE-2026-34477/34478/34480) - jsonschema2pojo 1.2.2 -> 1.3.0 (CVE-2025-3588) - netty-bom 4.1.132 -> 4.1.133 (netty-codec/transport GHSAs) - azure-identity 1.14.0 -> 1.15.2 in openmetadata-service to align with parent dependencyManagement * fix: bump jsonschema2pojo to 1.3.1 to fix maven-plugin classpath 1.3.0 dropped its declared dep on plexus-utils, breaking the maven-plugin at runtime with NoClassDefFoundError on org/codehaus/plexus/util/DirectoryScanner. 1.3.1 restores it. 1.3.3 has a separate regression (IndexOutOfBoundsException in ValidRule), so 1.3.1 is the right pin. |
||
|
|
483461a003
|
Add migrations to ensure PII are really enabled (#27921)
This is especially needed for instances that had already upgraded to 1.12.0 onwards, those instaces skipped the migration cherry-picked in 1.12.6 |
||
|
|
459dfa30a5
|
Add missing Customsearch.md (#27968)
Co-authored-by: Akash Verma <akashverma@Akashs-MacBook-Pro-2.local> |
||
|
|
d4387aa644
|
feat: Add request access button for data product (#27973)
* feat: Add request access button for data product * Fix lint checks * fix lint issue and addressed comments * fix test |
||
|
|
19ca2b96c0
|
fix: migrate and polish TestSuite pipeline tab (#27914)
Some checks are pending
Integration Tests - MySQL + Elasticsearch / Detect Changes (push) Waiting to run
Integration Tests - MySQL + Elasticsearch / integration-tests-mysql-elasticsearch (push) Blocked by required conditions
Integration Tests - PostgreSQL + OpenSearch / Detect Changes (push) Waiting to run
Integration Tests - PostgreSQL + OpenSearch / integration-tests-postgres-opensearch (push) Blocked by required conditions
Java Checkstyle / java-checkstyle (push) Waiting to run
Maven Collate Tests / maven-collate-ci (push) Waiting to run
OpenMetadata Service Unit Tests / Detect Changes (push) Waiting to run
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (mysql) (push) Blocked by required conditions
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (postgresql) (push) Blocked by required conditions
OpenMetadata Service Unit Tests / k8s_operator-unit-tests (push) Blocked by required conditions
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests-status (push) Blocked by required conditions
Publish Package to Maven Central Repository / publish-maven-packages (push) Waiting to run
* fix(ui): migrate and polish TestSuite pipeline tab Migrate the TestSuite Pipeline tab to core-ui table primitives and align behavior with the ingestion table experience, including row actions, count rendering, header tooltip styling, and placeholder spacing. * fix checkstyle * fix failing tests * address comments * fix playwright checkstyle * remove unnecessary changes |
||
|
|
10f26581b8
|
chore(mcp): add server.json for MCP Registry publishing (#27982)
* chore(mcp): add server.json for MCP Registry publishing
Adds metadata for publishing openmetadata-mcp to the official MCP
Registry (registry.modelcontextprotocol.io). Aggregators like PulseMCP
scrape the official registry, so this single entry surfaces the server
across the ecosystem.
The server is self-hosted per deployment, so the streamable-http URL
uses an {openmetadata_host} template variable that clients resolve to
their own OpenMetadata hostname.
* chore(mcp): align server.json description with #27975 messaging
Reframes the registry description to match the "trusted context and
business semantics for AI" positioning from the README rebrand in #27975.
Also tightens the description to satisfy the schema's 100-char cap on
the field (the prior 506-char copy would have failed validation at
publish time) and adds websiteUrl pointing to the MCP docs page.
* chore(mcp): mark server.json description as the official MCP
The registry namespace (io.github.open-metadata/*) is invisible to users
browsing aggregators like PulseMCP — they see only title and description.
Calling out "Official OpenMetadata MCP" differentiates this canonical
entry from any community wrappers people might publish under other
namespaces.
* chore(mcp): clarify host variable supports custom ports
Many self-hosted OpenMetadata deployments run on the default :8585
without a reverse proxy. Spell that out in the openmetadata_host
variable description so users know they can include a port.
* fix
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
||
|
|
44ed018064
|
MINOR: add more logs in pbi for lineage (#27970)
* add more logs on lineage * minor fix * string literal fix * RUF010 exception * space fix --------- Co-authored-by: Satender K <satendra.kumar@getcollate.io> |
||
|
|
bb6c43768f
|
Migrate ColumnProfileTable from antd to core components Table (#27965)
* feat(profiler): migrate ColumnProfileTable from antd to core-ui Table Replaces the antd-based Table wrapper in ColumnProfileTable with the @openmetadata/ui-core-components Table primitive (react-aria-components foundation). Removes antd ColumnsType column definitions in favour of explicit Table.Row/Table.Cell render, adds client-side sort via SortDescriptor state, manual expand/collapse for nested columns via FlatRow flattening, and preserves data-row-key/expand-icon attributes for e2e selector compatibility. Ref: https://github.com/open-metadata/openmetadata-collate/issues/3837 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix checkstyle * refactor(profiler): replace inline style width constants with Tailwind classes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
7c93c1c54a
|
[UI] Migrate Observability Alerts table to core-ui components (#27906)
* feat(ui): migrate observability alerts table to core-ui components Move Observability Alerts page table rendering to openmetadata core-ui Table components and align column layout, loading behavior, and pagination divider handling. Update unit and existing pagination e2e coverage to validate action controls and table structure, and close issue #3837. * address gitar-bot comments * fix ui checkstyle * fix failing tests * fix playwright checkstyle * fix failing test * fix failing pagination tests |
||
|
|
a90e7729a6
|
refactor: streamline SchemaTable component and optimize related metrics form (#27959)
* refactor: streamline SchemaTable component and optimize related metrics form * fix row expansion issue on update --------- Co-authored-by: Harsh Vador <harsh.vador@somaiya.edu> |
||
|
|
4e24ba1d8b
|
fix(cli-e2e): use profileSampleConfig in profiler test builders (#27947)
PR #27184 (commit
|
||
|
|
219c5683fa
|
ISSUE #3032 (#27912)
* feat: move flat sampling to sampling config + dynamic sampling option * feat: move flat sampling on the backend to sample profile conifg object * feat: fix circular import * feat: align UI with new profiler config * feat: fix json schema * feat: align python imports with new schema path * feat: update migration to look at extension * feat: remove enable * feat: remove enable * feat: added titles to sample config * feat: generated ts classes * feat: addressed comments * feat: change sample config instantiation to match new structure * feat: removed backward compatible fields * feat: ran java linting * feat: updated imports to point to generated files * feat: added dynamic sampler resolution logic * feat: ran python linting * feat: remove duplicate migration * chore: merge upstream and clean conflicts * feat: update logic to support dynamic and static sampling * feat: adjust sample config call * feat: test for statis, dynamic, row count and tier methods * feat: more sample config unit tests * feat: added tests for metric and sampling * feat: added tests to validate fallback is not called i nmetric computers * feat: strengthen profiler validation tests * feat: fix sampling config * feat: fix sampling config * feat: fix sampling config * feat: generated typescript models * feat: fixed missing dq pipeline migration * feat: fixed static check * feat: fixed ci failures * feat: fixed ci failures * feat: fixed unit tests faioure and linting * feat: fixed integration tests failures * chore: fixe burstiq refactor * chore: fix trino ci failures * chore: revert baseline.json file * chore: fix sampler availabl burst iq changes * feat: added smart sampling radio button * feat: ignore static checks errors * feat: ran ts linting * feat burstiq infinite recursion issue with dynamic as default * feat: translate i8n keys * feat: fix failing tests |
||
|
|
b42c9ad3ba
|
Fixed the translations issues in AdvancedSearch description option (#27961)
* Fixed the translations issues in AdvancedSearch description option * nit |
||
|
|
4c07b28c82
|
Add alias marketplace (#27943)
* Add alias marketplace * wire fingerprint and embeddings in domain_index_mapping |
||
|
|
54ae549fc6
|
Fixes #27852: propagate tolerations from CronOMJob to scheduled OMJob (#27955)
CronOMJobReconciler.deepCopyPodSpec was copying nodeSelector but silently dropping tolerations when generating an OMJob from a CronOMJob template. Manual runs worked because they go straight through K8sPipelineClient.buildOMJob, but scheduled runs went through this deep-copy and lost the field, leaving pods Pending on tainted nodes. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
80375a7dc6
|
Add data access request support (#27879)
* Add DAR tasks
* Removed UI related changes of DAR
* nit
* Update generated TypeScript types
* fix linting issue
* Removed all languages changes
* nit
* removed white space
* add request data access button with owner/status conditions
* fix lint issue
* fix minor validation for data access button
* fix lint issue
* fix data access button visiable condition
* fix java lint checks and fix test cases
* nit
* fix test
* fix(tasks): model CreateTask.about as entityLink, validate target entity
Replace `about` (FQN string) + `aboutType` (string) with a single
`about` field of type entityLink (`<#E::{entityType}::{fqn}>`). The
resource layer parses the link and resolves it via
`Entity.getEntityReferenceByName(type, fqn, NON_DELETED)`, which
guarantees the target asset exists and is not soft-deleted.
Why: long-FQN data assets were rejected with `[query param name size
must be between 1 and 256]` because the modal was constructing a Task
`name` from the FQN. The `about` was modelled as a free string with
no schema validation that the target was a real, non-deleted entity.
The Threads API already uses entityLink for this exact purpose; tasks
now align with that pattern. The link is supplied as a hidden field
by the UI — users never see it.
Also fixes the missing `@ExtendWith(TestNamespaceExtension.class)` on
`DataAccessRequestIT` that caused four test failures in CI.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix unit test failure
* fix(test): await workflow stage transition in DataAccessRequestIT
The workflow advances the task from pending-workflow-start to review
asynchronously. Asserting on the object returned by create() was a
race condition. Use Awaitility to poll until the stage is review,
matching the pattern in IncidentTaskIntegrationIT.
---------
Co-authored-by: Sriharsha Chintalapani <harsha@getcollate.io>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Ram Narayan Balaji <ramnarayanb3005@gmail.com>
Co-authored-by: Ram Narayan Balaji <81347100+yan-3005@users.noreply.github.com>
|
||
|
|
b12506fc6d
|
Add container entity type (#27957)
* Add alias marketplace * wire fingerprint and embeddings in domain_index_mapping * add container entity to dataAssetEmbeddings * add container to VECTOR_INDEXABLE_ENTITIES * Move changes for marketplace to another PR |
||
|
|
e91c90c144
|
fix: validate custom property name charset (#27808)
* fix: validate custom property name charset
Tighten custom property name validation to block characters that break
downstream parsers, with verified empirical reproduction:
- `"` causes HTTP 500 on PUT /metadata/types/{id}
- `:` breaks CSV import — exporter writes `key:value;key:value`, importer
splits at first colon, treats prefix as the field name
- `^` breaks OpenSearch query when the name is in
searchSettings.searchFields — Lucene reads `^` as the boost separator
in `field^boost`
- `$` breaks CSV import via java.util.regex.Matcher.replaceAll which
interprets `$<letter>` as a backreference
Adds a `customPropertyName` definition in basic.json and switches
customProperty.json to reference it. Adds a defensive regex check in
TypeRepository.validateProperty so the API returns 400 with a clear
error message even if schema validation is bypassed.
Tests cover allowed-charset acceptance, the four blocked characters,
leading-character validation, max-length enforcement, and unbalanced
brackets.
* Update generated TypeScript types
* test: add schema-vs-Java consistency test for custom property name
Guards against drift between basic.json#customPropertyName and the
TypeRepository regex/length constants. If either side is updated
without the other, CI fails with a message pointing to both files.
The Java validator is kept (better error message + covers internal
callers that bypass the HTTP layer); the consistency test guarantees
the two definitions cannot drift.
* fix: extend custom property name charset after gap-coverage matrix
Re-ran the matrix on previously-untested chars (+ ? * ~ ` \) across all
17 property types × create/patch/CSV/search:
- + ? * ~ ` all pass cleanly on every operation × every property type — add to allow list
- \ fails CSV roundtrip for entityReference and entityReferenceList types
(escape inconsistency in CSV serialization) — add to block list
Updates the regex, schema description, Java validator error message, and
adds the new chars to the allow/block integration tests. Consistency
unit tests in TypeRepositoryTest continue to pass.
Final allow set: alphanumeric _ - . / & % # @ ! , ; = | ' + ? * ~ `
space ( ) < > [ ] { }
Final block set: " : ^ $ \
* Update generated TypeScript types
* updated the custom property name validation
* added name suffix in custom property name
* lint fixes
* include backslash in invalid char
Co-authored-by: Copilot <copilot@github.com>
* fixed the playwright issue
Co-authored-by: Copilot <copilot@github.com>
* lint fix
* fix check style
* Drop redundant Java validator for custom property name; tighten IT assertions
Schema is the single source of truth: jsonschema2pojo emits @Pattern + @Size
on CustomProperty.name from basic.json#/definitions/customPropertyName, and
@Valid on TypeResource.addOrUpdateProperty enforces them at the HTTP boundary.
The hand-written Pattern constant, validateCustomPropertyName, and the
schema-vs-Java sync test were duplicating that rule and could never reach the
HTTP user (Bean Validation always fires first via @Valid).
Tighten the new TypeResourceIT cases from assertThrows(Exception.class) to
assertThrows(InvalidRequestException.class) so a regression to a different
exception type or status code fails loudly.
* restrict few more special characters from Cp name
* minor fix
* Disallow & < > in custom property names; align IT cases
Schema-side counterpart to the UI changes in the previous two commits:
basic.json#/definitions/customPropertyName now blocks &, <, > alongside the
existing " : ^ $ \\. The DOMPurify pass on the UI sanitizes &, <, > into HTML
entities, which produced inconsistent persisted values; rejecting them at the
schema layer prevents that drift across all write paths.
IT updates:
- Drop &, <, > from the allowed-charset cases (and the "withMatched(pair)And<more>" composite)
- Add &, <, > to the disallowed-charset cases
- Drop "<" leading-character case (now covered as a disallowed character)
- Drop "<" / ">" unbalanced-bracket cases
* Update generated TypeScript types
* Close PATCH bypass for custom property name validation on Type
Bean Validation runs for the dedicated PUT /types/{id} (addOrUpdateProperty)
because the resource declares @Valid CustomProperty, and the createOrUpdate
path can't carry customProperties at all (CreateType schema doesn't include
the field). PATCH /types/{id} accepts an opaque JsonPatch, so @Valid never
reaches into the resulting customProperties[] — a JSON Patch like
[{"op":"add","path":"/customProperties/-","value":{"name":"bad:colon",...}}]
persisted bad-named properties (verified live: HTTP 200 before this fix).
Run Hibernate Validator programmatically inside TypeRepository.prepare() so
every write path enforces the schema-derived @Pattern / @Size / @NotNull on
each CustomProperty. The rule still lives only in basic.json — picked up via
the generated @Pattern annotation, executed via ValidatorUtil.validate.
Tests in TypeResourceIT:
- test_patchCannotAddCustomPropertyWithDisallowedName — seeds a valid property
to ensure /customProperties exists, then PATCHes appending a name with ':',
asserts InvalidRequestException and verifies the bad name is not persisted
- test_patchCanAddCustomPropertyWithValidName — guards against the fix
rejecting valid PATCH-driven additions
* Block * in custom property names — breaks ES field-path lookup
When the property name appears in extension.<propertyName>^boost entries of
searchSettings.searchFields, OpenSearch treats * as a field-path wildcard.
The literal * field never matches its own wildcard pattern, so the field
gets silently skipped from the query and Explore search returns no hit for
the value. Bisected against the running server: of 12 candidate Lucene-special
chars, only * actually breaks the mainline UI search flow. ? ~ ( ) { } [ ] /
! and space all returned hits via the searchFields path because OS looks up
the field literally and only treats * as a wildcard at that layer.
Updates the regex + description in basic.json/customProperty.json, the UI
regex in regex.constants.ts, the validation message across 19 locales, the
generated TS docstrings, the Playwright invalid-name fixtures and spec, and
the IT TypeResourceIT case (with*asterisk moves from allowed to disallowed).
* Validate only newly-added custom properties; isolate PATCH IT to fresh types
prepare() previously validated the entire customProperties[] on every Type
write. An upgraded instance with a legacy property whose name contained a
now-banned char would then reject any subsequent PUT/PATCH on that type,
even when the write only adds a different valid property. Move the name
validation into TypeUpdater.updateCustomProperties() and scope it to the
`added` list computed by recordListChange against the original entity. New
properties are still validated; pre-existing names are left alone.
Replace the IT PATCH cases' shared `topic` Type with a fresh, namespaced
entity-category Type per test (createEntityTypeForTest). The shared `topic`
was mutated concurrently by other tests in the class — combined with
PATCH's lack of per-type locking, that produced lost-update races and
flaky asserts. The fresh per-test type has customProperties: [] from
creation, so the patch sets the array directly without a seed property.
* chore: prettier formatting on the new asterisk-rejection test
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* docs: add + ? ~ ` to JSDoc allow-list to match the regex
* fix(it): request customProperties field on read-back in PATCH IT
Type.customProperties is a lazy field — TypeRepository.setFields only
populates it when the request URL includes ?fields=customProperties. The
default getTypeById helper omits the param, so the read-back always saw
customProperties == null. That made test_patchCanAdd... fail (the just-
persisted property wasn't visible) and made test_patchCannotAdd... pass
for the wrong reason (would have stayed green even if the bad name had
slipped through validation).
Add a fields-aware getTypeById overload and use it in both PATCH cases.
Empirically verified against the live server: good name returns 200 +
appears in customProperties, bad name returns 400 + does not.
* minor fix
* playwright test fix
* removed unecessary test
* blocked ~ and / from custom property name
* lint-fix
* Block / and ~ in custom property names (JSON Pointer reservations)
Forward slash and tilde are reserved by JSON Pointer (RFC 6901): / is the
path separator and ~ is the escape lead-in (~0 = ~, ~1 = /). Allowing
them in a property name shifts the burden onto every caller that builds
a JSON Patch by string interpolation; a raw `/extension/${propertyName}`
either splits into the wrong number of segments or contains an invalid
escape sequence, and the server applies the patch to the wrong key (or
400s outright).
This surfaced as a reproducible failure in the table-cp Playwright suite:
the preceding test ended with `path: \`/extension/${propertyName}\`` where
propertyName ended in `/`. The server addressed extension[name-without-/][""]
instead of extension[name-with-/], returned 400, and TableClass.patch
overwrote entityResponseData with the error body — stripping id and FQN.
The next test fell into the search-based navigation path with an empty
search term and timed out at 180s.
Tighten the schema regex in openmetadata-spec/.../basic.json#customPropertyName
to drop / and ~ from the allowed set; update the human-readable description
in basic.json and customProperty.json to call out the RFC 6901 reservation.
Move the with/slash and with~tilde cases from the allowed-charset IT to
the disallowed-charset IT in TypeResourceIT.
* Update generated TypeScript types
* Use fresh per-test Type in custom-property name validation IT
The five charset/length/lead-char tests added in this PR previously mutated
the shared built-in TABLE_ENTITY_TYPE under @Execution(CONCURRENT). The
PUT path acquires TYPE_PROPERTY_LOCKS so concurrent writes serialize, but
relying on that lock for test isolation is fragile — the PATCH-driven IT
in the same class already uses a per-test fresh Type via
createEntityTypeForTest(client, ns, ...) for exactly this reason
(see
|
||
|
|
ea65ce78bf
|
Fixes 27433: task page is being updated when user is already on same page and clicks on the new assigned task from bell icon. (#27903)
* fixed issue 27433 * updated code as per GitAR comments * updated code for UI check fails * added E2E test case for issue 27433 * fix(e2e): make task notification refresh test self-contained Replace hardcoded 'raw_order' search with a test-owned TableClass entity, remove fragile URL-splitting FQN extraction, and clean up the created task in afterAll to prevent residual data across test runs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * style(e2e): apply prettier and import organization to TaskNavigation spec Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * worked up comments by Rohit * updated test case as per review comment * added afterAll back as removing it will leave resources leaked in DB, as per GitAR --------- Co-authored-by: Satender <sommy@Satenders-MacBook-Pro.local> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
339b3dfb18
|
fix(security): upgrade Java dependencies to resolve CRITICAL and HIGH CVEs (#27940)
* fix(security): upgrade Java dependencies to resolve CRITICAL and HIGH CVEs
- jetty-http: 12.1.6 → 12.1.7 (HTTP Request Smuggling, CRITICAL)
- bcpkix/bcprov/bcutil-jdk18on: 1.80 → 1.84 (Crypto Signature Bypass + Timing Attack)
- postgresql: 42.7.7 → 42.7.11 (SCRAM-SHA-256 DoS)
- httpcore5-h2: pinned to 5.3.5 (HTTP/2 stream reset DoS)
- commons-compress: pinned to 1.26.0 (Infinite Loop DoS)
- jackson-core: 2.18.6 → 2.19.0 (async parser resource exhaustion)
- maven-shade-plugin: 3.5.1 → 3.6.0 (supports Java 22 MR-JAR in jackson-core 2.19.0)
- openapi-generator template override: jackson-version 2.17.1 → 2.19.0 in generated swagger pom
* fix(security): upgrade spring-web 6.2.11 → 6.2.18
* fix(security): align jackson-dataformat-yaml, feign, gson, logback versions
- jackson-dataformat-yaml: 2.17.2 → ${jackson.version} (2.19.0)
- feign-core: 13.2.1 → 13.5 (in openapi-gen template)
- gson: 2.10.1 → 2.11.0 (in openapi-gen template)
- logback-classic: 1.3.13 → 1.5.25 (in openapi-gen template)
* fix(security): use jackson 2.18.7 — highest clean 2.x with full ecosystem
2.19.0-2.21.0 all carry a HIGH (CVSS 8.7) vulnerability per Sonatype.
2.18.7 is the latest clean patch where all Jackson modules are released.
* fix(security): remove hardcoded jackson 2.17.2 override in k8s-operator, inherit 2.18.7 from root
* fix(security): upgrade gson 2.11.0 → 2.13.1 (Medium CVE)
* fix(security): replace 436-line pom.mustache with minimal stub
The openapi-generator-maven-plugin writes target/generated-sources/swagger/pom.xml
at build time with hardcoded jackson 2.17.1. Snyk --all-projects picks up every
pom.xml on disk and flags it as HIGH.
The generated pom.xml is never packaged into any JAR or Docker image — it is a
generator artefact. The actual runtime jackson version comes from the module pom
inheriting jackson.version=2.18.7 from the root. Replace the 436-line verbatim
upstream template (maintained just to change 2 version lines) with a 10-line
coordinate-only stub. The generated pom.xml will have no <dependencies> block,
so Snyk finds nothing to flag.
|
||
|
|
c24e5098ce
|
fix(playwright): unblock glossary bulk import after modal close (#27952)
* fix(playwright): unblock glossary bulk import delete loop after modal close
The trailing `getByRole('dialog').getByRole('img').click()` at line 267
fired after the bulk-import modal had already been closed and asserted
not visible. It would either miss or grab a residual Ant modal element,
leaving a `.ant-modal-mask` attached over the page. The mask was invisible
to the accessibility tree but intercepted pointer events, so the next
`settingClick` in the delete-properties loop hung waiting for the
`customProperties.glossaryTerm` card to become actionable until the 180s
test timeout.
Replace the bogus click with a `.ant-modal-mask` count assertion so the
next step only proceeds once the overlay has detached, and gate each
loop iteration on a `waitForURL` to the glossary-term detail page.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(playwright): use toBeAttached over .ant-modal-mask for modal close gate
Drop the `.ant-modal-mask` count assertion — it leaks a UI-library
internal class into the test and would match unrelated modals.
The bulk-import modal is mounted via `{isModalOpen && (...)}`
(BulkImportVersionSummary.component.tsx), so the entire overlay subtree
unmounts atomically when closed. Asserting the existing
`bulk-import-details-modal` testid is `not.toBeAttached()` waits for
that unmount and guarantees no backdrop is left intercepting clicks
— stronger than `not.toBeVisible()`, which would pass mid-animation
while the overlay wrapper is still in the DOM.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Siddhant <siddhant@MacBook-Pro-678.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
e48f3d7ead
|
Upvote/Downvote Icon Loses Primary Color on Blur After Liking Entity Page (#27898)
* Upvote/Downvote Icon Loses Primary Color on Blur After Liking Entity Page * fixed bg color * minor fix |
||
|
|
b837ade95a
|
docs(github): require issue link, design, tests, UI recording in PR template (#27891)
Expands `.github/pull_request_template.md` to require a linked issue, a high-level design (for large PRs), a structured Tests section (use cases, unit + coverage %, backend/ingestion integration tests, Playwright, manual steps), and a UI screen recording for any UI change. Adds a `/pr-checklist` skill that walks the template, gathers evidence, and drafts the PR body before opening via `gh pr create`. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
3beb1e020b
|
Improve cache warmup configuration and availability (#27948)
* Fix cache warmup app config rendering * Add optional relationship cache warmup * Restore relationship repository in warmup test * Update generated TypeScript types * Disable cache warmup when cache is unavailable * Address cache warmup review comments * Address Copilot cache warmup comments * Memoize app detail tabs --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> |
||
|
|
a136325cf0
|
fix: API response for TableColumnCountToBeBetween (#27900)
* Fix typo in tablecolumnCount Changes: - Remove redundant None checks for min/max bounds (already have defaults in base class) - Add type: ignore for Optional[float] comparison to satisfy type checker - Update test to assert exact result message instead of substring matching - Test now verifies full message format including min/max bound values |
||
|
|
adcdd345be
|
Fix recognizer inclusion based on language (#27919) | ||
|
|
f9d3c85d20
|
fix(search): restore live settings on per-entity promote path (#27920)
* Restore live index settings on per-entity distributed-promote path
DefaultRecreateHandler exposes two finalization paths:
- finalizeReindex(...) — centralized end-of-job promotion. Calls
applyLiveServingSettings + maybeForceMerge
before the alias swap, reverting the bulk
overrides (refresh_interval=-1, replicas=0,
async translog) back to live values
(refresh=1s, replicas=1, durable translog).
- promoteEntityIndex(ctx, ok) — per-entity promotion. Used by the distributed
search-indexer's "promote as soon as all
partitions for an entity complete" callback
(DistributedSearchIndexExecutor.promoteEntityIndex).
Swaps the alias and cleans up old indices —
but never restored live settings.
When an entity finishes its partitions before the final reconciliation
(typically the smallest entities — e.g. knowledge `page` with ~11 rows),
its index is promoted via the per-entity path, the alias swap succeeds,
and the bulk-build overrides become the new live settings. refresh_interval
stays at -1 in production, so live writes after the reindex are buffered in
the translog and never reach searchable segments until a manual _refresh.
Externally this surfaces as "create an article, hierarchy is empty until I
re-trigger reindex" — exactly the user-reported bug.
Mirror the finalizeReindex sequence by calling applyLiveServingSettings
(and maybeForceMerge for parity) at the top of the promote block in
promoteEntityIndex, before the alias swap.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Wire jobData into per-entity reindex promotion handler
DefaultRecreateHandler.applyLiveServingSettings reads from the handler's
jobData field (live + bulk index-settings overrides on the EventPublisherJob).
The per-entity distributed-promotion path in DistributedSearchIndexExecutor
created its own DefaultRecreateHandler instance and never called
withJobData(jobData) on it. With jobData=null, buildRevertJson returns null
and applyLiveServingSettings silently no-ops — meaning the previous fix
(
|
||
|
|
88b932a90d
|
Added Missing operators(Contains, Not Contains) for description (#27913)
* Added Missing operators(Contains, Not Contains) for description * addressed PR comment and fixed unit test * addressed gitar comment * fix playwright * lint fix * removed dead code |
||
|
|
3487bfbcaa
|
fix(reindex): Stop button + O(N²) cursor init in distributed mode (#27927)
* Distributed reindex: fix Stop button + O(N²) cursor init Two independent bugs in the distributed search-index pipeline that surface together as "stop does nothing, distributed mode hangs even on a single server" in production. Reproduced both with new tests and fixed. Bug 1 — requestStop only cancels PENDING partitions ==================================================== DistributedSearchIndexCoordinator.requestStop() called partitionDAO.cancelPendingPartitions(jobId), whose SQL is: UPDATE search_index_partition SET status='CANCELLED' WHERE jobId = :jobId AND status = 'PENDING' PROCESSING rows are untouched. workerExecutor.shutdownNow() (added in PR #27876) interrupts the worker threads, but the partition rows the threads were holding stay PROCESSING in the DB. checkAndUpdateJobCompletion needs pending.isEmpty() && processing.isEmpty() to flip STOPPING → STOPPED; PROCESSING never empties because nothing updates the rows. Symptom: strategy's monitorDistributedJob loops forever waiting for a terminal status, the AppRunRecord never finalizes, the UI keeps showing "Running" with a ticking timer based on now() - startTime. Fix: - New SQL `cancelInFlightPartitions` covering PENDING + PROCESSING. - requestStop calls cancelInFlightPartitions and immediately invokes checkAndUpdateJobCompletion to drive STOPPING → STOPPED in-call rather than waiting for the next monitor tick. Test: testRequestStop_ProcessingPartitionsTransitionToStopped reproduces the production scenario (RUNNING job + PROCESSING partitions, user clicks Stop), verifies STOPPED is written before requestStop returns. Verified to fail with the old SQL. Bug 2 — Distributed reader is O(N²) due to getCursorAtOffset ============================================================ PartitionWorker.initializeKeysetCursor calls EntityRepository.getCursorAtOffset(filter, partitionStart) per partition. Underneath that's `dao.listAfter(filter, 1, partitionStart)` — SQL `LIMIT 1 OFFSET partitionStart`, which is O(partitionStart) every call. With partitionSize=10000 and 581k records, partitions start at offsets 0, 10k, 20k, ..., 570k. Total cursor-init scan cost is 0+10k+20k+...+570k ≈ 16.5M rows scanned just to find each partition's starting cursor. Single-server (KeysetBatchReader) does ~581k. ~28× more DB work per job + multi-worker parallelism amplifies into 140× wall-clock slowdown observed in production (1.4k r/s single-server reader vs 10 r/s distributed reader on the same dataset). Fix: - DistributedSearchIndexCoordinator.precomputePartitionStartCursors: one keyset walk per entity type at job initialization time, batching in 10k chunks and recording the cursor at every partition's rangeStart. O(N) total reads per entity type. - DistributedSearchIndexCoordinator.getPartitionStartCursor: O(1) lookup from the precomputed map. - PartitionWorker.initializeKeysetCursor consults the cache first; falls back to the existing OFFSET path on a miss (recovery scenarios where another server initialized the partitions and this server picks one up). Test: initializeKeysetCursorHitsPrecomputedCacheAndSkipsOffsetFallback verifies the cache hit short-circuits the OFFSET fallback (using verify(repository, never()).getCursorAtOffset(...)). |
||
|
|
8dd98fa765
|
fix(it): Stabilize Flaky integration tests (#27546)
* fix(it): stabilize three flaky integration tests
- TagResourceIT.test_searchTagByClassificationDisplayName: raise Awaitility
timeout from 30s to 90s — under full-suite concurrent load the tag search
index can lag well past 30s before the tag is discoverable by classification
display name
- GlossaryOntologyExportIT.testExportGlossaryAsRdfXml: replace legacy
model.write("RDF/XML") with RDFDataMgr.write(RDFXML_PLAIN) — the legacy
Jena API attempts external DTD/entity resolution from w3.org, hanging ~104s
in network-isolated CI before the client times out at 60s; RIOT writes
purely in-memory with no network I/O
- SearchResourceIT.testExportWithFromAndSizeForPagination: add _id as a
final tiebreaker sort on export requests in both ElasticSearch and
OpenSearch managers; from/size pagination without a unique tiebreaker
produces duplicate rows across pages when concurrent CI tests mutate the
same index between requests; also deduplicate the redundant name.keyword
secondary sort when the caller already sorts by name.keyword
* fix(search): use id.keyword instead of _id for export sort tiebreaker
_id is an Elasticsearch meta-field that requires fielddata to sort on,
disabled by default. Use the indexed id.keyword sub-field instead, which
is a proper keyword field with doc values and is sortable without any
cluster setting changes.
* fix(it): retry pagination assertion in Awaitility to tolerate transient index shifts
from/size pagination on a shared search index can return duplicate rows
across two consecutive requests when concurrent tests mutate the same
index in between. Wrapping both page fetches and the assertion in
untilAsserted lets the check retry until the index stabilises rather
than failing on the first transient collision.
* revert(search): drop id.keyword tiebreaker; rely on test-side Awaitility retry
* fix(search): strengthen pagination test assertions and restore id.keyword tiebreaker sort
* fix(it): revert RdfRepository prod change; increase GlossaryOntologyExportIT timeout to 150s for Jena DTD stall in CI
* fix(it): restore tag search index aliases in IndexTemplateIT after index deletion
testDocUpdateOnDeletedIndexUsesTemplateNotAutoInference deletes the physical
openmetadata_tag_search_index and previously restored it with a bare PUT — leaving
all aliases (openmetadata_tag, openmetadata_classification, openmetadata_all)
missing for the remainder of the run. This caused TagResourceIT.checkCreatedEntity
to time out (searches on tag_search_index hit an empty bare index) and delete_by_query
cleanup ops to fail with index_not_found_exception on openmetadata_tag.
Fix: replace the bare PUT with Entity.getSearchRepository().createIndex() which
recreates the physical index with proper OpenMetadata mappings and restores all aliases.
* fix(it): isolate IndexTemplateIT tag test to avoid wiping production search index
testDocUpdateOnDeletedIndexUsesTemplateNotAutoInference was deleting the
production openmetadata_tag_search_index backing index, racing with
TagResourceIT.test_searchTagByClassificationDisplayName which polls that
index for 90s. Use a test-scoped index name matching the template pattern
instead, consistent with the other tests in this class.
* fix(it): make testClaimPendingIncludesRetryStatuses race-tolerant
The production SearchIndexRetryWorker (4 daemon threads, 5s poll) races
the test by calling the same global claimPending SQL. Replace the brittle
size-based assertion with an Awaitility loop that checks claimedAt != null
for each inserted record — proving claimPending's SQL filter accepted the
record's status regardless of which thread won the race.
* fix(it): avoid stale entityStatus in patch_addDeleteReviewers
The GlossaryTermApprovalWorkflow fires asynchronously when reviewers are
added, setting entityStatus=IN_REVIEW. The final patch sent the stale
entityStatus=APPROVED from the previous response, causing a spurious
IN_REVIEW→APPROVED transition in the diff which requires the caller to
be a reviewer — admin is not. Re-fetch the entity before the reviewer
removal so the diff contains only the reviewer change.
* fix(it): handle claimedAt reset in testClaimPendingIncludesRetryStatuses
updateFailureAndRetryCount sets claimedAt=NULL after the worker processes
a record. Add retryCount > 0 as a secondary proof-of-claim signal so
records that were claimed, processed, and had claimedAt reset are still
counted — covers the FAILED exhaustion path and intermediate PENDING_RETRY_*
states where claimedAt is temporarily null.
* fix(it): avoid governance workflow race in testApplyFeedback_withRecognizerMetadata
repository.create() publishes a ChangeEvent that triggers
ApplyRecognizerFeedbackImpl asynchronously. That workflow call races
with the direct applyFeedback below: by the time the workflow runs, the
GENERATED tag is already removed by the direct call, so
getRecognizerIdFromTagLabel returns null and the workflow falls back to
ALL recognizers, contaminating recognizer2.
Fix: insert directly to DAO (bypassing publishChangeEvent) so the
governance workflow is never triggered for this unit-level test.
* fix(it): handle worker deleteByEntity path in testClaimPendingIncludesRetryStatuses
The worker's processRecord takes the delete path (removeStaleEntityById +
deleteByEntity) when resolveEntityReference returns null but entityId is
non-empty — which applies to our fake UUID test records. If the worker
wins and deletes a record, findByStatus finds nothing and the assertion
fails.
Fix: track which IDs are still visible in any status. An ID absent from
all statuses was deleted by the worker after a successful claim —
deleteByEntity is only reached after claimPending accepted the record,
so absence is equally valid proof that claimPending's SQL filter worked.
* fix(it): re-fetch before reviewer patches in test_glossaryTermReviewersMultipleUpdates
Same root cause as patch_addDeleteReviewers: GlossaryTermApprovalWorkflow
fires asynchronously after reviewers are added, setting entityStatus=IN_REVIEW.
Subsequent patches using the stale APPROVED status from the previous response
trigger a spurious IN_REVIEW→APPROVED transition, rejected because admin is
not a reviewer. Re-fetch before each subsequent patch to avoid the stale status.
---------
Co-authored-by: Mohit Yadav <105265192+mohityadav766@users.noreply.github.com>
|
||
|
|
83b9e55122
|
fix(test): flaky container and activity task specs (#27942) | ||
|
|
e56abb80d5
|
Fix Entity Promotion issue (#27930)
Some checks failed
Integration Tests - MySQL + Elasticsearch / integration-tests-mysql-elasticsearch (push) Has been cancelled
Integration Tests - PostgreSQL + OpenSearch / integration-tests-postgres-opensearch (push) Has been cancelled
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (mysql) (push) Has been cancelled
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests (postgresql) (push) Has been cancelled
OpenMetadata Service Unit Tests / k8s_operator-unit-tests (push) Has been cancelled
OpenMetadata Service Unit Tests / openmetadata-service-unit-tests-status (push) Has been cancelled
Integration Tests - MySQL + Elasticsearch / Detect Changes (push) Has been cancelled
Integration Tests - PostgreSQL + OpenSearch / Detect Changes (push) Has been cancelled
Java Checkstyle / java-checkstyle (push) Has been cancelled
Maven Collate Tests / maven-collate-ci (push) Has been cancelled
OpenMetadata Service Unit Tests / Detect Changes (push) Has been cancelled
Publish Package to Maven Central Repository / publish-maven-packages (push) Has been cancelled
|