From 32b517d661a73913bce2dbdd07a9091f8ad5487b Mon Sep 17 00:00:00 2001 From: Itay Donanhirsh Date: Tue, 26 Aug 2025 17:10:29 -0700 Subject: [PATCH] work --- azure_pipelines_bot/README.md | 45 +++++++++++++++++++ azure_pipelines_bot/autokitteh.yaml | 26 +++++++++++ azure_pipelines_bot/program.py | 69 +++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 azure_pipelines_bot/README.md create mode 100644 azure_pipelines_bot/autokitteh.yaml create mode 100644 azure_pipelines_bot/program.py diff --git a/azure_pipelines_bot/README.md b/azure_pipelines_bot/README.md new file mode 100644 index 00000000..786e6d43 --- /dev/null +++ b/azure_pipelines_bot/README.md @@ -0,0 +1,45 @@ +--- +title: Azure Pipelines Bot for Microsoft Teams +description: Monitor Azure DevOps build completions and enable interactive pipeline management through Microsoft Teams conversations +integrations: ["azurebot"] +categories: ["DevOps"] +tags: + [ + "webhook", + "interactive_workflows", + "user_interactions", + "subscribe", + "next_event", + "event_loops", + ] +--- + +# Azure Pipelines Bot + +[![Start with AutoKitteh](https://autokitteh.com/assets/autokitteh-badge.svg)](https://app.autokitteh.cloud/template?name=azure_pipelines_bot) + +This automation connects Azure DevOps pipelines to Microsoft Teams, enabling teams to monitor build completions and interact with pipelines directly from Teams conversations. When a build completes, the bot posts a notification to a Teams channel and allows users to retry failed builds through simple chat commands. + +## How It Works + +1. Receives webhook notifications when Azure DevOps builds complete +2. Posts build completion messages to a Microsoft Teams channel +3. Listens for user interactions in the Teams conversation +4. Allows users to retry builds by typing "retry" in response to build notifications +5. Queues new builds with the same parameters as the original failed build + +## Cloud Usage + +1. Initialize your Azure Bot connection +2. Set these required project variables: + - `CHANNEL_CONVO_ID` - Microsoft Teams channel conversation ID + - `AZURE_DEVOPS_PAT` - Azure DevOps Personal Access Token (marked as secret) + - `AZURE_DEVOPS_ORG` - Azure DevOps organization name +3. Deploy project +4. Configure Azure DevOps webhook to point to the generated webhook URL + +## Trigger Workflow + +The workflow is triggered by Azure DevOps webhooks when builds complete with `eventType='build.complete'`. Users can then interact with the bot by: + +- Typing `@ retry` in response to build completion messages to queue a new build diff --git a/azure_pipelines_bot/autokitteh.yaml b/azure_pipelines_bot/autokitteh.yaml new file mode 100644 index 00000000..dfa89963 --- /dev/null +++ b/azure_pipelines_bot/autokitteh.yaml @@ -0,0 +1,26 @@ +# This YAML file is a declarative manifest that describes the setup +# of an AutoKitteh project that demonstrates how to poll for new emails +version: v1 + +project: + name: azure_pipelines_bot + + vars: + - name: CHANNEL_CONVO_ID + value: "" + - name: AZURE_DEVOPS_PAT + value: "" + secret: true + - name: AZURE_DEVOPS_ORG + value: "" + + connections: + - name: bot + integration: azurebot + + triggers: + - name: azuredev_webhook + type: webhook + call: program.py:on_azuredev_webhook + event_type: POST + filter: data.body.json.eventType='build.complete' diff --git a/azure_pipelines_bot/program.py b/azure_pipelines_bot/program.py new file mode 100644 index 00000000..5f212cbd --- /dev/null +++ b/azure_pipelines_bot/program.py @@ -0,0 +1,69 @@ +"""MS Azure DevOps Pipelines -> MS Teams via Azure Bot""" + +from os import getenv +from autokitteh import subscribe, next_event +from autokitteh.azurebot import azurebot_client + +from azure.devops.connection import Connection +from azure.devops.v7_1.build.models import Build +from msrest.authentication import BasicAuthentication + + +_CHANNEL_CONVO_ID = getenv("CHANNEL_CONVO_ID") + + +devops_clients = Connection( + base_url=f"https://dev.azure.com/{getenv('AZURE_DEVOPS_ORG')}", + creds=BasicAuthentication("", getenv("AZURE_DEVOPS_PAT")), +).clients + +build_client = devops_clients.get_build_client() + +bot_client = azurebot_client("bot") + + +def on_azuredev_webhook(event): + data = event.data.body.json + + activity_id = bot_client.send_conversation_activity( + { + "type": "message", + "text": data["detailedMessage"]["markdown"], + }, + conversation_id=_CHANNEL_CONVO_ID, + )["id"] + + convo_id = f"{_CHANNEL_CONVO_ID};messageid={activity_id}" + + build_id, project_name = ( + data["resource"]["id"], + data["resource"]["project"]["name"], + ) + + print(f"Build completed: {build_id} in {project_name}") + + sub = subscribe("bot", filter=f"data.conversation.id='{convo_id}'") + + while True: + evt = next_event(sub) + print(evt) + + text = evt.text.lower() + + if "retry" in text: + build = build_client.get_build(project=project_name, build_id=build_id) + + new_build = build_client.queue_build( + build=Build( + definition=build.definition, + source_branch=build.source_branch, + source_version=build.source_version, + parameters=build.parameters, + ), + project=project_name, + ) + + bot_client.send_conversation_activity( + {"type": "message", "text": f"New build: {new_build.url}"}, + conversation_id=convo_id, + )