Skip to content

feat(ui): add TableV2 as Untitled UI migration wrapper for Table component - #26214

Closed
harsh-vador wants to merge 45 commits into
mainfrom
untitledui-table-migration
Closed

feat(ui): add TableV2 as Untitled UI migration wrapper for Table component#26214
harsh-vador wants to merge 45 commits into
mainfrom
untitledui-table-migration

Conversation

@harsh-vador

@harsh-vador harsh-vador commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

Fixes 3847

Describe your changes:

Summary

  • Introduces TableV2.tsx as a drop-in replacement for Table.tsx, rendering via @openmetadata/ui-core-components (React Aria + Untitled UI) instead of Ant Design
  • Preserves the exact TableComponentProps<T> interface — zero changes required for existing consumers
  • Smoke-tests the migration by swapping BotListV1 to use TableV2

What's migrated

Feature Status
Column rendering (AntD Table → React Aria Table compound)
Column customization dropdown (drag-to-reorder, show/hide, user preferences)
Search bar integration
Pagination (NextPrevious)
Loading overlay
Row selection (single + multiple)
Column sorting
Empty state (locale.emptyText)
Visual parity: font size (14px), color (#535862), padding (8px 8px 8px 16px)
Cell vertical alignment (top)

What's implemented

Feature Notes
Core rendering via React Aria UntitledTable Full parity for standard tables
rowKey with AntD index-fallback parity Falls back to array index when named property is absent (prevents key collision)
Client-side pagination via NextPrevious Slices sortedDataSource before rendering
Server-side pagination (customPaginationProps) Cursor-based, unchanged from Table.tsx
scroll.x / scroll.y overflowX/overflowY + maxHeight applied to inner wrapper
Row selection selectedRowKeys forwarded as controlled selectedKeys; onChange fired with correct type
Resizable columns (resizableColumns) react-resizable with stable per-column handlers (no closure-per-render)
Column customization Show/hide/reorder dropdown, persisted to user preferences
Built-in search (searchProps) Wraps Searchbar component
loading spinner overlay Absolute-positioned, non-layout-shifting
Client-side sorting sorter: (a,b) => number applied to full dataset before pagination; sorter: true delegates to parent onChange
rowClassName, cellClassName Forwarded to row/cell elements
onRow onClick and onDoubleClick forwarded to UntitledTable.Row
locale.emptyText Rendered inside renderEmptyState
extraTableFilters Aligned with column customization dropdown
data-row-key attribute Playwright-compatible row selector (React Aria doesn't forward id as DOM attribute)
className removed from props type Now a compile-time error — use containerClassName instead

Known limitations (v1)

Documented — accepted but ignored

  • expandable — React Aria has no built-in expandable row concept
  • components — AntD custom cell/header renderers

Silent gaps — will need fixes before migrating affected consumers

Gap Affected pattern
col.align not applied Any column with align: 'center' or 'right'
col.ellipsis not applied Description/name columns with overflow truncation
col.fixed (sticky columns) not implemented Tables with pinned left/right columns
col.colSpan/rowSpan from render return discarded Tables with merged cells
onRow other handlers (onMouseEnter, onContextMenu etc.) not wired Hover-highlight / context menu rows
Sticky <thead> not implemented Tables using scroll.y expect sticky headers
showHeader={false} not implemented Always renders header
rowSelection.getCheckboxProps ignored Per-row disabled/indeterminate checkboxes
onChange only fired for sort Consumers using onChange for pagination/filter side effects

Playwright fixes included

  • bot.ts: tr[id=…]tr[data-row-key=…] (React Aria doesn't set DOM id on rows)
  • importUtils.ts: getByRole('cell')getByRole('gridcell') (React Aria emits explicit role="gridcell")
  • importUtils.ts: getByRole('columnheader', { name }).filter({ hasText }) (inner role="group" wrapper breaks ARIA name computation)
  • Customproperties-part2.spec.ts: scroll test restructured — verifies 1 row = not scrollable, 3 rows = scrollable; uses distinct values per row

Consumers migrated in this PR

  • BotListV1 — listing table with search, sort, row click

SchemaTable

Screen.Recording.2026-03-10.at.5.26.33.PM.mov
Screen.Recording.2026-03-04.at.1.07.58.PM.mov

Type of change:

  • Bug fix
  • Improvement
  • New feature
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.

Summary by Gitar

  • RDF Graph Integration:
    • Added getGlossaryTermGraph to RdfRepository to enable graph-based visualization of glossary term relationships.
  • Authentication & Security:
    • Implemented UserSSOOAuthProvider to support unified SSO and Basic Auth for MCP servers.
    • Added OAuthHttpStatelessServerTransportProvider with authentication middleware and dynamic CORS configuration.
  • Search Resilience:
    • Introduced SearchIndexRetryWorker to manage and retry failed index events using SearchIndexRetryQueue.
  • New UI Components:
    • Added OntologyExplorer for visualizing glossary relationships and administrative settings via GlossaryTermRelationSettingsPage.
  • Configuration:
    • Added support for glossary term relation settings and MCP configuration schemas.

This will update automatically on new commits.

@harsh-vador harsh-vador self-assigned this Mar 4, 2026
@harsh-vador
harsh-vador requested a review from a team as a code owner March 4, 2026 07:38
@harsh-vador harsh-vador added UI UI specific issues safe to test Add this label to run secure Github workflows on PRs labels Mar 4, 2026
Comment thread openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx Outdated
Comment thread openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx Outdated
Comment thread openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx Outdated
Comment thread openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx Outdated
Comment thread openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx Outdated
@harsh-vador

Copy link
Copy Markdown
Contributor Author

@gitar-bot all the comments are addressed, can you re-review?

@gitar-bot

gitar-bot Bot commented Mar 17, 2026

Copy link
Copy Markdown

@gitar-bot all the comments are addressed, can you re-review?

Re-review is in progress. Results will be posted shortly.

return [{ 'text/plain': key }];
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getDropOperation(target: any) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Bug: Stale closure in getDropOperation defeats self-drop guard

getDropOperation closes over draggingFqn from the render cycle when useDragAndDrop was called. Although flushSync inside getItems forces a synchronous re-render with the new draggingFqn, React Aria holds onto the old getDropOperation closure from before the flush. As a result, draggingFqn is still null when getDropOperation runs on subsequent dragover events, so the self-drop and child-drop protection (targetFqn === draggingFqn || targetFqn.startsWith(draggingFqn + '.')) never fires — every target returns 'move'.

The fix is to mirror draggingFqn into a ref so getDropOperation always reads the latest value.

Suggested fix:

const draggingFqnRef = useRef<string | null>(null);

// Inside getItems:
flushSync(() => setDraggingFqn(key));
draggingFqnRef.current = key;

// Inside getDropOperation, read from ref:
const currentDraggingFqn = draggingFqnRef.current;
if (
  currentDraggingFqn &&
  (targetFqn === currentDraggingFqn ||
    targetFqn.startsWith(currentDraggingFqn + '.'))
) {
  return 'cancel';
}

// Inside onDragEnd:
draggingFqnRef.current = null;
setDraggingFqn(null);

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


const getRowKey = useCallback(
(record: T, index: number): string => {
if (typeof rest.rowKey === 'function') {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Edge Case: getRowKey function branch has no undefined/null guard

When rowKey is a function prop, getRowKey wraps the result with String(...) without checking for undefined/null. If the callback returns undefined for any record, the key becomes the literal string "undefined", causing key collisions across all such rows. The string-based rowKey path correctly falls back to the array index, but the function path does not.

In practice this is unlikely since callers provide well-behaved rowKey functions, but it's a subtle inconsistency with the string path's behavior.

Suggested fix:

if (typeof rest.rowKey === 'function') {
  const val = (rest.rowKey as (record: T) => string | number)(record);
  return val !== undefined && val !== null ? String(val) : String(index);
}

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

</div>
</div>

<div

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Bug: Loading overlay uses absolute but parent lacks relative

The loading spinner overlay at line 621 uses tw:absolute tw:inset-0 to cover the table area. However, its parent <div> at line 616-617 does not have position: relative, so the overlay will be positioned relative to the nearest positioned ancestor (the outermost container div at line 538, which also lacks position: relative unless set via containerClassName). This means the overlay will not correctly cover just the table area — it may cover the search bar and pagination as well, or escape the intended bounds entirely if no ancestor is positioned.

Suggested fix:

Add `tw:relative` to the parent div:
```tsx
<div
  className="tw:relative tw:flex tw:flex-col tw:w-full"
  data-testid={dataTestId}
  style={scrollStyle}>
```

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

getItems(keys: any) {
const key = String([...keys][0]);

flushSync(() => setDraggingFqn(key));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Bug: flushSync inside React Aria's getItems may corrupt drag state

In GlossaryTermTab.component.tsx line 1447, flushSync(() => setDraggingFqn(key)) is called inside the getItems callback of useDragAndDrop. This forces a synchronous React re-render during React Aria's internal drag-start sequence. React Aria maintains internal drag/drop state that can be left inconsistent when an external synchronous re-render interrupts its initialization. This is also fragile because flushSync is the only mechanism preventing a stale closure bug in getDropOperation (which reads draggingFqn from state). A safer pattern is to use a useRef to store the dragging key synchronously and read it in getDropOperation, avoiding flushSync entirely.

Suggested fix:

Replace the state-based approach with a ref:
```tsx
const draggingFqnRef = useRef<string | null>(null);

const { dragAndDropHooks } = useDragAndDrop({
  getItems(keys) {
    const key = String([...keys][0]);
    draggingFqnRef.current = key;
    setDraggingFqn(key); // normal setState for UI updates
    return [{ 'text/plain': key }];
  },
  getDropOperation(target) {
    if (target.type === 'item') {
      const targetFqn = String(target.key);
      const curDrag = draggingFqnRef.current;
      if (curDrag && (targetFqn === curDrag || targetFqn.startsWith(curDrag + '.')))
        return 'cancel';
      return 'move';
    }
    return 'cancel';
  },
  ...
});
```

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


// ─── Expand toggle ────────────────────────────────────────────────────────

const handleExpandToggle = useCallback(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Edge Case: Controlled expand: rapid toggles may send stale keys

In handleExpandToggle (TableV2.tsx ~line 321-335), when in controlled mode (expandedRowKeys provided), the next set passed to onExpandedRowsChange is computed from the current expandedKeys memo, which derives from the prop. If two rapid expand/collapse toggles happen before React re-renders with the parent's updated state, the second toggle computes next from a stale prop snapshot. This is a minor edge case since most expand interactions are single-click with synchronous parent state updates, but it could manifest in automated testing or with debounced parent state.

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

@gitar-bot

gitar-bot Bot commented Mar 24, 2026

Copy link
Copy Markdown
Code Review ⚠️ Changes requested 44 resolved / 47 findings

TableV2 migration wrapper adds Untitled UI compatibility for the Table component but has critical unresolved issues: loading overlay positioning lacks parent context, React Aria drag state may corrupt from flushSync usage, and rapid expand toggles can send stale keys. Address these before merging.

⚠️ Bug: Loading overlay uses absolute but parent lacks relative

📄 openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:616 📄 openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:621

The loading spinner overlay at line 621 uses tw:absolute tw:inset-0 to cover the table area. However, its parent <div> at line 616-617 does not have position: relative, so the overlay will be positioned relative to the nearest positioned ancestor (the outermost container div at line 538, which also lacks position: relative unless set via containerClassName). This means the overlay will not correctly cover just the table area — it may cover the search bar and pagination as well, or escape the intended bounds entirely if no ancestor is positioned.

Fix
Add `tw:relative` to the parent div:
```tsx
<div
  className="tw:relative tw:flex tw:flex-col tw:w-full"
  data-testid={dataTestId}
  style={scrollStyle}>
```
⚠️ Bug: flushSync inside React Aria's getItems may corrupt drag state

📄 openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTermTab/GlossaryTermTab.component.tsx:1447 📄 openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTermTab/GlossaryTermTab.component.tsx:1452

In GlossaryTermTab.component.tsx line 1447, flushSync(() => setDraggingFqn(key)) is called inside the getItems callback of useDragAndDrop. This forces a synchronous React re-render during React Aria's internal drag-start sequence. React Aria maintains internal drag/drop state that can be left inconsistent when an external synchronous re-render interrupts its initialization. This is also fragile because flushSync is the only mechanism preventing a stale closure bug in getDropOperation (which reads draggingFqn from state). A safer pattern is to use a useRef to store the dragging key synchronously and read it in getDropOperation, avoiding flushSync entirely.

Fix
Replace the state-based approach with a ref:
```tsx
const draggingFqnRef = useRef<string | null>(null);

const { dragAndDropHooks } = useDragAndDrop({
  getItems(keys) {
    const key = String([...keys][0]);
    draggingFqnRef.current = key;
    setDraggingFqn(key); // normal setState for UI updates
    return [{ 'text/plain': key }];
  },
  getDropOperation(target) {
    if (target.type === 'item') {
      const targetFqn = String(target.key);
      const curDrag = draggingFqnRef.current;
      if (curDrag && (targetFqn === curDrag || targetFqn.startsWith(curDrag + '.')))
        return 'cancel';
      return 'move';
    }
    return 'cancel';
  },
  ...
});
```
💡 Edge Case: Controlled expand: rapid toggles may send stale keys

📄 openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:321

In handleExpandToggle (TableV2.tsx ~line 321-335), when in controlled mode (expandedRowKeys provided), the next set passed to onExpandedRowsChange is computed from the current expandedKeys memo, which derives from the prop. If two rapid expand/collapse toggles happen before React re-renders with the parent's updated state, the second toggle computes next from a stale prop snapshot. This is a minor edge case since most expand interactions are single-click with synchronous parent state updates, but it could manifest in automated testing or with debounced parent state.

✅ 44 resolved
Bug: rowSelection onChange hardcodes info.type as 'multiple'

📄 openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:265
In handleSelectionChange, the third argument to rest.rowSelection.onChange() always passes { type: 'multiple' }, even when rest.rowSelection.type is 'radio' (single selection mode).

AntD's native Table passes { type: 'single' } when radio selection triggers the callback. Any future consumer that checks info.type in their onChange handler to distinguish single vs. multi-select events will receive incorrect metadata.

BotListV1 doesn't use rowSelection so this isn't breaking today, but it will bite the next component that migrates to TableV2 with radio selection.

Edge Case: Sort toggle-off maps undefined direction to 'descend'

📄 openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:290
In handleSortChange, when descriptor.direction is undefined (e.g., user clicks to clear sort), the ternary on line 290 falls through to 'descend' instead of null/undefined. In AntD's onChange callback, order is null when sorting is cleared, and consumers typically check for order === null to reset to the default sort state.

This means consumers that rely on sorterResult.order being null to detect "sort cleared" will instead receive 'descend', potentially causing an infinite sort cycle or preventing the user from clearing a sort.

Edge Case: Array-based dataIndex silently renders empty cells

📄 openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:354
resolveCellValue only handles typeof dataIndex === 'string', so if a column uses AntD's array-based dataIndex (e.g., ['user', 'name'] for nested object access) without a render function, the cell will silently render as empty.

No current columns use array dataIndex without a render function, so this is not immediately breaking. However, it's a latent compatibility gap — a consumer migrating from Table to TableV2 could silently lose cell content if they rely on AntD's nested path traversal. Consider adding a comment or runtime warning, or implementing basic path traversal:

const rawValue = Array.isArray(dataIndex)
  ? dataIndex.reduce((obj, key) => (obj as any)?.[key], record)
  : typeof dataIndex === 'string'
    ? (record as Record<string, unknown>)[dataIndex]
    : undefined;
Bug: Column key has no fallback to dataIndex when key is undefined

📄 openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:465 📄 openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:499 📄 openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:279
When col.key is undefined (which is common — multiple consumers define columns with only dataIndex and no explicit key), String(col.key) evaluates to the literal string "undefined". This causes three problems:

  1. Duplicate React keys: All keyless columns share key="undefined", triggering React warnings and incorrect reconciliation.
  2. Broken sort matching: handleSortChange (line 279) compares c.key === descriptor.column, but descriptor.column comes from the id prop ("undefined") while c.key is actual undefined — the === comparison fails, so matchedCol is always undefined for keyless columns.
  3. Duplicate column IDs in React Aria: Multiple <UntitledTable.Head id="undefined"> elements will confuse the Aria table's internal state.

Ant Design's Table falls back to dataIndex when key is absent. Since TableV2 is meant to be a drop-in replacement, it should replicate this behavior. Confirmed that consumers like DirectoryChildrenTable and ContainerChildren define columns without key.

Bug: data-testid and other HTML attributes silently dropped

📄 openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:396 📄 openmetadata-ui/src/main/resources/ui/src/components/common/CustomPropertyTable/TableTypeProperty/TableTypePropertyView.tsx:53
TableV2 is a "drop-in replacement" for AntD Table, but HTML attributes like data-testid passed as props are never forwarded to any rendered DOM element.

In the render output (line 397), the outer <div> only receives className and ref. The <UntitledTable> (line 489) only receives specific named props (aria-label, selectionMode, etc.) — no spread of remaining HTML attributes.

Consumers like TableTypePropertyView pass data-testid="table-type-property-value" which will be silently lost. This will break any tests or Playwright selectors that locate tables by data-testid.

Suggested fix: Forward data-testid (and potentially other HTML pass-through attributes) to the wrapper div or the UntitledTable element.

...and 39 more resolved from earlier reviews

🤖 Prompt for agents
Code Review: TableV2 migration wrapper adds Untitled UI compatibility for the Table component but has critical unresolved issues: loading overlay positioning lacks parent context, React Aria drag state may corrupt from `flushSync` usage, and rapid expand toggles can send stale keys. Address these before merging.

1. ⚠️ Bug: Loading overlay uses `absolute` but parent lacks `relative`
   Files: openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:616, openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:621

   The loading spinner overlay at line 621 uses `tw:absolute tw:inset-0` to cover the table area. However, its parent `<div>` at line 616-617 does not have `position: relative`, so the overlay will be positioned relative to the nearest positioned ancestor (the outermost container div at line 538, which also lacks `position: relative` unless set via `containerClassName`). This means the overlay will not correctly cover just the table area — it may cover the search bar and pagination as well, or escape the intended bounds entirely if no ancestor is positioned.

   Fix:
   Add `tw:relative` to the parent div:
   ```tsx
   <div
     className="tw:relative tw:flex tw:flex-col tw:w-full"
     data-testid={dataTestId}
     style={scrollStyle}>
   ```

2. ⚠️ Bug: `flushSync` inside React Aria's `getItems` may corrupt drag state
   Files: openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTermTab/GlossaryTermTab.component.tsx:1447, openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTermTab/GlossaryTermTab.component.tsx:1452

   In `GlossaryTermTab.component.tsx` line 1447, `flushSync(() => setDraggingFqn(key))` is called inside the `getItems` callback of `useDragAndDrop`. This forces a synchronous React re-render during React Aria's internal drag-start sequence. React Aria maintains internal drag/drop state that can be left inconsistent when an external synchronous re-render interrupts its initialization. This is also fragile because `flushSync` is the only mechanism preventing a stale closure bug in `getDropOperation` (which reads `draggingFqn` from state). A safer pattern is to use a `useRef` to store the dragging key synchronously and read it in `getDropOperation`, avoiding `flushSync` entirely.

   Fix:
   Replace the state-based approach with a ref:
   ```tsx
   const draggingFqnRef = useRef<string | null>(null);
   
   const { dragAndDropHooks } = useDragAndDrop({
     getItems(keys) {
       const key = String([...keys][0]);
       draggingFqnRef.current = key;
       setDraggingFqn(key); // normal setState for UI updates
       return [{ 'text/plain': key }];
     },
     getDropOperation(target) {
       if (target.type === 'item') {
         const targetFqn = String(target.key);
         const curDrag = draggingFqnRef.current;
         if (curDrag && (targetFqn === curDrag || targetFqn.startsWith(curDrag + '.')))
           return 'cancel';
         return 'move';
       }
       return 'cancel';
     },
     ...
   });
   ```

3. 💡 Edge Case: Controlled expand: rapid toggles may send stale keys
   Files: openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.tsx:321

   In `handleExpandToggle` (TableV2.tsx ~line 321-335), when in controlled mode (`expandedRowKeys` provided), the `next` set passed to `onExpandedRowsChange` is computed from the current `expandedKeys` memo, which derives from the prop. If two rapid expand/collapse toggles happen before React re-renders with the parent's updated state, the second toggle computes `next` from a stale prop snapshot. This is a minor edge case since most expand interactions are single-click with synchronous parent state updates, but it could manifest in automated testing or with debounced parent state.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

This PR has had no activity for 30 days and will be closed in 7 days if no further activity occurs.
Feel free to reopen it if you'd like to continue working on it.

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

This PR has had no activity for 30 days and will be closed in 7 days if no further activity occurs.
Feel free to reopen it if you'd like to continue working on it.

@github-actions

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.

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant