mirror of
https://github.com/semaphoreui/semaphore.git
synced 2024-11-23 12:30:41 +01:00
feat: add more logs to alerts and use same structure for teams alerts
This commit is contained in:
parent
5c8b87620e
commit
dba0b8e35e
@ -3,11 +3,13 @@ package tasks
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
log "github.com/sirupsen/logrus"
|
"fmt"
|
||||||
"github.com/ansible-semaphore/semaphore/api/sockets"
|
|
||||||
"github.com/ansible-semaphore/semaphore/util"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ansible-semaphore/semaphore/api/sockets"
|
||||||
|
"github.com/ansible-semaphore/semaphore/util"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t *TaskRunner) Log2(msg string, now time.Time) {
|
func (t *TaskRunner) Log2(msg string, now time.Time) {
|
||||||
@ -36,6 +38,10 @@ func (t *TaskRunner) Log(msg string) {
|
|||||||
t.Log2(msg, time.Now())
|
t.Log2(msg, time.Now())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TaskRunner) Logf(format string, a ...any) {
|
||||||
|
t.Log2(fmt.Sprintf(format, a...), time.Now())
|
||||||
|
}
|
||||||
|
|
||||||
// Readln reads from the pipe
|
// Readln reads from the pipe
|
||||||
func Readln(r *bufio.Reader) (string, error) {
|
func Readln(r *bufio.Reader) (string, error) {
|
||||||
var (
|
var (
|
||||||
|
@ -17,59 +17,6 @@ import (
|
|||||||
//go:embed templates/*.tmpl
|
//go:embed templates/*.tmpl
|
||||||
var templates embed.FS
|
var templates embed.FS
|
||||||
|
|
||||||
const microsoftTeamsTemplate = `{
|
|
||||||
"type": "message",
|
|
||||||
"attachments": [
|
|
||||||
{
|
|
||||||
"contentType": "application/vnd.microsoft.card.adaptive",
|
|
||||||
"content": {
|
|
||||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
|
||||||
"type": "AdaptiveCard",
|
|
||||||
"version": "1.5",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "TextBlock",
|
|
||||||
"text": "Ansible Task Template Execution by: {{ .Author }}",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "FactSet",
|
|
||||||
"facts": [
|
|
||||||
{
|
|
||||||
"title": "Task:",
|
|
||||||
"value": "{{ .Name }}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Status:",
|
|
||||||
"value": "{{ .TaskResult }}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Task ID:",
|
|
||||||
"value": "{{ .TaskID }}"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"separator": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"actions": [
|
|
||||||
{
|
|
||||||
"type": "Action.OpenUrl",
|
|
||||||
"title": "Task URL",
|
|
||||||
"url": "{{ .TaskURL }}"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"msteams": {
|
|
||||||
"width": "Full"
|
|
||||||
},
|
|
||||||
"backgroundImage": {
|
|
||||||
"horizontalAlignment": "Center",
|
|
||||||
"url": "data:image/jpg;base64,iVBORw0KGgoAAAANSUhEUgAABSgAAAAFCAYAAABGmwLHAAAARklEQVR4nO3YMQEAIBDEsANPSMC/AbzwMm5JJHTseuf+AAAAAAAUbNEBAAAAgBaDEgAAAACoMSgBAAAAgBqDEgAAAADoSDL8RAJfcbcsoQAAAABJRU5ErkJggg==",
|
|
||||||
"fillMode": "RepeatHorizontally"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}`
|
|
||||||
|
|
||||||
// Alert represents an alert that will be templated and sent to the appropriate service
|
// Alert represents an alert that will be templated and sent to the appropriate service
|
||||||
type Alert struct {
|
type Alert struct {
|
||||||
Name string
|
Name string
|
||||||
@ -124,6 +71,11 @@ func (t *TaskRunner) sendMailAlert() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if body.Len() == 0 {
|
||||||
|
t.Log("Buffer for email alert is empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for _, uid := range t.users {
|
for _, uid := range t.users {
|
||||||
user, err := t.pool.store.GetUser(uid)
|
user, err := t.pool.store.GetUser(uid)
|
||||||
|
|
||||||
@ -136,6 +88,8 @@ func (t *TaskRunner) sendMailAlert() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Logf("Attempting to send email alert to %s", user.Email)
|
||||||
|
|
||||||
if err := mailer.Send(
|
if err := mailer.Send(
|
||||||
util.Config.EmailSecure,
|
util.Config.EmailSecure,
|
||||||
util.Config.EmailHost,
|
util.Config.EmailHost,
|
||||||
@ -148,7 +102,10 @@ func (t *TaskRunner) sendMailAlert() {
|
|||||||
body.String(),
|
body.String(),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
util.LogError(err)
|
util.LogError(err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Logf("Sent successfully email alert to %s", user.Email)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,6 +158,13 @@ func (t *TaskRunner) sendTelegramAlert() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if body.Len() == 0 {
|
||||||
|
t.Log("Buffer for telegram alert is empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log("Attempting to send telegram alert")
|
||||||
|
|
||||||
resp, err := http.Post(
|
resp, err := http.Post(
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
"https://api.telegram.org/bot%s/sendMessage",
|
"https://api.telegram.org/bot%s/sendMessage",
|
||||||
@ -215,6 +179,8 @@ func (t *TaskRunner) sendTelegramAlert() {
|
|||||||
} else if resp.StatusCode != 200 {
|
} else if resp.StatusCode != 200 {
|
||||||
t.Log("Can't send telegram alert! Response code: " + strconv.Itoa(resp.StatusCode))
|
t.Log("Can't send telegram alert! Response code: " + strconv.Itoa(resp.StatusCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Log("Sent successfully telegram alert")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TaskRunner) sendSlackAlert() {
|
func (t *TaskRunner) sendSlackAlert() {
|
||||||
@ -254,6 +220,13 @@ func (t *TaskRunner) sendSlackAlert() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if body.Len() == 0 {
|
||||||
|
t.Log("Buffer for slack alert is empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log("Attempting to send slack alert")
|
||||||
|
|
||||||
resp, err := http.Post(
|
resp, err := http.Post(
|
||||||
util.Config.SlackUrl,
|
util.Config.SlackUrl,
|
||||||
"application/json",
|
"application/json",
|
||||||
@ -265,6 +238,67 @@ func (t *TaskRunner) sendSlackAlert() {
|
|||||||
} else if resp.StatusCode != 200 {
|
} else if resp.StatusCode != 200 {
|
||||||
t.Log("Can't send slack alert! Response code: " + strconv.Itoa(resp.StatusCode))
|
t.Log("Can't send slack alert! Response code: " + strconv.Itoa(resp.StatusCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Log("Sent successfully slack alert")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TaskRunner) sendMicrosoftTeamsAlert() {
|
||||||
|
if !util.Config.MicrosoftTeamsAlert || !t.alert {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.Template.SuppressSuccessAlerts && t.Task.Status == lib.TaskSuccessStatus {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
body := bytes.NewBufferString("")
|
||||||
|
author, version := t.alertInfos()
|
||||||
|
|
||||||
|
alert := Alert{
|
||||||
|
Name: t.Template.Name,
|
||||||
|
Author: author,
|
||||||
|
Color: t.alertColor("micorsoft-teams"),
|
||||||
|
Task: alertTask{
|
||||||
|
ID: strconv.Itoa(t.Task.ID),
|
||||||
|
URL: t.taskLink(),
|
||||||
|
Result: strings.ToUpper(string(t.Task.Status)),
|
||||||
|
Version: version,
|
||||||
|
Desc: t.Task.Message,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tpl, err := template.ParseFS(templates, "templates/microsoft-teams.tmpl")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Log("Can't parse microsoft teams alert template!")
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tpl.Execute(body, alert); err != nil {
|
||||||
|
t.Log("Can't generate microsoft teams alert template!")
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if body.Len() == 0 {
|
||||||
|
t.Log("Buffer for microsoft teams alert is empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log("Attempting to send microsoft teams alert")
|
||||||
|
|
||||||
|
resp, err := http.Post(
|
||||||
|
util.Config.MicrosoftTeamsUrl,
|
||||||
|
"application/json",
|
||||||
|
body,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Log("Can't send microsoft teams alert! Error: " + err.Error())
|
||||||
|
} else if resp.StatusCode != 200 {
|
||||||
|
t.Log("Can't send microsoft teams alert! Response code: " + strconv.Itoa(resp.StatusCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log("Sent successfully microsoft teams alert")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TaskRunner) alertInfos() (string, string) {
|
func (t *TaskRunner) alertInfos() (string, string) {
|
||||||
@ -324,102 +358,3 @@ func (t *TaskRunner) taskLink() string {
|
|||||||
t.Task.ID,
|
t.Task.ID,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TaskRunner) sendMicrosoftTeamsAlert() {
|
|
||||||
if !util.Config.MicrosoftTeamsAlert || !t.alert {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if t.Template.SuppressSuccessAlerts && t.Task.Status == lib.TaskSuccessStatus {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
MicrosoftTeamsUrl := util.Config.MicrosoftTeamsUrl
|
|
||||||
|
|
||||||
var microsoftTeamsBuffer bytes.Buffer
|
|
||||||
|
|
||||||
var version string
|
|
||||||
if t.Task.Version != nil {
|
|
||||||
version = *t.Task.Version
|
|
||||||
} else if t.Task.BuildTaskID != nil {
|
|
||||||
version = "build " + strconv.Itoa(*t.Task.BuildTaskID)
|
|
||||||
} else {
|
|
||||||
version = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var message string
|
|
||||||
if t.Task.Message != "" {
|
|
||||||
message = "- " + t.Task.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
var author string
|
|
||||||
if t.Task.UserID != nil {
|
|
||||||
user, err := t.pool.store.GetUser(*t.Task.UserID)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
author = user.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
var color string
|
|
||||||
if t.Task.Status == lib.TaskSuccessStatus {
|
|
||||||
color = "good"
|
|
||||||
} else if t.Task.Status == lib.TaskFailStatus {
|
|
||||||
color = "bad"
|
|
||||||
} else if t.Task.Status == lib.TaskRunningStatus {
|
|
||||||
color = "#333CFF"
|
|
||||||
} else if t.Task.Status == lib.TaskWaitingStatus {
|
|
||||||
color = "#FFFC33"
|
|
||||||
} else if t.Task.Status == lib.TaskStoppingStatus {
|
|
||||||
color = "#BEBEBE"
|
|
||||||
} else if t.Task.Status == lib.TaskStoppedStatus {
|
|
||||||
color = "#5B5B5B"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instantiate an alert object
|
|
||||||
alert := Alert{
|
|
||||||
TaskID: strconv.Itoa(t.Task.ID),
|
|
||||||
Name: t.Template.Name,
|
|
||||||
TaskURL: util.Config.WebHost + "/project/" + strconv.Itoa(t.Template.ProjectID) + "/templates/" + strconv.Itoa(t.Template.ID) + "?t=" + strconv.Itoa(t.Task.ID),
|
|
||||||
TaskResult: strings.ToUpper(string(t.Task.Status)),
|
|
||||||
TaskVersion: version,
|
|
||||||
TaskDescription: message,
|
|
||||||
Author: author,
|
|
||||||
Color: color,
|
|
||||||
}
|
|
||||||
|
|
||||||
tpl := template.New("MicrosoftTeams body template")
|
|
||||||
|
|
||||||
tpl, err := tpl.Parse(microsoftTeamsTemplate)
|
|
||||||
if err != nil {
|
|
||||||
t.Log("Can't parse MicrosoftTeams template!")
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The tpl.Execute(µsoftTeamsBuffer, alert) line is used to apply the data from the alert struct to the template.
|
|
||||||
// This operation fills in the placeholders in the template with the corresponding values from the alert struct
|
|
||||||
// and writes the result to the microsoftTeamsBuffer. In essence, it generates a JSON message based on the template and the data in the alert struct.
|
|
||||||
err = tpl.Execute(µsoftTeamsBuffer, alert)
|
|
||||||
if err != nil {
|
|
||||||
t.Log("Can't generate alert template!")
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// test if buffer is empty
|
|
||||||
if microsoftTeamsBuffer.Len() == 0 {
|
|
||||||
t.Log("MicrosoftTeams buffer is empty!")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Log("Attempting to send MicrosoftTeams alert")
|
|
||||||
|
|
||||||
resp, err := http.Post(MicrosoftTeamsUrl, "application/json", µsoftTeamsBuffer)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Log("Can't send MicrosoftTeams alert! Error: " + err.Error())
|
|
||||||
} else if resp.StatusCode != 200 {
|
|
||||||
t.Log("Can't send MicrosoftTeams alert! Response code: " + strconv.Itoa(resp.StatusCode))
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Log("MicrosoftTeams alert sent successfully")
|
|
||||||
}
|
|
||||||
|
52
services/tasks/templates/microsoft-teams.tmpl
Normal file
52
services/tasks/templates/microsoft-teams.tmpl
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"type": "message",
|
||||||
|
"attachments": [
|
||||||
|
{
|
||||||
|
"contentType": "application/vnd.microsoft.card.adaptive",
|
||||||
|
"content": {
|
||||||
|
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||||
|
"type": "AdaptiveCard",
|
||||||
|
"version": "1.5",
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "TextBlock",
|
||||||
|
"text": "Ansible Task Template Execution by: {{ .Author }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "FactSet",
|
||||||
|
"facts": [
|
||||||
|
{
|
||||||
|
"title": "Task:",
|
||||||
|
"value": "{{ .Name }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Status:",
|
||||||
|
"value": "{{ .Task.Result }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Task ID:",
|
||||||
|
"value": "{{ .Task.ID }}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"separator": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"type": "Action.OpenUrl",
|
||||||
|
"title": "Task URL",
|
||||||
|
"url": "{{ .Task.URL }}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"msteams": {
|
||||||
|
"width": "Full"
|
||||||
|
},
|
||||||
|
"backgroundImage": {
|
||||||
|
"horizontalAlignment": "Center",
|
||||||
|
"url": "data:image/jpg;base64,iVBORw0KGgoAAAANSUhEUgAABSgAAAAFCAYAAABGmwLHAAAARklEQVR4nO3YMQEAIBDEsANPSMC/AbzwMm5JJHTseuf+AAAAAAAUbNEBAAAAgBaDEgAAAACoMSgBAAAAgBqDEgAAAADoSDL8RAJfcbcsoQAAAABJRU5ErkJggg==",
|
||||||
|
"fillMode": "RepeatHorizontally"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user