Azure DevOps Pipelines
Azure DevOps integration actions allow workflows to trigger pipelines and manage pull requests directly using your installed Azure DevOps integration.
Prerequisites
- An Azure DevOps integration installed in your Port organization in Single Account mode.
- Actions processing must be enabled on your integration:
- Hosted by Port / UI installations: actions processing is enabled automatically.
- Self-hosted (Helm or Docker): actions processing is disabled by default and must be explicitly enabled. See Enable actions processing (self-hosted) below.
- Your Azure DevOps credentials must be able to perform the operations you invoke:
- Pipeline actions: queue pipeline runs and manage service hooks (webhooks) used for status reporting.
- Pull request actions: read and write code in the target repository.
- For pipeline actions, the pipeline you want to trigger must exist in the target Azure DevOps project.
Enable actions processing (self-hosted)
If you installed the Azure DevOps Ocean integration as hosted by Port (via the UI), actions processing is enabled automatically and you can skip to Configuration.
For self-hosted deployments (Kubernetes/Helm or Docker), the actions processor is disabled by default. You need to enable it explicitly using the flags below, depending on how you deployed the integration:
- Helm
- Docker
Pass the following flags when installing or upgrading the Helm chart:
helm upgrade --install azure-devops port-labs/port-ocean \
--set actionsProcessor.enabled=true \
--set liveEvents.baseUrl=<YOUR_INTEGRATION_BASE_URL> \
# ... rest of your values
actionsProcessor.enabled=true- enables the actions processor so the integration can receive and execute Azure DevOps pipeline trigger requests from Port.liveEvents.baseUrl=<YOUR_INTEGRATION_BASE_URL>- setsOCEAN__BASE_URL, which is required whenreportPipelineStatusis enabled (the default). Port uses this URL to receive webhook events from Azure DevOps and update the action run status in real time. The URL must be reachable from Azure DevOps.
Add the following environment variables to your Docker run command or docker-compose configuration:
docker run \
-e OCEAN__ACTIONS_PROCESSOR__ENABLED=true \
-e OCEAN__BASE_URL=<YOUR_INTEGRATION_BASE_URL> \
# ... rest of your env vars
ghcr.io/port-labs/port-ocean-azure-devops:latest
reportPipelineStatus?By default, Port automatically updates the workflow node status when the triggered Azure DevOps pipeline finishes. This requires Azure DevOps to send a pipeline run-state-changed webhook event back to the integration. If the integration's base URL is not set, Port cannot receive this callback and the run status will not be updated automatically.
To disable this behavior, set reportPipelineStatus: false in the execution properties of your action node, or turn off the Report pipeline status toggle in the UI.
Configuration
All Azure DevOps integration actions share the same node structure:
| Field | Type | Description |
|---|---|---|
type | string | Required. Must be "INTEGRATION_ACTION" |
installationId | string | Required. Your Azure DevOps integration installation ID |
integrationProvider | string | Required. Must be "azure-devops" |
integrationInvocationType | enum | Required. One of the values listed in available actions |
integrationActionExecutionProperties | object | Required. Properties for the selected action |
The remaining sections describe the execution properties of each action.
Execution properties are validated strictly. Pass strings to string properties (including pullRequestId and line) and booleans to boolean properties. A boolean property that receives the string "true" is rejected.
Available actions
Each action is selected with the integrationInvocationType field:
| Action | Invocation type | Description |
|---|---|---|
| Trigger a pipeline | trigger_pipeline | Queue a pipeline run and optionally wait for its result |
| Manage a pull request | create_pull_request | Open a pull request between two branches |
| Manage a pull request | update_pull_request | Change a pull request's title, description, status, target branch, or completion options |
| Manage a pull request | close_pull_request | Abandon a pull request without merging it |
| Manage a pull request | merge_pull_request | Complete a pull request by merging its source branch |
| Add a pull request label | update_pull_request_labels | Add a label to a pull request |
| Create a pull request comment thread | create_pull_request_thread | Add a comment thread to a pull request, optionally anchored to a file and line |
The remaining sections describe the execution properties of each action.
Pipeline actions
Trigger a pipeline
Queues a run of an existing Azure DevOps pipeline. Set integrationInvocationType to trigger_pipeline.
Execution properties
| Field | Type | Description |
|---|---|---|
project | string | Required. Azure DevOps project name or ID that contains the pipeline |
pipelineId | string | Required. Numeric pipeline ID (for example, 12 from https://dev.azure.com/org/project/_build?definitionId=12) |
branch | string | Branch (ref) to run the pipeline on (for example, main). When omitted, the pipeline's default branch is used |
templateParameters | object | Runtime template parameters declared in the pipeline YAML |
variables | object | Queue-time variables to pass to the pipeline run |
reportPipelineStatus | boolean | Whether to report pipeline completion status back to Port (default: true) |
Basic example
Trigger an Azure DevOps pipeline (click to expand)
Trigger an Azure DevOps pipeline, passing environment and version from the trigger inputs:
{
"identifier": "trigger-azure-devops-pipeline",
"title": "Trigger Azure DevOps Pipeline",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "your-installation-id",
"integrationProvider": "azure-devops",
"integrationInvocationType": "trigger_pipeline",
"integrationActionExecutionProperties": {
"project": "My Project",
"pipelineId": "12",
"branch": "{{ .outputs.trigger.branch }}",
"templateParameters": {
"environment": "{{ .outputs.trigger.environment }}",
"version": "{{ .outputs.trigger.version }}"
}
}
}
}
Template parameters and variables
Template parameters and variables (click to expand)
Pass runtime values into your pipeline with templateParameters and variables. Values can be static or dynamically resolved from workflow outputs:
{
"integrationActionExecutionProperties": {
"project": "My Project",
"pipelineId": "12",
"branch": "main",
"templateParameters": {
"environment": "{{ .outputs.trigger.environment }}",
"version": "{{ .outputs.trigger.version }}"
},
"variables": {
"DRY_RUN": "{{ .outputs.trigger.dryRun | tostring }}"
}
}
}
templateParametersmap to parameters declared in your Azure Pipelines YAML (parameters:).variablesare queue-time variables sent to the Azure DevOps Run Pipeline API.
Status reporting
Status reporting (click to expand)
By default, Port monitors the triggered pipeline and updates the workflow node status when it completes. To opt out:
{
"integrationActionExecutionProperties": {
"project": "My Project",
"pipelineId": "12",
"reportPipelineStatus": false
}
}
When reportPipelineStatus is false, Port does not track the pipeline's completion at all: the node is left in progress after the pipeline is queued, and it is up to you to report its outcome back to Port (for example, from a step in your Azure Pipelines YAML that calls the Port API).
When reportPipelineStatus is true (the default), Port correlates the Azure DevOps ms.vss-pipelines.run-state-changed-event webhook back to the workflow node and reports success or failure when the run completes.
Pull request actions
Manage a pull request
Create, update, close, or merge a pull request.
- Create
- Update
- Close
- Merge
Opens a pull request between two branches. Set integrationInvocationType to create_pull_request.
Execution properties
| Field | Type | Description |
|---|---|---|
organization | string | Required. Azure DevOps organization name. Must match the organization configured on the integration |
project | string | Required. Project name or ID that contains the repository |
repositoryId | string | Required. Repository name or ID |
title | string | Required. Title of the new pull request |
sourceRefName | string | Required. Branch to merge from (for example, feature/add-caching or refs/heads/feature/add-caching) |
targetRefName | string | Required. Branch to merge into (for example, main or refs/heads/main) |
description | string | Description of the pull request |
Branch names are normalized for you, so main and refs/heads/main are equivalent.
Basic example Open a pull request from a feature branch into Create a pull request (click to expand)
main:
Changes an existing pull request. Set integrationInvocationType to update_pull_request.
Use this action when you need to edit pull request metadata or set completion options. For the common cases of abandoning or merging a pull request, prefer the dedicated Close and Merge tabs above.
Execution properties
At least one optional property is required, since an update with no changes is rejected.
| Field | Type | Description |
|---|---|---|
project | string | Required. Project name or ID that contains the repository |
repositoryId | string | Required. Repository name or ID |
pullRequestId | string | Required. ID of the pull request to update |
title | string | New title |
description | string | New description, up to 4000 characters |
status | string | New status: active, abandoned, or completed |
targetBranch | string | New target branch (for example, main) |
mergeStrategy | string | Merge strategy applied on completion: noFastForward, squash, rebase, or rebaseMerge |
deleteSourceBranch | boolean | Whether to delete the source branch after completion |
mergeCommitMessage | string | Commit message used for the merge commit |
bypassPolicy | boolean | Whether to bypass branch policies on completion |
bypassReason | string | Reason recorded when bypassing branch policies |
transitionWorkItems | boolean | Whether to transition linked work items on completion |
autoCompleteIgnoreConfigIds | string | Comma-separated policy configuration IDs to ignore for auto-complete (for example, "12,15") |
disableRenames | boolean | Whether to disable rename detection in the merge |
conflictAuthorshipCommits | boolean | Whether to create individual commits for conflict resolutions |
detectRenameFalsePositives | boolean | Whether to detect rename false positives in the merge |
autoCompleteSetById | string | Identity ID to set auto-complete on behalf of |
Status and merge strategy values are matched case-insensitively, so squash and Squash are both accepted.
Basic example Rename a pull request and queue it to squash-merge once its policies pass:Update a pull request (click to expand)
Setting status to completed merges the pull request. Azure DevOps only allows this once it has computed a merge preview for the source branch, so a pull request with unresolved conflicts is rejected.
Abandons a pull request without merging it. Set integrationInvocationType to close_pull_request.
Execution properties
| Field | Type | Description |
|---|---|---|
organization | string | Required. Azure DevOps organization name. Must match the organization configured on the integration |
project | string | Required. Project name or ID that contains the repository |
repositoryId | string | Required. Repository name or ID |
pullRequestId | string | Required. ID of the pull request to abandon |
Basic exampleClose a pull request (click to expand)
Completes a pull request by merging its source branch. Set integrationInvocationType to merge_pull_request.
Execution properties
| Field | Type | Description |
|---|---|---|
organization | string | Required. Azure DevOps organization name. Must match the organization configured on the integration |
project | string | Required. Project name or ID that contains the repository |
repositoryId | string | Required. Repository name or ID |
pullRequestId | string | Required. ID of the pull request to merge |
The merge uses the repository's default merge strategy. To choose a strategy or delete the source branch on merge, use the Update tab above with status set to completed.
Basic exampleMerge a pull request (click to expand)
The action fails if Azure DevOps has not finished computing the pull request's merge preview, which happens while a merge is still being evaluated or when the branches conflict. Resolve the conflict or retry once the preview is ready.
Add a pull request label
Adds a label to an existing pull request. Set integrationInvocationType to update_pull_request_labels.
Each run adds one label. To apply several labels, use multiple action nodes or run the action more than once.
Execution properties
| Field | Type | Description |
|---|---|---|
organization | string | Required. Azure DevOps organization name. Must match the organization configured on the integration |
project | string | Required. Project name or ID that contains the repository |
repositoryId | string | Required. Repository name or ID |
pullRequestId | string | Required. ID of the pull request to label |
label | string | Required. Name of the label to add |
Basic example
Add a pull request label (click to expand)
{
"identifier": "label-pull-request",
"title": "Add Pull Request Label",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "your-installation-id",
"integrationProvider": "azure-devops",
"integrationInvocationType": "update_pull_request_labels",
"integrationActionExecutionProperties": {
"organization": "my-org",
"project": "My Project",
"repositoryId": "my-service",
"pullRequestId": "{{ .outputs.trigger.pullRequestId }}",
"label": "approved"
}
}
}
Create a pull request comment thread
Adds a comment thread to a pull request. Set integrationInvocationType to create_pull_request_thread.
Execution properties
| Field | Type | Description |
|---|---|---|
project | string | Required. Project name or ID that contains the repository |
repositoryId | string | Required. Repository name or ID |
pullRequestId | string | Required. ID of the pull request to comment on |
content | string | Required. Body of the first comment in the thread. Supports Markdown |
status | string | Thread status: active, fixed, wontFix, closed, byDesign, or pending (default: active) |
filePath | string | Path of the file to anchor the thread to (for example, /src/main.py). When omitted, the thread is not anchored |
line | string | Line number in filePath to anchor the thread to, starting at 1. Requires filePath. When omitted, the thread is anchored to the file as a whole |
Each run creates a new thread, so a node that runs more than once on the same pull request adds a comment each time rather than editing an existing one.
Basic example
Create a pull request comment thread (click to expand)
Post a review summary produced by an earlier AI node, anchored to the file it refers to:
{
"identifier": "comment-on-pull-request",
"title": "Comment on Pull Request",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "your-installation-id",
"integrationProvider": "azure-devops",
"integrationInvocationType": "create_pull_request_thread",
"integrationActionExecutionProperties": {
"project": "My Project",
"repositoryId": "my-service",
"pullRequestId": "{{ .outputs.trigger.pullRequestId }}",
"content": "{{ .outputs.review.summary }}",
"status": "active",
"filePath": "/src/main.py",
"line": "42"
}
}
}
Complete workflow examples
Deploy a service with a pipeline (click to expand)
A self-service deployment workflow that triggers an Azure DevOps pipeline and updates the service entity on completion:
{
"identifier": "deploy-with-azure-devops",
"title": "Deploy Service with Azure DevOps",
"icon": "AzureDevops",
"description": "Trigger a deployment pipeline using Azure DevOps",
"nodes": [
{
"identifier": "trigger",
"title": "Request Deployment",
"config": {
"type": "SELF_SERVE_TRIGGER",
"userInputs": {
"properties": {
"service": {
"type": "string",
"format": "entity",
"blueprint": "service",
"title": "Service"
},
"environment": {
"type": "string",
"title": "Environment",
"enum": ["staging", "production"]
},
"version": {
"type": "string",
"title": "Version",
"description": "Git tag or commit SHA"
}
},
"required": ["service", "environment", "version"]
}
}
},
{
"identifier": "trigger-pipeline",
"title": "Trigger Azure DevOps Pipeline",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "ado-integration-123",
"integrationProvider": "azure-devops",
"integrationInvocationType": "trigger_pipeline",
"integrationActionExecutionProperties": {
"project": "My Project",
"pipelineId": "12",
"branch": "{{ .outputs.trigger.version }}",
"templateParameters": {
"environment": "{{ .outputs.trigger.environment }}",
"version": "{{ .outputs.trigger.version }}"
},
"reportPipelineStatus": true
}
}
},
{
"identifier": "update-entity",
"title": "Update Service Status",
"config": {
"type": "UPSERT_ENTITY",
"blueprintIdentifier": "service",
"mapping": {
"identifier": "{{ .outputs.trigger.service }}",
"properties": {
"lastDeployedVersion": "{{ .outputs.trigger.version }}",
"lastDeployedEnvironment": "{{ .outputs.trigger.environment }}",
"lastDeployedAt": "{{ now | todateiso8601 }}"
}
}
}
}
],
"connections": [
{
"sourceIdentifier": "trigger",
"targetIdentifier": "trigger-pipeline"
},
{
"sourceIdentifier": "trigger-pipeline",
"targetIdentifier": "update-entity"
}
]
}
Open and announce a pull request (click to expand)
A self-service workflow that opens a pull request and adds a comment thread linking back to the requester:
{
"identifier": "open-pull-request-with-azure-devops",
"title": "Open Pull Request with Azure DevOps",
"icon": "AzureDevops",
"description": "Open a pull request and announce who requested it",
"nodes": [
{
"identifier": "trigger",
"title": "Request Pull Request",
"config": {
"type": "SELF_SERVE_TRIGGER",
"userInputs": {
"properties": {
"repository": {
"type": "string",
"title": "Repository"
},
"branch": {
"type": "string",
"title": "Source branch"
},
"title": {
"type": "string",
"title": "Pull request title"
}
},
"required": ["repository", "branch", "title"]
}
}
},
{
"identifier": "create-pr",
"title": "Create Pull Request",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "ado-integration-123",
"integrationProvider": "azure-devops",
"integrationInvocationType": "create_pull_request",
"integrationActionExecutionProperties": {
"organization": "my-org",
"project": "My Project",
"repositoryId": "{{ .outputs.trigger.repository }}",
"title": "{{ .outputs.trigger.title }}",
"sourceRefName": "{{ .outputs.trigger.branch }}",
"targetRefName": "main",
"description": "Opened from Port by {{ .trigger.by.user.email }}"
}
}
}
],
"connections": [
{
"sourceIdentifier": "trigger",
"targetIdentifier": "create-pr"
}
]
}
Limitations
- Single Account mode only: Azure DevOps integration actions are supported when the integration is configured in Single Account mode. Multi-account (service principal across many organizations) is not supported for these actions yet.
- Run expiry: Runs that remain unprocessed for more than 3 hours are automatically expired and will not be executed.