Skip to content

feat(providers): add Azure DevOps support for PR operations#30

Merged
aletc1 merged 1 commit intodevfrom
claude/magical-lalande-48c96c
Apr 20, 2026
Merged

feat(providers): add Azure DevOps support for PR operations#30
aletc1 merged 1 commit intodevfrom
claude/magical-lalande-48c96c

Conversation

@aletc1
Copy link
Copy Markdown
Owner

@aletc1 aletc1 commented Apr 20, 2026

Summary

  • Auto-detect Azure DevOps remotes (dev.azure.com, *.visualstudio.com, HTTPS + SSH variants) from the git origin URL and route PR status, merge, rename, and Create-PR through the az CLI (azure-devops extension). GitHub path stays byte-identical — a thin dispatcher in src/main/lib/git/providers/ forwards by provider and the PR widget / status bar / rename dialog keep consuming the existing shape.
  • Silent detection of az CLI + azure-devops extension + az account. Queries degrade to null / [] on any failure so the 30s poll never throws; mutations throw toast-ready messages (missing CLI, missing extension, not logged in). Merge conflicts surface via the existing MERGE_CONFLICT: contract — no renderer changes needed.
  • Adds a nullable git_project column (Drizzle migration 0010) so the Azure project slug doesn't collide with git_owner (still used to build github.com/{owner}.png avatars). Extends getPrContext to return provider info; pr-message.ts and git-activity.ts now emit and parse az repos pr create.

v1 scope (confirmed before implementation)

  • Cloud only — on-prem Azure DevOps Server URLs stay "unknown provider" (same behavior as gitlab/bitbucket today).
  • Azure PR comments stubbed to [] (threads are a different data model — deferred).
  • Additions/deletions report 0 for Azure PRs (widget handles zero; git diff --numstat planned for v2).
  • method: "rebase" falls back to non-squash merge on Azure with a console warn (az CLI only exposes --squash <bool>).

Test plan

GitHub regression (must be byte-identical)

  • Open a GitHub project → PR widget shows existing PR with checks, review state, mergeability.
  • Rename PR via dialog → succeeds, refreshes within 10s.
  • Merge PR (squash) → succeeds, widget shows "Merged".
  • Create PR on fresh branch → browser opens github.com/…/compare/…?expand=1.
  • Agent "Create PR" prompt → Claude runs gh pr create, activity badge appears.
  • Induce a conflict → merge surfaces MERGE_CONFLICT toast with "Sync with Main".
  • Uninstall gh temporarily → widget shows empty state, no toast, no crash.

Azure DevOps happy path

  • Import an Azure DevOps repo → project row has gitProvider="azure", gitOwner=<org>, gitProject=<project>, gitRepo=<repo>.
  • Open a PR on web → widget populates within 30s with title, state, reviewers, policies.
  • Rename via dialog → reflected on dev.azure.com.
  • Merge (squash) → PR completes on Azure, source branch deleted, widget → "Merged".
  • Create PR button → opens dev.azure.com/…/pullrequestcreate?sourceRef=…&targetRef=….
  • Agent mode → pr-message.ts emits az repos pr create with correct org/project/repo and --output json.
  • Settings › Repository section shows org/project/repo with an "Azure DevOps" external-link button.

Azure failure modes (each must toast OR silently show empty state — never crash)

  • az not on PATH → query silent; merge shows "Azure CLI not found" toast.
  • azure-devops extension missing → merge shows "Azure DevOps extension missing. Run: az extension add --name azure-devops".
  • az logout → merge shows "Not logged in to Azure. Run az login and retry".
  • No PR for branch → widget shows "No pull request for this branch yet" (silent).
  • Network error during az repos pr show → query returns null, no toast, console warn only.

URL parsing sanity check

  • https://dev.azure.com/myorg/MyProject/_git/myrepo.git{ provider: "azure", owner: "myorg", project: "MyProject", repo: "myrepo" }
  • https://myorg@dev.azure.com/myorg/MyProject/_git/myrepo → same
  • git@ssh.dev.azure.com:v3/myorg/MyProject/myrepo → same
  • https://myorg.visualstudio.com/DefaultCollection/MyProject/_git/myrepo → same
  • https://github.com/owner/repo still returns { provider: "github", project: null }

Build / typecheck

  • bun run build succeeds (30.95s).
  • tsc --noEmit clean on all modified/new files (6 pre-existing errors in src/renderer/components/update-banner.tsx are unrelated).

Deferred to v2

  • On-prem Azure DevOps Server (custom hostnames).
  • PR comments for Azure (az repos pr thread list with thread-model mapping).
  • Accurate additions/deletions on Azure PRs.
  • True rebase merge strategy on Azure.

🤖 Generated with Claude Code

Detects dev.azure.com / visualstudio.com remotes automatically and routes
PR status, merge, title updates, and Create-PR flows through the az CLI
(azure-devops extension). GitHub path is unchanged — a thin dispatcher in
src/main/lib/git/providers forwards by provider, and the PR widget, status
bar, and rename dialog consume the existing provider-agnostic shape.

Silent detection of az / extension / login; queries degrade to null on any
failure so the 30s poll never throws, mutations throw toast-ready messages
(missing CLI, missing extension, not logged in). Conflict errors surface
via the existing MERGE_CONFLICT: contract so no renderer changes are
needed.

Also adds a new git_project column (Drizzle migration 0010) to store the
Azure project slug without colliding with gitOwner, extends getPrContext
to return provider info for the agent prompt, and teaches pr-message.ts
and git-activity.ts to emit and parse az repos pr create.

v1 scope: cloud only; PR comments stubbed to [] for Azure; additions/
deletions report 0; rebase merge falls back to non-squash. On-prem Azure
DevOps Server is out of scope.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aletc1 aletc1 merged commit 25f5b3e into dev Apr 20, 2026
@aletc1 aletc1 deleted the claude/magical-lalande-48c96c branch April 20, 2026 17:37
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