@@ -2,6 +2,8 @@ package pagerduty
22
33import (
44 "fmt"
5+ "log"
6+ "sort"
57
68 pd "github.com/PagerDuty/go-pagerduty"
79)
@@ -25,3 +27,110 @@ func (pdc Config) FireAlert(details pd.V2Payload) (*pd.V2EventResponse, error) {
2527 }
2628 return e , nil
2729}
30+
31+ // MergeCICDIncidents merges all incidents for the CI Watcher by their title.
32+ func MergeCICDIncidents (client * pd.Client ) error {
33+ options := pd.ListIncidentsOptions {
34+ ServiceIDs : []string {"P7VT2V5" },
35+ Statuses : []string {"triggered" , "acknowledged" },
36+ APIListObject : pd.APIListObject {
37+ Limit : 100 ,
38+ },
39+ }
40+ var incidents []pd.Incident
41+ if err := Incidents (client , options , func (i pd.Incident ) error {
42+ incidents = append (incidents , i )
43+ return nil
44+ }); err != nil {
45+ return fmt .Errorf ("failed collecting incidents: %w" , err )
46+ }
47+ if err := MergeIncidentsByTitle (client , incidents ); err != nil {
48+ return fmt .Errorf ("failed merging incidents: %w" , err )
49+ }
50+ return nil
51+ }
52+
53+ // MergeIncidentsByTitle will combine all incidents in the provided slice that share the
54+ // same title into a single incident with multiple alerts.
55+ func MergeIncidentsByTitle (c * pd.Client , incidents []pd.Incident ) error {
56+ titleToIncident := make (map [string ][]pd.Incident )
57+
58+ for _ , incident := range incidents {
59+ titleToIncident [incident .Title ] = append (titleToIncident [incident .Title ], incident )
60+ }
61+
62+ for _ , incidents := range titleToIncident {
63+ sort .Slice (incidents , func (i , j int ) bool {
64+ return incidents [i ].Id < incidents [j ].Id
65+ })
66+ if len (incidents ) < 2 {
67+ continue
68+ }
69+ first := incidents [0 ]
70+ mergeOptions := []pd.MergeIncidentsOptions {}
71+ for _ , toMerge := range incidents [1 :] {
72+ mergeOptions = append (mergeOptions , pd.MergeIncidentsOptions {
73+ ID : toMerge .Id ,
74+ Type : toMerge .APIObject .Type ,
75+ })
76+ }
77+ log .Printf ("Merging into %s: %v" , first .Id , mergeOptions )
78+ _ , err := c .MergeIncidents ("" , first .Id , mergeOptions )
79+ if err != nil {
80+ return fmt .Errorf ("Failed merging %d incidents into %s: %w" , len (incidents )- 1 , first .Id , err )
81+ }
82+ }
83+ return nil
84+ }
85+
86+ // Incidents uses the provided client to retrieve all Incidents matching the provided
87+ // list options and calls the handler function on each one.
88+ func Incidents (c * pd.Client , options pd.ListIncidentsOptions , handler func (pd.Incident ) error ) error {
89+ var (
90+ il = new (pd.ListIncidentsResponse )
91+ err error
92+ previousLen int
93+ )
94+ firstIteration := true
95+ for il .APIListObject .More || firstIteration {
96+ firstIteration = false
97+ options .APIListObject .Offset = il .APIListObject .Offset + uint (previousLen )
98+ il , err = c .ListIncidents (options )
99+ if err != nil {
100+ return fmt .Errorf ("failed listing incidents: %w" , err )
101+ }
102+ previousLen = len (il .Incidents )
103+ for _ , incident := range il .Incidents {
104+ if err := handler (incident ); err != nil {
105+ return fmt .Errorf ("handler failed: %w" , err )
106+ }
107+ }
108+ }
109+ return nil
110+ }
111+
112+ // Alerts uses the provided client to retrieve all Alerts associated with the provided
113+ // incident, calling the provided handler function on each alert.
114+ func Alerts (c * pd.Client , incident pd.Incident , options pd.ListIncidentAlertsOptions , handler func (pd.IncidentAlert ) error ) error {
115+ var (
116+ il = new (pd.ListAlertsResponse )
117+ err error
118+ previousLen int
119+ )
120+ firstIteration := true
121+ for il .APIListObject .More || firstIteration {
122+ firstIteration = false
123+ options .APIListObject .Offset = il .APIListObject .Offset + uint (previousLen )
124+ il , err = c .ListIncidentAlertsWithOpts (incident .Id , options )
125+ if err != nil {
126+ return fmt .Errorf ("failed listing alerts: %w" , err )
127+ }
128+ previousLen = len (il .Alerts )
129+ for _ , alert := range il .Alerts {
130+ if err := handler (alert ); err != nil {
131+ return fmt .Errorf ("handler failed: %w" , err )
132+ }
133+ }
134+ }
135+ return nil
136+ }
0 commit comments