@@ -15,30 +15,34 @@ import (
1515 goslack "github.com/slack-go/slack"
1616)
1717
18- // PublishAsGeneralSlackMessage publishes a report of the vulnerabilities scanned to a slack channel
19- func PublishAsGeneralSlackMessage (channelName string , reports []scanner.Report , paths []string , s slack.IService ) (err error ) {
18+ // PublishAsGeneralSlackMessage publishes a report of the vulnerabilities scanned to a list of slack channels
19+ func PublishAsGeneralSlackMessage (channelNames []string , reports []scanner.Report , paths []string , s slack.IService ) error {
20+ var wg sync.WaitGroup
21+ errChan := make (chan error , len (channelNames ))
2022 vulnerableReportsBySeverityKind := groupVulnReportsByMaxSeverityKind (reports )
2123
2224 summary := formatSummary (vulnerableReportsBySeverityKind , len (reports ), paths )
23-
24- ts , err := s .PostMessage (channelName , summary ... )
25- if err != nil {
26- return errors .Join (errors .New ("failed to post slack summary" ), err )
25+ threadMsgs := formatReportMessage (vulnerableReportsBySeverityKind )
26+ for _ , slackChannel := range channelNames {
27+ log .Info ().Str ("slackChannel" , slackChannel ).Msg ("Posting report to slack channel" )
28+ wg .Add (1 )
29+ go func (errChan chan <- error ) {
30+ defer wg .Done ()
31+ if err := publishAsGeneralSlackMessageSingleChannel (slackChannel , summary , threadMsgs , s ); err != nil {
32+ log .Error ().Err (err ).Str ("slackChannel" , slackChannel ).Msg ("Failed to post slack report" )
33+ errChan <- err
34+ }
35+ }(errChan )
2736 }
37+ wg .Wait ()
38+ close (errChan )
2839
29- msgOptions := formatReportMessage (vulnerableReportsBySeverityKind )
30- for _ , option := range msgOptions {
31- _ , err = s .PostMessage (
32- channelName ,
33- option ,
34- goslack .MsgOptionTS (ts ), // Replies to the summary message in thread
35- )
36- if err != nil {
37- return errors .Join (errors .New ("failed to message in slack summary thread" ), err )
38- }
40+ var outErr error
41+ for err := range errChan {
42+ outErr = errors .Join (err , outErr )
3943 }
4044
41- return
45+ return outErr
4246}
4347
4448func PublishAsSpecificChannelSlackMessage (reports []scanner.Report , s slack.IService ) (warn error ) {
@@ -209,6 +213,26 @@ func formatReportMessage(reportsBySeverityKind map[scanner.SeverityScoreKind][]s
209213 return
210214}
211215
216+ func publishAsGeneralSlackMessageSingleChannel (channelName string , summary []goslack.MsgOption , threadMsgs []goslack.MsgOption , s slack.IService ) (err error ) {
217+ ts , err := s .PostMessage (channelName , summary ... )
218+ if err != nil {
219+ return errors .Join (errors .New ("failed to post slack summary" ), err )
220+ }
221+
222+ for _ , option := range threadMsgs {
223+ _ , err = s .PostMessage (
224+ channelName ,
225+ option ,
226+ goslack .MsgOptionTS (ts ), // Replies to the summary message in thread
227+ )
228+ if err != nil {
229+ return errors .Join (errors .New ("failed to message in slack summary thread" ), err )
230+ }
231+ }
232+
233+ return
234+ }
235+
212236// splitMessage splits a string into chunks of at most maxLen characters.
213237// Each chunk is determined by the closest newline character
214238func splitMessage (s string , maxLen int ) []string {
0 commit comments