Skip to content

Commit 2d08da6

Browse files
authored
Merge pull request #73 from clcollins/auto-ack
auto ack
2 parents 695b582 + 8482d04 commit 2d08da6

File tree

6 files changed

+101
-20
lines changed

6 files changed

+101
-20
lines changed

pkg/pd/pd.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type PagerDutyClientInterface interface {
2626
ListIncidentAlertsWithContext(ctx context.Context, id string, opts pagerduty.ListIncidentAlertsOptions) (*pagerduty.ListAlertsResponse, error)
2727
ListIncidentsWithContext(ctx context.Context, opts pagerduty.ListIncidentsOptions) (*pagerduty.ListIncidentsResponse, error)
2828
ListIncidentNotesWithContext(ctx context.Context, id string) ([]pagerduty.IncidentNote, error)
29+
ListOnCallsWithContext(ctx context.Context, opts pagerduty.ListOnCallOptions) (*pagerduty.ListOnCallsResponse, error)
2930
ManageIncidentsWithContext(ctx context.Context, email string, opts []pagerduty.ManageIncidentsOptions) (*pagerduty.ListIncidentsResponse, error)
3031
}
3132

@@ -257,6 +258,28 @@ func GetUser(client PagerDutyClient, id string, opts pagerduty.GetUserOptions) (
257258
return u, nil
258259
}
259260

261+
func GetUserOnCalls(client PagerDutyClient, id string, opts pagerduty.ListOnCallOptions) ([]pagerduty.OnCall, error) {
262+
var ctx = context.Background()
263+
var o []pagerduty.OnCall
264+
265+
for {
266+
response, err := client.ListOnCallsWithContext(ctx, opts)
267+
if err != nil {
268+
return o, fmt.Errorf("pd.GetUserOnCalls(): failed to get on-call entries for user `%v`: %v", id, err)
269+
}
270+
271+
o = response.OnCalls
272+
273+
opts.Offset += opts.Limit
274+
275+
if !response.More {
276+
break
277+
}
278+
}
279+
280+
return o, nil
281+
}
282+
260283
func ReassignIncidents(client PagerDutyClient, incidents []pagerduty.Incident, user *pagerduty.User, users []*pagerduty.User) ([]pagerduty.Incident, error) {
261284
var ctx = context.Background()
262285
var i []pagerduty.Incident

pkg/tui/commands.go

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -169,19 +169,19 @@ func AssignedToAnyUsers(i pagerduty.Incident, ids []string) bool {
169169

170170
// ShouldBeAcknowledged returns true if the incident is assigned to the given user,
171171
// the user has not acknowledged the incident yet, and autoAcknowledge is enabled
172-
func ShouldBeAcknowledged(i pagerduty.Incident, id string, autoAcknowledge bool) bool {
172+
func ShouldBeAcknowledged(p *pd.Config, i pagerduty.Incident, id string, autoAcknowledge bool) bool {
173173
assigned := AssignedToUser(i, id)
174174
acknowledged := AcknowledgedByUser(i, id)
175-
doIt := assigned && !acknowledged && autoAcknowledge
176-
if doIt {
177-
log.Debug(
178-
"commands.ShouldBeAcknowledged",
179-
"assigned", assigned,
180-
"acknowledged", acknowledged,
181-
"autoAcknowledge", autoAcknowledge,
182-
"doIt", doIt,
183-
)
184-
}
175+
userIsOnCall := UserIsOnCall(p, id)
176+
doIt := assigned && !acknowledged && autoAcknowledge && userIsOnCall
177+
log.Debug(
178+
"commands.ShouldBeAcknowledged",
179+
"assigned", assigned,
180+
"acknowledged", acknowledged,
181+
"autoAcknowledge", autoAcknowledge,
182+
"userIsOnCall", userIsOnCall,
183+
"doIt", doIt,
184+
)
185185
return AssignedToUser(i, id) && !AcknowledgedByUser(i, id) && autoAcknowledge
186186
}
187187

@@ -205,6 +205,43 @@ func AcknowledgedByUser(i pagerduty.Incident, id string) bool {
205205
return false
206206
}
207207

208+
// UserIsOnCall returns true if the current time is between any of the current user's pagerduty.OnCalls in the next six hours
209+
func UserIsOnCall(p *pd.Config, id string) bool {
210+
var timeLayout = "2006-01-02T15:04:05Z"
211+
opts := pagerduty.ListOnCallOptions{
212+
UserIDs: []string{id},
213+
Since: time.Now().String(),
214+
Until: time.Now().Add(time.Hour * 6).String(),
215+
}
216+
217+
onCalls, err := pd.GetUserOnCalls(p.Client, id, opts)
218+
if err != nil {
219+
log.Debug("commands.UserIsOnCall", "error", err)
220+
return false
221+
}
222+
223+
for _, o := range onCalls {
224+
log.Debug("commands.UserIsOnCall", "on-call", o)
225+
226+
start, err := time.Parse(timeLayout, o.Start)
227+
if err != nil {
228+
log.Debug("commands.UserIsOnCall", "error parsing on-call start time", err)
229+
return false
230+
}
231+
end, err := time.Parse(timeLayout, o.End)
232+
if err != nil {
233+
log.Debug("commands.UserIsOnCall", "error parsing on-call end time", err)
234+
return false
235+
}
236+
237+
if start.Before(time.Now()) && end.After(time.Now()) {
238+
return true
239+
}
240+
}
241+
242+
return false
243+
}
244+
208245
// TODO: Can we use a single function and struct to handle
209246
// the openEditorCmd, login and openBrowserCmd commands?
210247

pkg/tui/keymap.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ func (k keymap) FullHelp() [][]key.Binding {
1111
return [][]key.Binding{
1212
// Each slice here is a column in the help window
1313
{k.Up, k.Down, k.Enter, k.Back},
14-
{k.Enter, k.Ack, k.Silence, k.Note},
15-
{k.Login, k.Open, k.Team, k.AutoRefresh},
14+
{k.Ack, k.Note, k.Silence},
15+
{k.Login, k.Open},
16+
{k.Team, k.Refresh, k.AutoRefresh, k.AutoAck},
1617
{k.Quit, k.Help},
1718
}
1819
}
@@ -32,6 +33,7 @@ type keymap struct {
3233
Note key.Binding
3334
Silence key.Binding
3435
Ack key.Binding
36+
AutoAck key.Binding
3537
Input key.Binding
3638
Login key.Binding
3739
Open key.Binding
@@ -80,7 +82,7 @@ var defaultKeyMap = keymap{
8082
),
8183
AutoRefresh: key.NewBinding(
8284
key.WithKeys("ctrl+r"),
83-
key.WithHelp("ctrl+r", "toggle auto refresh"),
85+
key.WithHelp("ctrl+r", "toggle auto-refresh"),
8486
),
8587
Note: key.NewBinding(
8688
key.WithKeys("n"),
@@ -94,6 +96,10 @@ var defaultKeyMap = keymap{
9496
key.WithKeys("a"),
9597
key.WithHelp("a", "acknowledge"),
9698
),
99+
AutoAck: key.NewBinding(
100+
key.WithKeys("ctrl+a"),
101+
key.WithHelp("ctrl+a", "toggle auto-acknowledge"),
102+
),
97103
Input: key.NewBinding(
98104
key.WithKeys("i"),
99105
key.WithHelp("i", "input"),

pkg/tui/msgHandlers.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ func (m model) keyMsgHandler(msg tea.Msg) (tea.Model, tea.Cmd) {
118118
return m, nil
119119
}
120120

121+
if key.Matches(msg.(tea.KeyMsg), defaultKeyMap.AutoAck) {
122+
m.autoAcknowledge = !m.autoAcknowledge
123+
return m, nil
124+
}
125+
121126
// Default commands for the table view
122127
switch {
123128
case m.err != nil:

pkg/tui/tui.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"reflect"
66
"regexp"
77
"slices"
8+
"strings"
89
"time"
910

1011
"github.com/PagerDuty/go-pagerduty"
@@ -221,7 +222,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
221222
// Check if any incidents should be auto-acknowledged;
222223
// This must be done before adding the stale incidents
223224
for _, i := range m.incidentList {
224-
if ShouldBeAcknowledged(i, m.config.CurrentUser.ID, m.autoAcknowledge) {
225+
if ShouldBeAcknowledged(m.config, i, m.config.CurrentUser.ID, m.autoAcknowledge) {
225226
acknowledgeIncidentsList = append(acknowledgeIncidentsList, i)
226227
}
227228
}
@@ -368,10 +369,16 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
368369
)
369370

370371
case acknowledgedIncidentsMsg:
372+
var incidentIDs []string
371373
if msg.err != nil {
372374
return m, func() tea.Msg { return errMsg{msg.err} }
373375
}
374-
m.setStatus(fmt.Sprintf("acknowledged incidents %v; refreshing Incident List ", msg))
376+
for _, i := range msg.incidents {
377+
incidentIDs = append(incidentIDs, i.ID)
378+
}
379+
incidents := strings.Join(incidentIDs, " ")
380+
m.setStatus(fmt.Sprintf("acknowledged incidents: " + incidents))
381+
375382
return m, func() tea.Msg { return updateIncidentListMsg("sender: acknowledgedIncidentsMsg") }
376383

377384
case waitForSelectedIncidentsThenAcknowledgeMsg:

pkg/tui/views.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ func (m model) renderFooter() string {
216216
s.WriteString(
217217
lipgloss.JoinHorizontal(
218218
0.2,
219-
paddedStyle.Render(refreshArea(m.autoRefresh)),
219+
paddedStyle.Render(refreshArea(m.autoRefresh, m.autoAcknowledge)),
220220
),
221221
)
222222

@@ -267,13 +267,16 @@ func statusArea(s string) string {
267267
return fmt.Sprintf(fstring, s)
268268
}
269269

270-
func refreshArea(autoRefresh bool) string {
270+
func refreshArea(autoRefresh bool, autoAck bool) string {
271271
var fstring = "Watching for updates... "
272-
if !autoRefresh {
272+
273+
if autoRefresh && autoAck {
274+
fstring = fstring + " [auto-acknowledge]"
275+
} else if !autoRefresh {
273276
fstring = fstring + " [PAUSED]"
274277
}
275-
fstring = strings.TrimSuffix(fstring, "\n")
276278

279+
fstring = strings.TrimSuffix(fstring, "\n")
277280
return fstring
278281
}
279282

0 commit comments

Comments
 (0)