lita-statuspage 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0f12e1170e61e7e7ad6e4b72fe16873083d2162f
4
+ data.tar.gz: 2dbfd05ac2b3370142a543fd0415a1852694db6d
5
+ SHA512:
6
+ metadata.gz: c7a0db84d67ab9c655c0cf4a46a5dfd36d392beb76f59d72d57a615b0f13cfb8a9ffd3c3591933c896afd43254ca5b1570198897b87bf67f1bfce7e039edb643
7
+ data.tar.gz: 6ede61840a2aa080797894fbb7638fd4c30594a40375f1f1678c20864fc25fa4a8ff28580e77a2a5800e7403ea9cd7463b7950703caead04a4dd47c9cccd46c4
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.swp
data/.rubocop.yml ADDED
@@ -0,0 +1,17 @@
1
+ ClassLength:
2
+ Max: 400
3
+
4
+ CyclomaticComplexity:
5
+ Max: 10
6
+
7
+ Documentation:
8
+ Enabled: false
9
+
10
+ FileName:
11
+ Enabled: false
12
+
13
+ LineLength:
14
+ Max: 120
15
+
16
+ MethodLength:
17
+ Max: 30
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ script: bundle exec rake
5
+ before_install:
6
+ - gem update --system
7
+ services:
8
+ - redis-server
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,9 @@
1
+ Pull requests are awesome! Pull requests with tests are even more awesome!
2
+
3
+ ## Quick steps
4
+
5
+ 1. Fork the repo.
6
+ 2. Run the tests: `bundle && rake`
7
+ 3. Add a test for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or fixing a bug, it needs a test!
8
+ 4. Make the test pass.
9
+ 5. Push to your fork and submit a pull request.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2014 Eric Sigler
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # lita-statuspage
2
+
3
+ [![Build Status](https://travis-ci.org/esigler/lita-statuspage.png?branch=master)](https://travis-ci.org/esigler/lita-statuspage)
4
+ [![Code Climate](https://codeclimate.com/github/esigler/lita-statuspage.png)](https://codeclimate.com/github/esigler/lita-statuspage)
5
+ [![Coverage Status](https://coveralls.io/repos/esigler/lita-statuspage/badge.png?branch=master)](https://coveralls.io/r/esigler/lita-statuspage?branch=master)
6
+
7
+ Statuspage.io (http://statuspage.io) handler for updating incidents, service status, etc.
8
+
9
+ ## Installation
10
+
11
+ Add lita-statuspage to your Lita instance's Gemfile:
12
+
13
+ ``` ruby
14
+ gem "lita-statuspage"
15
+ ```
16
+
17
+ ## Configuration
18
+
19
+ You'll need to get an API key and your Page ID, instructions for how to do so are here:
20
+ http://doers.statuspage.io/api/authentication/
21
+
22
+ Add the following variable to your Lita config file:
23
+
24
+ ``` ruby
25
+ config.handlers.statuspage.api_key = '_your_key_here_'
26
+ config.handlers.statuspage.page_id = '_your_page_id_here_'
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ### Incidents
32
+
33
+ #### Create
34
+
35
+ ```
36
+ Lita statuspage incident new name:"<name>" - Create a new realtime incident
37
+ status:<status> - (Optional) One of: investigating|identified|monitoring|resolved (default: investigating)
38
+ message:"<message>" - (Optional) The initial message
39
+ twitter:<state> - (Optional) Post the new incident to Twitter, one of (true|t|false|f) (default:false)
40
+ impact:<state> - (Optional) Override calculated impact value, one of: (minor|major|critical)
41
+ ```
42
+
43
+ #### Update
44
+
45
+ ```
46
+ Lita statuspage incident update id:<id> - Update an incident
47
+ status:<status> - (Optional) One of (investigating|identified|monitoring|resolved) (if realtime) or (scheduled|in_progress|verifying|completed) (if scheduled)
48
+ message:"<message>" - (Optional) The body of the new incident update that will be created
49
+ twitter:<state> - (Optional) Post the new incident update to twitter, one of: (true|t|false|f) (default:false)
50
+ impact:<state> - (Optional) Override calculated impact value, one of (minor|major|critical)
51
+ ```
52
+
53
+ **NOTE:** If either of status or message is modified, a new incident update will be generated. You should update both of these attributes at the same time to avoid two separate incident updates being generated.
54
+
55
+ #### List
56
+
57
+ ```
58
+ Lita statuspage incident list all - List all incidents
59
+ Lita statuspage incident list scheduled - List scheduled incidents
60
+ Lita statuspage incident list unresolved - List unresolved incidents
61
+ ```
62
+
63
+ #### Delete
64
+
65
+ ```
66
+ Lita statuspage incident delete latest - Delete latest incident
67
+ Lita statuspage incident delete id:<id> - Delete a specific incident
68
+ ```
69
+
70
+
71
+ ### Components
72
+
73
+ #### List
74
+
75
+ ```
76
+ Lita statuspage component list all - Lists all components
77
+ ```
78
+
79
+ #### Update
80
+
81
+ ```
82
+ Lita statuspage component update (id:<id>|name:"<name>") - Updates the component
83
+ status:<status> - One of (operational|degraded_performance|partial_outage|major_outage|none)
84
+ ```
85
+
86
+ ## License
87
+
88
+ [MIT](http://opensource.org/licenses/MIT)
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ Rubocop::RakeTask.new(:rubocop)
7
+
8
+ task default: [ :spec, :rubocop ]
@@ -0,0 +1,10 @@
1
+ require 'lita'
2
+
3
+ Lita.load_locales Dir[File.expand_path(
4
+ File.join('..', '..', 'locales', '*.yml'), __FILE__
5
+ )]
6
+
7
+ require 'lita/handlers/statuspage'
8
+
9
+ require 'multi_json'
10
+ require 'shellwords'
@@ -0,0 +1,403 @@
1
+ module Lita
2
+ module Handlers
3
+ class Statuspage < Handler
4
+ route(
5
+ /^statuspage\sincident\snew\s(.+)$/,
6
+ :incident_new,
7
+ command: true,
8
+ help: {
9
+ 'statuspage incident new (...)' => 'Create a new realtime incident'
10
+ }
11
+ )
12
+
13
+ route(
14
+ /^statuspage\sincident\supdate\s(.+)$/,
15
+ :incident_update,
16
+ command: true,
17
+ help: {
18
+ 'statuspage incident update (...)' => 'Update an incident'
19
+ }
20
+ )
21
+
22
+ route(
23
+ /^statuspage\sincident\slist(\sall)?$/,
24
+ :incident_list_all,
25
+ command: true,
26
+ help: {
27
+ 'statuspage incident list all' => 'List all incidents'
28
+ }
29
+ )
30
+
31
+ route(
32
+ /^statuspage\sincident\slist\sscheduled$/,
33
+ :incident_list_scheduled,
34
+ command: true,
35
+ help: {
36
+ 'statuspage incident list scheduled' => 'List scheduled incidents'
37
+ }
38
+ )
39
+
40
+ route(
41
+ /^statuspage\sincident\slist\sunresolved$/,
42
+ :incident_list_unresolved,
43
+ command: true,
44
+ help: {
45
+ 'statuspage incident list unresolved' => 'List unresolved incidents'
46
+ }
47
+ )
48
+
49
+ route(
50
+ /^statuspage\sincident\sdelete\slatest$/,
51
+ :incident_delete_latest,
52
+ command: true,
53
+ help: {
54
+ 'statuspage incident delete latest' => 'Delete latest incident'
55
+ }
56
+ )
57
+
58
+ route(
59
+ /^statuspage\sincident\sdelete\sid:(\w+)$/,
60
+ :incident_delete,
61
+ command: true,
62
+ help: {
63
+ 'statuspage incident delete id:<id>' => 'Delete a specific incident'
64
+ }
65
+ )
66
+
67
+ route(
68
+ /^statuspage\scomponent\slist(\sall)?$/,
69
+ :component_list,
70
+ command: true,
71
+ help: {
72
+ 'statuspage component list' => 'Lists all components'
73
+ }
74
+ )
75
+
76
+ route(
77
+ /^statuspage\scomponent\supdate\s(.+)$/,
78
+ :component_update,
79
+ command: true,
80
+ help: {
81
+ 'statuspage component update' => 'Updates the component'
82
+ }
83
+ )
84
+
85
+ def self.default_config(config)
86
+ config.api_key = nil
87
+ config.page_id = nil
88
+ end
89
+
90
+ def incident_new(response)
91
+ args = parse_args(response.matches[0][0])
92
+
93
+ unless args.key?('name')
94
+ response.reply('Can\'t create incident, missing incident name')
95
+ return
96
+ end
97
+
98
+ if args.key?('status') && !valid_incident_status?(args['status'])
99
+ response.reply('Can\'t create incident, invalid incident state')
100
+ return
101
+ end
102
+
103
+ if args.key?('twitter') && !valid_twitter_status?(args['twitter'])
104
+ response.reply('Can\'t create incident, invalid twitter state')
105
+ return
106
+ end
107
+
108
+ if args.key?('impact') && !valid_impact_value?(args['impact'])
109
+ response.reply('Can\'t create incident, invalid impact value')
110
+ return
111
+ end
112
+
113
+ response.reply(create_incident(args))
114
+ end
115
+
116
+ def incident_update(response)
117
+ args = parse_args(response.matches[0][0])
118
+
119
+ unless args.key?('id')
120
+ response.reply('Can\'t update incident, missing incident ID')
121
+ return
122
+ end
123
+
124
+ if args.length < 2
125
+ response.reply('Can\'t update incident, nothing to update')
126
+ return
127
+ end
128
+
129
+ if args.key?('status') && !valid_incident_status?(args['status'])
130
+ response.reply('Can\'t update incident, invalid incident state')
131
+ return
132
+ end
133
+
134
+ if args.key?('twitter') && !valid_twitter_status?(args['twitter'])
135
+ response.reply('Can\'t update incident, invalid twitter state')
136
+ return
137
+ end
138
+
139
+ if args.key?('impact') && !valid_impact_value?(args['impact'])
140
+ response.reply('Can\'t update incident, invalid impact value')
141
+ return
142
+ end
143
+
144
+ response.reply(update_incident(args['id'], args))
145
+ end
146
+
147
+ def incident_list_all(response)
148
+ list_incidents('incidents.json').each do |msg|
149
+ response.reply(msg)
150
+ end
151
+ end
152
+
153
+ def incident_list_scheduled(response)
154
+ list_incidents('incidents/scheduled.json').each do |msg|
155
+ response.reply(msg)
156
+ end
157
+ end
158
+
159
+ def incident_list_unresolved(response)
160
+ list_incidents('incidents/unresolved.json').each do |msg|
161
+ response.reply(msg)
162
+ end
163
+ end
164
+
165
+ def incident_delete_latest(response)
166
+ incident = latest_incident
167
+ if incident
168
+ response.reply(delete_incident(incident['id']))
169
+ else
170
+ response.reply('No latest incident found')
171
+ end
172
+ end
173
+
174
+ def incident_delete(response)
175
+ incident_id = response.matches[0][0]
176
+ response.reply(delete_incident(incident_id))
177
+ end
178
+
179
+ def component_list(response)
180
+ components = api_request('get', 'components')
181
+ if components
182
+ if components.count > 0
183
+ components.each do |component|
184
+ response.reply(format_component(component))
185
+ end
186
+ else
187
+ response.reply('No components to list')
188
+ end
189
+ else
190
+ response.reply('Error fetching components')
191
+ end
192
+ end
193
+
194
+ def component_update(response)
195
+ args = parse_args(response.matches[0][0])
196
+ request_args = {}
197
+ if !args.key?('name') && !args.key?('id')
198
+ response.reply('Need an identifier for the component')
199
+ else
200
+ if args.key?('status')
201
+ if valid_component_status?(args['status'])
202
+ request_args['component[status]'] = args['status']
203
+ else
204
+ response.reply('Invalid status to use in updates')
205
+ return
206
+ end
207
+ else
208
+ request_args['component[status]='] = ''
209
+ end
210
+
211
+ if args.key?('id')
212
+ response.reply(update_component(args['id'], request_args))
213
+ elsif args.key?('name')
214
+ component = component(args['name'])
215
+ response.reply(update_component(component['id'], request_args))
216
+ else
217
+ response.reply('Need an identifier for the component')
218
+ end
219
+ end
220
+ end
221
+
222
+ private
223
+
224
+ def incident(id)
225
+ incidents = api_request('get', 'incidents')
226
+ if incidents && incidents.count > 0
227
+ incidents.each do |incident|
228
+ return incident if incident['id'] == id
229
+ end
230
+ end
231
+ nil
232
+ end
233
+
234
+ def latest_incident
235
+ incidents = api_request('get', 'incidents')
236
+ return nil unless incidents && incidents.count > 0
237
+ incidents.first
238
+ end
239
+
240
+ def list_incidents(resource)
241
+ incidents = api_request('get', resource)
242
+ response = []
243
+ if incidents
244
+ response = ['No incidents to list'] unless incidents.count > 0
245
+ incidents.each do |incident|
246
+ response.push("#{format_incident(incident)}")
247
+ end
248
+ else
249
+ response = ['Error fetching incidents']
250
+ end
251
+ response
252
+ end
253
+
254
+ def create_incident(args)
255
+ request_args = {}
256
+ request_args['incident[name]'] = args['name']
257
+ request_args['incident[status]'] = args['status'] if args.key?('status')
258
+ request_args['incident[wants_twitter_update]'] = args['twitter'] if args.key?('twitter')
259
+ request_args['incident[message]'] = args['message'] if args.key?('message')
260
+ request_args['incident[impact_override]'] = args['impact'] if args.key?('impact')
261
+ result = api_request('post', 'incidents.json', request_args)
262
+ if result
263
+ "Incident #{result['id']} created"
264
+ else
265
+ 'Error creating incident'
266
+ end
267
+ end
268
+
269
+ def update_incident(id, args)
270
+ incident = incident(id)
271
+ if incident
272
+ request_args = {}
273
+ request_args['incident[status]'] = args['status'] if args.key?('status')
274
+ request_args['incident[wants_twitter_update]'] = args['twitter'] if args.key?('twitter')
275
+ request_args['incident[message]'] = args['message'] if args.key?('message')
276
+ request_args['incident[impact_override]'] = args['impact'] if args.key?('impact')
277
+ result = api_request('patch', "incidents/#{id}.json", request_args)
278
+ if result
279
+ "Incident #{id} updated"
280
+ else
281
+ 'Error updating incident'
282
+ end
283
+ else
284
+ 'Can\'t update incident, does not exist'
285
+ end
286
+ end
287
+
288
+ def delete_incident(id)
289
+ incident = incident(id)
290
+ if incident
291
+ result = api_request('delete', "incidents/#{id}.json")
292
+ if result
293
+ "Incident #{id} deleted"
294
+ else
295
+ 'Error deleting incident'
296
+ end
297
+ else
298
+ 'Incident not found'
299
+ end
300
+ end
301
+
302
+ def component(identifier)
303
+ components = api_request('get', 'components')
304
+ if components && components.count > 0
305
+ components.each do |component|
306
+ return component if component['id'] == identifier ||
307
+ component['name'] == identifier
308
+ end
309
+ end
310
+ end
311
+
312
+ def update_component(id, args)
313
+ component = component(id)
314
+ if component
315
+ result = api_request('patch', "components/#{id}.json", args)
316
+ if result
317
+ "Component #{id} updated"
318
+ else
319
+ 'Error updating component'
320
+ end
321
+ else
322
+ 'Component not found'
323
+ end
324
+ end
325
+
326
+ def format_incident(incident)
327
+ name = incident['name']
328
+ id = incident['id']
329
+ status = incident['status']
330
+ created = Date.parse(incident['created_at'])
331
+ "#{name} (" \
332
+ "created: #{created.strftime('%Y-%m-%d')}, " \
333
+ "status: #{status}, " \
334
+ "id:#{id})"
335
+ end
336
+
337
+ def format_component(component)
338
+ name = component['name']
339
+ id = component['id']
340
+ status = component['status']
341
+ "#{name} (" \
342
+ "status: #{status}, " \
343
+ "id:#{id})"
344
+ end
345
+
346
+ def valid_incident_status?(status)
347
+ %w(investigating identified monitoring resolved).include?(status)
348
+ end
349
+
350
+ def valid_twitter_status?(status)
351
+ %w(true t false f).include?(status)
352
+ end
353
+
354
+ def valid_impact_value?(value)
355
+ %w(minor major critical).include?(value)
356
+ end
357
+
358
+ def valid_component_status?(status)
359
+ %w(operational degraded_performance partial_outage major_outage).include?(status)
360
+ end
361
+
362
+ def parse_args(string)
363
+ results = {}
364
+ # TODO: Error handling on parse errors
365
+ arg_pairs = Shellwords.split(string)
366
+ arg_pairs.each do |pair|
367
+ keyval = pair.split(':', 2)
368
+ results[keyval[0]] = keyval[1]
369
+ end
370
+ results
371
+ end
372
+
373
+ def api_request(method, component, args = {})
374
+ if Lita.config.handlers.statuspage.api_key.nil? ||
375
+ Lita.config.handlers.statuspage.page_id.nil?
376
+ Lita.logger.error('Missing API key or Page ID for Statuspage')
377
+ fail 'Missing config'
378
+ end
379
+
380
+ url = "https://api.statuspage.io/v1/pages/" \
381
+ "#{Lita.config.handlers.statuspage.page_id}" \
382
+ "/#{component}"
383
+
384
+ http_response = http.send(method) do |req|
385
+ req.url url, args
386
+ req.headers['Authorization'] =
387
+ "OAuth #{Lita.config.handlers.statuspage.api_key}"
388
+ end
389
+
390
+ if http_response.status == 200 ||
391
+ http_response.status == 201
392
+ MultiJson.load(http_response.body)
393
+ else
394
+ Lita.logger.error("HTTP #{method} for #{url} with #{args} returned #{http_response.status}")
395
+ Lita.logger.error(http_response.body)
396
+ nil
397
+ end
398
+ end
399
+ end
400
+
401
+ Lita.register_handler(Statuspage)
402
+ end
403
+ end
@@ -0,0 +1,26 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'lita-statuspage'
3
+ spec.version = '0.1.0'
4
+ spec.authors = ['Eric Sigler']
5
+ spec.email = ['me@esigler.com']
6
+ spec.description = %q{A Lita handler to interact with Statuspage.io}
7
+ spec.summary = %q{A Lita handler to interact with Statuspage.io}
8
+ spec.homepage = 'https://github.com/esigler/lita-statuspage'
9
+ spec.license = 'MIT'
10
+ spec.metadata = { 'lita_plugin_type' => 'handler' }
11
+
12
+ spec.files = `git ls-files`.split($/)
13
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
14
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
15
+ spec.require_paths = ['lib']
16
+
17
+ spec.add_runtime_dependency 'lita', '>= 3.0'
18
+ spec.add_runtime_dependency 'multi_json'
19
+
20
+ spec.add_development_dependency 'bundler', '~> 1.3'
21
+ spec.add_development_dependency 'rake'
22
+ spec.add_development_dependency 'rspec', '>= 3.0.0.beta2'
23
+ spec.add_development_dependency 'simplecov'
24
+ spec.add_development_dependency 'coveralls'
25
+ spec.add_development_dependency 'rubocop'
26
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,4 @@
1
+ en:
2
+ lita:
3
+ handlers:
4
+ statuspage:
@@ -0,0 +1 @@
1
+ {"status":"major_outage","name":"Management Portal (example)","created_at":"2014-03-23T18:11:33.099Z","updated_at":"2014-03-31T01:43:50.931Z","position":2,"description":null,"id":"v6z6tpldcw85","page_id":"g229z91sc3ff"}
@@ -0,0 +1 @@
1
+ [{"status":"operational","name":"API (example)","created_at":"2014-03-23T18:11:33.082Z","updated_at":"2014-03-23T18:11:33.082Z","position":1,"description":null,"id":"rdfbrztshlr2","page_id":"g229z91sc3ff"},{"status":"operational","name":"Management Portal (example)","created_at":"2014-03-23T18:11:33.099Z","updated_at":"2014-03-23T18:11:33.099Z","position":2,"description":null,"id":"v6z6tpldcw85","page_id":"g229z91sc3ff"}]
@@ -0,0 +1 @@
1
+ {"name":"Unresolved incident","status":"investigating","created_at":"2014-03-30T22:47:14.362Z","updated_at":"2014-03-30T22:47:15.718Z","monitoring_at":null,"resolved_at":null,"impact":"none","shortlink":"http://stspg.io/MUB","postmortem_ignored":false,"postmortem_body":null,"postmortem_body_last_updated_at":null,"postmortem_published_at":null,"postmortem_notified_subscribers":false,"postmortem_notified_twitter":false,"backfilled":false,"scheduled_for":null,"scheduled_until":null,"scheduled_remind_prior":false,"scheduled_reminded_at":null,"impact_override":null,"scheduled_auto_in_progress":false,"scheduled_auto_completed":false,"id":"2ttv50n0n8zj","page_id":"g229z91sc3ff","incident_updates":[]}
@@ -0,0 +1 @@
1
+ {"name":"lp0 on fire","status":"investigating","created_at":"2014-03-31T23:39:43.169Z","updated_at":"2014-03-31T23:39:44.397Z","monitoring_at":null,"resolved_at":null,"impact":"none","shortlink":"http://stspg.io/MZJ","postmortem_ignored":false,"postmortem_body":null,"postmortem_body_last_updated_at":null,"postmortem_published_at":null,"postmortem_notified_subscribers":false,"postmortem_notified_twitter":false,"backfilled":false,"scheduled_for":null,"scheduled_until":null,"scheduled_remind_prior":false,"scheduled_reminded_at":null,"impact_override":null,"scheduled_auto_in_progress":false,"scheduled_auto_completed":false,"id":"b0m7dz4tzpl3","page_id":"g229z91sc3ff","incident_updates":[{"status":"investigating","body":"We are currently investigating this issue.","created_at":"2014-03-31T23:39:44.395Z","wants_twitter_update":false,"twitter_updated_at":null,"updated_at":"2014-03-31T23:39:44.395Z","display_at":"2014-03-31T23:39:44.395Z","id":"gc9bndsygg42","incident_id":"b0m7dz4tzpl3"}]}
@@ -0,0 +1 @@
1
+ {"name":"lp0 on fire","status":"investigating","created_at":"2014-03-31T23:39:43.169Z","updated_at":"2014-04-01T00:16:11.095Z","monitoring_at":null,"resolved_at":null,"impact":"none","shortlink":"http://stspg.io/MZJ","postmortem_ignored":false,"postmortem_body":null,"postmortem_body_last_updated_at":null,"postmortem_published_at":null,"postmortem_notified_subscribers":false,"postmortem_notified_twitter":false,"backfilled":false,"scheduled_for":null,"scheduled_until":null,"scheduled_remind_prior":false,"scheduled_reminded_at":null,"impact_override":null,"scheduled_auto_in_progress":false,"scheduled_auto_completed":false,"id":"b0m7dz4tzpl3","page_id":"g229z91sc3ff","incident_updates":[{"status":"investigating","body":"Howdy","created_at":"2014-04-01T00:16:11.084Z","wants_twitter_update":false,"twitter_updated_at":null,"updated_at":"2014-04-01T00:16:11.084Z","display_at":"2014-04-01T00:16:11.084Z","id":"kxbqvtqxdl6m","incident_id":"b0m7dz4tzpl3"},{"status":"investigating","body":"We are currently investigating this issue.","created_at":"2014-03-31T23:39:44.395Z","wants_twitter_update":false,"twitter_updated_at":null,"updated_at":"2014-03-31T23:39:44.395Z","display_at":"2014-03-31T23:39:44.395Z","id":"gc9bndsygg42","incident_id":"b0m7dz4tzpl3"}]}
@@ -0,0 +1 @@
1
+ [{"name":"Test Incident","status":"resolved","created_at":"2014-03-24T23:01:40.312Z","updated_at":"2014-03-24T23:01:53.944Z","monitoring_at":null,"resolved_at":"2014-03-24T23:01:41.529Z","impact":"none","shortlink":"http://stspg.io/M1A","postmortem_ignored":true,"postmortem_body":null,"postmortem_body_last_updated_at":null,"postmortem_published_at":null,"postmortem_notified_subscribers":false,"postmortem_notified_twitter":false,"backfilled":false,"scheduled_for":null,"scheduled_until":null,"scheduled_remind_prior":false,"scheduled_reminded_at":null,"impact_override":null,"scheduled_auto_in_progress":false,"scheduled_auto_completed":false,"id":"td9ftgzcyz4m","page_id":"g229z91sc3ff","incident_updates":[{"status":"resolved","body":"Just checking!","created_at":"2014-03-24T23:01:41.529Z","wants_twitter_update":false,"twitter_updated_at":null,"updated_at":"2014-03-24T23:01:41.529Z","display_at":"2014-03-24T23:01:41.529Z","id":"c0n0qt5rmct9","incident_id":"td9ftgzcyz4m"}]}]
@@ -0,0 +1 @@
1
+ [{"name":"Test Maintenance","status":"scheduled","created_at":"2014-03-30T22:44:33.573Z","updated_at":"2014-03-30T22:44:34.927Z","monitoring_at":null,"resolved_at":null,"impact":"none","shortlink":"http://stspg.io/MU9","postmortem_ignored":true,"postmortem_body":null,"postmortem_body_last_updated_at":null,"postmortem_published_at":null,"postmortem_notified_subscribers":false,"postmortem_notified_twitter":false,"backfilled":false,"scheduled_for":"2014-03-31T00:00:00.000Z","scheduled_until":"2014-04-01T00:00:00.000Z","scheduled_remind_prior":false,"scheduled_reminded_at":null,"impact_override":null,"scheduled_auto_in_progress":false,"scheduled_auto_completed":false,"id":"3tzsm37ryws0","page_id":"g229z91sc3ff","incident_updates":[{"status":"scheduled","body":"Some details","created_at":"2014-03-30T22:44:34.926Z","wants_twitter_update":false,"twitter_updated_at":null,"updated_at":"2014-03-30T22:44:34.926Z","display_at":"2014-03-30T22:44:34.926Z","id":"cb1wstkgn1zh","incident_id":"3tzsm37ryws0"}]}]
@@ -0,0 +1 @@
1
+ [{"name":"Unresolved incident","status":"investigating","created_at":"2014-03-30T22:47:14.362Z","updated_at":"2014-03-30T22:47:15.718Z","monitoring_at":null,"resolved_at":null,"impact":"none","shortlink":"http://stspg.io/MUB","postmortem_ignored":false,"postmortem_body":null,"postmortem_body_last_updated_at":null,"postmortem_published_at":null,"postmortem_notified_subscribers":false,"postmortem_notified_twitter":false,"backfilled":false,"scheduled_for":null,"scheduled_until":null,"scheduled_remind_prior":false,"scheduled_reminded_at":null,"impact_override":null,"scheduled_auto_in_progress":false,"scheduled_auto_completed":false,"id":"2ttv50n0n8zj","page_id":"g229z91sc3ff","incident_updates":[{"status":"investigating","body":"The server is on fire.","created_at":"2014-03-30T22:47:15.716Z","wants_twitter_update":false,"twitter_updated_at":null,"updated_at":"2014-03-30T22:47:15.716Z","display_at":"2014-03-30T22:47:15.716Z","id":"s913j9324v4t","incident_id":"2ttv50n0n8zj"}]}]
@@ -0,0 +1 @@
1
+ [{"name":"lp0 on fire","status":"investigating","created_at":"2014-03-31T23:39:43.169Z","updated_at":"2014-03-31T23:39:44.397Z","monitoring_at":null,"resolved_at":null,"impact":"none","shortlink":"http://stspg.io/MZJ","postmortem_ignored":false,"postmortem_body":null,"postmortem_body_last_updated_at":null,"postmortem_published_at":null,"postmortem_notified_subscribers":false,"postmortem_notified_twitter":false,"backfilled":false,"scheduled_for":null,"scheduled_until":null,"scheduled_remind_prior":false,"scheduled_reminded_at":null,"impact_override":null,"scheduled_auto_in_progress":false,"scheduled_auto_completed":false,"id":"b0m7dz4tzpl3","page_id":"g229z91sc3ff","incident_updates":[{"status":"investigating","body":"We are currently investigating this issue.","created_at":"2014-03-31T23:39:44.395Z","wants_twitter_update":false,"twitter_updated_at":null,"updated_at":"2014-03-31T23:39:44.395Z","display_at":"2014-03-31T23:39:44.395Z","id":"gc9bndsygg42","incident_id":"b0m7dz4tzpl3"}]}]
@@ -0,0 +1,358 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lita::Handlers::Statuspage, lita_handler: true do
4
+ let(:incidents) do
5
+ File.read('spec/files/incidents.json')
6
+ end
7
+
8
+ let(:incidents_empty) do
9
+ '[]'
10
+ end
11
+
12
+ let(:incidents_scheduled) do
13
+ File.read('spec/files/incidents_scheduled.json')
14
+ end
15
+
16
+ let(:incidents_unresolved) do
17
+ File.read('spec/files/incidents_unresolved.json')
18
+ end
19
+
20
+ let(:incidents_updated) do
21
+ File.read('spec/files/incidents_update.json')
22
+ end
23
+
24
+ let(:incident_new) do
25
+ File.read('spec/files/incident_new.json')
26
+ end
27
+
28
+ let(:incident_deleted) do
29
+ File.read('spec/files/incident_deleted.json')
30
+ end
31
+
32
+ let(:incident_updated) do
33
+ File.read('spec/files/incident_updated.json')
34
+ end
35
+
36
+ let(:components) do
37
+ File.read('spec/files/components.json')
38
+ end
39
+
40
+ let(:components_empty) do
41
+ '[]'
42
+ end
43
+
44
+ let(:component_update) do
45
+ File.read('spec/files/component_update.json')
46
+ end
47
+
48
+ it { routes_command('statuspage incident new name:"foo"').to(:incident_new) }
49
+ it { routes_command('statuspage incident update latest').to(:incident_update) }
50
+ it { routes_command('statuspage incident list').to(:incident_list_all) }
51
+ it { routes_command('statuspage incident list all').to(:incident_list_all) }
52
+ it { routes_command('statuspage incident list scheduled').to(:incident_list_scheduled) }
53
+ it { routes_command('statuspage incident list unresolved').to(:incident_list_unresolved) }
54
+ it { routes_command('statuspage incident delete latest').to(:incident_delete_latest) }
55
+ it { routes_command('statuspage incident delete id:omgwtfbbq').to(:incident_delete) }
56
+ it { routes_command('statuspage component list').to(:component_list) }
57
+ it { routes_command('statuspage component list all').to(:component_list) }
58
+ it { routes_command('statuspage component update latest').to(:component_update) }
59
+
60
+ describe '.default_config' do
61
+ it 'sets api_key to nil' do
62
+ expect(Lita.config.handlers.statuspage.api_key).to be_nil
63
+ end
64
+
65
+ it 'sets page_id to nil' do
66
+ expect(Lita.config.handlers.statuspage.page_id).to be_nil
67
+ end
68
+ end
69
+
70
+ describe 'without valid config' do
71
+ it 'should error out on any command' do
72
+ expect { send_command('statuspage incident list all') }.to raise_error('Missing config')
73
+ end
74
+ end
75
+
76
+ describe 'with valid config' do
77
+ before do
78
+ Lita.config.handlers.statuspage.api_key = 'foo'
79
+ Lita.config.handlers.statuspage.page_id = 'bar'
80
+ end
81
+
82
+ describe '#incident_new' do
83
+ it 'shows an ack when the incident is created' do
84
+ response = double('Faraday::Response', status: 201, body: incident_new)
85
+ allow_any_instance_of(Faraday::Connection).to receive(:post).and_return(response)
86
+ send_command('statuspage incident new name:"lp0 on fire"')
87
+ expect(replies.last).to eq('Incident b0m7dz4tzpl3 created')
88
+ end
89
+
90
+ it 'shows a warning if the incident does not have a required name' do
91
+ send_command('statuspage incident new status:investigating')
92
+ expect(replies.last).to eq('Can\'t create incident, missing incident name')
93
+ end
94
+
95
+ it 'shows a warning if the incident status is not valid' do
96
+ send_command('statuspage incident new name:"It dun broke" status:ignoring')
97
+ expect(replies.last).to eq('Can\'t create incident, invalid incident state')
98
+ end
99
+
100
+ it 'shows a warning if the twitter status is not valid' do
101
+ send_command('statuspage incident new name:"It dun broke" twitter:lavender')
102
+ expect(replies.last).to eq('Can\'t create incident, invalid twitter state')
103
+ end
104
+
105
+ it 'shows a warning if the impact value is not valid' do
106
+ send_command('statuspage incident new name:"It dun broke" impact:apocalypse')
107
+ expect(replies.last).to eq('Can\'t create incident, invalid impact value')
108
+ end
109
+
110
+ it 'shows an error if there was an issue creating the incident' do
111
+ response = double('Faraday::Response', status: 500, body: '')
112
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
113
+ send_command('statuspage incident new name:"It dun broke"')
114
+ expect(replies.last).to eq('Error creating incident')
115
+ end
116
+ end
117
+
118
+ describe '#incident_update' do
119
+ it 'shows an ack when the incident is updated' do
120
+ get_response = double('Faraday::Response', status: 200, body: incidents_updated)
121
+ patch_response = double('Faraday::Response', status: 200, body: incident_updated)
122
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(get_response)
123
+ allow_any_instance_of(Faraday::Connection).to receive(:patch).and_return(patch_response)
124
+ send_command('statuspage incident update id:b0m7dz4tzpl3 message:"Howdy"')
125
+ expect(replies.last).to eq('Incident b0m7dz4tzpl3 updated')
126
+ end
127
+
128
+ it 'shows a warning if the incident does not exist' do
129
+ response = double('Faraday::Response', status: 200, body: incidents)
130
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
131
+ send_command('statuspage incident update id:b0m7dz4tzpl3 message:"Howdy"')
132
+ expect(replies.last).to eq('Can\'t update incident, does not exist')
133
+ end
134
+
135
+ it 'shows a warning if there is nothing to update' do
136
+ send_command('statuspage incident update id:b0m7dz4tzpl3')
137
+ expect(replies.last).to eq('Can\'t update incident, nothing to update')
138
+ end
139
+
140
+ it 'shows a warning if the incident does not have an id' do
141
+ send_command('statuspage incident update status:investigating')
142
+ expect(replies.last).to eq('Can\'t update incident, missing incident ID')
143
+ end
144
+
145
+ it 'shows a warning if the incident status is not valid' do
146
+ send_command('statuspage incident update id:b0m7dz4tzpl3 status:running_away')
147
+ expect(replies.last).to eq('Can\'t update incident, invalid incident state')
148
+ end
149
+
150
+ it 'shows a warning if the twitter status is not valid' do
151
+ send_command('statuspage incident update id:b0m7dz4tzpl3 twitter:magenta')
152
+ expect(replies.last).to eq('Can\'t update incident, invalid twitter state')
153
+ end
154
+
155
+ it 'shows a warning if the impact value is not valid' do
156
+ send_command('statuspage incident update id:b0m7dz4tzpl3 impact:ragnarok')
157
+ expect(replies.last).to eq('Can\'t update incident, invalid impact value')
158
+ end
159
+
160
+ it 'shows an error if there was an issue updating the incident' do
161
+ get_response = double('Faraday::Response', status: 200, body: incidents_updated)
162
+ patch_response = double('Faraday::Response', status: 500, body: '')
163
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(get_response)
164
+ allow_any_instance_of(Faraday::Connection).to receive(:patch).and_return(patch_response)
165
+ send_command('statuspage incident update id:b0m7dz4tzpl3 message:"Howdy"')
166
+ expect(replies.last).to eq('Error updating incident')
167
+ end
168
+ end
169
+
170
+ describe '#incident_list_all' do
171
+ it 'shows a list of incidents if there are any' do
172
+ response = double('Faraday::Response', status: 200, body: incidents)
173
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
174
+ send_command('statuspage incident list all')
175
+ expect(replies.last).to eq('Test Incident (created: 2014-03-24, ' \
176
+ 'status: resolved, id:td9ftgzcyz4m)')
177
+ end
178
+
179
+ it 'shows a warning if there arent any' do
180
+ response = double('Faraday::Response', status: 200, body: incidents_empty)
181
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
182
+ send_command('statuspage incident list all')
183
+ expect(replies.last).to eq('No incidents to list')
184
+ end
185
+
186
+ it 'shows an error if there was an issue fetching the incidents' do
187
+ response = double('Faraday::Response', status: 500, body: '')
188
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
189
+ send_command('statuspage incident list all')
190
+ expect(replies.last).to eq('Error fetching incidents')
191
+ end
192
+ end
193
+
194
+ describe '#incident_list_scheduled' do
195
+ it 'shows a list of incidents if there are any' do
196
+ response = double('Faraday::Response', status: 200, body: incidents_scheduled)
197
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
198
+ send_command('statuspage incident list scheduled')
199
+ expect(replies.last).to eq('Test Maintenance (created: 2014-03-30, ' \
200
+ 'status: scheduled, id:3tzsm37ryws0)')
201
+ end
202
+
203
+ it 'shows a warning if there arent any' do
204
+ response = double('Faraday::Response', status: 200, body: incidents_empty)
205
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
206
+ send_command('statuspage incident list scheduled')
207
+ expect(replies.last).to eq('No incidents to list')
208
+ end
209
+
210
+ it 'shows an error if there was an issue fetching the incidents' do
211
+ response = double('Faraday::Response', status: 500, body: '')
212
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
213
+ send_command('statuspage incident list scheduled')
214
+ expect(replies.last).to eq('Error fetching incidents')
215
+ end
216
+ end
217
+
218
+ describe '#incident_list_unresolved' do
219
+ it 'shows a list of incidents if there are any' do
220
+ response = double('Faraday::Response', status: 200, body: incidents_unresolved)
221
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
222
+ send_command('statuspage incident list unresolved')
223
+ expect(replies.last).to eq('Unresolved incident (created: 2014-03-30, ' \
224
+ 'status: investigating, id:2ttv50n0n8zj)')
225
+ end
226
+
227
+ it 'shows a warning if there arent any' do
228
+ response = double('Faraday::Response', status: 200, body: incidents_empty)
229
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
230
+ send_command('statuspage incident list scheduled')
231
+ expect(replies.last).to eq('No incidents to list')
232
+ end
233
+
234
+ it 'shows an error if there was an issue fetching the incidents' do
235
+ response = double('Faraday::Response', status: 500, body: '')
236
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
237
+ send_command('statuspage incident list scheduled')
238
+ expect(replies.last).to eq('Error fetching incidents')
239
+ end
240
+ end
241
+
242
+ describe '#incident_delete_latest' do
243
+ it 'shows an ack if the incident was deleted' do
244
+ get_response = double('Faraday::Response', status: 200, body: incidents_unresolved)
245
+ delete_response = double('Faraday::Response', status: 200, body: incident_deleted)
246
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(get_response)
247
+ allow_any_instance_of(Faraday::Connection).to receive(:delete).and_return(delete_response)
248
+ send_command('statuspage incident delete latest')
249
+ expect(replies.last).to eq('Incident 2ttv50n0n8zj deleted')
250
+ end
251
+
252
+ it 'shows a warning if there wasnt an incident to delete' do
253
+ response = double('Faraday::Response', status: 404, body: '')
254
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
255
+ send_command('statuspage incident delete latest')
256
+ expect(replies.last).to eq('No latest incident found')
257
+ end
258
+
259
+ it 'shows an error if there was an issue deleting the incident' do
260
+ get_response = double('Faraday::Response', status: 200, body: incidents_unresolved)
261
+ delete_response = double('Faraday::Response', status: 500, body: '')
262
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(get_response)
263
+ allow_any_instance_of(Faraday::Connection).to receive(:delete).and_return(delete_response)
264
+ send_command('statuspage incident delete latest')
265
+ expect(replies.last).to eq('Error deleting incident')
266
+ end
267
+ end
268
+
269
+ describe '#incident_delete' do
270
+ it 'shows an ack if the incident was deleted' do
271
+ get_response = double('Faraday::Response', status: 200, body: incidents_unresolved)
272
+ delete_response = double('Faraday::Response', status: 200, body: incident_deleted)
273
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(get_response)
274
+ allow_any_instance_of(Faraday::Connection).to receive(:delete).and_return(delete_response)
275
+ send_command('statuspage incident delete id:2ttv50n0n8zj')
276
+ expect(replies.last).to eq('Incident 2ttv50n0n8zj deleted')
277
+ end
278
+
279
+ it 'shows a warning if there wasnt an incident to delete' do
280
+ response = double('Faraday::Response', status: 404, body: '')
281
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
282
+ send_command('statuspage incident delete id:2ttv50n0n8zj')
283
+ expect(replies.last).to eq('Incident not found')
284
+ end
285
+
286
+ it 'shows an error if there was an issue deleting the incident' do
287
+ get_response = double('Faraday::Response', status: 200, body: incidents_unresolved)
288
+ delete_response = double('Faraday::Response', status: 500, body: '')
289
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(get_response)
290
+ allow_any_instance_of(Faraday::Connection).to receive(:delete).and_return(delete_response)
291
+ send_command('statuspage incident delete id:2ttv50n0n8zj')
292
+ expect(replies.last).to eq('Error deleting incident')
293
+ end
294
+ end
295
+
296
+ describe '#component_list' do
297
+ it 'shows a list of components if there are any' do
298
+ response = double('Faraday::Response', status: 200, body: components)
299
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
300
+ send_command('statuspage component list')
301
+ expect(replies.last).to eq('Management Portal (example) (status: operational, id:v6z6tpldcw85)')
302
+ end
303
+
304
+ it 'shows a warning if there arent any' do
305
+ response = double('Faraday::Response', status: 200, body: components_empty)
306
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
307
+ send_command('statuspage component list')
308
+ expect(replies.last).to eq('No components to list')
309
+ end
310
+
311
+ it 'shows an error if there was an issue fetching the components' do
312
+ response = double('Faraday::Response', status: 500, body: '')
313
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(response)
314
+ send_command('statuspage component list')
315
+ expect(replies.last).to eq('Error fetching components')
316
+ end
317
+ end
318
+
319
+ describe '#component_update' do
320
+ it 'shows an ack if the component is updated via id' do
321
+ get_response = double('Faraday::Response', status: 200, body: components)
322
+ patch_response = double('Faraday::Response', status: 200, body: component_update)
323
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(get_response)
324
+ allow_any_instance_of(Faraday::Connection).to receive(:patch).and_return(patch_response)
325
+ send_command('statuspage component update id:v6z6tpldcw85 status:major_outage')
326
+ expect(replies.last).to eq('Component v6z6tpldcw85 updated')
327
+ end
328
+
329
+ it 'shows an ack if the component is updated via name' do
330
+ get_response = double('Faraday::Response', status: 200, body: components)
331
+ patch_response = double('Faraday::Response', status: 200, body: component_update)
332
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(get_response)
333
+ allow_any_instance_of(Faraday::Connection).to receive(:patch).and_return(patch_response)
334
+ send_command('statuspage component update name:"Management Portal (example)" status:major_outage')
335
+ expect(replies.last).to eq('Component v6z6tpldcw85 updated')
336
+ end
337
+
338
+ it 'shows a warning if there is no identifier to the component' do
339
+ send_command('statuspage component update status:major_outage')
340
+ expect(replies.last).to eq('Need an identifier for the component')
341
+ end
342
+
343
+ it 'shows a warning if the status is invalid' do
344
+ send_command('statuspage component update id:v6z6tpldcw85 status:big_problem')
345
+ expect(replies.last).to eq('Invalid status to use in updates')
346
+ end
347
+
348
+ it 'shows an error if there was an issue updating the component' do
349
+ get_response = double('Faraday::Response', status: 200, body: components)
350
+ patch_response = double('Faraday::Response', status: 500, body: '')
351
+ allow_any_instance_of(Faraday::Connection).to receive(:get).and_return(get_response)
352
+ allow_any_instance_of(Faraday::Connection).to receive(:patch).and_return(patch_response)
353
+ send_command('statuspage component update id:v6z6tpldcw85 status:major_outage')
354
+ expect(replies.last).to eq('Error updating component')
355
+ end
356
+ end
357
+ end
358
+ end
@@ -0,0 +1,10 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
4
+ SimpleCov::Formatter::HTMLFormatter,
5
+ Coveralls::SimpleCov::Formatter
6
+ ]
7
+ SimpleCov.start { add_filter '/spec/' }
8
+
9
+ require 'lita-statuspage'
10
+ require 'lita/rspec'
metadata ADDED
@@ -0,0 +1,191 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lita-statuspage
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Eric Sigler
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: lita
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: multi_json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 3.0.0.beta2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 3.0.0.beta2
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: coveralls
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: A Lita handler to interact with Statuspage.io
126
+ email:
127
+ - me@esigler.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".rubocop.yml"
134
+ - ".travis.yml"
135
+ - CONTRIBUTING.md
136
+ - Gemfile
137
+ - LICENSE
138
+ - README.md
139
+ - Rakefile
140
+ - lib/lita-statuspage.rb
141
+ - lib/lita/handlers/statuspage.rb
142
+ - lita-statuspage.gemspec
143
+ - locales/en.yml
144
+ - spec/files/component_update.json
145
+ - spec/files/components.json
146
+ - spec/files/incident_deleted.json
147
+ - spec/files/incident_new.json
148
+ - spec/files/incident_updated.json
149
+ - spec/files/incidents.json
150
+ - spec/files/incidents_scheduled.json
151
+ - spec/files/incidents_unresolved.json
152
+ - spec/files/incidents_update.json
153
+ - spec/lita/handlers/statuspage_spec.rb
154
+ - spec/spec_helper.rb
155
+ homepage: https://github.com/esigler/lita-statuspage
156
+ licenses:
157
+ - MIT
158
+ metadata:
159
+ lita_plugin_type: handler
160
+ post_install_message:
161
+ rdoc_options: []
162
+ require_paths:
163
+ - lib
164
+ required_ruby_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ required_rubygems_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ requirements: []
175
+ rubyforge_project:
176
+ rubygems_version: 2.2.1
177
+ signing_key:
178
+ specification_version: 4
179
+ summary: A Lita handler to interact with Statuspage.io
180
+ test_files:
181
+ - spec/files/component_update.json
182
+ - spec/files/components.json
183
+ - spec/files/incident_deleted.json
184
+ - spec/files/incident_new.json
185
+ - spec/files/incident_updated.json
186
+ - spec/files/incidents.json
187
+ - spec/files/incidents_scheduled.json
188
+ - spec/files/incidents_unresolved.json
189
+ - spec/files/incidents_update.json
190
+ - spec/lita/handlers/statuspage_spec.rb
191
+ - spec/spec_helper.rb