package webhook import ( "context" "fmt" "strings" "time" "gitea.oblak.solutions/dimitar/gitFlow/internal/httpclient" ) // SlackSender posts to a Slack incoming webhook using Block Kit (mrkdwn). type SlackSender struct { cfg Config http *httpclient.Client } func newSlack(cfg Config) *SlackSender { return &SlackSender{cfg: cfg, http: httpclient.New(httpclient.WithTimeout(cfg.TimeoutOrDefault()))} } func (s *SlackSender) Name() string { return s.cfg.Name } type slackMessage struct { Blocks []slackBlock `json:"blocks"` } type slackBlock struct { Type string `json:"type"` Text *slackText `json:"text,omitempty"` } type slackText struct { Type string `json:"type"` // "mrkdwn" or "plain_text" Text string `json:"text"` } func (s *SlackSender) Send(ctx context.Context, payload Payload) error { msg := slackMessage{ Blocks: []slackBlock{ {Type: "header", Text: &slackText{Type: "plain_text", Text: "gitflow: scan results"}}, {Type: "section", Text: &slackText{Type: "mrkdwn", Text: slackSummary(payload)}}, }, } if len(payload.Changed) > 0 { msg.Blocks = append(msg.Blocks, slackBlock{Type: "divider"}, slackBlock{Type: "section", Text: &slackText{Type: "mrkdwn", Text: slackChanges(payload)}}, ) } msg.Blocks = append(msg.Blocks, slackBlock{Type: "context", Text: &slackText{Type: "mrkdwn", Text: slackFooter(payload)}}, ) return s.http.PostJSON(ctx, s.cfg.URL, nil, msg, nil) } func slackSummary(p Payload) string { s := p.Summary return fmt.Sprintf("Scanned *%s* — %d repos: %d clean, %d need attention, %d errors", p.ParentDir, s.Total, s.Clean, s.Attention, s.Errored) } func slackChanges(p Payload) string { var b strings.Builder b.WriteString("*Changed repositories:*\n") for _, r := range p.Changed { sym := statusSymbol(r.Status) line := fmt.Sprintf("• %s `%s` — %s _(%s)_", sym, r.Name, r.Status, r.Branch) if r.AheadBy > 0 || r.BehindBy > 0 { line += fmt.Sprintf(" +%d/-%d", r.AheadBy, r.BehindBy) } if n := r.FileCount(); n > 0 { line += fmt.Sprintf(" %d change(s)", n) } b.WriteString(line + "\n") } return b.String() } func slackFooter(p Payload) string { return fmt.Sprintf("_%s | gitflow_", p.Timestamp.Format(time.RFC3339)) }