Open nickjj opened 4 months ago
+1 I'm seeing the same thing
Thanks for bring this up! Not sure what the LoE would be to update the connector but it would be nice to keep the connector up to date (if possible).
+1 I'm seeing the same thing. specifically, the only valid card schema is an adaptive card (https://learn.microsoft.com/en-us/connectors/teams/?tabs=text1#request-body).
when just switching the webhook endpoint and trying to use the existing teams templates, the error message is displayed on the teams workflow failed run details:
The execution of template action 'Send_each_adaptive_card' failed: the result of the evaluation of 'foreach' expression '@triggerOutputs()?['body']?['attachments']' is of type 'Null'. The result must be a valid array.
using the teams templates, i don't see a way to override the card schema to adaptive card. there might be a way to implement the proper schema using the generic webhook and specify a custom one.
You know, the most annoying thing about this... the day I finished the integration with notifications to teams, was the day they published the deprecation notice. That's MSFT for you I guess... never upgrade, just replace. https://devblogs.microsoft.com/microsoft365dev/retirement-of-office-365-connectors-within-microsoft-teams/
+1
+1
I brought this up at the Contributors Office Hours and @pasha-codefresh is going to look at it to see what the LoE would be
If other system administrators are having difficulties locating the affected teams: I have written a small tool in Golang that uses the Graph API to output the affected teams.
This has helped us enormously, as Microsoft does not offer its own solution for reading the affected channels and teams. We have over 350 teams in our company, which we would otherwise have had to search through manually.
+1
+1 I'm seeing the same thing. specifically, the only valid card schema is an adaptive card (https://learn.microsoft.com/en-us/connectors/teams/?tabs=text1#request-body).
when just switching the webhook endpoint and trying to use the existing teams templates, the error message is displayed on the teams workflow failed run details:
The execution of template action 'Send_each_adaptive_card' failed: the result of the evaluation of 'foreach' expression '@triggerOutputs()?['body']?['attachments']' is of type 'Null'. The result must be a valid array.
using the teams templates, i don't see a way to override the card schema to adaptive card. there might be a way to implement the proper schema using the generic webhook and specify a custom one.
Getting same issue :( not sure best way to convert existing format into adaptative card format
Getting below error while posting a message with using new workflow URL
The execution of template action 'Send_each_adaptive_card' failed: the result of the evaluation of 'foreach' expression '@triggerOutputs()?['body']?['attachments']' is of type 'Null'. The result must be a valid array.
I am using legacy card like that used to work with webhook URL. It's throwing an above error when use workflow URL
[Array]$audit =
@{
name = "LastBuildStatus and Provisioning State"
value = ("$($results.LastRunStatusRunState)" + " - " + "$($results.ProvisioningState -join ',')")
}
$body = ConvertTo-Json -Depth 10 @{
title = "Status"
text = "Reminder "
separator = "true"
sections = @(
@{
activityTitle = "Test "
activitySubtitle = "Please take an action, accordingly, refer [document](https: doc link)"
facts = $audit
}
)
}
Invoke-RestMethod -Method post -ContentType 'application/Json' -Body $body -Uri $workflowUrl
Any one encountered same issue? Do we really need to convert legacy card into adaptative card format ?
I hope this helps those of you who are suffering from the webhook policy change in teams.
I'm using notfication's webhook feature and creating the following body in adaptive card format.
The following is a complete example of the argocd-notifications-cm configmap
apiVersion: v1
data:
context: |
argocdUrl: <<your-argocd-url>>
service.webhook.teams-workflow: |
url: <<your-microsoft-teams-workflow-webhook-url>>
headers:
- name: "Content-Type"
value: "application/json"
subscriptions: |
- recipients:
- teams-workflow
triggers:
- on-created
- on-deleted
- on-deployed
- on-health-degraded
- on-sync-failed
- on-sync-running
- on-sync-status-unknown
- on-sync-status-outofsync
- on-sync-succeeded
template.app-created: |
webhook:
teams-workflow:
method: POST
body: |
{
"attachments": [
{
"contentType": "object",
"content": {
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": "Application has been created.",
"color": "Good"
},
{
"type": "FactSet",
"facts": [
{
"title": "Project",
"value": "{{.app.spec.project}}"
}
}
]
}
}
]
}
template.app-deleted: |
webhook:
teams-workflow:
method: POST
body: |
{
"attachments": [
{
"contentType": "object",
"content": {
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"style": "Person",
"url": "https://argo-cd.readthedocs.io/en/stable/assets/logo.png",
"size": "Small"
}
],
"width": "auto"
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "TextBlock",
"weight": "Bolder",
"text": "{{.app.metadata.name}}",
"wrap": true,
"size": "ExtraLarge"
}
]
}
]
},
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": "Application has been deleted.",
"color": "Attention"
},
{
"type": "FactSet",
"facts": [
{
"title": "Project",
"value": "{{.app.spec.project}}"
}
}
]
}
}
]
}
template.app-deployed: |
webhook:
teams-workflow:
method: POST
body: |
{
"attachments": [
{
"contentType": "object",
"content": {
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"style": "Person",
"url": "https://argo-cd.readthedocs.io/en/stable/assets/logo.png",
"size": "Small"
}
],
"width": "auto"
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "TextBlock",
"weight": "Bolder",
"text": "{{.app.metadata.name}}",
"wrap": true,
"size": "ExtraLarge"
}
]
}
]
},
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": "New version of application is up and running.",
"color": "Good"
},
{
"type": "FactSet",
"facts": [
{
"title": "Project",
"value": "{{.app.spec.project}}"
},
{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}"
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}"
},
{
"title": "Revision",
"value": "{{.app.status.sync.revision}}"
}
{{range $index, $c := .app.status.conditions}}
{{if not $index}},{{end}}
{{if $index}},{{end}}
{
"title": "{{$c.type}}",
"value": "{{$c.message}}"
}
{{end}}
]
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.OpenUrl",
"title": "Go To Application",
"url": "{{.context.argocdUrl}}/applications/{{.app.metadata.namespace}}/{{.app.metadata.name}}"
},
{
"type": "Action.OpenUrl",
"title": "Go To Commit",
"url": "{{.app.spec.source.repoURL}}/-/commit/{{.app.status.sync.revision}}"
}
]
}
]
}
}
]
}
template.app-health-degraded: |
webhook:
teams-workflow:
method: POST
body: |
{
"attachments": [
{
"contentType": "object",
"content": {
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"style": "Person",
"url": "https://argo-cd.readthedocs.io/en/stable/assets/logo.png",
"size": "Small"
}
],
"width": "auto"
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "TextBlock",
"weight": "Bolder",
"text": "{{.app.metadata.name}}",
"wrap": true,
"size": "ExtraLarge"
}
]
}
]
},
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": "Application has degraded.",
"color": "Warning"
},
{
"type": "FactSet",
"facts": [
{
"title": "Project",
"value": "{{.app.spec.project}}"
},
{
"title": "Health Status",
"value": "{{.app.status.health.status}}"
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}"
}
{{range $index, $c := .app.status.conditions}}
{{if not $index}},{{end}}
{{if $index}},{{end}}
{
"title": "{{$c.type}}",
"value": "{{$c.message}}"
}
{{end}}
]
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.OpenUrl",
"title": "Go To Application",
"url": "{{.context.argocdUrl}}/applications/{{.app.metadata.namespace}}/{{.app.metadata.name}}"
}
]
}
]
}
}
]
}
template.app-sync-failed: |
webhook:
teams-workflow:
method: POST
body: |
{
"attachments": [
{
"contentType": "object",
"content": {
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"style": "Person",
"url": "https://argo-cd.readthedocs.io/en/stable/assets/logo.png",
"size": "Small"
}
],
"width": "auto"
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "TextBlock",
"weight": "Bolder",
"text": "{{.app.metadata.name}}",
"wrap": true,
"size": "ExtraLarge"
}
]
}
]
},
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": "Failed to sync application.",
"color": "Attention"
},
{
"type": "FactSet",
"facts": [
{
"title": "Project",
"value": "{{.app.spec.project}}"
},
{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}"
},
{
"title": "Failed at",
"value": "{{.app.status.operationState.finishedAt}}"
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}"
}
{{range $index, $c := .app.status.conditions}}
{{if not $index}},{{end}}
{{if $index}},{{end}}
{
"title": "{{$c.type}}",
"value": "{{$c.message}}"
}
{{end}}
]
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.OpenUrl",
"title": "Go To Application",
"url": "{{.context.argocdUrl}}/applications/{{.app.metadata.namespace}}/{{.app.metadata.name}}"
}
]
}
]
}
}
]
}
template.app-sync-running: |
webhook:
teams-workflow:
method: POST
body: |
{
"attachments": [
{
"contentType": "object",
"content": {
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"style": "Person",
"url": "https://argo-cd.readthedocs.io/en/stable/assets/logo.png",
"size": "Small"
}
],
"width": "auto"
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "TextBlock",
"weight": "Bolder",
"text": "{{.app.metadata.name}}",
"wrap": true,
"size": "ExtraLarge"
}
]
}
]
},
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": "Start syncing application.",
"color": "Warning"
},
{
"type": "FactSet",
"facts": [
{
"title": "Project",
"value": "{{.app.spec.project}}"
},
{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}"
},
{
"title": "Started at",
"value": "{{.app.status.operationState.startedAt}}"
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}"
}
{{range $index, $c := .app.status.conditions}}
{{if not $index}},{{end}}
{{if $index}},{{end}}
{
"title": "{{$c.type}}",
"value": "{{$c.message}}"
}
{{end}}
]
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.OpenUrl",
"title": "Go To Application",
"url": "{{.context.argocdUrl}}/applications/{{.app.metadata.namespace}}/{{.app.metadata.name}}"
}
]
}
]
}
}
]
}
template.app-sync-status-unknown: |
webhook:
teams-workflow:
method: POST
body: |
{
"attachments": [
{
"contentType": "object",
"content": {
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"style": "Person",
"url": "https://argo-cd.readthedocs.io/en/stable/assets/logo.png",
"size": "Small"
}
],
"width": "auto"
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "TextBlock",
"weight": "Bolder",
"text": "{{.app.metadata.name}}",
"wrap": true,
"size": "ExtraLarge"
}
]
}
]
},
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": "Application sync status is 'Unknown'.",
"color": "Warning"
},
{
"type": "FactSet",
"facts": [
{
"title": "Project",
"value": "{{.app.spec.project}}"
},
{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}"
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}"
}
{{range $index, $c := .app.status.conditions}}
{{if not $index}},{{end}}
{{if $index}},{{end}}
{
"title": "{{$c.type}}",
"value": "{{$c.message}}"
}
{{end}}
]
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.OpenUrl",
"title": "Go To Application",
"url": "{{.context.argocdUrl}}/applications/{{.app.metadata.namespace}}/{{.app.metadata.name}}"
}
]
}
]
}
}
]
}
template.app-sync-status-outofsync: |
webhook:
teams-workflow:
method: POST
body: |
{
"attachments": [
{
"contentType": "object",
"content": {
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"style": "Person",
"url": "https://argo-cd.readthedocs.io/en/stable/assets/logo.png",
"size": "Small"
}
],
"width": "auto"
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "TextBlock",
"weight": "Bolder",
"text": "{{.app.metadata.name}}",
"wrap": true,
"size": "ExtraLarge"
}
]
}
]
},
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": "Application sync status is 'OutOfSync'.",
"color": "Warning"
},
{
"type": "FactSet",
"facts": [
{
"title": "Project",
"value": "{{.app.spec.project}}"
},
{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}"
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}"
}
{{range $index, $c := .app.status.conditions}}
{{if not $index}},{{end}}
{{if $index}},{{end}}
{
"title": "{{$c.type}}",
"value": "{{$c.message}}"
}
{{end}}
]
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.OpenUrl",
"title": "Go To Application",
"url": "{{.context.argocdUrl}}/applications/{{.app.metadata.namespace}}/{{.app.metadata.name}}"
}
]
}
]
}
}
]
}
template.app-sync-succeeded: |
webhook:
teams-workflow:
method: POST
body: |
{
"attachments": [
{
"contentType": "object",
"content": {
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"style": "Person",
"url": "https://argo-cd.readthedocs.io/en/stable/assets/logo.png",
"size": "Small"
}
],
"width": "auto"
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "TextBlock",
"weight": "Bolder",
"text": "{{.app.metadata.name}}",
"wrap": true,
"size": "ExtraLarge"
}
]
}
]
},
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": "Application has been successfully synced.",
"color": "Good"
},
{
"type": "FactSet",
"facts": [
{
"title": "Project",
"value": "{{.app.spec.project}}"
},
{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}"
},
{
"title": "Synced at",
"value": "{{.app.status.operationState.finishedAt}}"
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}"
}
{{range $index, $c := .app.status.conditions}}
{{if not $index}},{{end}}
{{if $index}},{{end}}
{
"title": "{{$c.type}}",
"value": "{{$c.message}}"
}
{{end}}
]
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.OpenUrl",
"title": "Go To Application",
"url": "{{.context.argocdUrl}}/applications/{{.app.metadata.namespace}}/{{.app.metadata.name}}"
}
]
}
]
}
}
]
}
trigger.on-created: |
- description: Application is created.
oncePer: app.metadata.name
send:
- app-created
when: "true"
trigger.on-deleted: |
- description: Application is deleted.
oncePer: app.metadata.name
send:
- app-deleted
when: app.metadata.deletionTimestamp != nil
trigger.on-deployed: |
- description: Application is synced and healthy. Triggered once per commit.
oncePer: app.status.operationState?.syncResult?.revision
send:
- app-deployed
when: app.status.operationState != nil and app.status.operationState.phase in ['Succeeded']
and app.status.health.status == 'Healthy'
trigger.on-health-degraded: |
- description: Application has degraded
send:
- app-health-degraded
when: app.status.health.status == 'Degraded'
trigger.on-sync-failed: |
- description: Application syncing has failed
send:
- app-sync-failed
when: app.status.operationState != nil and app.status.operationState.phase in ['Error', 'Failed']
trigger.on-sync-running: |
- description: Application is being synced
send:
- app-sync-running
when: app.status.operationState != nil and app.status.operationState.phase in ['Running']
trigger.on-sync-status-unknown: |
- description: Application status is 'Unknown'
send:
- app-sync-status-unknown
when: app.status.sync.status == 'Unknown'
trigger.on-sync-status-outofsync: |
- description: Application status is 'OutOfSync'
send:
- app-sync-status-outofsync
when: app.status.sync.status == 'OutOfSync'
trigger.on-sync-succeeded: |
- description: Application syncing has succeeded
send:
- app-sync-succeeded
when: app.status.operationState != nil and app.status.operationState.phase in ['Succeeded']
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/component: notifications-controller
app.kubernetes.io/instance: argocd
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: argocd-notifications-controller
app.kubernetes.io/part-of: argocd
app.kubernetes.io/version: v2.11.2
helm.sh/chart: argo-cd-6.11.1
name: argocd-notifications-cm
namespace: argocd
hello @bestend, could you please explain how you've created workflows in MSTeams? and what template do you use there?
@awsaabr you need to use template Post to a channel when a webhook request is received
. once you select, it's pretty much straight forward like legacy teams webhook creation.
once you completed the setup you will get a webhook URL. keep it safe you won't be able to get that info again. you can test it by sending a POST request to webhook URL with one of the JSON bodies which is provide by @bestend on the above example.
Oh Microsoft... how I love wasting hours redoing things that already work... If you want your cards to fill the width of the window, I found this property -
"msteams": {
"width": "Full"
},
In context:
template.app-health-degraded: |
webhook:
teams-workflow:
method: POST
body: |
{
"attachments": [
{
"contentType": "object",
"content": {
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"msteams": {
"width": "Full"
},
I've got 3 environments (dev / qa / prod) all on one controller, and they'll each get notifications to different teams channels. That pretty much triples the size of the configmap for the webhook flavor, so an update to the now legacy teams service would be very useful indeed.
I am getting weird behaviour after switching to the Teams Workflows. The alerts come through OK, then, something bad happens in the ArgoCD Matrix and a flood of messages come through, all for "sync succeeded"
@awsaabr you need to use template
Post to a channel when a webhook request is received
. once you select, it's pretty much straight forward like legacy teams webhook creation.once you completed the setup you will get a webhook URL. keep it safe you won't be able to get that info again. you can test it by sending a POST request to webhook URL with one of the JSON bodies which is provide by @bestend on the above example.
@kirankumar-grootan with workflows can we replicate the webhook behaviour where we can use same webhook tokens to send messages to multiple groups where group names can be passed in annotations? As I guess workflows are generated per group
I've started to see this today (July 8th 2024) in all deployment notifications:
On Friday July 5th 2024 the normal deployment notification was being shown.
I'm using Argo CD v2.11.4 and have been using it on both days.
Their time line looks pretty aggressive:
Will this require a code change on the Argo CD side of things? I know there's generic webhook connector support built into Argo CD but based on glancing the docs, it would be a pretty big quality of life hit to use that vs how easy it was to use the Teams integration.