Repository navigation
Microsoft Teams
tf-snag can post a run's findings to a Teams channel as an Adaptive Card.
export TF_SNAG_TEAMS_WEBHOOK=... # the channel's workflow URL, a secret
tf-snag -check all -plan plan.json -plan-log plan.jsonl -baseline prev.sarif \
-teams-notify new \
-teams-context "nightly-drift · main · run 20260901.3" \
-run-url "$RUN_URL"In a pipeline, set the tf-snag@0 task's teamsWebhook input from a secret variable.
Microsoft has retired Office 365 connectors (Incoming Webhook), so tf-snag posts to their replacement, a Power Automate Workflows trigger:
- In the Teams channel, open ⋯ → Workflows.
- Choose Post to a channel when a webhook request is received.
- Pick the team and channel, and copy the HTTP POST URL it gives you.
The URL is a credential: anyone who has it can post to the channel. Pass it through TF_SNAG_TEAMS_WEBHOOK rather than -teams-webhook, since command lines end up in process listings and CI logs. tf-snag strips the URL from any error it prints.
-teams-notify |
Posts |
|---|---|
findings (CLI default) |
whenever anything not ignored is found |
new (tf-snag@0 default) |
only when a finding is new since -baseline, or has just stopped being ignored |
always |
every run, clean or not. Useful to prove the webhook works |
Use new on a schedule. Re-posting the same unfixed drift every morning is how a channel learns to ignore an alert. new stays quiet until something actually appears. It needs -baseline to tell new from old; without one it falls back to findings and says so on stderr.

- A banner with the verdict: red for drift, amber for deprecations only, green for a clean run, then the counts
- Drift and deprecations each in a collapsed group that expands in place, so the post stays glanceable
- Each finding marked with its change (green create, red delete, amber update) and its attribute changes
- With a baseline, new findings first with a New badge; the rest show how long they have been there
- With
-run-url, that age links to the run that first found the finding, and the card gets a View run button - Ignored findings counted, not listed
The New count is relative to the previous check, not the previous card. Under new, a quiet week means no cards at all.
Each section shows at most five findings, and two attribute changes per resource, with an "…and N more" line, so a large drift set cannot exceed the webhook's size limit.
A failed post exits 2, with the status and response body on stderr: a notification you believe is going out but is not is worse than a loud failure. 429, 5xx and connection errors are retried automatically, three attempts in total, honouring Retry-After.
-format teams prints the card instead of posting it, to inspect or diff the payload.
Start here
How it works
Integrations
Project