PMM-15337 Gate diagnostics on ServiceNow setup - #5770
Conversation
The settings form and the Support diagnostics setup gate ask the same question of the same settings LIST response, so the derivation moves out of the form into useServiceNowConnection. TanStack Query dedupes the request, so both surfaces share one fetch. Signed-off-by: Ignacio Durand <[email protected]>
Everything the app can do ends in an upload to a ServiceNow case, so on an unconfigured instance a user could browse, create an incident and run a script only to find at the last step that nothing can be delivered. A setup screen now replaces the app until delivery is configured: what the tool does, a link to the settings tab that configures it, and the promise that nothing is collected without an explicit confirmation. The gate sits inside SepAuthGate, since reading the SEP settings needs the exchanged bearer. A failed settings read says nothing about the connection, so it fails open and lets the app report its own errors. SepPage wrapped its children in a plain div, which broke the flex chain from Page and left nothing below it able to centre vertically; it is now a growing flex column. Signed-off-by: Ignacio Durand <[email protected]>
"Collect Diagnostic Data" described the mechanism; "Support diagnostics" describes what it is for. The icon follows. Signed-off-by: Ignacio Durand <[email protected]>
Heading follows the rename. The create action is withheld once the list request has failed — creating would hit the backend that just failed and only produce a second error the user cannot act on — and disabled while the list is still loading. Signed-off-by: Ignacio Durand <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR updates the SEP “ATW” diagnostics experience in the PMM UI by renaming it to Support diagnostics, improving the incident list’s error/loading behavior, and gating access to the app behind a ServiceNow connection setup prompt when delivery isn’t configured.
Changes:
- Rename “Collect Diagnostic Data” to Support diagnostics (navigation + page heading) and update the sidebar icon.
- Add a ServiceNow setup gate (with loading + fail-open semantics) in front of the Support diagnostics app, backed by a shared
useServiceNowConnectionhook. - Improve incident list UX by hiding New incident after a list load failure and disabling it while loading; fix
SepPagelayout so gated content can vertically center.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| ui/packages/plugins/atw/tests/IncidentListPage.test.tsx | Adds plugin tests asserting create button is disabled while loading and withheld on list failure. |
| ui/packages/plugins/atw/src/IncidentListPage.tsx | Renames heading and adjusts “New incident” button rendering/disabled logic based on list loading/error state. |
| ui/apps/pmm/src/sep/ServiceNowSetupGate.tsx | Introduces the setup prompt + gate logic for ServiceNow connection state. |
| ui/apps/pmm/src/sep/ServiceNowSetupGate.test.tsx | Adds unit tests for gate behavior across configured / not-configured / drifted / loading / error scenarios. |
| ui/apps/pmm/src/sep/ServiceNowSetupGate.messages.ts | Adds user-facing strings for the setup prompt and loading label. |
| ui/apps/pmm/src/sep/SepPage.tsx | Fixes flex layout so children can occupy full page height and center vertically. |
| ui/apps/pmm/src/router.tsx | Wraps the ATW app route with ServiceNowSetupGate inside SepPage. |
| ui/apps/pmm/src/pages/settings/Settings.messages.ts | Switches support URL import to lib/constants. |
| ui/apps/pmm/src/pages/settings/Settings.constants.ts | Removes duplicated PERCONA_SUPPORT_URL, leaving only MAX_LABEL_WIDTH. |
| ui/apps/pmm/src/pages/settings/components/servicenow/ServiceNowConnectionForm.tsx | Switches to shared useServiceNowConnection hook instead of duplicating derivation logic. |
| ui/apps/pmm/src/pages/settings/components/servicenow/ServiceNowConnection.hooks.ts | Adds shared hook that derives declared secrets, stored inputs, and connection status from one settings LIST call. |
| ui/apps/pmm/src/lib/constants.ts | Adds ServiceNow settings route constant and docs placeholder URL for Support diagnostics. |
| ui/apps/pmm/src/contexts/navigation/navigation.utils.tsx | Renames nav entry to “Support diagnostics” and swaps the icon. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| return { | ||
| declaredNames, | ||
| stored, | ||
| status: connectionStatus(declaredNames, stored), | ||
| isLoading, | ||
| error, | ||
| }; |
There was a problem hiding this comment.
Verified and fixed in 52b4f1d. Confirmed the dead end: ServiceNowConnectionForm returns the servicenow-unavailable alert when !stored.isPresent, so the prompt was sending the operator to a tab that can only say it is unavailable. The gate now fails open on a missing key, same as it does on a failed read — both are "cannot tell, and cannot act", and the app reports its own failures.
| it('renders the app once the connection is configured', () => { | ||
| mockList({ data: sepGroups(['sn_api_key'], { sn_api_key: 'secret' }) }); | ||
| renderGate(); | ||
|
|
||
| expect(screen.getByTestId('atw-app')).toBeInTheDocument(); | ||
| expect( | ||
| screen.queryByTestId('servicenow-setup-prompt') | ||
| ).not.toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('prompts for setup when nothing is stored', () => { | ||
| mockList({ data: sepGroups(['sn_api_key']) }); | ||
| renderGate(); | ||
|
|
||
| expect(screen.getByTestId('servicenow-setup-prompt')).toBeInTheDocument(); | ||
| expect(screen.getByText(Messages.title)).toBeInTheDocument(); | ||
| expect(screen.queryByTestId('atw-app')).not.toBeInTheDocument(); | ||
| }); |
There was a problem hiding this comment.
Added in 52b4f1d — "renders the app when SEP does not carry the delivery inputs key", covering a settings group that ships DIAGNOSTICS_DELIVERY without DIAGNOSTICS_DELIVERY_INPUTS. Gate suite is 7/7, app suite 445 passed.
A SEP build whose settings carry no DIAGNOSTICS_DELIVERY_INPUTS key read as "not configured", so the gate sent the operator to a settings tab that can only answer that it is unavailable. Treat a missing key like a failed read and let the app render. Signed-off-by: Ignacio Durand <[email protected]>
A build whose settings carry no DIAGNOSTICS_DELIVERY_INPUTS key read as "not configured", so the prompt told an admin to fill in a key that is not there. Treat a missing key like a failed read and let the app render. Ported from the PMM-embedded gate (percona/pmm#5770). Signed-off-by: Ignacio Durand <[email protected]>
Ticket number: PMM-15337
Feature build: SUBMODULES-0
What
Renames the Collect Diagnostic Data app to Support diagnostics, gives it an icon that matches what it does, and puts a setup screen in front of it unless the SEP ServiceNow delivery connection is configured.
MedicalServicesOutlined. No occurrence of "Collect Diagnostic Data" remains underui/apps/pmm/srcorui/packages/plugins/atw.declaredSecretNames/storedDeliveryInputs/connectionStatusderivation moves out ofServiceNowConnectionForminto a newuseServiceNowConnectionhook. OneuseSettingsListcall backs both the settings form and the gate — TanStack Query dedupes the request. No API surface is added.ServiceNowSetupGatewraps<AtwApp/>insideSepPage→SepAuthGate(reading SEP settings needs the exchanged SEP bearer from PMM-15293, so gating outside the auth gate would fire an unauthenticated request). It shows a spinner while settings load, the app when the connection isconfigured, and a centred setup screen fornot-configured/drifted.SepPagewrapped its children in a plain<div>, breaking the flex chain fromPageso nothing below it could centre vertically. It is now a growing flex column.Why
Everything the diagnostics app can do ends in an upload to a ServiceNow case. Today it renders its incident list to every admin regardless of whether this PMM instance has a connection configured, so on an unconfigured instance a user can browse, create an incident, run a script — and only discover at the very last step that nothing can be delivered. The setup screen replaces that dead end with an explanation, a promise that nothing is collected without an explicit confirmation, and a button to the settings tab that fixes it.
Likewise, offering New incident after the list request has failed only produces a second error on top of one the user cannot act on.
Deliberate trade-off: the gate fails open
configurednot-configured(no override, or a declared secret stored empty)drifted(stored values no longer satisfy the delivery plan)A failed settings read says nothing about the connection. Showing the setup screen there would tell an operator with a perfectly good connection to go configure one, so the gate fails open and lets the app report its own errors.
Open items for review
SUPPORT_DIAGNOSTICS_DOCS_URL(ui/apps/pmm/src/lib/constants.ts). The final URL is still to be defined and must be supplied before release — it is a one-line change to that constant.MedicalServicesOutlinedfrom the MUI Material set (no custom SVG). Swapping it is a one-line import change innavigation.utils.tsx.How to Test
Setup. A PMM Server with a reachable SEP backend, signed in as a PMM admin. The SEP session exchange (PMM-15293) must be working — without it the SEP settings call is unauthenticated and the gate fails open, masking every case below.
A — Unconfigured instance shows the setup screen
SEPSettings→DIAGNOSTICS_DELIVERY_INPUTShas no override).B — Layout
max-width: 480px,padding: 16px, and 32px of separation between the button and the text above and below it.C — The button reaches the settings tab
D — Configuring flips the gate
E — Drift re-gates the app
DIAGNOSTICS_DELIVERY_INPUTSoverride) and reload.F — Fail open on a settings error
/v1/sep/**settings LIST in dev tools) and reload the page.G — Loading state
H — Incident list error state
I — Rename and icon
J — Regression
SepPage, which this PR changes) — no layout or width regression.Automated
All green. Gate unit tests cover configured / not-configured / drifted / load-error / loading and the CTA target; plugin tests cover the button's error and loading behaviour.