From 641810d4410b96dfb550bc1fcb1b7beeeac6fed0 Mon Sep 17 00:00:00 2001 From: James Yang Date: Thu, 15 Apr 2021 22:03:28 +0800 Subject: [PATCH] feat. support teams theme color templating (#256) * feat. support teams theme color templating * UPD. update markdown syntax conventions, mention themeColor field in teams integration guide * UPD. rollback to single quote for passing CI/CD validations, add screenshot in doc --- catalog/install.yaml | 4 ++++ catalog/templates/app-deployed.yaml | 1 + catalog/templates/app-health-degraded.yaml | 1 + catalog/templates/app-sync-failed.yaml | 1 + catalog/templates/app-sync-succeeded.yaml | 1 + docs/catalog.md | 4 ++++ docs/services/teams.md | 17 +++++++++++++++-- pkg/services/teams.go | 19 +++++++++++++++++++ pkg/services/teams_test.go | 4 ++++ 9 files changed, 50 insertions(+), 2 deletions(-) diff --git a/catalog/install.yaml b/catalog/install.yaml index cce21d0a..937db528 100644 --- a/catalog/install.yaml +++ b/catalog/install.yaml @@ -90,6 +90,7 @@ data: "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" }] }] + themeColor: '#000080' title: New version of an application {{.app.metadata.name}} is up and running. template.app-health-degraded: | email: @@ -161,6 +162,7 @@ data: "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" }] }] + themeColor: '#FF0000' title: Application {{.app.metadata.name}} has degraded. template.app-sync-failed: | email: @@ -236,6 +238,7 @@ data: "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" }] }] + themeColor: '#FF0000' title: Failed to sync application {{.app.metadata.name}}. template.app-sync-running: | email: @@ -462,6 +465,7 @@ data: "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" }] }] + themeColor: '#000080' title: Application {{.app.metadata.name}} has been successfully synced trigger.on-created: | - description: Application is created. diff --git a/catalog/templates/app-deployed.yaml b/catalog/templates/app-deployed.yaml index 7bc5ee17..7b7eefff 100644 --- a/catalog/templates/app-deployed.yaml +++ b/catalog/templates/app-deployed.yaml @@ -36,6 +36,7 @@ slack: ] }] teams: + themeColor: "#000080" title: New version of an application {{.app.metadata.name}} is up and running. facts: | [{ diff --git a/catalog/templates/app-health-degraded.yaml b/catalog/templates/app-health-degraded.yaml index 0842d1d3..441f9064 100644 --- a/catalog/templates/app-health-degraded.yaml +++ b/catalog/templates/app-health-degraded.yaml @@ -32,6 +32,7 @@ slack: ] }] teams: + themeColor: "#FF0000" title: Application {{.app.metadata.name}} has degraded. facts: | [{ diff --git a/catalog/templates/app-sync-failed.yaml b/catalog/templates/app-sync-failed.yaml index e020edcd..b8bf8619 100644 --- a/catalog/templates/app-sync-failed.yaml +++ b/catalog/templates/app-sync-failed.yaml @@ -32,6 +32,7 @@ slack: ] }] teams: + themeColor: "#FF0000" title: Failed to sync application {{.app.metadata.name}}. facts: | [{ diff --git a/catalog/templates/app-sync-succeeded.yaml b/catalog/templates/app-sync-succeeded.yaml index 63eabe97..a7958761 100644 --- a/catalog/templates/app-sync-succeeded.yaml +++ b/catalog/templates/app-sync-succeeded.yaml @@ -32,6 +32,7 @@ slack: ] }] teams: + themeColor: "#000080" title: Application {{.app.metadata.name}} has been successfully synced facts: | [{ diff --git a/docs/catalog.md b/docs/catalog.md index a0077cf2..34346b73 100644 --- a/docs/catalog.md +++ b/docs/catalog.md @@ -112,6 +112,7 @@ teams: "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" }] }] + themeColor: '#000080' title: New version of an application {{.app.metadata.name}} is up and running. ``` @@ -187,6 +188,7 @@ teams: "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" }] }] + themeColor: '#FF0000' title: Application {{.app.metadata.name}} has degraded. ``` @@ -266,6 +268,7 @@ teams: "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" }] }] + themeColor: '#FF0000' title: Failed to sync application {{.app.metadata.name}}. ``` @@ -504,6 +507,7 @@ teams: "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" }] }] + themeColor: '#000080' title: Application {{.app.metadata.name}} has been successfully synced ``` diff --git a/docs/services/teams.md b/docs/services/teams.md index 73c39b6e..ba13bb03 100644 --- a/docs/services/teams.md +++ b/docs/services/teams.md @@ -21,7 +21,7 @@ metadata: name: argocd-notifications-cm data: service.teams: | - recipientUrls: + recipientUrls: channelName: $channel-teams-url ``` @@ -48,11 +48,12 @@ metadata: ![](https://user-images.githubusercontent.com/18019529/114271500-9d2b8880-9a4c-11eb-85c1-f6935f0431d5.png) -Notification templates can be customized to leverage teams message sections, facts and potentialAction [feature](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using). +Notification templates can be customized to leverage teams message sections, facts, themeColor, and potentialAction [feature](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using). ```yaml template.app-sync-succeeded: | teams: + themeColor: "#000080" sections: | [{ "facts": [ @@ -96,3 +97,15 @@ template.app-sync-succeeded: | "value": "{{.app.spec.source.repoURL}}" }] ``` + +### theme color field + +You can set theme color as hex string for the message. + +![](https://user-images.githubusercontent.com/1164159/114864810-0718a900-9e24-11eb-8127-8d95da9544c1.png) + +```yaml +template.app-sync-succeeded: | + teams: + themeColor: "#000080" +``` \ No newline at end of file diff --git a/pkg/services/teams.go b/pkg/services/teams.go index 8f0ea093..2c5022dd 100644 --- a/pkg/services/teams.go +++ b/pkg/services/teams.go @@ -16,6 +16,7 @@ type TeamsNotification struct { Template string `json:"template,omitempty"` Title string `json:"title,omitempty"` Text string `json:"text,omitempty"` + ThemeColor string `json:"themeColor,omitempty"` Facts string `json:"facts,omitempty"` Sections string `json:"sections,omitempty"` PotentialAction string `json:"potentialAction,omitempty"` @@ -37,6 +38,11 @@ func (n *TeamsNotification) GetTemplater(name string, f texttemplate.FuncMap) (T return nil, fmt.Errorf("error in '%s' teams.text : %w", name, err) } + themeColor, err := texttemplate.New(name).Funcs(f).Parse(n.ThemeColor) + if err != nil { + return nil, fmt.Errorf("error in '%s' teams.themeColor: %w", name, err) + } + facts, err := texttemplate.New(name).Funcs(f).Parse(n.Facts) if err != nil { return nil, fmt.Errorf("error in '%s' teams.facts : %w", name, err) @@ -81,6 +87,14 @@ func (n *TeamsNotification) GetTemplater(name string, f texttemplate.FuncMap) (T notification.Teams.Text = val } + var themeColorBuff bytes.Buffer + if err := themeColor.Execute(&themeColorBuff, vars); err != nil { + return err + } + if val := themeColorBuff.String(); val != "" { + notification.Teams.ThemeColor = val + } + var factsData bytes.Buffer if err := facts.Execute(&factsData, vars); err != nil { return err @@ -177,6 +191,10 @@ func teamsNotificationToMessage(n Notification) (*teamsMessage, error) { message.Text = n.Teams.Text } + if n.Teams.ThemeColor != "" { + message.ThemeColor = n.Teams.ThemeColor + } + if n.Teams.Sections != "" { unmarshalledSections := make([]teamsSection, 2) err := json.Unmarshal([]byte(n.Teams.Sections), &unmarshalledSections) @@ -234,6 +252,7 @@ type teamsMessage struct { Context string `json:"context"` Title string `json:"title"` Text string `json:"text"` + ThemeColor string `json:"themeColor,omitempty"` PotentialAction []teamsAction `json:"potentialAction,omitempty"` Sections []teamsSection `json:"sections,omitempty"` } diff --git a/pkg/services/teams_test.go b/pkg/services/teams_test.go index d4511faf..67155f72 100644 --- a/pkg/services/teams_test.go +++ b/pkg/services/teams_test.go @@ -20,6 +20,7 @@ func TestGetTemplater_Teams(t *testing.T) { Facts: "facts {{.value}}", Sections: "sections {{.value}}", PotentialAction: "actions {{.value}}", + ThemeColor: "theme color {{.value}}", }, } @@ -47,6 +48,7 @@ func TestGetTemplater_Teams(t *testing.T) { assert.Equal(t, notification.Teams.Sections, "sections value") assert.Equal(t, notification.Teams.Facts, "facts value") assert.Equal(t, notification.Teams.PotentialAction, "actions value") + assert.Equal(t, notification.Teams.ThemeColor, "theme color value") } func TestTeams_DefaultMessage(t *testing.T) { @@ -150,6 +152,7 @@ func TestTeams_MessageFields(t *testing.T) { Sections: "[{\"sections\": true}]", PotentialAction: "[{\"actions\": true}]", Title: "Title", + ThemeColor: "#000080", }, } @@ -164,6 +167,7 @@ func TestTeams_MessageFields(t *testing.T) { assert.Contains(t, receivedBody.Text, notification.Teams.Text) assert.Contains(t, receivedBody.Title, notification.Teams.Title) + assert.Contains(t, receivedBody.ThemeColor, notification.Teams.ThemeColor) assert.Contains(t, receivedBody.PotentialAction, teamsAction{"actions": true}) assert.Contains(t, receivedBody.Sections, teamsSection{"sections": true}) assert.EqualValues(t, receivedBody.Sections[len(receivedBody.Sections)-1]["facts"],