Skip to content

feat(review): add Azure DevOps PR review support#414

Open
jmbp1999 wants to merge 1 commit intobacknotprop:mainfrom
jmbp1999:feat/azure-devops-pr-review
Open

feat(review): add Azure DevOps PR review support#414
jmbp1999 wants to merge 1 commit intobacknotprop:mainfrom
jmbp1999:feat/azure-devops-pr-review

Conversation

@jmbp1999
Copy link
Copy Markdown

Summary

Adds full Azure DevOps pull request review as a first-class platform alongside GitHub and GitLab, following the same provider pattern used throughout the codebase.

What's included

New platform support

  • Parse dev.azure.com and legacy visualstudio.com PR URLs
  • URL-encoded project/repo names decoded automatically
  • Case-insensitive pullrequest segment

Diff fetching (two-stage fallback)

  1. Try git diff <baseSha>..<headSha> locally (fast path — works when repo is cloned)
  2. Fall back to ADO REST API: fetches changed file list from PR iteration changes, then fetches old/new file content at base/head SHAs and builds a git-style unified diff using a self-contained LCS diff engine (no external deps)

Review submission

  • General comments → POST /threads via ADO REST API
  • Inline file comments → POST /threads with threadContext position info
  • Approve → PUT /reviewers/{userId} with vote: 10; user ID resolved from _apis/connectionData
  • All az rest calls use --resource 499b84ac-1321-427f-aa17-267ca6975798 to get an ADO-scoped token (ARM token is rejected by ADO APIs)

UI

  • New AzureDevOpsIcon component added
  • Review destination button shows ADO icon for ADO PRs
  • Fixed missing @plannotator/ui/config export in packages/ui/package.json (the config/ directory existed but was not declared in exports)

New types

  • AzureDevOpsPRRef, AzureDevOpsPRMetadata in pr-provider.ts
  • Platform union extended: github | gitlab | azuredevops
  • All label helpers (getPlatformLabel, getMRLabel, getMRNumberLabel, getDisplayRepo, getCliName, getCliInstallUrl) updated
  • New types re-exported from packages/server/pr.ts

Tests

22 new tests in packages/shared/pr-azuredevops.test.ts:

  • URL parsing: dev.azure.com, visualstudio.com, URL-encoded names, case-insensitive, large IDs
  • GitHub/GitLab regression coverage
  • buildFilePatch: add/edit/delete/rename, identical files, no trailing newline, hunk merging, hunk splitting
  • computeHunks: identical, add, delete, replace

All 170 tests pass (148 pre-existing + 22 new).

Prerequisites (user-side)

brew install azure-cli
az extension add --name azure-devops
az login

Usage

/plannotator-review https://dev.azure.com/{org}/{project}/_git/{repo}/pullrequest/{id}
/plannotator-review https://{org}.visualstudio.com/{project}/_git/{repo}/pullrequest/{id}

Test plan

  • URL parser covers both ADO URL formats, encoded names, large IDs
  • GitHub and GitLab URL parsing unaffected (regression tests)
  • Diff engine: add/edit/delete/rename files, hunk merging/splitting
  • 170/170 tests pass
  • Full build succeeds (review editor + hook + binary)
  • Tested against real ADO PR (zuelligpharmadevops/eZRxPlus — PR #155857): metadata fetch, diff via API, comment posting, approval vote

Adds full Azure DevOps pull request review support as a first-class
platform alongside GitHub and GitLab, following the same provider
pattern (pr-provider.ts dispatch → platform-specific implementation).

## What's new

### URL parsing
- `https://dev.azure.com/{org}/{project}/_git/{repo}/pullrequest/{id}`
- `https://{org}.visualstudio.com/{project}/_git/{repo}/pullrequest/{id}` (legacy)
- URL-encoded project/repo names decoded automatically
- Case-insensitive `pullrequest` segment

### PR diff strategy
1. Try `git diff <baseSha>..<headSha>` locally (fast path)
2. If commits not present, try `git fetch origin` + retry
3. Fall back to ADO REST API: iterates PR change entries, fetches
   old/new file content at the base/head SHAs, builds a git-style
   unified diff using a self-contained LCS diff engine (no deps)

### Submitting reviews
- General comments → `POST /threads` via ADO REST API
- Inline file comments → `POST /threads` with `threadContext` position
- Approve → `PUT /reviewers/{userId}` with `vote: 10`
- User ID resolved from `_apis/connectionData` at submit time

### Auth
- All `az rest` calls use `--resource 499b84ac-1321-427f-aa17-267ca6975798`
  to acquire an ADO-scoped token (ARM token rejected by ADO APIs)
- `az repos pr show` uses ADO extension which handles auth natively

### UI
- `AzureDevOpsIcon` component added to `packages/ui/components/`
- Review destination button shows the ADO icon when reviewing ADO PRs
- `@plannotator/ui/config` export added to `packages/ui/package.json`
  (was missing — `config/index.ts` existed but was undeclared)

### Types
- `AzureDevOpsPRRef` and `AzureDevOpsPRMetadata` added to `pr-provider.ts`
- `Platform` union extended to `"github" | "gitlab" | "azuredevops"`
- All label helpers (`getPlatformLabel`, `getMRLabel`, etc.) updated
- New types re-exported from `packages/server/pr.ts`

### Tests (22 new)
- Full URL parsing coverage (dev.azure.com, visualstudio.com, encoded,
  case-insensitive, large IDs)
- GitHub/GitLab regression tests
- `buildFilePatch`: add/edit/delete/rename, empty diff, no-trailing-newline,
  hunk merging for nearby changes, hunk splitting for distant changes
- `computeHunks`: identical, add, delete, replace

## Prerequisites (user-side)
```bash
brew install azure-cli
az extension add --name azure-devops
az login
```

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant