Airflow-MS-Teams-Operator

Airflow operator that can send messages to MS Teams

Stars
80

This is an Airflow operator that can send cards to MS Teams via webhooks. There are various options to customize the appearance of the cards.

Screenshots

Header, subtitle, and body Header, subtitle, body, facts, and a button
Card with a header, subtitle, and body Card with a header, subtitle, body, and a button
Body with coloured text and coloured button Coloured header, body, button, in dark mode
Body with coloured text and coloured button Header, body, button, in dark mode
Body and empty green header Body and coloured header, without logo
Body with empty green header Body and header, without logo

Setup

Create a webhook to post to Teams. The Webhook needs to be of the PowerAutomate type, not the deprecated Incoming Webhook type. Currently this is done either through the 'workflows' app in Teams, or via PowerAutomate.

Once that's ready, create an HTTP Connection in Airflow with the Webhook URL.

  • Conn Type: HTTP
  • Host: The URL without the https://
  • Schema: https

Copy the ms_teams_power_automate_webhook_operator.py file into your Airflow dags folder and import it in your DAG code.

Usage

The usage can be very basic from just a message, to several parameters including a full card with header, subtitle, body, facts, and a button. There are some style options too.

A very basic message:

 op1 = MSTeamsPowerAutomateWebhookOperator(
        task_id="send_to_teams",
        http_conn_id="msteams_webhook_url",
        body_message="DAG **lorem_ipsum** has completed successfully in **localhost**",
    )

Add a button:

op1 = MSTeamsPowerAutomateWebhookOperator(
        task_id="send_to_teams",
        http_conn_id="msteams_webhook_url",
        body_message="DAG **lorem_ipsum** has completed successfully in **localhost**",
        button_text="View Logs",
        button_url="https://example.com",
    )

Add a heading and subtitle:

op1 = MSTeamsPowerAutomateWebhookOperator(
        task_id="send_to_teams",
        http_conn_id="msteams_webhook_url",
        heading_title="DAG **lorem_ipsum** has completed successfully",
        heading_subtitle="In **localhost**",
        body_message="DAG **lorem_ipsum** has completed successfully in **localhost**",
        button_text="View Logs",
        button_url="https://example.com",
    )

Add some colouring — header bar colour, subtle subtitle, body text colour, button colour:

op1 = MSTeamsPowerAutomateWebhookOperator(
        task_id="send_to_teams",
        http_conn_id="msteams_webhook_url",
        header_bar_style="good",
        heading_title="DAG **lorem_ipsum** has completed successfully",
        heading_subtitle="In **localhost**",
        heading_subtitle_subtle=False,
        body_message="DAG **lorem_ipsum** has completed successfully in **localhost**",
        body_message_color_type="good",
        button_text="View Logs",
        button_url="https://example.com",
        button_style="positive",
    )

You can also look at sample_dag.py for an example of how to use this operator in a DAG.

Parameters

Here are all the parameters that can be set.

Parameter Values Notes
http_conn_id The connection ID, eg "msteams_webhook_url"
card_width_full True(default) or False If false, the card will be the MSTeams default.
header_bar_show True(default) or False If false, heading title, subtitle, logo won't be shown.
header_bar_style default, emphasis, good, attention, warning, accent docs - style
heading_title Limited Markdown support, no monospace
heading_title_size default, small, medium, large, extraLarge docs - size
heading_subtitle Appears just below the title, Limited Markdown support, no monospace
heading_subtitle_subtle True(default) or False Subtle means toned down to appear less prominent
heading_show_logo True(default) or False
body_message Limited Markdown support, no monospace
body_message_color_type default, dark, light, accent, good, warning, attention docs - color
body_facts_dict Example: {'aaa':'bbb','ccc':'ddd'} The key value pairs show up as facts in the card
button_text Example: "View Logs" If not set, button won't be shown
button_url Example: "https://example.com" For example, the URL to the Airflow log
button_style default, positive, destructive docs - style
button_show True(default) or False

The old incoming webhooks

This operator only works with the new PowerAutomate webhooks. The old incoming webhooks were deprecated in this Teams announcement. It says they'll keep working until December 2025 but I expect much degradation in the service before then.

The previous version of this operator, which worked with the old incoming webhooks, is in the master-old-connectors branch. This operator is not a drop-in replacement for the old one, as there are too many differences.

Contribute

Any simple feature requests, please fork and submit a PR.

Testing this operator locally for development

I'm using the Airflow Docker Compose, with a few changes. Load examples is false and added an extra_hosts.

Run this to prepare the environment:

mkdir -p ./dags ./logs ./plugins ./config
echo -e "AIRFLOW_UID=$(id -u)" > .env
docker compose up airflow-init
docker compose up

Then wait a bit, and open http://localhost:8080 with airflow:airflow.

To create a connection quickly, use this CLI command, substitute the url bit.

docker compose exec -it airflow-webserver airflow connections add 'msteams_webhook_url' --conn-json '{"conn_type": "http", "description": "", "host": "<url-goes-here-without https://>", "schema": "https", "login": "", "password": null, "port": null }'

Now run the sample_dag to see the operator in action.

Echoing requests

To troubleshoot the requests going out, use the included httpecho container which echoes the request to output. In Airflow connections, create an HTTP Connection to http://httpecho:8081

docker compose exec -it airflow-webserver airflow connections add 'msteams_webhook_url' --conn-json '{"conn_type": "http", "description": "", "host": "httpecho:8081/a/b/c", "schema": "http", "login": "", "password": null, "port": null }'

docker compose logs -f httpecho

Now when you run the sample_dag, you can see the request reflected in the httpecho container.

Posting a card with curl

To manually post the sample card to a webhook URL, just for testing, use the included samplecard.json file.

curl -X POST -H 'Content-Type: application/json' --data-binary @samplecard.json  "https://prod-11.westus.logic.azure.com:443/workflows/.............."

License

Apache 2.0 (see code file headers)