Skip to content

feat(governance): per-entity workflow trigger fields#28935

Open
yan-3005 wants to merge 6 commits into
mainfrom
feat/per-entity-workflow-trigger-fields
Open

feat(governance): per-entity workflow trigger fields#28935
yan-3005 wants to merge 6 commits into
mainfrom
feat/per-entity-workflow-trigger-fields

Conversation

@yan-3005

Copy link
Copy Markdown
Contributor

What

Moves the set of fields that can trigger a governance workflow from a single global enum (WorkflowTriggerFields) to a per-entity declaration in each entity's JSON Schema (workflowTriggerFields). The schema becomes the single source of truth and the trigger surface is now entity-specific.

Why

The global enum was an allowlist shared across all entities:

  • Hard to maintain — every new field had to be added manually; missing one fails silently (the workflow just never fires).
  • No per-entity semantics — e.g. testCaseResolutionStatus is a real field on a test case but should not trigger governance workflows; a single global list cannot exclude it for one entity without removing it for all.
  • Mixed concerns — ~40 entities with very different fields all gated by one list.

How

  • Schema (source of truth): Added a top-level workflowTriggerFields array to the 39 workflow-target entity schemas. Seeded as globalEnum ∩ entityProperties, which is behavior-preserving: a field can only appear in a changeDescription if it is a serialized property of the entity, so intersecting against the global set never drops a field that could actually occur.
  • Registry: WorkflowTriggerFieldsRegistry scans the entity schemas once and caches entityType -> Set<field>, with a fallback to the global enum for entities that declare none.
  • Runtime gate: FilterEntityImpl now resolves trigger fields per entity type via the registry instead of iterating the global enum.
  • API: new GET /v1/metadata/types/fields/{entityType}/workflowTriggerFields.
  • UI: NodeConfigSidebar fetches trigger fields per selected data asset (mirroring the existing custom-properties flow) instead of using the static enum.

Field changes

  • Added entity-relevant structural/definition fields where applicable: columns, tableConstraints, tablePartition, schemaDefinition, messageSchema, requestSchema/responseSchema, fields (search index), mlFeatures, algorithm, mlHyperParameters, tasks, sql, storedProcedureCode/code, metricExpression, retentionPeriod, dataContract.
  • Removed lifeCycle and deleted from the trigger fields entirely.

Testing

  • FilterEntityImplTest extended for per-entity behavior (e.g. table triggers on columns, glossaryTerm on synonyms; testCase does not trigger on testCaseResolutionStatus; structural fields are entity-specific and not global) and for the lifeCycle/deleted removals.
  • Full governance.workflows package: 240 tests pass.
  • UI: WorkflowConfigFormV1 test passes; eslint + prettier clean on changed files.

Follow-ups (not in this PR)

  • The CheckChangeDescription condition-builder filter node still uses the global field list (now minus lifeCycle/deleted). Making it per-entity needs the trigger node's dataAssets threaded into that form (cross-node). Harmless today since the backend enforces per-entity.
  • Newly added per-entity fields don't yet have i18n labels in the condition builder; they render by raw name via the existing fallback.

🤖 Generated with Claude Code

Move the set of fields that can trigger a governance workflow from a
single global enum to a per-entity declaration in each entity's JSON
Schema, making the trigger surface entity-specific and the schema the
single source of truth.

- Add a top-level `workflowTriggerFields` array to 39 workflow-target
  entity schemas. Seeded as the intersection of the existing global set
  with each entity's own fields, so existing behavior is preserved (a
  field can only appear in a changeDescription if the entity has it).
- Add WorkflowTriggerFieldsRegistry: scans the entity schemas once and
  caches an entityType -> trigger-field-set map, with a global-enum
  fallback for entities that declare none.
- FilterEntityImpl now gates changed fields per entity type via the
  registry instead of iterating the global enum.
- Expose GET /v1/metadata/types/fields/{entityType}/workflowTriggerFields
  so the workflow builder can fetch fields per entity.
- NodeConfigSidebar fetches trigger fields per selected data asset
  (mirroring the existing custom-properties flow) instead of the static
  global enum.
- Add entity-relevant structural/definition fields as triggers where
  applicable (columns, table constraints/partition, schema definitions,
  message/request/response schemas, search index fields, ML features,
  pipeline tasks, stored procedure code, metric expression, retention
  period, data contract).
- Remove lifeCycle and deleted from the trigger fields.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@yan-3005 yan-3005 requested a review from a team as a code owner June 10, 2026 18:53
Copilot AI review requested due to automatic review settings June 10, 2026 18:53
@yan-3005 yan-3005 added the safe to test Add this label to run secure Github workflows on PRs label Jun 10, 2026
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

This PR cannot be merged until the following are addressed on its linked issue:

  • No GitHub issue is linked. Link an issue in the Development section of the PR (or add Fixes #12345 to the description). For a same-org cross-repo issue, add Fixes open-metadata/<repo>#123 to the description.

The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically.

Maintainers can bypass this check by adding the skip-pr-checks label.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR makes governance workflow trigger fields entity-specific by declaring them in each entity’s JSON Schema (workflowTriggerFields), then wiring backend + UI to consume those per-entity declarations (with a safe fallback to the legacy global enum).

Changes:

  • Added workflowTriggerFields declarations across workflow-target schemas and removed deleted/lifeCycle from the legacy global WorkflowTriggerFields enum.
  • Backend: introduced WorkflowTriggerFieldsRegistry, updated FilterEntityImpl to gate triggers per entity type, and added an API to fetch trigger fields by entity type.
  • UI: updated the workflow builder sidebar to fetch per-entity trigger fields instead of using the static enum.

Reviewed changes

Copilot reviewed 47 out of 47 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
openmetadata-ui/src/main/resources/ui/src/rest/metadataTypeAPI.ts Adds REST helper to fetch workflow trigger fields per entity type.
openmetadata-ui/src/main/resources/ui/src/components/WorkflowDefinitions/WorkflowBuilder/NodeConfigSidebar.tsx Fetches trigger fields per selected data asset and uses them for exclude-field options.
openmetadata-ui/src/main/resources/ui/src/components/WorkflowDefinitions/WorkflowBuilder/forms/ConditionBuilder/ConditionBuilder.constants.ts Removes deleted boolean handling after deleted is removed from global trigger fields enum.
openmetadata-spec/src/main/resources/json/schema/type/workflowTriggerFields.json Removes deleted and lifeCycle from the global enum list.
openmetadata-spec/src/main/resources/json/schema/tests/testSuite.json Declares workflowTriggerFields for testSuite.
openmetadata-spec/src/main/resources/json/schema/tests/testCase.json Declares workflowTriggerFields for testCase (excluding internal-only fields).
openmetadata-spec/src/main/resources/json/schema/entity/teams/user.json Declares workflowTriggerFields for user.
openmetadata-spec/src/main/resources/json/schema/entity/teams/team.json Declares workflowTriggerFields for team.
openmetadata-spec/src/main/resources/json/schema/entity/services/storageService.json Declares workflowTriggerFields for storageService.
openmetadata-spec/src/main/resources/json/schema/entity/services/searchService.json Declares workflowTriggerFields for searchService.
openmetadata-spec/src/main/resources/json/schema/entity/services/pipelineService.json Declares workflowTriggerFields for pipelineService.
openmetadata-spec/src/main/resources/json/schema/entity/services/mlmodelService.json Declares workflowTriggerFields for mlmodelService.
openmetadata-spec/src/main/resources/json/schema/entity/services/metadataService.json Declares workflowTriggerFields for metadataService.
openmetadata-spec/src/main/resources/json/schema/entity/services/messagingService.json Declares workflowTriggerFields for messagingService.
openmetadata-spec/src/main/resources/json/schema/entity/services/databaseService.json Declares workflowTriggerFields for databaseService.
openmetadata-spec/src/main/resources/json/schema/entity/services/dashboardService.json Declares workflowTriggerFields for dashboardService.
openmetadata-spec/src/main/resources/json/schema/entity/services/apiService.json Declares workflowTriggerFields for apiService.
openmetadata-spec/src/main/resources/json/schema/entity/domains/domain.json Declares workflowTriggerFields for domain.
openmetadata-spec/src/main/resources/json/schema/entity/domains/dataProduct.json Declares workflowTriggerFields for dataProduct (incl. lifecycleStage, SLA, relationships).
openmetadata-spec/src/main/resources/json/schema/entity/data/topic.json Declares workflowTriggerFields for topic (incl. messageSchema).
openmetadata-spec/src/main/resources/json/schema/entity/data/table.json Declares workflowTriggerFields for table (incl. structural fields like columns/constraints/partition).
openmetadata-spec/src/main/resources/json/schema/entity/data/storedProcedure.json Declares workflowTriggerFields for storedProcedure (incl. code fields).
openmetadata-spec/src/main/resources/json/schema/entity/data/searchIndex.json Declares workflowTriggerFields for searchIndex (incl. fields).
openmetadata-spec/src/main/resources/json/schema/entity/data/report.json Declares workflowTriggerFields for report.
openmetadata-spec/src/main/resources/json/schema/entity/data/query.json Declares workflowTriggerFields for query.
openmetadata-spec/src/main/resources/json/schema/entity/data/pipeline.json Declares workflowTriggerFields for pipeline (incl. tasks).
openmetadata-spec/src/main/resources/json/schema/entity/data/page.json Declares workflowTriggerFields for page.
openmetadata-spec/src/main/resources/json/schema/entity/data/mlmodel.json Declares workflowTriggerFields for mlmodel (incl. mlFeatures/hyperparameters).
openmetadata-spec/src/main/resources/json/schema/entity/data/metric.json Declares workflowTriggerFields for metric (incl. metricExpression).
openmetadata-spec/src/main/resources/json/schema/entity/data/glossaryTerm.json Declares workflowTriggerFields for glossaryTerm (incl. synonyms/relationships).
openmetadata-spec/src/main/resources/json/schema/entity/data/glossary.json Declares workflowTriggerFields for glossary.
openmetadata-spec/src/main/resources/json/schema/entity/data/dataContract.json Declares workflowTriggerFields for dataContract (schema/semantics/quality/etc).
openmetadata-spec/src/main/resources/json/schema/entity/data/databaseSchema.json Declares workflowTriggerFields for databaseSchema.
openmetadata-spec/src/main/resources/json/schema/entity/data/database.json Declares workflowTriggerFields for database.
openmetadata-spec/src/main/resources/json/schema/entity/data/dashboardDataModel.json Declares workflowTriggerFields for dashboardDataModel (incl. columns/sql).
openmetadata-spec/src/main/resources/json/schema/entity/data/dashboard.json Declares workflowTriggerFields for dashboard.
openmetadata-spec/src/main/resources/json/schema/entity/data/container.json Declares workflowTriggerFields for container (incl. hierarchy + retention).
openmetadata-spec/src/main/resources/json/schema/entity/data/chart.json Declares workflowTriggerFields for chart.
openmetadata-spec/src/main/resources/json/schema/entity/data/apiEndpoint.json Declares workflowTriggerFields for apiEndpoint (incl. request/response schema).
openmetadata-spec/src/main/resources/json/schema/entity/data/apiCollection.json Declares workflowTriggerFields for apiCollection.
openmetadata-spec/src/main/resources/json/schema/entity/classification/tag.json Declares workflowTriggerFields for tag (incl. hierarchy/style).
openmetadata-spec/src/main/resources/json/schema/entity/classification/classification.json Declares workflowTriggerFields for classification.
openmetadata-spec/src/main/resources/json/schema/dataInsight/dataInsightChart.json Declares workflowTriggerFields for dataInsightChart.
openmetadata-service/src/test/java/org/openmetadata/service/governance/workflows/elements/triggers/impl/FilterEntityImplTest.java Expands tests to validate per-entity trigger behavior + removal of deleted/lifeCycle.
openmetadata-service/src/main/java/org/openmetadata/service/resources/types/TypeResource.java Adds API endpoint to retrieve workflow trigger fields by entity type.
openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/WorkflowTriggerFieldsRegistry.java New registry that scans schemas once and caches trigger fields per entity type (fallback to global enum).
openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/triggers/impl/FilterEntityImpl.java Switches runtime trigger gating to use per-entity trigger fields via the registry.

@github-actions

Copy link
Copy Markdown
Contributor

✅ TypeScript Types Auto-Updated

The generated TypeScript types have been automatically updated based on JSON schema changes in this PR.

Address PR review feedback:
- WorkflowTriggerFieldsRegistry: scan only the canonical entity schema
  roots (entity, tests, dataInsight) and keep-first + log on basename
  collisions, so the entityType mapping can never become order-dependent
  if a same-named schema elsewhere later declares workflowTriggerFields.
- NodeConfigSidebar: use Promise.allSettled so one failed request does not
  clear the whole exclude-field list, and guard setState with a cancel
  flag to avoid stale updates after unmount / dependency change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 10, 2026 19:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 47 out of 48 changed files in this pull request and generated 1 comment.

The scan-root selection does not by itself prevent basename collisions
(entity/ still contains same-named schemas such as entity/feed/domain.json);
determinism on a clash is provided by the keep-first + error guard in
readSchema. Reword the comment to reflect that and the broad-scan /
auto-discovery intent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 62%
62.72% (67098/106971) 43.94% (36977/84152) 46.05% (11274/24480)

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

🟡 Playwright Results — all passed (14 flaky)

✅ 4270 passed · ❌ 0 failed · 🟡 14 flaky · ⏭️ 88 skipped

Shard Passed Failed Flaky Skipped
✅ Shard 1 301 0 0 4
🟡 Shard 2 805 0 1 9
🟡 Shard 3 806 0 2 8
🟡 Shard 4 840 0 3 12
🟡 Shard 5 719 0 2 47
🟡 Shard 6 799 0 6 8
🟡 14 flaky test(s) (passed on retry)
  • Features/DataQuality/BundleSuiteBulkOperations.spec.ts › Add test case to existing Bundle Suite (shard 2, 1 retry)
  • Features/RTL.spec.ts › Verify Following widget functionality (shard 3, 2 retries)
  • Features/Table.spec.ts › Table pagination with sorting should works (shard 3, 1 retry)
  • Pages/CustomProperties.spec.ts › Table (shard 4, 1 retry)
  • Pages/CustomProperties.spec.ts › Timestamp (shard 4, 1 retry)
  • Pages/DataProducts.spec.ts › Data Product List Page - Initial Load (shard 4, 1 retry)
  • Pages/EntityDataConsumer.spec.ts › Tier Add, Update and Remove (shard 5, 1 retry)
  • Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts › Should remove user owner for knowledgeCenter (shard 5, 2 retries)
  • Pages/Lineage/LineageFilters.spec.ts › Verify lineage service type filter selection (shard 6, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify lineage schema filter selection (shard 6, 1 retry)
  • Pages/Lineage/LineageRightPanel.spec.ts › Verify custom properties tab IS visible for supported type: searchIndex (shard 6, 1 retry)
  • Pages/Lineage/PlatformLineage.spec.ts › Verify domain platform view (shard 6, 1 retry)
  • Pages/ServiceEntity.spec.ts › Tier Add, Update and Remove (shard 6, 1 retry)
  • Pages/UserDetails.spec.ts › Admin user can get all the roles hierarchy and edit roles (shard 6, 1 retry)

📦 Download artifacts

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

Copilot AI review requested due to automatic review settings June 11, 2026 05:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 47 out of 48 changed files in this pull request and generated 1 comment.

@gitar-bot

gitar-bot Bot commented Jun 11, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 3 resolved / 3 findings

Refactors governance workflow triggers to use per-entity schemas as the source of truth, replacing the rigid global enum. This change resolves potential UI fetch failures and registry key collisions, with no outstanding issues.

✅ 3 resolved
Quality: UI exclude-field list empties when trigger-fields fetch fails

📄 openmetadata-ui/src/main/resources/ui/src/components/WorkflowDefinitions/WorkflowBuilder/NodeConfigSidebar.tsx:140-154
availableExcludeFields is now [...triggerFields, ...customPropertyFields], where triggerFields comes solely from getWorkflowTriggerFieldsByEntityType. Previously the static WorkflowTriggerFields enum always populated the base list regardless of network state. With the new code, the .catch() resets both triggerFields and customPropertyFields to [], so any failure of the per-entity fetch leaves the exclude-field selector completely empty and the user cannot configure (or even see previously-saved) excluded fields until the request succeeds. Consider handling each asset's two requests independently (e.g. Promise.allSettled) so a custom-property failure doesn't wipe trigger fields and vice-versa, and degrading gracefully instead of clearing everything.

Edge Case: Registry keys entity type by filename, risking basename collisions

📄 openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/WorkflowTriggerFieldsRegistry.java:69-83
scanSchemas() walks every *.json under json/schema and maps the file basename (minus .json) to its workflowTriggerFields set, storing into a ConcurrentHashMap via put. Several schema files share a basename across directories: entity/domains/domain.json vs entity/feed/domain.json, entity/classification/tag.json vs entity/feed/tag.json, entity/data/page.json vs system/ui/page.json. Today this is harmless only because just one file of each pair declares workflowTriggerFields (and readSchema skips files without the key), and ClassGraph scan order is otherwise non-deterministic. If a sibling file with a colliding basename ever gains a workflowTriggerFields array, the cached set for that entity type becomes order-dependent and effectively random. Consider deriving the entity type from the schema's $id/javaType, or restricting the scan to the canonical entity schema directories, so the mapping is deterministic and collision-free.

Bug: workflowTriggerFields references non-existent inputPorts/outputPorts

📄 openmetadata-spec/src/main/resources/json/schema/entity/domains/dataProduct.json:64-78 📄 openmetadata-spec/src/main/resources/json/schema/entity/domains/dataProduct.json:260-264 📄 openmetadata-spec/src/main/resources/json/schema/entity/domains/dataProduct.json:265
In dataProduct.json, workflowTriggerFields (line 265) now adds "inputPorts" and "outputPorts", but neither is a declared property of the entity. The properties block (lines 134-264) defines no inputPorts/outputPorts; there is only a dataProductPort definition (lines 64-100) that is never referenced by any property.

Per this PR's own stated invariant — a field can only appear in a changeDescription if it is a serialized property of the entity — these two trigger fields can never fire and are dead entries. The commit message ("Add input output ports in the dataProduct") suggests the intent was to also add the actual inputPorts/outputPorts properties (likely arrays of #/definitions/dataProductPort), but only the trigger list was updated.

Fix: either add the corresponding entity properties so the trigger fields are meaningful, or remove inputPorts/outputPorts from workflowTriggerFields until the properties exist. Note the existing trigger-field names (consumesFrom, providesTo, etc.) match real properties; these two do not.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

Copy link
Copy Markdown

@sonarqubecloud

Copy link
Copy Markdown

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants