lita-pagerduty 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -1
  3. data/.rubocop.yml +6 -5
  4. data/README.md +11 -9
  5. data/Rakefile +4 -2
  6. data/lib/exceptions.rb +11 -0
  7. data/lib/lita-pagerduty.rb +7 -29
  8. data/lib/lita/commands/ack.rb +15 -0
  9. data/lib/lita/commands/ack_all.rb +21 -0
  10. data/lib/lita/commands/ack_mine.rb +26 -0
  11. data/lib/lita/commands/base.rb +75 -0
  12. data/lib/lita/commands/forget.rb +13 -0
  13. data/lib/lita/commands/identify.rb +13 -0
  14. data/lib/lita/commands/incident.rb +13 -0
  15. data/lib/lita/commands/incidents_all.rb +18 -0
  16. data/lib/lita/commands/incidents_mine.rb +23 -0
  17. data/lib/lita/commands/notes.rb +15 -0
  18. data/lib/lita/commands/on_call_list.rb +13 -0
  19. data/lib/lita/commands/on_call_lookup.rb +41 -0
  20. data/lib/lita/commands/pager_me.rb +48 -0
  21. data/lib/lita/commands/resolve.rb +15 -0
  22. data/lib/lita/commands/resolve_all.rb +21 -0
  23. data/lib/lita/commands/resolve_mine.rb +26 -0
  24. data/lib/lita/handlers/commands.yml +30 -0
  25. data/lib/lita/handlers/pagerduty.rb +57 -0
  26. data/lib/pagerduty.rb +94 -0
  27. data/lib/store.rb +20 -0
  28. data/lita-pagerduty.gemspec +1 -2
  29. data/locales/en.yml +2 -2
  30. data/spec/lita/handlers/ack_all_spec.rb +26 -0
  31. data/spec/lita/handlers/ack_id_spec.rb +23 -0
  32. data/spec/lita/handlers/ack_mine_spec.rb +38 -0
  33. data/spec/lita/handlers/forget_spec.rb +22 -0
  34. data/spec/lita/handlers/identify_email_spec.rb +22 -0
  35. data/spec/lita/handlers/incident_id_spec.rb +23 -0
  36. data/spec/lita/handlers/incidents_all_spec.rb +31 -0
  37. data/spec/lita/handlers/incidents_mine_spec.rb +35 -0
  38. data/spec/lita/handlers/notes_spec.rb +29 -0
  39. data/spec/lita/handlers/on_call_list_spec.rb +21 -0
  40. data/spec/lita/handlers/on_call_lookup_spec.rb +29 -0
  41. data/spec/lita/handlers/pager_me_spec.rb +56 -0
  42. data/spec/lita/handlers/resolve_all_spec.rb +26 -0
  43. data/spec/lita/handlers/resolve_id_spec.rb +21 -0
  44. data/spec/lita/handlers/resolve_mine_spec.rb +38 -0
  45. data/spec/pagerduty_spec.rb +106 -0
  46. data/spec/spec_helper.rb +3 -189
  47. data/templates/.gitkeep +0 -0
  48. metadata +57 -35
  49. data/lib/lita/handlers/pagerduty_ack.rb +0 -77
  50. data/lib/lita/handlers/pagerduty_incident.rb +0 -68
  51. data/lib/lita/handlers/pagerduty_note.rb +0 -50
  52. data/lib/lita/handlers/pagerduty_resolve.rb +0 -77
  53. data/lib/lita/handlers/pagerduty_utility.rb +0 -136
  54. data/lib/pagerduty_helper/incident.rb +0 -64
  55. data/lib/pagerduty_helper/regex.rb +0 -8
  56. data/lib/pagerduty_helper/utility.rb +0 -43
  57. data/spec/lita/handlers/pagerduty_ack_spec.rb +0 -95
  58. data/spec/lita/handlers/pagerduty_incident_spec.rb +0 -103
  59. data/spec/lita/handlers/pagerduty_note_spec.rb +0 -43
  60. data/spec/lita/handlers/pagerduty_resolve_spec.rb +0 -95
  61. data/spec/lita/handlers/pagerduty_utility_spec.rb +0 -59
@@ -1,50 +0,0 @@
1
- # Lita-related code
2
- module Lita
3
- # Plugin-related code
4
- module Handlers
5
- # Note-related routes
6
- class PagerdutyNote < Handler
7
- namespace 'Pagerduty'
8
-
9
- include ::PagerdutyHelper::Incident
10
- include ::PagerdutyHelper::Regex
11
- include ::PagerdutyHelper::Utility
12
-
13
- route(
14
- /^pager\snotes\s#{INCIDENT_ID_PATTERN}$/,
15
- :notes,
16
- command: true,
17
- help: {
18
- t('help.notes.syntax') => t('help.notes.desc')
19
- }
20
- )
21
-
22
- route(
23
- /^pager\snote\s#{INCIDENT_ID_PATTERN}\s(.+)$/,
24
- :note,
25
- command: true,
26
- help: {
27
- t('help.note.syntax') => t('help.note.desc')
28
- }
29
- )
30
-
31
- # rubocop:disable Metrics/AbcSize
32
- def notes(response)
33
- incident_id = response.match_data['incident_id']
34
- incident = fetch_incident(incident_id)
35
- return response.reply(t('incident.not_found', id: incident_id)) if incident == 'No results'
36
- return response.reply("#{incident_id}: No notes") unless incident.notes.notes.count > 0
37
- incident.notes.notes.each do |note|
38
- response.reply(format_note(incident, note))
39
- end
40
- end
41
- # rubocop:enable Metrics/AbcSize
42
-
43
- def note(response)
44
- response.reply(t('error.not_implemented'))
45
- end
46
- end
47
-
48
- Lita.register_handler(PagerdutyNote)
49
- end
50
- end
@@ -1,77 +0,0 @@
1
- # Lita-related code
2
- module Lita
3
- # Plugin-related code
4
- module Handlers
5
- # Resolve-related routes
6
- class PagerdutyResolve < Handler
7
- namespace 'Pagerduty'
8
-
9
- include ::PagerdutyHelper::Incident
10
- include ::PagerdutyHelper::Regex
11
- include ::PagerdutyHelper::Utility
12
-
13
- route(
14
- /^pager\sresolve\sall$/,
15
- :resolve_all,
16
- command: true,
17
- help: {
18
- t('help.resolve_all.syntax') => t('help.resolve_all.desc')
19
- }
20
- )
21
-
22
- route(
23
- /^pager\sresolve\smine$/,
24
- :resolve_mine,
25
- command: true,
26
- help: {
27
- t('help.resolve_mine.syntax') => t('help.resolve_mine.desc')
28
- }
29
- )
30
-
31
- route(
32
- /^pager\sresolve\s#{INCIDENT_ID_PATTERN}$/,
33
- :resolve,
34
- command: true,
35
- help: {
36
- t('help.resolve.syntax') => t('help.resolve.desc')
37
- }
38
- )
39
-
40
- # rubocop:disable Metrics/AbcSize
41
- def resolve_all(response)
42
- incidents = fetch_all_incidents
43
- return response.reply(t('incident.none')) unless incidents.count > 0
44
- completed = []
45
- incidents.each do |incident|
46
- result = resolve_incident(incident.id)
47
- completed.push(incident.id) if result == "#{incident.id}: Incident resolved"
48
- response.reply(t('all.resolved', list: completed.join(',')))
49
- end
50
- end
51
- # rubocop:enable Metrics/AbcSize
52
-
53
- # rubocop:disable Metrics/AbcSize
54
- def resolve_mine(response)
55
- email = fetch_user(response.user)
56
- return response.reply(t('identify.missing')) unless email
57
- incidents = fetch_my_incidents(email)
58
- return response.reply(t('incident.none_mine')) unless incidents.count > 0
59
- completed = []
60
- incidents.each do |incident|
61
- result = resolve_incident(incident.id)
62
- completed.push(incident.id) if result == "#{incident.id}: Incident resolved"
63
- response.reply(t('all.resolved', list: completed.join(',')))
64
- end
65
- end
66
- # rubocop:enable Metrics/AbcSize
67
-
68
- def resolve(response)
69
- incident_id = response.match_data['incident_id']
70
- return if incident_id == 'all' || incident_id == 'mine'
71
- response.reply(resolve_incident(incident_id))
72
- end
73
- end
74
-
75
- Lita.register_handler(PagerdutyResolve)
76
- end
77
- end
@@ -1,136 +0,0 @@
1
- require 'time'
2
-
3
- # Lita-related code
4
- module Lita
5
- # Plugin-related code
6
- module Handlers
7
- # Utility-ish routes
8
- class PagerdutyUtility < Handler
9
- config :api_key, required: true
10
- config :subdomain, required: true
11
-
12
- namespace 'Pagerduty'
13
-
14
- include ::PagerdutyHelper::Incident
15
- include ::PagerdutyHelper::Regex
16
- include ::PagerdutyHelper::Utility
17
-
18
- route(
19
- /^pager\soncall$/,
20
- :on_call_list,
21
- command: true,
22
- help: {
23
- t('help.on_call_list.syntax') => t('help.on_call_list.desc')
24
- }
25
- )
26
-
27
- route(
28
- /^pager\soncall\s(.*)$/,
29
- :on_call_lookup,
30
- command: true,
31
- help: {
32
- t('help.on_call_lookup.syntax') => t('help.on_call_lookup.desc')
33
- }
34
- )
35
-
36
- route(
37
- /^pager\sidentify\s#{EMAIL_PATTERN}$/,
38
- :identify,
39
- command: true,
40
- help: {
41
- t('help.identify.syntax') => t('help.identify.desc')
42
- }
43
- )
44
-
45
- route(
46
- /^pager\sforget$/,
47
- :forget,
48
- command: true,
49
- help: {
50
- t('help.forget.syntax') => t('help.forget.desc')
51
- }
52
- )
53
-
54
- route(
55
- /^pager\s+me\s+(.+?)\s+(\d+)m?$/,
56
- :pager_me,
57
- command: true,
58
- help: { t('help.pager_me.syntax') => t('help.pager_me.desc') }
59
- )
60
-
61
- def on_call_list(response)
62
- schedules = pd_client.get_schedules.schedules
63
- if schedules.any?
64
- schedule_list = schedules.map(&:name).join("\n")
65
- response.reply(t('on_call_list.response', schedules: schedule_list))
66
- else
67
- response.reply(t('on_call_list.no_schedules_found'))
68
- end
69
- end
70
-
71
- # rubocop:disable Metrics/AbcSize
72
- def on_call_lookup(response)
73
- schedule_name = response.match_data[1].strip
74
- schedule = pd_client.get_schedules.schedules.find { |s| s.name.casecmp(schedule_name) == 0 }
75
-
76
- unless schedule
77
- return response.reply(t('on_call_lookup.no_matching_schedule', schedule_name: schedule_name))
78
- end
79
-
80
- if (user = lookup_on_call_user(schedule.id))
81
- response.reply(t('on_call_lookup.response', name: user.name, email: user.email, schedule_name: schedule_name))
82
- else
83
- response.reply(t('on_call_lookup.no_one_on_call', schedule_name: schedule_name))
84
- end
85
- end
86
- # rubocop:enable Metrics/AbcSize
87
-
88
- # rubocop:disable Metrics/AbcSize
89
- def pager_me(response)
90
- schedule_name = response.match_data[1].strip
91
- schedule = pd_client.get_schedules.schedules.find { |s| s.name.casecmp(schedule_name) == 0 }
92
- return response.reply(t('on_call_lookup.no_matching_schedule', schedule_name: schedule_name)) unless schedule
93
-
94
- email = fetch_user(response.user)
95
- return response.reply(t('identify.missing')) unless email
96
-
97
- users = pd_client.get_users(query: email)
98
- return response.reply(t('identify.unrecognised')) unless users.total == 1
99
-
100
- override = take_pager(schedule.id, users.users.first.id, response.match_data[2].strip.to_i)
101
- return response.reply(t('pager_me.failure')) unless override
102
-
103
- response.reply(t('pager_me.success', name: override.user.name, email: override.user.email, finish: override.end))
104
- end
105
- # rubocop:enable Metrics/AbcSize
106
-
107
- def identify(response)
108
- email = response.match_data['email']
109
- stored_email = fetch_user(response.user)
110
- return response.reply(t('identify.already')) if stored_email
111
- store_user(response.user, email)
112
- response.reply(t('identify.complete'))
113
- end
114
-
115
- def forget(response)
116
- stored_email = fetch_user(response.user)
117
- return response.reply(t('forget.unknown')) unless stored_email
118
- delete_user(response.user)
119
- response.reply(t('forget.complete'))
120
- end
121
-
122
- private
123
-
124
- def lookup_on_call_user(schedule_id)
125
- now = ::Time.now.utc
126
- pd_client.get_schedule_users(
127
- id: schedule_id,
128
- since: now.iso8601,
129
- until: (now + 3600).iso8601
130
- ).first
131
- end
132
- end
133
-
134
- Lita.register_handler(PagerdutyUtility)
135
- end
136
- end
@@ -1,64 +0,0 @@
1
- # Helper Code for PagerDuty Lita Handler
2
- module PagerdutyHelper
3
- # Incident-related functions
4
- module Incident
5
- def format_incident(incident)
6
- t('incident.info', id: incident.id,
7
- subject: incident.trigger_summary_data.subject,
8
- url: incident.html_url,
9
- assigned: incident.assigned_to_user.nil? ? 'none' : incident.assigned_to_user.email)
10
- end
11
-
12
- def resolve_incident(incident_id)
13
- incident = fetch_incident(incident_id)
14
- return t('incident.not_found', id: incident_id) if incident == 'No results'
15
- return t('incident.already_set', id: incident_id, status: incident.status) if incident.status == 'resolved'
16
- results = incident.resolve
17
- if results.key?('status') && results['status'] == 'resolved'
18
- t('incident.resolved', id: incident_id)
19
- else
20
- t('incident.unable_to_resolve', id: incident_id)
21
- end
22
- end
23
-
24
- def fetch_all_incidents
25
- client = pd_client
26
- list = []
27
- # FIXME: Workaround on current PD Gem
28
- client.incidents.incidents.each do |incident|
29
- list.push(incident) if incident.status != 'resolved'
30
- end
31
- list
32
- end
33
-
34
- def fetch_my_incidents(email)
35
- # FIXME: Workaround
36
- incidents = fetch_all_incidents
37
- list = []
38
- incidents.each do |incident|
39
- list.push(incident) if incident.assigned_to_user.email == email
40
- end
41
- list
42
- end
43
-
44
- def fetch_incident(incident_id)
45
- client = pd_client
46
- client.get_incident(id: incident_id)
47
- end
48
-
49
- # rubocop:disable Metrics/AbcSize
50
- def acknowledge_incident(incident_id)
51
- incident = fetch_incident(incident_id)
52
- return t('incident.not_found', id: incident_id) if incident == 'No results'
53
- return t('incident.already_set', id: incident_id, status: incident.status) if incident.status == 'acknowledged'
54
- return t('incident.already_set', id: incident_id, status: incident.status) if incident.status == 'resolved'
55
- results = incident.acknowledge
56
- if results.key?('status') && results['status'] == 'acknowledged'
57
- t('incident.acknowledged', id: incident_id)
58
- else
59
- t('incident.unable_to_acknowledge', id: incident_id)
60
- end
61
- end
62
- # rubocop:enable Metrics/AbcSize
63
- end
64
- end
@@ -1,8 +0,0 @@
1
- # Helper Code for PagerDuty Lita Handler
2
- module PagerdutyHelper
3
- # Utility functions
4
- module Regex
5
- INCIDENT_ID_PATTERN = /(?<incident_id>[a-zA-Z0-9+]+)/
6
- EMAIL_PATTERN = /(?<email>[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+)/i
7
- end
8
- end
@@ -1,43 +0,0 @@
1
- # Helper Code for PagerDuty Lita Handler
2
- module PagerdutyHelper
3
- # Utility functions
4
- module Utility
5
- def pd_client
6
- ::Pagerduty.new(token: config.api_key, subdomain: config.subdomain)
7
- end
8
-
9
- def format_note(incident, note)
10
- t('note.show', id: incident.id, content: note.content, email: note.user.email)
11
- end
12
-
13
- def store_user(user, email)
14
- redis.set(format_user(user), email)
15
- end
16
-
17
- def fetch_user(user)
18
- redis.get(format_user(user))
19
- end
20
-
21
- def delete_user(user)
22
- redis.del(format_user(user))
23
- end
24
-
25
- def format_user(user)
26
- "email_#{user.id}"
27
- end
28
-
29
- def take_pager(schedule_id, user_id, duration_mins)
30
- from = ::Time.now.utc + 10
31
- to = from + (60 * duration_mins)
32
-
33
- pd_client.create_schedule_override(
34
- id: schedule_id,
35
- override: {
36
- user_id: user_id,
37
- start: from.iso8601,
38
- end: to.iso8601
39
- }
40
- )
41
- end
42
- end
43
- end
@@ -1,95 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Lita::Handlers::PagerdutyAck, lita_handler: true do
4
- include_context 'basic fixtures'
5
-
6
- it do
7
- is_expected.to route_command('pager ack all').to(:ack_all)
8
- is_expected.to route_command('pager ack mine').to(:ack_mine)
9
- is_expected.to route_command('pager ack ABC123').to(:ack)
10
- end
11
-
12
- describe '#ack_all' do
13
- describe 'when there are acknowledgable incidents' do
14
- it 'shows them as acknowledged' do
15
- expect(Pagerduty).to receive(:new).twice { incidents }
16
- send_command('pager ack all')
17
- expect(replies.last).to eq('Acknowledged: ABC789')
18
- end
19
- end
20
-
21
- describe 'when there are no acknowledgable incidents' do
22
- it 'shows a warning' do
23
- expect(Pagerduty).to receive(:new) { no_incidents }
24
- send_command('pager ack all')
25
- expect(replies.last).to eq('No triggered, open, or acknowledged ' \
26
- 'incidents')
27
- end
28
- end
29
- end
30
-
31
- describe '#ack_mine' do
32
- describe 'when there are acknowledgable incidents for the user' do
33
- it 'shows them as acknowledged' do
34
- bar = Lita::User.create(123, name: 'bar')
35
- expect(Pagerduty).to receive(:new).twice { incidents }
36
- send_command('pager identify bar@example.com', as: bar)
37
- send_command('pager ack mine', as: bar)
38
- expect(replies.last).to eq('Acknowledged: ABC789')
39
- end
40
- end
41
-
42
- describe 'when there are no acknowledgable incidents for the user' do
43
- it 'shows a warning' do
44
- foo = Lita::User.create(123, name: 'foo')
45
- expect(Pagerduty).to receive(:new) { incidents }
46
- send_command('pager identify foo@example.com', as: foo)
47
- send_command('pager ack mine', as: foo)
48
- expect(replies.last).to eq('You have no triggered, open, or ' \
49
- 'acknowledged incidents')
50
- end
51
- end
52
-
53
- describe 'when the user has not identified themselves' do
54
- it 'shows a warning' do
55
- send_command('pager ack mine')
56
- expect(replies.last).to eq('You have not identified yourself (use ' \
57
- 'the help command for more info)')
58
- end
59
- end
60
- end
61
-
62
- describe '#ack' do
63
- describe 'when the incident has not been acknowledged' do
64
- it 'shows the acknowledgement' do
65
- expect(Pagerduty).to receive(:new) { new_incident }
66
- send_command('pager ack ABC123')
67
- expect(replies.last).to eq('ABC123: Incident acknowledged')
68
- end
69
- end
70
-
71
- describe 'when the incident has already been acknowledged' do
72
- it 'shows the warning' do
73
- expect(Pagerduty).to receive(:new) { acknowledged_incident }
74
- send_command('pager ack ABC123')
75
- expect(replies.last).to eq('ABC123: Incident already acknowledged')
76
- end
77
- end
78
-
79
- describe 'when the incident does not exist' do
80
- it 'shows an error' do
81
- expect(Pagerduty).to receive(:new) { no_incident }
82
- send_command('pager ack ABC123')
83
- expect(replies.last).to eq('ABC123: Incident not found')
84
- end
85
- end
86
-
87
- describe 'when the incident cannot be acknowledged' do
88
- it 'shows that its unable to acknowledge' do
89
- expect(Pagerduty).to receive(:new) { unable_to_ack_incident }
90
- send_command('pager ack ABC123')
91
- expect(replies.last).to eq('ABC123: Unable to acknowledge incident')
92
- end
93
- end
94
- end
95
- end