plan_my_stuff 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +28 -0
  3. data/README.md +284 -0
  4. data/app/controllers/plan_my_stuff/application_controller.rb +76 -0
  5. data/app/controllers/plan_my_stuff/comments_controller.rb +82 -0
  6. data/app/controllers/plan_my_stuff/issues_controller.rb +145 -0
  7. data/app/controllers/plan_my_stuff/labels_controller.rb +30 -0
  8. data/app/controllers/plan_my_stuff/project_items_controller.rb +93 -0
  9. data/app/controllers/plan_my_stuff/projects_controller.rb +17 -0
  10. data/app/views/plan_my_stuff/comments/edit.html.erb +16 -0
  11. data/app/views/plan_my_stuff/comments/partials/_form.html.erb +32 -0
  12. data/app/views/plan_my_stuff/issues/edit.html.erb +12 -0
  13. data/app/views/plan_my_stuff/issues/index.html.erb +37 -0
  14. data/app/views/plan_my_stuff/issues/new.html.erb +7 -0
  15. data/app/views/plan_my_stuff/issues/partials/_form.html.erb +41 -0
  16. data/app/views/plan_my_stuff/issues/partials/_labels.html.erb +23 -0
  17. data/app/views/plan_my_stuff/issues/partials/_viewers.html.erb +32 -0
  18. data/app/views/plan_my_stuff/issues/show.html.erb +58 -0
  19. data/app/views/plan_my_stuff/projects/index.html.erb +13 -0
  20. data/app/views/plan_my_stuff/projects/show.html.erb +101 -0
  21. data/config/routes.rb +25 -0
  22. data/lib/generators/plan_my_stuff/install/install_generator.rb +38 -0
  23. data/lib/generators/plan_my_stuff/install/templates/initializer.rb +106 -0
  24. data/lib/generators/plan_my_stuff/views/views_generator.rb +22 -0
  25. data/lib/plan_my_stuff/application_record.rb +39 -0
  26. data/lib/plan_my_stuff/base_metadata.rb +136 -0
  27. data/lib/plan_my_stuff/client.rb +143 -0
  28. data/lib/plan_my_stuff/comment.rb +360 -0
  29. data/lib/plan_my_stuff/comment_metadata.rb +56 -0
  30. data/lib/plan_my_stuff/configuration.rb +139 -0
  31. data/lib/plan_my_stuff/custom_fields.rb +65 -0
  32. data/lib/plan_my_stuff/engine.rb +11 -0
  33. data/lib/plan_my_stuff/errors.rb +87 -0
  34. data/lib/plan_my_stuff/issue.rb +486 -0
  35. data/lib/plan_my_stuff/issue_metadata.rb +111 -0
  36. data/lib/plan_my_stuff/label.rb +59 -0
  37. data/lib/plan_my_stuff/markdown.rb +83 -0
  38. data/lib/plan_my_stuff/metadata_parser.rb +53 -0
  39. data/lib/plan_my_stuff/project.rb +504 -0
  40. data/lib/plan_my_stuff/project_item.rb +414 -0
  41. data/lib/plan_my_stuff/test_helpers.rb +501 -0
  42. data/lib/plan_my_stuff/user_resolver.rb +61 -0
  43. data/lib/plan_my_stuff/verifier.rb +102 -0
  44. data/lib/plan_my_stuff/version.rb +19 -0
  45. data/lib/plan_my_stuff.rb +69 -0
  46. data/lib/tasks/plan_my_stuff.rake +23 -0
  47. metadata +126 -0
@@ -0,0 +1,501 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'plan_my_stuff'
4
+
5
+ module PlanMyStuff
6
+ # Test support for consuming apps. Provides:
7
+ # - `PlanMyStuff.test_mode!` to stub all API calls
8
+ # - Factory-style builders: `build_issue`, `build_comment`, `build_project`
9
+ # - RSpec matchers: `expect_pms_issue_created`, `expect_pms_comment_created`, `expect_pms_item_moved`
10
+ #
11
+ # Usage:
12
+ # require 'plan_my_stuff/test_helpers'
13
+ #
14
+ # RSpec.configure do |config|
15
+ # config.include PlanMyStuff::TestHelpers
16
+ # end
17
+ module TestHelpers
18
+ # Recorded actions during test mode, keyed by type:
19
+ # :issue_created, :comment_created, :item_moved
20
+ thread_mattr_accessor :recorded_actions
21
+ self.recorded_actions = []
22
+
23
+ class << self
24
+ # Builds a fake persisted Issue without hitting the API.
25
+ #
26
+ # @param title [String]
27
+ # @param body [String]
28
+ # @param state [Symbol, String]
29
+ # @param number [Integer]
30
+ # @param repo [String]
31
+ # @param labels [Array<String>]
32
+ # @param metadata [Hash] raw metadata fields to merge
33
+ #
34
+ # @return [PlanMyStuff::Issue]
35
+ #
36
+ def build_issue(
37
+ title: 'Test Issue',
38
+ body: 'Test body',
39
+ state: :open,
40
+ number: 1,
41
+ repo: 'TestOrg/TestRepo',
42
+ labels: [],
43
+ metadata: {}
44
+ )
45
+ issue = PlanMyStuff::Issue.new(
46
+ title: title,
47
+ body: body,
48
+ state: state.to_s,
49
+ number: number,
50
+ repo: repo,
51
+ labels: labels,
52
+ )
53
+
54
+ issue_metadata = PlanMyStuff::IssueMetadata.from_hash({
55
+ schema_version: PlanMyStuff::BaseMetadata::SCHEMA_VERSION,
56
+ gem_version: PlanMyStuff::VERSION::STRING,
57
+ visibility: 'public',
58
+ custom_fields: {},
59
+ }.merge(metadata))
60
+
61
+ issue.instance_variable_set(:@metadata, issue_metadata)
62
+ issue.instance_variable_set(:@persisted, true)
63
+
64
+ body_comment = build_comment(
65
+ body: body,
66
+ issue: issue,
67
+ metadata: { issue_body: true },
68
+ )
69
+ issue.instance_variable_set(:@comments, [body_comment])
70
+
71
+ issue
72
+ end
73
+
74
+ # Builds a fake persisted Comment without hitting the API.
75
+ #
76
+ # @param body [String]
77
+ # @param visibility [Symbol, String]
78
+ # @param id [Integer]
79
+ # @param issue [PlanMyStuff::Issue, nil] parent issue (auto-built if nil)
80
+ # @param metadata [Hash] raw metadata fields to merge
81
+ #
82
+ # @return [PlanMyStuff::Comment]
83
+ #
84
+ def build_comment(body: 'Test comment', visibility: :public, id: 1, issue: nil, metadata: {})
85
+ issue ||= build_issue
86
+
87
+ comment = PlanMyStuff::Comment.new(
88
+ body: body,
89
+ id: id,
90
+ issue: issue,
91
+ )
92
+ comment.visibility = visibility.to_sym
93
+
94
+ comment_metadata = PlanMyStuff::CommentMetadata.from_hash({
95
+ schema_version: PlanMyStuff::BaseMetadata::SCHEMA_VERSION,
96
+ gem_version: PlanMyStuff::VERSION::STRING,
97
+ visibility: visibility.to_s,
98
+ custom_fields: {},
99
+ }.merge(metadata))
100
+
101
+ comment.instance_variable_set(:@metadata, comment_metadata)
102
+ comment.instance_variable_set(:@persisted, true)
103
+ comment
104
+ end
105
+
106
+ # Builds a fake persisted Project without hitting the API.
107
+ #
108
+ # @param title [String]
109
+ # @param number [Integer]
110
+ # @param statuses [Array<String>] status names (auto-assigned IDs)
111
+ # @param items [Array<Hash>] item data hashes
112
+ #
113
+ # @return [PlanMyStuff::Project]
114
+ #
115
+ def build_project(title: 'Test Project', number: 1, statuses: [], items: [])
116
+ status_options = statuses.each_with_index.map do |name, i|
117
+ { id: "status_option_#{i}", name: name }
118
+ end
119
+
120
+ project = PlanMyStuff::Project.new(
121
+ id: "PVT_fake_#{number}",
122
+ number: number,
123
+ title: title,
124
+ statuses: status_options,
125
+ fields: [{ id: 'field_status', name: 'Status', options: status_options }],
126
+ )
127
+ project.instance_variable_set(:@persisted, true)
128
+
129
+ project.items = items.map do |item_hash|
130
+ PlanMyStuff::ProjectItem.build(
131
+ {
132
+ id: item_hash[:id] || "PVTI_fake_#{rand(10_000)}",
133
+ title: item_hash[:title] || 'Untitled',
134
+ number: item_hash[:number],
135
+ url: item_hash[:url],
136
+ state: item_hash[:state],
137
+ status: item_hash[:status],
138
+ field_values: item_hash[:field_values] || {},
139
+ },
140
+ project: project,
141
+ )
142
+ end
143
+
144
+ project
145
+ end
146
+ end
147
+
148
+ # RSpec matchers included when the module is included in a test config.
149
+ # Each matcher asserts that a matching action was recorded during test mode.
150
+
151
+ # @param filters [Hash] attribute filters (e.g. repo:, title:)
152
+ def expect_pms_issue_created(**filters)
153
+ expect_pms_action(:issue_created, 'issue to be created', **filters)
154
+ end
155
+
156
+ # @param filters [Hash] attribute filters (e.g. number:, repo:)
157
+ def expect_pms_issue_found(**filters)
158
+ expect_pms_action(:issue_found, 'issue to be found', **filters)
159
+ end
160
+
161
+ # @param filters [Hash] attribute filters
162
+ def expect_pms_issues_listed(**filters)
163
+ expect_pms_action(:issues_listed, 'issues to be listed', **filters)
164
+ end
165
+
166
+ # @param filters [Hash] attribute filters (e.g. number:, state:)
167
+ def expect_pms_issue_updated(**filters)
168
+ expect_pms_action(:issue_updated, 'issue to be updated', **filters)
169
+ end
170
+
171
+ # @param filters [Hash] attribute filters (e.g. number:, user_ids:)
172
+ def expect_pms_viewers_added(**filters)
173
+ expect_pms_action(:viewers_added, 'viewers to be added', **filters)
174
+ end
175
+
176
+ # @param filters [Hash] attribute filters (e.g. number:, user_ids:)
177
+ def expect_pms_viewers_removed(**filters)
178
+ expect_pms_action(:viewers_removed, 'viewers to be removed', **filters)
179
+ end
180
+
181
+ # @param filters [Hash] attribute filters (e.g. issue_number:, visibility:)
182
+ def expect_pms_comment_created(**filters)
183
+ expect_pms_action(:comment_created, 'comment to be created', **filters)
184
+ end
185
+
186
+ # @param filters [Hash] attribute filters (e.g. issue_number:, pms_only:)
187
+ def expect_pms_comments_listed(**filters)
188
+ expect_pms_action(:comments_listed, 'comments to be listed', **filters)
189
+ end
190
+
191
+ # @param filters [Hash] attribute filters (e.g. id:, body:)
192
+ def expect_pms_comment_updated(**filters)
193
+ expect_pms_action(:comment_updated, 'comment to be updated', **filters)
194
+ end
195
+
196
+ # @param filters [Hash] attribute filters
197
+ def expect_pms_projects_listed(**filters)
198
+ expect_pms_action(:projects_listed, 'projects to be listed', **filters)
199
+ end
200
+
201
+ # @param filters [Hash] attribute filters (e.g. number:)
202
+ def expect_pms_project_found(**filters)
203
+ expect_pms_action(:project_found, 'project to be found', **filters)
204
+ end
205
+
206
+ # @param filters [Hash] attribute filters (e.g. project:, status:)
207
+ def expect_pms_item_moved(**filters)
208
+ expect_pms_action(:item_moved, 'item to be moved', **filters)
209
+ end
210
+
211
+ # @param filters [Hash] attribute filters (e.g. project:, title:)
212
+ def expect_pms_item_created(**filters)
213
+ expect_pms_action(:item_created, 'item to be created', **filters)
214
+ end
215
+
216
+ # @param filters [Hash] attribute filters (e.g. project:, assignee:)
217
+ def expect_pms_item_assigned(**filters)
218
+ expect_pms_action(:item_assigned, 'item to be assigned', **filters)
219
+ end
220
+
221
+ private
222
+
223
+ # @return [void]
224
+ def expect_pms_action(type, description, **filters)
225
+ match = PlanMyStuff::TestHelpers.recorded_actions.find do |action|
226
+ action[:type] == type && matches_filters?(action[:params], filters)
227
+ end
228
+
229
+ expect(match).to(
230
+ be_truthy,
231
+ "Expected PMS #{description} with #{filters.inspect}, " \
232
+ "but recorded actions were: #{format_actions(type)}",
233
+ )
234
+ end
235
+
236
+ # @return [Boolean]
237
+ def matches_filters?(params, filters)
238
+ filters.all? do |key, value|
239
+ params.key?(key) && params[key].to_s == value.to_s
240
+ end
241
+ end
242
+
243
+ # @return [String]
244
+ def format_actions(type)
245
+ actions = PlanMyStuff::TestHelpers.recorded_actions.select { |a| a[:type] == type }
246
+ return '(none)' if actions.empty?
247
+
248
+ actions.map { |a| a[:params].inspect }.join(', ')
249
+ end
250
+ end
251
+
252
+ class << self
253
+ # Activates test mode: stubs all API-calling class methods on Issue,
254
+ # Comment, and ProjectItem so no real HTTP requests are made.
255
+ # Records all actions for assertion matchers.
256
+ #
257
+ # @return [void]
258
+ #
259
+ def test_mode!
260
+ TestHelpers.recorded_actions = []
261
+ return if @_test_mode
262
+
263
+ @_test_mode_originals = {}
264
+ stub_issue_class_methods!
265
+ stub_comment_class_methods!
266
+ stub_project_class_methods!
267
+ stub_project_item_class_methods!
268
+ @_test_mode = true
269
+ end
270
+
271
+ # Restores original class methods overwritten by test_mode!
272
+ #
273
+ # @return [void]
274
+ #
275
+ def exit_test_mode!
276
+ return unless @_test_mode
277
+
278
+ (@_test_mode_originals || {}).each do |klass, methods|
279
+ methods.each do |name, original|
280
+ klass.define_singleton_method(name, original)
281
+ end
282
+ end
283
+
284
+ @_test_mode_originals = nil
285
+ @_test_mode = false
286
+ TestHelpers.recorded_actions = []
287
+ end
288
+
289
+ private
290
+
291
+ # Saves the original method so it can be restored by exit_test_mode!
292
+ #
293
+ # @param klass [Class]
294
+ # @param method_name [Symbol]
295
+ #
296
+ # @return [void]
297
+ #
298
+ def save_original(klass, method_name)
299
+ @_test_mode_originals[klass] ||= {}
300
+ @_test_mode_originals[klass][method_name] = klass.method(method_name)
301
+ end
302
+
303
+ # @return [void]
304
+ def stub_issue_class_methods!
305
+ issue_mod = PlanMyStuff::Issue
306
+ %i[create! find list update! add_viewers remove_viewers].each { |m| save_original(issue_mod, m) }
307
+
308
+ issue_mod.define_singleton_method(:create!) do |**params|
309
+ PlanMyStuff::TestHelpers.recorded_actions << {
310
+ type: :issue_created,
311
+ params: {
312
+ title: params[:title],
313
+ body: params[:body],
314
+ repo: params[:repo],
315
+ labels: params[:labels] || [],
316
+ },
317
+ }
318
+
319
+ PlanMyStuff::TestHelpers.build_issue(
320
+ title: params[:title],
321
+ body: params[:body],
322
+ repo: params[:repo]&.to_s || 'TestOrg/TestRepo',
323
+ labels: params[:labels] || [],
324
+ )
325
+ end
326
+
327
+ issue_mod.define_singleton_method(:find) do |number, repo: nil|
328
+ PlanMyStuff::TestHelpers.recorded_actions << {
329
+ type: :issue_found,
330
+ params: { number: number, repo: repo },
331
+ }
332
+
333
+ PlanMyStuff::TestHelpers.build_issue(number: number, repo: repo&.to_s || 'TestOrg/TestRepo')
334
+ end
335
+
336
+ issue_mod.define_singleton_method(:list) do |**params|
337
+ PlanMyStuff::TestHelpers.recorded_actions << {
338
+ type: :issues_listed,
339
+ params: params,
340
+ }
341
+
342
+ []
343
+ end
344
+
345
+ issue_mod.define_singleton_method(:update!) do |**params|
346
+ PlanMyStuff::TestHelpers.recorded_actions << {
347
+ type: :issue_updated,
348
+ params: params,
349
+ }
350
+
351
+ nil
352
+ end
353
+
354
+ issue_mod.define_singleton_method(:add_viewers) do |**params|
355
+ PlanMyStuff::TestHelpers.recorded_actions << {
356
+ type: :viewers_added,
357
+ params: params,
358
+ }
359
+
360
+ nil
361
+ end
362
+
363
+ issue_mod.define_singleton_method(:remove_viewers) do |**params|
364
+ PlanMyStuff::TestHelpers.recorded_actions << {
365
+ type: :viewers_removed,
366
+ params: params,
367
+ }
368
+
369
+ nil
370
+ end
371
+ end
372
+
373
+ # @return [void]
374
+ def stub_comment_class_methods!
375
+ comment_mod = PlanMyStuff::Comment
376
+ %i[create! list update!].each { |m| save_original(comment_mod, m) }
377
+
378
+ comment_mod.define_singleton_method(:create!) do |**params|
379
+ issue_number = params[:issue].respond_to?(:number) ? params[:issue].number : nil
380
+
381
+ PlanMyStuff::TestHelpers.recorded_actions << {
382
+ type: :comment_created,
383
+ params: {
384
+ issue_number: issue_number,
385
+ body: params[:body],
386
+ visibility: (params[:visibility] || :public).to_sym,
387
+ },
388
+ }
389
+
390
+ PlanMyStuff::TestHelpers.build_comment(
391
+ body: params[:body],
392
+ visibility: params[:visibility] || :public,
393
+ issue: params[:issue],
394
+ )
395
+ end
396
+
397
+ comment_mod.define_singleton_method(:list) do |**params|
398
+ PlanMyStuff::TestHelpers.recorded_actions << {
399
+ type: :comments_listed,
400
+ params: {
401
+ issue_number: params[:issue].respond_to?(:number) ? params[:issue].number : nil,
402
+ pms_only: params[:pms_only] || false,
403
+ },
404
+ }
405
+
406
+ []
407
+ end
408
+
409
+ comment_mod.define_singleton_method(:update!) do |**params|
410
+ PlanMyStuff::TestHelpers.recorded_actions << {
411
+ type: :comment_updated,
412
+ params: params,
413
+ }
414
+
415
+ nil
416
+ end
417
+ end
418
+
419
+ # @return [void]
420
+ def stub_project_class_methods!
421
+ project_mod = PlanMyStuff::Project
422
+ %i[list find].each { |m| save_original(project_mod, m) }
423
+
424
+ project_mod.define_singleton_method(:list) do |**params|
425
+ PlanMyStuff::TestHelpers.recorded_actions << {
426
+ type: :projects_listed,
427
+ params: params,
428
+ }
429
+
430
+ []
431
+ end
432
+
433
+ project_mod.define_singleton_method(:find) do |number, **params|
434
+ PlanMyStuff::TestHelpers.recorded_actions << {
435
+ type: :project_found,
436
+ params: { number: number }.merge(params),
437
+ }
438
+
439
+ PlanMyStuff::TestHelpers.build_project(number: number)
440
+ end
441
+ end
442
+
443
+ # @return [void]
444
+ def stub_project_item_class_methods!
445
+ item_mod = PlanMyStuff::ProjectItem
446
+ %i[move_item create! assign].each { |m| save_original(item_mod, m) }
447
+
448
+ item_mod.define_singleton_method(:move_item) do |**params|
449
+ PlanMyStuff::TestHelpers.recorded_actions << {
450
+ type: :item_moved,
451
+ params: {
452
+ project: params[:project_number],
453
+ item_id: params[:item_id],
454
+ status: params[:status],
455
+ },
456
+ }
457
+ nil
458
+ end
459
+
460
+ item_mod.define_singleton_method(:create!) do |issue_or_title, **params|
461
+ title = issue_or_title.respond_to?(:title) ? issue_or_title.title : issue_or_title.to_s
462
+ number = issue_or_title.respond_to?(:number) ? issue_or_title.number : nil
463
+
464
+ PlanMyStuff::TestHelpers.recorded_actions << {
465
+ type: :item_created,
466
+ params: {
467
+ project: params[:project_number],
468
+ title: title,
469
+ number: number,
470
+ draft: params[:draft] || false,
471
+ },
472
+ }
473
+
474
+ project = PlanMyStuff::TestHelpers.build_project(number: params[:project_number] || 1)
475
+ PlanMyStuff::ProjectItem.build(
476
+ {
477
+ id: "PVTI_fake_#{rand(10_000)}",
478
+ title: title,
479
+ number: number,
480
+ status: nil,
481
+ field_values: {},
482
+ },
483
+ project: project,
484
+ )
485
+ end
486
+
487
+ item_mod.define_singleton_method(:assign) do |**params|
488
+ PlanMyStuff::TestHelpers.recorded_actions << {
489
+ type: :item_assigned,
490
+ params: {
491
+ project: params[:project_number],
492
+ item_id: params[:item_id],
493
+ assignee: params[:assignee],
494
+ },
495
+ }
496
+
497
+ nil
498
+ end
499
+ end
500
+ end
501
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlanMyStuff
4
+ # Resolves user objects from user objects or integer IDs, and extracts
5
+ # display names, IDs, and support status using configuration methods.
6
+ module UserResolver
7
+ class << self
8
+ # Resolves a user param (object or integer ID) into a user object.
9
+ #
10
+ # @param user [Object, Integer] user object or user_id integer
11
+ #
12
+ # @return [Object] the resolved user object
13
+ #
14
+ def resolve(user)
15
+ return if user.nil?
16
+
17
+ return user unless user.is_a?(Integer)
18
+
19
+ config = PlanMyStuff.configuration
20
+ klass = Object.const_get(config.user_class)
21
+ klass.find_by!(config.user_id_method => user)
22
+ end
23
+
24
+ # Extracts the display name from a user object.
25
+ #
26
+ # @param user [Object] user object (not an integer ID)
27
+ #
28
+ # @return [String]
29
+ #
30
+ def display_name(user)
31
+ user.public_send(PlanMyStuff.configuration.display_name_method)
32
+ end
33
+
34
+ # Extracts the app-side user ID from a user object.
35
+ #
36
+ # @param user [Object] user object (not an integer ID)
37
+ #
38
+ # @return [Integer]
39
+ #
40
+ def user_id(user)
41
+ user.public_send(PlanMyStuff.configuration.user_id_method)
42
+ end
43
+
44
+ # Checks whether a user is support staff.
45
+ #
46
+ # @param user [Object] user object (not an integer ID)
47
+ #
48
+ # @return [Boolean]
49
+ #
50
+ def support?(user)
51
+ method = PlanMyStuff.configuration.support_method
52
+
53
+ if method.is_a?(Proc)
54
+ method.call(user)
55
+ else
56
+ user.public_send(method)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlanMyStuff
4
+ # Verifies PlanMyStuff configuration by making API calls to GitHub.
5
+ # Checks token validity, org access, repo access, and project access.
6
+ class Verifier
7
+ Result = Struct.new(:name, :passed, :message)
8
+
9
+ # @return [Array<Result>]
10
+ attr_reader :results
11
+
12
+ # @return [Verifier]
13
+ def initialize
14
+ @results = []
15
+ end
16
+
17
+ # Runs all verification checks and returns self.
18
+ #
19
+ # @return [Verifier]
20
+ #
21
+ def run
22
+ check_token
23
+ check_organization
24
+ check_repos
25
+ check_default_project
26
+ self
27
+ end
28
+
29
+ # @return [Boolean]
30
+ def passed?
31
+ results.all?(&:passed)
32
+ end
33
+
34
+ private
35
+
36
+ # @return [void]
37
+ def check_token
38
+ user = PlanMyStuff.client.rest(:user)
39
+ @results << Result.new('Token', true, "Authenticated as #{user.login}")
40
+ rescue => e
41
+ @results << Result.new('Token', false, e.message)
42
+ end
43
+
44
+ # @return [void]
45
+ def check_organization
46
+ org = PlanMyStuff.configuration.organization
47
+ PlanMyStuff.client.rest(:organization, org)
48
+ @results << Result.new('Organization', true, "Access to #{org} confirmed")
49
+ rescue => e
50
+ @results << Result.new('Organization', false, "#{org}: #{e.message}")
51
+ end
52
+
53
+ # @return [void]
54
+ def check_repos
55
+ config = PlanMyStuff.configuration
56
+
57
+ if config.repos.empty? && config.default_repo.nil?
58
+ @results << Result.new('Repos', true, 'No repos configured (skipped)')
59
+ return
60
+ end
61
+
62
+ config.repos.each do |key, full_name|
63
+ check_single_repo(key, full_name)
64
+ end
65
+
66
+ return if config.default_repo.nil? || config.repos.key?(config.default_repo)
67
+
68
+ @results << Result.new(
69
+ 'Default repo',
70
+ false,
71
+ "default_repo #{config.default_repo.inspect} not found in repos hash",
72
+ )
73
+ end
74
+
75
+ # @return [void]
76
+ def check_single_repo(key, full_name)
77
+ PlanMyStuff.client.rest(:repository, full_name)
78
+ @results << Result.new("Repo :#{key}", true, "Access to #{full_name} confirmed")
79
+ rescue => e
80
+ @results << Result.new("Repo :#{key}", false, "#{full_name}: #{e.message}")
81
+ end
82
+
83
+ # @return [void]
84
+ def check_default_project
85
+ project_number = PlanMyStuff.configuration.default_project_number
86
+
87
+ if project_number.nil?
88
+ @results << Result.new('Project', true, 'No default project configured (skipped)')
89
+ return
90
+ end
91
+
92
+ project = PlanMyStuff::Project.find(project_number)
93
+ @results << Result.new(
94
+ 'Project',
95
+ true,
96
+ "Access to project ##{project_number} (#{project.title}) confirmed",
97
+ )
98
+ rescue => e
99
+ @results << Result.new('Project', false, "Project ##{project_number}: #{e.message}")
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlanMyStuff
4
+ module VERSION
5
+ MAJOR = 0
6
+ MINOR = 1
7
+ TINY = 0
8
+
9
+ # Set PRE to nil unless it's a pre-release (beta, rc, etc.)
10
+ PRE = nil
11
+
12
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.').freeze
13
+
14
+ # :nodoc:
15
+ def self.to_s
16
+ STRING
17
+ end
18
+ end
19
+ end