Jira issue updates to a Microsoft Teams channel
Created and updated Jira issues are announced in the Teams channel the squad actually watches.
Drag to pan, pinch to zoom. This is the real graph the template installs.
Purpose
Created and updated Jira issues are announced in the Teams channel the squad actually watches.
How it works
What it does
- Subscribes to Jira issue created and updated events for high-priority issues in one project.
- Posts an HTML card into a Microsoft Teams channel with a link back to the issue.
Validation
This template is contract-validated: the unit suite checks every node type, every config key and the whole graph against the same rules a saved workflow passes. It has not been run against the live provider — the ids, names and columns below are placeholders to replace with your own.
Nodes 2
- 01Issue created or updatedtrigger.jira_eventTrigger
- 02Post to Teamsteams.send_messageApp
View template JSON
{
"format": "mantle-workflow/v1",
"id": "jira-issue-to-teams",
"name": "Jira issue updates to a Microsoft Teams channel",
"graph": {
"nodes": [
{
"id": "event",
"type": "trigger.jira_event",
"label": "Issue created or updated",
"config": {
"events": [
"jira:issue_created",
"jira:issue_updated"
],
"jql_filter": "project = ENG AND priority in (High, Highest)"
},
"worker_type": "generic-worker",
"position": {
"x": 60,
"y": 220
}
},
{
"id": "teams",
"type": "teams.send_message",
"label": "Post to Teams",
"config": {
"team_id": "00000000-0000-0000-0000-000000000000",
"channel_id": "19:0000000000000000000000000000000@thread.tacv2",
"message": "<b>{{ $json.issue.key }}</b> — {{ $json.issue.summary }}<br>{{ $json.webhookEvent }} · {{ $json.issue.status }} · <a href=\"{{ $json.issue.url }}\">open</a>",
"content_type": "html"
},
"worker_type": "generic-worker",
"position": {
"x": 380,
"y": 220
}
}
],
"edges": [
{
"from": "event",
"to": "teams"
}
]
}
}Requirements
The connections and permissions each step needs, from the node contracts in the catalog.
- JiraUsername & password
Used by Issue created or updated.
Credential: {"email", "api_token"}
- Mantle creates the webhook in Jira when the workflow is published and deletes it when the workflow is unpublished, disabled or archived — do not add it by hand.
- The connection's account must be a Jira administrator: registering a webhook is an admin operation, and publish fails with Jira's own message if it is not.
- Deliveries are signed. Mantle generates a random secret, registers it, and verifies the X-Hub-Signature HMAC over the raw body; a bad signature is refused before any run starts.
- If your site does not confirm signing (no isSigned on registration) the webhook is deleted again and the publish fails, rather than leaving an unauthenticated URL armed. Tick allow_unsigned to accept URL-only authentication anyway — then anyone who learns the callback URL can start runs.
- jql_filter and events are applied when the workflow is published, so they cannot use {{ }} expressions — there is no run to evaluate them against.
- Jira sends no delivery id. Runs are deduped on webhookEvent + issue id + timestamp + the change-group / comment / worklog id, so a Jira retry cannot start a second run.
- MANTLE_APP_PUBLIC_BASE_URL must be a public https:// URL — Jira refuses to register a plain-http or unreachable callback.
- Microsoft TeamsOAuth 2.0
Used by Post to Teams.
Credential: {"client_id", "client_secret", "refresh_token"}
- Needs a delegated ChannelMessage.Send permission on the Azure AD app; the team/channel ids come from the channel's ••• → Get link to channel.
Setup
- Edit
jql_filterfor your project and priority rule. - Replace
team_idandchannel_id— both appear in the channel's Get link to channel. - The Teams connection needs a refresh token; Connect-with-Microsoft does not mint Teams connections yet, so supply it on the connection directly.
Sample input and output
Synthetic examples: node-contract samples or placeholders, never customer data.
Input
What the Issue created or updated trigger receives, as its node contract samples it.
{
"changelog": [],
"changelog_id": "",
"comment": {
"author": {
"accountId": "",
"displayName": "",
"emailAddress": ""
},
"body": "",
"created": "",
"id": "",
"updated": ""
},
"issue": {
"assignee": {
"accountId": "",
"displayName": "",
"emailAddress": ""
},
"id": "",
"issue_type": "",
"key": "ENG-412",
"labels": [],
"priority": "",
"project": {
"id": "",
"key": "ENG",
"name": ""
},
"reporter": {
"accountId": "",
"displayName": "",
"emailAddress": ""
},
"status": "",
"status_category": "",
"summary": "",
"url": ""
},
"issue_event_type_name": "issue_updated",
"payload": {},
"timestamp": 0,
"user": {
"accountId": "",
"displayName": "",
"emailAddress": ""
},
"webhookEvent": "jira:issue_updated",
"worklog": {
"author": {
"accountId": "",
"displayName": "",
"emailAddress": ""
},
"comment": "",
"id": "",
"started": "",
"time_spent": "",
"time_spent_seconds": 0
}
}Output
Post to Teams teams.send_message
{
"message_id": "",
"ok": true,
"web_url": ""
}Failure handling
What the graph does when a step fails, read from its retry settings, error branches and error policies.
- A step that fails, after any retries, fails the run. The failed step is kept with its input and error.
See it run, then make it yours.
Templates install as drafts. Edit any step, and Workflow Health re-checks the graph on every save.