Prometheus Alertmanager webhook receiver for Azure DevOps.
alert-az-do implements Alertmanager's webhook HTTP API and connects to one or more Azure DevOps organizations to create highly configurable Azure DevOps work items. One work item is created per distinct group key — as defined by the group_by parameter of Alertmanager's route configuration section — but not closed when the alert is resolved. The expectation is that a human will look at the work item, take any necessary action, then close it. If no human interaction is necessary then it should probably not alert in the first place. This behavior however can be modified by setting the auto_resolve section, which will resolve the Azure DevOps work item with the required state.
If a corresponding Azure DevOps work item already exists but is resolved, it is reopened. An Azure DevOps state transition must exist between the resolved state and the reopened state — as defined by reopen_state — or reopening will fail. Optionally a "skip reopen state" — defined by skip_reopen_state — may be defined: an Azure DevOps work item in this state will not be reopened by alert-az-do (e.g., work items marked as "Removed" or "Cut").
- Multiple Authentication Methods: Support for Service Principal, Managed Identity, and Personal Access Token authentication
- Flexible Work Item Creation: Create different types of work items (Bug, Task, Issue, etc.) based on alert content
- Template-based Content: Use Go templates to generate dynamic work item titles, descriptions, and field values
- Auto-resolution: Automatically resolve work items when alerts are resolved
- Custom Fields: Set standard and custom Azure DevOps fields using templates
- Multi-project Support: Search across multiple projects for existing work items
- Label Management: Copy Prometheus labels as Azure DevOps tags
- Update Modes: Choose between updating work items directly or adding comments
- Environment Variable Support: Environment variables take precedence over config file settings
Get alert-az-do, either as a packaged release or build it yourself:
go get github.com/stakater/alert-az-do/cmd/alert-az-dothen run it from the command line:
alert-az-doUse the -help flag to get help information.
alert-az-do -help
Usage of alert-az-do:
-config string
The alert-az-do configuration file (default "config/alert-az-do.yml")
-listen-address string
The address to listen on for HTTP requests. (default ":9097")
-log-level string
Only log messages with the given severity or above (debug, info, warn, error) (default "info")
-log-format string
Output format of log messages (logfmt, json) (default "logfmt")alert-az-do expects a JSON object from Alertmanager. The format of this JSON is described in the Alertmanager documentation or, alternatively, in the Alertmanager GoDoc.
To quickly test if alert-az-do is working you can run:
curl -H "Content-type: application/json" -X POST \
-d '{"receiver": "contoso-ab", "status": "firing", "alerts": [{"status": "firing", "labels": {"alertname": "TestAlert", "severity": "critical"} }], "groupLabels": {"alertname": "TestAlert"}}' \
http://localhost:9097/alertThe configuration file is essentially a list of receivers matching 1-to-1 all Alertmanager receivers using alert-az-do; plus defaults (in the form of a partially defined receiver); and a pointer to the template file.
Each receiver must have a unique name (matching the Alertmanager receiver name), Azure DevOps API access fields (organization, authentication credentials), a handful of required work item fields (such as the Azure DevOps project and work item summary), some optional work item fields (e.g. priority, area path, iteration path) and a fields map for other (standard or custom) Azure DevOps fields. Most of these may use Go templating to generate the actual field values based on the contents of the Alertmanager notification. The exact same data structures and functions as those defined in the Alertmanager template reference are available in alert-az-do.
Similar to Alertmanager, alert-az-do supports environment variable substitution with the $(...) syntax.
alert-az-do supports three authentication methods with automatic precedence handling:
Use when running alert-az-do as an application with Azure AD registration:
organization: contoso
tenant_id: "12345678-1234-1234-1234-123456789012"
client_id: "87654321-4321-4321-4321-210987654321"
client_secret: $(CLIENT_SECRET)Use when running alert-az-do on Azure compute resources (VMs, Container Instances, AKS, etc.):
organization: contoso
client_id: "87654321-4321-4321-4321-210987654321"
subscription_id: "11111111-2222-3333-4444-555555555555"Use for development or when other methods are not feasible:
organization: contoso
personal_access_token: $(PAT_TOKEN)alert-az-do uses the following precedence order (highest to lowest):
-
Environment Variables (any complete authentication method)
- Service Principal:
AZURE_TENANT_ID,AZURE_CLIENT_ID,AZURE_CLIENT_SECRET - Managed Identity:
AZURE_CLIENT_ID,AZURE_SUBSCRIPTION_ID - PAT:
AZURE_PAT
- Service Principal:
-
Configuration File (receiver-specific settings)
-
Configuration File (defaults section)
Important: Authentication methods are mutually exclusive. You cannot mix Service Principal fields with Managed Identity fields or PAT tokens.
# Service Principal via environment
export AZURE_TENANT_ID="12345678-1234-1234-1234-123456789012"
export AZURE_CLIENT_ID="87654321-4321-4321-4321-210987654321"
export AZURE_CLIENT_SECRET="your-secret-here"
# OR Managed Identity via environment
export AZURE_CLIENT_ID="87654321-4321-4321-4321-210987654321"
export AZURE_SUBSCRIPTION_ID="11111111-2222-3333-4444-555555555555"
# OR PAT via environment
export AZURE_PAT="your-pat-token-here"# Global defaults - Service Principal authentication
defaults:
organization: contoso
tenant_id: $(TENANT_ID)
client_id: $(CLIENT_ID)
client_secret: $(CLIENT_SECRET)
issue_type: Bug
priority: '{{ template "azdo.priority" . }}'
summary: '{{ template "azdo.summary" . }}'
description: '{{ template "azdo.description" . }}'
reopen_state: "To Do"
skip_reopen_state: "Removed"
receivers:
# Inherits Service Principal from defaults
- name: 'team-alpha'
project: TeamAlpha
add_group_labels: true
# Uses Managed Identity authentication
- name: 'team-beta-managed'
project: TeamBeta
client_id: $(MI_CLIENT_ID)
subscription_id: $(SUBSCRIPTION_ID)
issue_type: Task
fields:
System.AssignedTo: '{{ .CommonLabels.owner }}'
System.AreaPath: '\datacenter\Container'
System.IterationPath: '\datacenter'
# Uses PAT authentication
- name: 'team-gamma-pat'
project: TeamGamma
personal_access_token: $(GAMMA_PAT)
issue_type: Issue
priority: Critical
template: alert-az-do.tmplYou can find your IterationPath/AreaPath here: https://dev.azure.com/{organisation}/{project}/_apis/wit/classificationnodes?api-version=7.1&$depth=10
Supported Item Types: https://dev.azure.com/{organisation}/{project}/_apis/wit/workitemtypes?api-version=7.1
Field reference: https://dev.azure.com/{organisation}/{project}/_apis/wit/fields?api-version=7.1 https://dev.azure.com/{organisation}/{project}/_apis/wit/workitemtypes/{Work Item Type}/fields?api-version=7.1
When environment variables are set, they take precedence over config file settings:
# Minimal config - authentication comes from environment variables
defaults:
organization: contoso # AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET set via env
issue_type: Bug
summary: '{{ template "azdo.summary" . }}'
reopen_state: "To Do"
receivers:
- name: 'alerts'
project: Operations
template: alert-az-do.tmpl# Environment variables provide authentication
export AZURE_TENANT_ID="12345678-1234-1234-1234-123456789012"
export AZURE_CLIENT_ID="87654321-4321-4321-4321-210987654321"
export AZURE_CLIENT_SECRET="your-secret-here"alert-az-do provides additional template functions beyond the standard Alertmanager functions:
toUpper: Convert string to uppercasetoLower: Convert string to lowercasejoin: Join string slice with separatormatch: Test if string matches regex patternreReplaceAll: Replace all regex matches in stringstringSlice: Create a string slice from argumentsgetEnv: Get environment variable value
To enable Alertmanager to talk to alert-az-do you need to configure a webhook in Alertmanager. You can do that by adding a webhook receiver to your Alertmanager configuration.
receivers:
- name: 'team-alpha'
webhook_configs:
- url: 'http://localhost:9097/alert'
# Send resolved alerts if you want auto-resolution
send_resolved: trueThe authentication method you choose needs the following Azure DevOps permissions:
- Work Items: Read & write
- Project and team: Read (to access project information)
Best for: Development, testing, or simple setups
- Go to Azure DevOps → User Settings → Personal Access Tokens
- Create a new token with "Work Items (Read & write)" scope
- Use the token in your configuration:
personal_access_token: $(PAT_TOKEN)
Best for: Production applications, CI/CD pipelines
- Go to Azure Portal → Azure Active Directory → App registrations
- Create a new application
- Note the Application (client) ID and Directory (tenant) ID
- Create a client secret in "Certificates & secrets"
- Add the application to your Azure DevOps organization:
- Go to Azure DevOps → Organization Settings → Users
- Add the service principal with appropriate permissions
- Use in configuration:
tenant_id: "your-tenant-id" client_id: "your-client-id" client_secret: $(CLIENT_SECRET)
Best for: Azure compute resources (VMs, Container Instances, AKS)
- Enable managed identity on your Azure resource
- Note the Client ID of the managed identity
- Add the managed identity to your Azure DevOps organization:
- Go to Azure DevOps → Organization Settings → Users
- Add the managed identity with appropriate permissions
- Use in configuration:
client_id: "your-managed-identity-client-id" subscription_id: "your-azure-subscription-id"
For containerized deployments, use environment variables:
# Kubernetes Secret example
apiVersion: v1
kind: Secret
metadata:
name: alert-az-do-auth
type: Opaque
stringData:
AZURE_TENANT_ID: "12345678-1234-1234-1234-123456789012"
AZURE_CLIENT_ID: "87654321-4321-4321-4321-210987654321"
AZURE_CLIENT_SECRET: "your-secret-here"# Deployment example
apiVersion: apps/v1
kind: Deployment
metadata:
name: alert-az-do
spec:
template:
spec:
containers:
- name: alert-az-do
image: ghcr.io/stakater/alert-az-do:latest
envFrom:
- secretRef:
name: alert-az-do-authalert-az-do imports net/http/pprof to expose runtime profiling data on the /debug/pprof endpoint. For example, to use the pprof tool to look at a 30-second CPU profile:
go tool pprof http://localhost:9097/debug/pprof/profileTo enable mutex and block profiling (i.e. /debug/pprof/mutex and /debug/pprof/block) run alert-az-do with the DEBUG environment variable set:
env DEBUG=1 ./alert-az-doalert-az-do is available as a Docker image with multiple authentication options:
docker run \
-v $(pwd)/config:/config \
-p 9097:9097 \
-e AZURE_TENANT_ID="12345678-1234-1234-1234-123456789012" \
-e AZURE_CLIENT_ID="87654321-4321-4321-4321-210987654321" \
-e AZURE_CLIENT_SECRET="your-secret-here" \
ghcr.io/stakater/alert-az-do:latest \
-config /config/alert-az-do.ymldocker run \
-v $(pwd)/config:/config \
-p 9097:9097 \
-e AZURE_PAT="your-pat-token-here" \
ghcr.io/stakater/alert-az-do:latest \
-config /config/alert-az-do.ymldocker run -v $(pwd)/config:/config \
-p 9097:9097 \
ghcr.io/stakater/alert-az-do:latest \
-config /config/alert-az-do.ymlThis error occurs when no complete authentication method is configured. Ensure you have one of:
- Service Principal:
tenant_id,client_id, andclient_secret - Managed Identity:
client_idandsubscription_id - PAT:
personal_access_token
This error occurs when you mix authentication methods. Examples of invalid configurations:
# ❌ Invalid - mixing Service Principal with PAT
tenant_id: "..."
client_id: "..."
client_secret: "..."
personal_access_token: "..." # Cannot mix with Service Principal
# ❌ Invalid - mixing Service Principal with Managed Identity
tenant_id: "..."
client_id: "..."
client_secret: "..."
subscription_id: "..." # Creates ambiguity between methodsEnable debug logging to see which authentication method is selected:
alert-az-do -log-level debug -config config/alert-az-do.ymlLook for log entries showing credential selection logic.
Check if environment variables are set correctly:
# Check Service Principal environment variables
echo "Tenant: $AZURE_TENANT_ID"
echo "Client: $AZURE_CLIENT_ID"
echo "Secret: ${AZURE_CLIENT_SECRET:0:4}..." # Only show first 4 chars
# Check Managed Identity environment variables
echo "Client: $AZURE_CLIENT_ID"
echo "Subscription: $AZURE_SUBSCRIPTION_ID"
# Check PAT environment variable
echo "PAT: ${AZURE_PAT:0:4}..." # Only show first 4 charsWe welcome contributions! Please see our contributing guidelines for details.
alert-az-do is an open source project and we welcome new contributors and members of the community. Here are ways to get in touch with the community:
- Issue Tracker: GitHub Issues
alert-az-do is licensed under the Apache License 2.0.
Copyright (c) 2025 Stakater AB