Skip to content

Feat/azure-devops integration#4642

Open
mzxchandra wants to merge 15 commits into
simstudioai:stagingfrom
mzxchandra:feat/azure-devops-integration
Open

Feat/azure-devops integration#4642
mzxchandra wants to merge 15 commits into
simstudioai:stagingfrom
mzxchandra:feat/azure-devops-integration

Conversation

@mzxchandra
Copy link
Copy Markdown

Summary

Adds Azure DevOps as a new integration to Sim, covering the two highest-value enterprise use cases: pipeline failure triage and work item lifecycle automation.

Azure DevOps is the primary DevOps platform for Microsoft-stack enterprises (~52,000 US companies, dominant in automotive, financial services, and government). Sim already has GitHub and GitLab — this completes the engineering platform story for the other major segment. no existing PR for this integration.

What's included

16 tools across 3 service areas

Pipelines

  • azureDevopsListPipelines — enumerate pipelines in a project
  • azureDevopsGetPipeline — get pipeline metadata
  • azureDevopsListPipelineRuns — list runs with status/result
  • azureDevopsGetPipelineRun — get a specific run's details

Build

  • azureDevopsListBuilds — list builds with filter support
  • azureDevopsListBuildLogs — list log files for a build
  • azureDevopsGetBuildLog — fetch raw log text for a specific step
  • azureDevopsGetBuildTimeline — get execution timeline with per-task results
  • azureDevopsGetWorkItemsBetweenBuilds — surface work items that landed between two builds

Work Item Tracking

  • azureDevopsQueryWorkItems — WIQL query with internal hydration (returns full field data, not just IDs)
  • azureDevopsGetWorkItem — get a single work item with all fields
  • azureDevopsGetWorkItemsBatch — bulk fetch by IDs
  • azureDevopsCreateWorkItem — create with structured fields (title, description, priority, assignee, area path, iteration, tags)
  • azureDevopsUpdateWorkItem — update any field combination
  • azureDevopsAddComment — add internal or public comment
  • azureDevopsGetComments — read comment history

Block

Single azure_devops block with all 16 operations, structured subfields per
operation (no raw JSON), conditional field visibility based on selected operation.

2 webhook triggers

  • azure_devops_build_failed — fires on build.complete where result is failed/canceled/partiallySucceeded
  • azure_devops_work_item_created — fires on workitem.created with normalized field output

Auth

Personal Access Token via HTTP Basic auth (Authorization: Basic base64(:PAT)).

Required PAT scopes:

  • Build: Read — covers both Build API and Pipelines API
  • Work Items: Read & Write

Targets Azure DevOps Services (cloud) only. API version: 7.2.

Fixes #(issue)

Type of Change

  • Bug fix
  • [ ✅] New feature
  • Breaking change
  • Documentation
  • Other: ___________

Testing

Tested by creating azure devops workflows in sim canvas and verifying successful runs, and followed repo rules for integrations, triggers, and blocks.

Checklist

  • [✅ ] Code follows project style guidelines
  • [✅ ] Self-reviewed my changes
  • [✅ ] Tests added/updated and passing
  • [ ✅] No new warnings introduced
  • [✅ ] I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Screenshots/Videos

Copilot AI review requested due to automatic review settings May 17, 2026 06:49
@vercel
Copy link
Copy Markdown

vercel Bot commented May 17, 2026

@mzxchandra is attempting to deploy a commit to the Sim Team on Vercel.

A member of the Team first needs to authorize it.

@cursor
Copy link
Copy Markdown

cursor Bot commented May 17, 2026

PR Summary

Medium Risk
Adds a new integration surface (16 tools + webhook provider + triggers) that hits external Azure DevOps APIs and introduces new parameter coercion/JSON-patch logic, so regressions are possible but changes are mostly additive and well-tested.

Overview
Adds Azure DevOps as a first-class integration across the product.

Introduces a new azure_devops block with a single operation dropdown covering pipelines, builds/logs/timelines, and work items/comments, including execution-time param normalization (number coercion and date normalization) and trigger sub-block wiring.

Implements and registers 16 new Azure DevOps tools (PAT Basic auth) plus shared mapping/formatting utilities and a comprehensive Vitest suite validating request builders and response transforms.

Adds Azure DevOps webhook support via a new provider handler and three triggers (build_failed, work_item_created, and a generic webhook envelope), and updates docs, icon mapping, and integration metadata so Azure DevOps appears in docs/landing UI.

Reviewed by Cursor Bugbot for commit 64fd6fc. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread apps/sim/tools/azure_devops/list_pipelines.ts
placeholder: 'Numeric effort (Issue only)',
condition: { field: 'operation', value: 'azure_devops_update_work_item' },
mode: 'advanced',
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate subBlock IDs for create/update field pairs

Low Severity

Six subBlock fields (effort, startDate, targetDate, activity, remainingWork, completedWork) each appear twice in the subBlocks array with the same id — once for azure_devops_create_work_item and once for azure_devops_update_work_item. Since the workflow store and subBlocks.find() key by id, the second entry silently overwrites or shadows the first during initialization. This works today only because both entries share the same id and the stored value is reused regardless of which condition is active, but it's fragile and would break if the create/update variants ever diverged.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4aeed9f. Configure here.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Azure DevOps as a first-class Sim integration, including workflow block support, tool execution coverage, webhook trigger handling, landing-page metadata, docs, icons, and tests.

Changes:

  • Adds 16 Azure DevOps tools for pipelines, builds, work items, and comments, with registry/block wiring.
  • Adds Azure DevOps webhook triggers and provider-specific event matching/input formatting.
  • Adds integration/docs metadata, icons, and Vitest coverage for block/tool contracts.

Reviewed changes

Copilot reviewed 41 out of 41 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
apps/sim/triggers/registry.ts Registers Azure DevOps triggers.
apps/sim/triggers/azure_devops/work_item_created.ts Adds work item created trigger config.
apps/sim/triggers/azure_devops/webhook.ts Adds generic Azure DevOps webhook trigger config.
apps/sim/triggers/azure_devops/utils.ts Adds trigger matching, setup instructions, and payload formatting helpers.
apps/sim/triggers/azure_devops/index.ts Exports Azure DevOps trigger configs.
apps/sim/triggers/azure_devops/build_failed.ts Adds build failed trigger config.
apps/sim/tools/registry.ts Registers Azure DevOps tools.
apps/sim/tools/azure_devops/utils.ts Adds shared Azure DevOps work item/comment helpers.
apps/sim/tools/azure_devops/update_work_item.ts Adds update work item tool.
apps/sim/tools/azure_devops/types.ts Defines Azure DevOps tool parameter/response types.
apps/sim/tools/azure_devops/query_work_items.ts Adds WIQL query tool with hydration.
apps/sim/tools/azure_devops/list_pipelines.ts Adds list pipelines tool.
apps/sim/tools/azure_devops/list_pipeline_runs.ts Adds list pipeline runs tool.
apps/sim/tools/azure_devops/list_builds.ts Adds list builds tool.
apps/sim/tools/azure_devops/list_build_logs.ts Adds list build logs tool.
apps/sim/tools/azure_devops/index.ts Exports Azure DevOps tools.
apps/sim/tools/azure_devops/get_work_items_between_builds.ts Adds work-items-between-builds tool.
apps/sim/tools/azure_devops/get_work_items_batch.ts Adds batch work item fetch tool.
apps/sim/tools/azure_devops/get_work_item.ts Adds single work item fetch tool.
apps/sim/tools/azure_devops/get_pipeline.ts Adds get pipeline tool.
apps/sim/tools/azure_devops/get_pipeline_run.ts Adds get pipeline run tool.
apps/sim/tools/azure_devops/get_comments.ts Adds list comments tool.
apps/sim/tools/azure_devops/get_build_timeline.ts Adds build timeline tool.
apps/sim/tools/azure_devops/get_build_log.ts Adds build log fetch tool.
apps/sim/tools/azure_devops/create_work_item.ts Adds create work item tool.
apps/sim/tools/azure_devops/azure-devops.test.ts Adds tool contract/request/transform tests.
apps/sim/tools/azure_devops/add_comment.ts Adds add comment tool.
apps/sim/lib/webhooks/providers/registry.ts Registers Azure DevOps webhook provider handler.
apps/sim/lib/webhooks/providers/azure-devops.ts Adds Azure DevOps webhook event matching and input formatting.
apps/sim/components/icons.tsx Adds Azure DevOps icon for app UI.
apps/sim/blocks/registry.ts Registers Azure DevOps block.
apps/sim/blocks/blocks/azure_devops.ts Adds Azure DevOps block config and tool/trigger mapping.
apps/sim/blocks/blocks/azure_devops.test.ts Adds block contract tests.
apps/sim/app/(landing)/integrations/data/integrations.json Adds Azure DevOps landing integration metadata and updates generated entries.
apps/sim/app/(landing)/integrations/data/icon-mapping.ts Maps Azure DevOps integration to icon.
apps/docs/content/docs/en/triggers/meta.json Adds Azure DevOps trigger docs entry.
apps/docs/content/docs/en/triggers/azure_devops.mdx Adds Azure DevOps trigger docs.
apps/docs/content/docs/en/tools/meta.json Adds Azure DevOps tool docs entry.
apps/docs/content/docs/en/tools/azure_devops.mdx Adds Azure DevOps tool docs.
apps/docs/components/ui/icon-mapping.ts Maps Azure DevOps docs card to icon.
apps/docs/components/icons.tsx Adds Azure DevOps icon for docs UI.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +143 to +144
body: (params) => {
const ops: AzureDevOpsJsonPatchOp[] = []
},
{
"name": "Get Work Items Batch",
"description": "Fetch full details for multiple work items by ID from Azure DevOps in a single call. Pass comma-separated IDs (e.g. "

### `azure_devops_get_work_items_batch`

Fetch full details for multiple work items by ID from Azure DevOps in a single call. Pass comma-separated IDs (e.g.
Comment on lines +1 to +3
---
title: Azure Devops
description: Available Azure Devops triggers for automating workflows
color="#FFFFFF"
/>

Azure Devops provides 3 triggers for automating workflows based on events.
Comment on lines +111 to +127
const expectedIds = [
'azure_devops_add_comment',
'azure_devops_create_work_item',
'azure_devops_get_build_log',
'azure_devops_get_comments',
'azure_devops_get_pipeline',
'azure_devops_get_pipeline_run',
'azure_devops_get_work_item',
'azure_devops_get_work_items_batch',
'azure_devops_get_work_items_between_builds',
'azure_devops_list_build_logs',
'azure_devops_list_builds',
'azure_devops_list_pipeline_runs',
'azure_devops_list_pipelines',
'azure_devops_query_work_items',
'azure_devops_update_work_item',
]
Comment on lines +82 to +90
const detailsResponse = await fetch(detailsUrl.toString(), {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${btoa(`:${params!.accessToken}`)}`,
},
})

const detailsData = await detailsResponse.json()
Comment on lines +49 to +60
export function mapWorkItem(raw: AzureDevOpsRawWorkItem): AzureDevOpsWorkItem {
const fields = raw.fields ?? {}
return {
id: raw.id,
title: (fields['System.Title'] as string | undefined) ?? '',
state: (fields['System.State'] as string | undefined) ?? '',
workItemType: (fields['System.WorkItemType'] as string | undefined) ?? '',
assignedTo:
(fields['System.AssignedTo'] as { displayName?: string } | undefined)?.displayName ?? null,
areaPath: (fields['System.AreaPath'] as string | undefined) ?? '',
url: raw.url,
}
title: 'Area Path',
type: 'short-input',
placeholder: 'e.g. MyProject\\Team',
condition: { field: 'operation', value: 'azure_devops_create_work_item' },
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 17, 2026

Greptile Summary

This PR adds Azure DevOps as a new integration with 16 tools covering Pipelines, Builds, and Work Items, plus two webhook triggers (build.complete and workitem.created) and a generic pass-through webhook trigger.

  • 16 tools registered across pipeline, build, and work-item APIs using PAT-based Basic auth; shared mapping utilities (mapWorkItem, mapComment, appendFieldPatchOp) keep the per-tool files thin.
  • 2 webhook triggers + a generic service-hook trigger; a new azureDevOpsHandler routes payloads by triggerId/eventType in formatInput.
  • Two correctness bugs stand out: formatWorkItemCreatedInput in triggers/azure_devops/utils.ts casts IdentityRef objects (System.CreatedBy, System.AssignedTo) as plain strings, so the workitem.created trigger outputs the raw object instead of a display name; and query_work_items.ts makes a secondary batch fetch with no HTTP error check, silently returning zero results when the fetch fails.

Confidence Score: 3/5

Hold for the two correctness fixes before merging — the identity-field bug causes the work item trigger to output raw objects where strings are expected, and the missing error check in query_work_items silently hides batch API failures.

The formatWorkItemCreatedInput identity-field cast affects every workitem.created webhook delivery — createdBy and assignedTo will always carry the raw IdentityRef object rather than the display name, breaking any workflow that reads those fields. The query_work_items secondary-fetch issue turns an API auth or server error into a silent 'no results' response, which is particularly hard to diagnose. Both affect the two highest-value use cases called out in the PR description.

apps/sim/triggers/azure_devops/utils.ts (identity-field cast and build-result filter) and apps/sim/tools/azure_devops/query_work_items.ts (missing error check on secondary fetch) need the most attention before merge.

Important Files Changed

Filename Overview
apps/sim/triggers/azure_devops/utils.ts Core webhook formatting utilities with two bugs: IdentityRef fields cast as plain strings (wrong values for createdBy/assignedTo in formatWorkItemCreatedInput), and build-failed filter fires on undefined result (false positives).
apps/sim/tools/azure_devops/query_work_items.ts Two-phase WIQL query + batch-fetch pattern; secondary fetch lacks an error check, so HTTP failures silently return an empty work item list instead of surfacing the error.
apps/sim/tools/azure_devops/update_work_item.ts Generates a JSON Patch body for work item updates; no guard against sending an empty patch array when all optional fields are omitted, which will trigger a 400 from Azure DevOps.
apps/sim/lib/webhooks/providers/azure-devops.ts Webhook provider handler; routes matchEvent and formatInput correctly by triggerId/eventType. Static imports from the same module that's also dynamically imported in matchEvent is a minor redundancy but not a bug.
apps/sim/blocks/blocks/azure_devops.ts Block config with 16 operations, conditional subBlock visibility, and correct user-only visibility on accessToken in tools. Duplicate subBlock IDs for create vs. update path are intentional conditional duplication, not errors.
apps/sim/tools/azure_devops/create_work_item.ts Creates Basic-process work items via JSON Patch. Uses correct user-only visibility for the PAT, builds ops correctly, and delegates mapping to shared utilities.
apps/sim/tools/azure_devops/utils.ts Shared mapping utilities (mapWorkItem, mapComment, appendFieldPatchOp); correctly handles IdentityRef objects via ?.displayName in REST API responses. No issues found.
apps/sim/tools/azure_devops/types.ts Type definitions for all 16 tool operations; well-structured with clear separation per tool. No issues found.

Sequence Diagram

sequenceDiagram
    participant AzDO as Azure DevOps
    participant WH as Webhook Handler
    participant ME as matchEvent
    participant FI as formatInput
    participant WF as Workflow

    AzDO->>WH: POST /webhook
    WH->>ME: matchEvent(triggerId, body)
    alt "triggerId == azure_devops_webhook"
        ME-->>WH: true
    else "triggerId == azure_devops_build_failed"
        ME->>ME: isAzureDevOpsEventMatch
        ME-->>WH: "result !== succeeded"
    else "triggerId == azure_devops_work_item_created"
        ME->>ME: isAzureDevOpsEventMatch
        ME-->>WH: "eventType === workitem.created"
    end
    WH->>FI: formatInput(body, webhook)
    alt "triggerId == azure_devops_webhook"
        FI-->>WH: formatWebhookEnvelopeInput
    else "eventType == build.complete"
        FI-->>WH: formatBuildCompleteInput
    else "eventType == workitem.created"
        FI-->>WH: formatWorkItemCreatedInput - IdentityRef cast bug
    end
    WH->>WF: Trigger with normalized input

    Note over WF: azure_devops_query_work_items
    WF->>AzDO: POST /wit/wiql
    AzDO-->>WF: work item refs
    WF->>AzDO: GET /wit/workitems?ids - no error check
    AzDO-->>WF: work item details
    WF-->>WF: Return results
Loading

Reviews (1): Last reviewed commit: "committing the tests for azure devops to..." | Re-trigger Greptile

Comment thread apps/sim/triggers/azure_devops/utils.ts Outdated
Comment on lines +82 to +90
const detailsResponse = await fetch(detailsUrl.toString(), {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${btoa(`:${params!.accessToken}`)}`,
},
})

const detailsData = await detailsResponse.json()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 The secondary fetch for work item details has no error check. If the batch endpoint returns a non-2xx response (e.g., 401, 403, or 500), detailsResponse.json() is called regardless. An error body has no value property, so detailsData.value ?? [] returns [] and the tool outputs "No work item details found." — a misleading success that silently swallows the actual API failure.

Comment thread apps/sim/tools/azure_devops/update_work_item.ts
Comment thread apps/sim/triggers/azure_devops/utils.ts Outdated
mzxchandra and others added 3 commits May 17, 2026 02:04
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 64fd6fc. Configure here.

params.priority === undefined && !params.state && params.effort === undefined &&
!params.startDate && !params.targetDate && !params.activity &&
params.remainingWork === undefined && params.completedWork === undefined && !params.tags) {
throw new Error('Update Work Item requires at least one field to update.')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update body throws but test expects empty array

Medium Severity

The body function in updateWorkItemTool throws an Error when no update fields are provided, but the test on line 320 asserts that buildBody(updateWorkItemTool, { ...baseParams, workItemId: 101 }) returns []. Since no optional fields are set, the guard condition is fully satisfied and the function throws, causing this test to fail.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 64fd6fc. Configure here.

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.

2 participants