Skip to Content
IntegrationsAzure DevOps

Azure DevOps Integration

Pilot integrates with Azure DevOps to receive work items and create pull requests. It supports both Azure DevOps Services (cloud) and Azure DevOps Server (on-premises).

Azure DevOps uses work items and tags rather than GitHub’s issues and labels. Pilot automatically adapts to these concepts while maintaining the same workflow.

Setup

1. Create a Personal Access Token (PAT)

  1. Go to Azure DevOpsUser Settings (top right) → Personal Access Tokens
  2. Click New Token
  3. Configure the token:
    • Name: Pilot Bot
    • Organization: Select your organization
    • Expiration: Set an appropriate expiration
    • Scopes:
      • Work Items: Read & Write
      • Code: Read & Write
      • Pull Request Threads: Read & Write

Store your PAT securely. It cannot be viewed again after creation. For production, use Azure Key Vault or environment variables.

2. Create the pilot Tag

In your Azure DevOps project:

  1. Go to BoardsWork Items
  2. Open any work item
  3. Add a tag: pilot
  4. The tag is now available for all work items in the project

3. Configure Pilot

# ~/.pilot/config.yaml adapters: azure_devops: enabled: true pat: ${AZURE_DEVOPS_PAT} organization: myorg project: MyProject repository: myrepo pilot_tag: pilot work_item_types: - User Story - Bug - Task polling: enabled: true interval: 30s

Configuration Reference

FieldTypeDefaultDescription
enabledboolfalseEnable the Azure DevOps adapter
patstringrequiredPersonal Access Token
organizationstringrequiredAzure DevOps organization name
projectstringrequiredProject name
repositorystringRepository name (defaults to project name)
base_urlstring"https://dev.azure.com"Azure DevOps instance URL
webhook_secretstringSecret for webhook basic authentication
pilot_tagstring"pilot"Tag that triggers Pilot to process a work item
work_item_types[]string["Bug", "Task", "User Story"]Work item types to process
polling.enabledboolfalseEnable polling for new work items
polling.intervalduration30sPolling interval
stale_label_cleanup.enabledbooltrueAuto-remove stale pilot-in-progress tags
stale_label_cleanup.intervalduration30mCleanup check interval
stale_label_cleanup.thresholdduration1hTag age before cleanup

Polling Mode

When polling is enabled, Pilot uses WIQL (Work Item Query Language) to find work items:

SELECT [System.Id] FROM WorkItems WHERE [System.Tags] CONTAINS 'pilot' AND ([System.State] = 'New' OR [System.State] = 'Active') AND ([System.WorkItemType] = 'Bug' OR [System.WorkItemType] = 'Task' OR [System.WorkItemType] = 'User Story') ORDER BY [System.CreatedDate] ASC

Sequential Execution

In sequential mode (default), Pilot:

  1. Finds the oldest unprocessed work item with the pilot tag
  2. Skips work items with pilot-in-progress or pilot-done tags
  3. Processes the work item and creates a PR
  4. Waits for the PR to be merged
  5. Moves to the next work item

Work Item States

Pilot filters work items by state:

StatePolled
NewYes
ActiveYes
ResolvedNo
ClosedNo

Webhook Mode

For real-time work item detection, configure Azure DevOps service hooks:

1. Set Up Service Hook

  1. Go to Project SettingsService hooks
  2. Click Create subscription
  3. Select Web Hooks
  4. Configure triggers:
    • Work item created
    • Work item updated
  5. Set URL to https://your-pilot.example.com/webhooks/azuredevops
  6. Set Basic authentication credentials if using webhook_secret

2. Configure Authentication

adapters: azure_devops: webhook_secret: ${AZURE_DEVOPS_WEBHOOK_SECRET}

Azure DevOps service hooks support basic authentication. The webhook_secret is used as the password with an empty username.

Supported Events

Event TypeBehavior
workitem.createdProcess if work item has pilot tag
workitem.updatedProcess if pilot tag was just added
workitem.deletedIgnored
workitem.restoredIgnored

Pull Request Management

When Pilot completes work, it creates a pull request in Azure DevOps Repos.

PR Features

  • Automatic branch creation: pilot/ADO-{workitem_id}
  • Work item linking: PR is linked to the source work item
  • Thread comments: Status updates posted as PR comments
  • Merge completion: Automatic merge when enabled

Branch Naming

Pilot creates branches in the format: refs/heads/pilot/ADO-{workitem_id}

PR States

StatusDescription
activePR is open and awaiting review
completedPR has been merged
abandonedPR was closed without merge

Merge Status

StatusDescription
succeededMerge completed successfully
conflictsMerge conflicts exist
failureMerge failed
queuedMerge is pending

Tags

Pilot uses tags to track work item status:

TagPurpose
pilotTriggers Pilot to process the work item
pilot-in-progressApplied while Pilot is working
pilot-doneApplied after successful completion
pilot-failedApplied if execution fails

Tag Operations

Azure DevOps stores tags as a semicolon-separated string. Pilot handles tag manipulation:

// Current: "frontend; pilot; urgent" // After adding pilot-in-progress: "frontend; pilot; urgent; pilot-in-progress"

Priority Mapping

Azure DevOps uses numeric priority fields:

Azure DevOps PriorityValuePilot Priority
Priority 11Urgent
Priority 22High
Priority 33Medium
Priority 44Low

Work Item Type Mapping

Configure which work item types Pilot should process:

work_item_types: - User Story # Requirements - Bug # Defects - Task # Implementation tasks - Feature # Large features (optional)

Task Conversion

Work items are converted to Pilot tasks:

Azure DevOps FieldPilot FieldFormat
System.IdTask IDADO-{id}
System.TitleTitleDirect
System.DescriptionDescriptionHTML cleaned
Microsoft.VSTS.Common.PriorityPriorityMapped (see above)
System.TagsLabelsSplit by semicolon
System.WorkItemTypeTypeDirect

Stale Tag Cleanup

Pilot automatically removes orphaned pilot-in-progress tags:

stale_label_cleanup: enabled: true interval: 30m threshold: 1h

The cleaner:

  • Runs every interval
  • Removes pilot-in-progress if no active execution exists and tag is older than threshold
  • Adds a comment explaining the cleanup

Self-Hosted Azure DevOps Server

For on-premises Azure DevOps Server:

adapters: azure_devops: enabled: true pat: ${AZURE_DEVOPS_PAT} base_url: https://azuredevops.mycompany.com organization: DefaultCollection project: MyProject repository: myrepo

Ensure your self-hosted instance is accessible from where Pilot runs. You may need to configure network rules or VPN access.

API Operations

Pilot uses these Azure DevOps REST API endpoints:

OperationEndpointPurpose
WIQL QueryPOST /_apis/wit/wiqlFind work items
Get Work ItemGET /_apis/wit/workitems/{id}Fetch details
Update Work ItemPATCH /_apis/wit/workitems/{id}Update tags/state
Add CommentPOST /_apis/wit/workitems/{id}/commentsPost updates
Create BranchPOST /_apis/git/repositories/{repo}/refsCreate feature branch
Create PRPOST /_apis/git/repositories/{repo}/pullrequestsSubmit changes
Complete PRPATCH /_apis/git/repositories/{repo}/pullrequests/{id}Merge PR
Get PRGET /_apis/git/repositories/{repo}/pullrequests/{id}Check status

Differences from GitHub

AspectAzure DevOpsGitHub
Issue typeWork ItemIssue
Label typeTag (semicolon-separated)Label (array)
Auth headerAuthorization: BasicAuthorization: Bearer
Webhook securityBasic authHMAC-SHA256
PR terminologyPull RequestPull Request
Merge resultcompleted statusmerged boolean
Task ID formatADO-{id}GH-{number}
PriorityNumeric field (1-4)Labels (priority:high)

Troubleshooting

Work Item Not Being Picked Up

  1. Verify the work item has the pilot tag
  2. Check that work item state is New or Active
  3. Ensure work item type is in work_item_types list
  4. Check for existing pilot-in-progress or pilot-done tags
  5. Verify PAT has Work Items Read permission

Authentication Errors

  1. Check PAT hasn’t expired
  2. Verify PAT has required scopes
  3. Ensure organization name is correct (case-sensitive)
  4. For self-hosted, verify base_url includes the collection

PR Creation Fails

  1. Check PAT has Code Write permission
  2. Verify repository name is correct
  3. Ensure default branch exists
  4. Check branch policies aren’t blocking

Webhook Not Triggering

  1. Verify service hook URL is accessible
  2. Check service hook subscription is active
  3. Verify basic auth credentials match webhook_secret
  4. Review service hook delivery history in Azure DevOps