From 8bd192cb45ca7b06fa022ae642f6dd87888752ca Mon Sep 17 00:00:00 2001 From: daniel-lxs Date: Thu, 30 Jul 2026 01:01:37 -0500 Subject: [PATCH] fix(ado): request connectionData with the 7.1-preview api-version Azure DevOps only serves /_apis/connectionData at preview api-versions: plain 7.1 (and 7.0) always answer 400 with "The -preview flag must be supplied". That made getAdoDeploymentUser throw on every call, silently degrading Roomote's own-comment detection on ADO PR and work item comments (isDeploymentTokenAuthor fails open), and broke ADO approve/request-changes reviewer votes, which resolve the voting identity through the same resource. Use a dedicated ADO_CONNECTION_DATA_API_VERSION = '7.1-preview' for the two connectionData call sites, matching the constant apps/web already uses for its vssps connectionData probe. The shared ADO_API_VERSION stays 7.1 for the GA resources. Co-Authored-By: Claude Fable 5 --- .changeset/ado-connection-data-preview.md | 6 ++++++ packages/ado/src/__tests__/api.test.ts | 4 +++- packages/ado/src/api.ts | 5 ++++- .../__tests__/source-control-pull-request-writes.test.ts | 2 +- .../lib/pull-requests/source-control-pull-request-writes.ts | 5 ++++- 5 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 .changeset/ado-connection-data-preview.md diff --git a/.changeset/ado-connection-data-preview.md b/.changeset/ado-connection-data-preview.md new file mode 100644 index 000000000..adcd92881 --- /dev/null +++ b/.changeset/ado-connection-data-preview.md @@ -0,0 +1,6 @@ +--- +'@roomote/ado': patch +'@roomote/sdk': patch +--- + +Request Azure DevOps `/_apis/connectionData` with api-version `7.1-preview`. The resource is preview-only, so the plain `7.1` version always failed with a 400, which silently disabled Roomote's own-comment detection on Azure DevOps pull request and work item comments and broke approve/request-changes reviewer votes on pull requests. diff --git a/packages/ado/src/__tests__/api.test.ts b/packages/ado/src/__tests__/api.test.ts index 6a74e034a..d3e13a0ac 100644 --- a/packages/ado/src/__tests__/api.test.ts +++ b/packages/ado/src/__tests__/api.test.ts @@ -771,8 +771,10 @@ describe('Azure DevOps API helpers', () => { }); expect(second).toEqual(first); expect(fetchMock).toHaveBeenCalledTimes(1); + // connectionData is preview-only: Azure DevOps 400s on api-version=7.1 + // unless the -preview suffix is present. expect(fetchMock).toHaveBeenCalledWith( - 'https://dev.azure.com/acme/_apis/connectionData?api-version=7.1', + 'https://dev.azure.com/acme/_apis/connectionData?api-version=7.1-preview', expect.objectContaining({ method: 'GET', headers: expect.objectContaining({ diff --git a/packages/ado/src/api.ts b/packages/ado/src/api.ts index 19d4a6755..f6168ce85 100644 --- a/packages/ado/src/api.ts +++ b/packages/ado/src/api.ts @@ -23,6 +23,9 @@ export * from './ci'; const ADO_PROVIDER = 'ado' satisfies SourceControlProvider; const DEFAULT_ADO_BASE_URL = 'https://dev.azure.com'; export const ADO_API_VERSION = '7.1'; +// `/_apis/connectionData` is a preview-only resource: Azure DevOps answers +// plain `7.1` (and `7.0`) with a 400 demanding the `-preview` suffix. +const ADO_CONNECTION_DATA_API_VERSION = '7.1-preview'; const ADO_TOKEN_VALIDATION_TIMEOUT_MS = 10_000; // Fits the whole TF401444 sentence (~204 chars with its three GUIDs) while // still keeping pathological provider messages toast-sized. @@ -807,7 +810,7 @@ export async function getAdoDeploymentUser(options?: { organizationApiBaseUrl, fetchImpl: options?.fetchImpl, path: '/_apis/connectionData', - params: { 'api-version': ADO_API_VERSION }, + params: { 'api-version': ADO_CONNECTION_DATA_API_VERSION }, token: adoToken, schema: adoConnectionDataSchema, }); diff --git a/packages/sdk/src/server/lib/pull-requests/__tests__/source-control-pull-request-writes.test.ts b/packages/sdk/src/server/lib/pull-requests/__tests__/source-control-pull-request-writes.test.ts index b7fc871e5..b4c1d9766 100644 --- a/packages/sdk/src/server/lib/pull-requests/__tests__/source-control-pull-request-writes.test.ts +++ b/packages/sdk/src/server/lib/pull-requests/__tests__/source-control-pull-request-writes.test.ts @@ -300,7 +300,7 @@ describe('writeSourceControlPullRequestForTaskRun', () => { expect(fetchImpl).toHaveBeenNthCalledWith( 1, - 'https://dev.azure.com/acme/_apis/connectionData?api-version=7.1', + 'https://dev.azure.com/acme/_apis/connectionData?api-version=7.1-preview', expect.objectContaining({ method: 'GET', headers: expect.objectContaining({ diff --git a/packages/sdk/src/server/lib/pull-requests/source-control-pull-request-writes.ts b/packages/sdk/src/server/lib/pull-requests/source-control-pull-request-writes.ts index 39aee8b03..ec93eac48 100644 --- a/packages/sdk/src/server/lib/pull-requests/source-control-pull-request-writes.ts +++ b/packages/sdk/src/server/lib/pull-requests/source-control-pull-request-writes.ts @@ -34,6 +34,9 @@ import { } from './source-control-pull-request-shared'; const ADO_API_VERSION = '7.1'; +// `/_apis/connectionData` is a preview-only resource: Azure DevOps answers +// plain `7.1` (and `7.0`) with a 400 demanding the `-preview` suffix. +const ADO_CONNECTION_DATA_API_VERSION = '7.1-preview'; /** * Optional id fields from LLM/tool clients often arrive as `""` or whitespace @@ -1351,7 +1354,7 @@ async function writeAdoPullRequest({ const connectionData = await requestJson({ fetchImpl, url: buildApiUrl(organizationApiBaseUrl, '/_apis/connectionData', { - 'api-version': ADO_API_VERSION, + 'api-version': ADO_CONNECTION_DATA_API_VERSION, }), tokenHeader, schema: adoConnectionDataSchema,