test: retry per-credential integration matrix (do not merge) - #728
test: retry per-credential integration matrix (do not merge)#728amrit-agarwal-1 wants to merge 11 commits into
Conversation
… under both Squashed from 25 commits (kept on backup/minter-pre-rebase). - Mint a user access token with Minter in CI (ACR scoped token, masked, written into tests/.env.integration) so suites whose APIs reject PATs can run at all: insightsrtm_ (Agents, Memory, Agent Traces, Governance) and the notification service, all previously describe.skip. - describeIntegration(name, requirement, modes, body, options?) declares a suite once and expands it over init modes x credentials, naming cells [initMode][authMode]. 'any' runs under every configured credential — PAT and user token both, per the decision that neither subsumes the other. - User-token cells resolve MINTER_BASE_URL when set; PAT cells keep UIPATH_BASE_URL. getActiveAuth() gives the raw-fetch call sites the credential and host of the cell actually running. - Fixture ownership: suites create and own what they read rather than depending on tenant state; rolling time windows replace hardcoded dates; the traces suite falls back to expired spans when the pinned trace ages out. - Five tests skipped with the blocker named: the notification $filter server stall, topic groups absent from the tenant, and three agent-activity data gaps. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…mments 'any' read as 'either one will do' when it means 'run under every configured credential' — the suite executes once per credential, not once. 'both' says that. Type, call sites, and docs renamed together; no behaviour change. Also trimmed the comment blocks that had grown past their value, including a JSDoc citing a specific CI run number that would not age well. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…drop unused helpers - Unskip the 18 insightsrtm_ describe blocks in maestro processes/cases/case-instances and gate them on the user-token cell instead; they were skipped only because PAT is rejected there. - Remove the unused canAuthenticate() helper. - Make initializeServices' authMode required — every caller passes it. - Delete tests/.env.integration after the run so the minted token does not outlive the job on a reused runner.
The env var the tests read is now UIPATH_TENANT_ID. The GitHub secret keeps the UIPATH_TENANT_ID_DEV || UIPATH_TENANT_ID override pair, matching every other secret in the workflow.
15 of the 18 unskipped insightsrtm_ blocks pass under the user token. The three that do not fail on tenant data, not auth: getInstanceStats' duration fields are undefined with no completed instances in the window, and getSlaSummary's slaDueTime is empty. Also drops the worker-count comment on the integration step, per review.
The pat and user cells ran back-to-back in one job, so the run cost the sum of both credentials. Each leg now runs on its own runner via INTEGRATION_AUTH_MODE, which needs SonarCloud out of the test job: it must see both lcov reports and must run once, so it moves to a job that downloads and merges them.
| const url = `${getActiveAuth().baseUrl}/${config.orgName}/${config.tenantName}/orchestrator_/odata/TaskCatalogs(${id})`; | ||
| await fetch(url, { | ||
| method: 'DELETE', | ||
| headers: { | ||
| Authorization: `Bearer ${config.secret}`, | ||
| Authorization: `Bearer ${getActiveAuth().token}`, |
There was a problem hiding this comment.
getActiveAuth() is called twice, invoking resolveToken and resolveBaseUrl separately each time. Destructure once:
| const url = `${getActiveAuth().baseUrl}/${config.orgName}/${config.tenantName}/orchestrator_/odata/TaskCatalogs(${id})`; | |
| await fetch(url, { | |
| method: 'DELETE', | |
| headers: { | |
| Authorization: `Bearer ${config.secret}`, | |
| Authorization: `Bearer ${getActiveAuth().token}`, | |
| const { baseUrl, token } = getActiveAuth(); | |
| const url = `${baseUrl}/${config.orgName}/${config.tenantName}/orchestrator_/odata/TaskCatalogs(${id})`; | |
| await fetch(url, { | |
| method: 'DELETE', | |
| headers: { | |
| Authorization: `Bearer ${token}`, |
The failures are transient 504s and timeouts from Data Fabric, not assertion failures — a single retry absorbs them.
|
✅ No issues found. Checked for bugs and CLAUDE.md compliance. |
This reverts commit a8aa0a4.
Scratch only. Do not merge.
| const config = getTestConfig(); | ||
| const attachmentId = config.orchestratorAttachmentId!; | ||
| const base = `${getActiveAuth().baseUrl}/${config.orgName}/${config.tenantName}/orchestrator_`; | ||
| await fetch(`${base}/odata/Attachments(${attachmentId})`, { | ||
| method: 'DELETE', | ||
| headers: { Authorization: `Bearer ${getActiveAuth().token}` }, |
There was a problem hiding this comment.
getActiveAuth() is called twice — once for .baseUrl (line 35) and once for .token (line 38) — same pattern as the open thread on task-catalogs.integration.test.ts:19. Destructure once:
| const config = getTestConfig(); | |
| const attachmentId = config.orchestratorAttachmentId!; | |
| const base = `${getActiveAuth().baseUrl}/${config.orgName}/${config.tenantName}/orchestrator_`; | |
| await fetch(`${base}/odata/Attachments(${attachmentId})`, { | |
| method: 'DELETE', | |
| headers: { Authorization: `Bearer ${getActiveAuth().token}` }, | |
| const config = getTestConfig(); | |
| const { baseUrl, token } = getActiveAuth(); | |
| const base = `${baseUrl}/${config.orgName}/${config.tenantName}/orchestrator_`; | |
| await fetch(`${base}/odata/Attachments(${attachmentId})`, { | |
| method: 'DELETE', | |
| headers: { Authorization: `Bearer ${token}` }, |
Same fix needed in the create/delete afterAll around lines 123–128.
|
Review summary New finding posted this run:
|
| // skip: insightsrtm_ endpoints do not support PAT auth — requires OAuth | ||
| // skip: the duration fields (minDurationMs onward) come back undefined — the | ||
| // tenant has no completed instances in the window to compute them from. | ||
| describe.skip('getInstanceStats', () => { |
There was a problem hiding this comment.
describe.skip is not allowed for missing test data per the convention updated in this PR's own rules.md update: "Do not use describe.skip for missing test data, missing config, or flakiness."
The reason is now data-based ("no completed instances"), not an auth issue. This PR uses it.skip for identical situations elsewhere (e.g. memory.integration.test.ts, governance.integration.test.ts). Collapse the wrapping describe and move the skip inward:
| describe.skip('getInstanceStats', () => { | |
| // skip: the duration fields (minDurationMs onward) come back undefined — the | |
| // tenant has no completed instances in the window to compute them from. | |
| it.skip('should retrieve instance stats for a case', async () => { | |
| const { cases } = getServices(); | |
| await testGetInstanceStats(cases, 'cases'); | |
| }); |
| // skip: insightsrtm_ endpoints do not support PAT auth — requires OAuth | ||
| // skip: the duration fields (minDurationMs onward) come back undefined — the | ||
| // tenant has no completed instances in the window to compute them from. | ||
| describe.skip('getInstanceStats', () => { |
There was a problem hiding this comment.
Same describe.skip-for-missing-data violation as cases.integration.test.ts:237. Per the convention updated in this PR, use it.skip for a single skipped test blocked on tenant state (no completed instances to compute from):
| describe.skip('getInstanceStats', () => { | |
| // skip: the duration fields (minDurationMs onward) come back undefined — the | |
| // tenant has no completed instances in the window to compute them from. | |
| it.skip('should retrieve instance stats for a process', async () => { | |
| const { maestroProcesses } = getServices(); | |
| await testGetInstanceStats(maestroProcesses, 'processes'); | |
| }); |
|
Review summary New findings posted this run:
|
Scratch PR to re-run the pat/user split gates and see whether the extra failures reproduce or were tenant weather. Based on the Minter PR branch.
Do not merge.