plan_my_stuff 0.3.0 → 0.5.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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/README.md +569 -38
  4. data/app/controllers/plan_my_stuff/comments_controller.rb +5 -1
  5. data/app/controllers/plan_my_stuff/issues/approvals_controller.rb +102 -0
  6. data/app/controllers/plan_my_stuff/issues/closures_controller.rb +37 -0
  7. data/app/controllers/plan_my_stuff/issues/links_controller.rb +127 -0
  8. data/app/controllers/plan_my_stuff/issues/takes_controller.rb +88 -0
  9. data/app/controllers/plan_my_stuff/issues/viewers_controller.rb +48 -0
  10. data/app/controllers/plan_my_stuff/issues/waitings_controller.rb +47 -0
  11. data/app/controllers/plan_my_stuff/issues_controller.rb +22 -55
  12. data/app/controllers/plan_my_stuff/labels_controller.rb +4 -4
  13. data/app/controllers/plan_my_stuff/project_items/assignments_controller.rb +75 -0
  14. data/app/controllers/plan_my_stuff/project_items/statuses_controller.rb +40 -0
  15. data/app/controllers/plan_my_stuff/project_items_controller.rb +0 -75
  16. data/app/controllers/plan_my_stuff/projects_controller.rb +11 -1
  17. data/app/controllers/plan_my_stuff/testing_project_items/results_controller.rb +54 -0
  18. data/app/controllers/plan_my_stuff/testing_project_items_controller.rb +39 -0
  19. data/app/controllers/plan_my_stuff/testing_projects_controller.rb +93 -0
  20. data/app/controllers/plan_my_stuff/webhooks/aws_controller.rb +148 -0
  21. data/app/controllers/plan_my_stuff/webhooks/github_controller.rb +284 -0
  22. data/app/jobs/plan_my_stuff/application_job.rb +9 -0
  23. data/app/jobs/plan_my_stuff/reminders_sweep_job.rb +81 -0
  24. data/app/views/plan_my_stuff/comments/partials/_form.html.erb +7 -0
  25. data/app/views/plan_my_stuff/issues/partials/_approvals.html.erb +87 -0
  26. data/app/views/plan_my_stuff/issues/partials/_labels.html.erb +2 -2
  27. data/app/views/plan_my_stuff/issues/partials/_links.html.erb +70 -0
  28. data/app/views/plan_my_stuff/issues/partials/_viewers.html.erb +2 -2
  29. data/app/views/plan_my_stuff/issues/show.html.erb +46 -3
  30. data/app/views/plan_my_stuff/projects/index.html.erb +15 -1
  31. data/app/views/plan_my_stuff/projects/show.html.erb +10 -5
  32. data/app/views/plan_my_stuff/testing_project_items/new.html.erb +12 -0
  33. data/app/views/plan_my_stuff/testing_project_items/results/new.html.erb +22 -0
  34. data/app/views/plan_my_stuff/testing_projects/edit.html.erb +7 -0
  35. data/app/views/plan_my_stuff/testing_projects/new.html.erb +7 -0
  36. data/app/views/plan_my_stuff/testing_projects/partials/_form.html.erb +39 -0
  37. data/app/views/plan_my_stuff/testing_projects/partials/_item.html.erb +51 -0
  38. data/app/views/plan_my_stuff/testing_projects/partials/items/_form.html.erb +35 -0
  39. data/app/views/plan_my_stuff/testing_projects/show.html.erb +65 -0
  40. data/config/routes.rb +38 -15
  41. data/lib/generators/plan_my_stuff/install/templates/initializer.rb +172 -5
  42. data/lib/plan_my_stuff/application_record.rb +121 -0
  43. data/lib/plan_my_stuff/approval.rb +80 -0
  44. data/lib/plan_my_stuff/archive/sweep.rb +85 -0
  45. data/lib/plan_my_stuff/archive.rb +14 -0
  46. data/lib/plan_my_stuff/aws_sns_simulator.rb +110 -0
  47. data/lib/plan_my_stuff/base_project.rb +661 -0
  48. data/lib/plan_my_stuff/base_project_item.rb +562 -0
  49. data/lib/plan_my_stuff/base_project_metadata.rb +16 -0
  50. data/lib/plan_my_stuff/cache.rb +197 -0
  51. data/lib/plan_my_stuff/client.rb +7 -0
  52. data/lib/plan_my_stuff/comment.rb +171 -50
  53. data/lib/plan_my_stuff/configuration.rb +210 -10
  54. data/lib/plan_my_stuff/custom_fields.rb +31 -17
  55. data/lib/plan_my_stuff/engine.rb +0 -4
  56. data/lib/plan_my_stuff/errors.rb +49 -0
  57. data/lib/plan_my_stuff/graphql/queries.rb +392 -0
  58. data/lib/plan_my_stuff/issue.rb +1476 -175
  59. data/lib/plan_my_stuff/issue_metadata.rb +122 -0
  60. data/lib/plan_my_stuff/label.rb +82 -11
  61. data/lib/plan_my_stuff/link.rb +144 -0
  62. data/lib/plan_my_stuff/notifications.rb +142 -0
  63. data/lib/plan_my_stuff/pipeline/issue_linker.rb +62 -0
  64. data/lib/plan_my_stuff/pipeline/status.rb +44 -0
  65. data/lib/plan_my_stuff/pipeline.rb +293 -0
  66. data/lib/plan_my_stuff/project.rb +30 -693
  67. data/lib/plan_my_stuff/project_item.rb +3 -417
  68. data/lib/plan_my_stuff/project_item_metadata.rb +55 -0
  69. data/lib/plan_my_stuff/project_metadata.rb +9 -3
  70. data/lib/plan_my_stuff/reminders/closer.rb +70 -0
  71. data/lib/plan_my_stuff/reminders/fire.rb +129 -0
  72. data/lib/plan_my_stuff/reminders/sweep.rb +54 -0
  73. data/lib/plan_my_stuff/reminders.rb +16 -0
  74. data/lib/plan_my_stuff/test_helpers.rb +260 -15
  75. data/lib/plan_my_stuff/testing_project.rb +291 -0
  76. data/lib/plan_my_stuff/testing_project_item.rb +216 -0
  77. data/lib/plan_my_stuff/testing_project_metadata.rb +94 -0
  78. data/lib/plan_my_stuff/user_resolver.rb +8 -3
  79. data/lib/plan_my_stuff/version.rb +1 -1
  80. data/lib/plan_my_stuff/webhook_replayer.rb +280 -0
  81. data/lib/plan_my_stuff.rb +15 -0
  82. data/lib/tasks/plan_my_stuff.rake +179 -0
  83. metadata +77 -3
@@ -1,6 +1,11 @@
1
1
  <h1><%= @project.title %></h1>
2
2
 
3
- <p><%= link_to('Edit', plan_my_stuff.edit_project_path(@project.number)) %></p>
3
+ <p>
4
+ <%= link_to('Edit', plan_my_stuff.edit_project_path(@project.number)) %>
5
+ <% if @support_user && @project.url.present? %>
6
+ <%= link_to('View on GitHub', @project.url, target: '_blank', rel: 'noopener') %>
7
+ <% end %>
8
+ </p>
4
9
 
5
10
  <% if @statuses.any? %>
6
11
  <table>
@@ -29,7 +34,7 @@
29
34
 
30
35
  <%=
31
36
  form_with(
32
- url: plan_my_stuff.move_project_item_path(@project.number, item.id),
37
+ url: plan_my_stuff.project_item_status_path(@project.number, item.id),
33
38
  method: :patch,
34
39
  local: true,
35
40
  ) do |form|
@@ -45,8 +50,8 @@
45
50
  <%= username %>
46
51
  <%=
47
52
  form_with(
48
- url: plan_my_stuff.unassign_project_item_path(@project.number, item.id),
49
- method: :patch,
53
+ url: plan_my_stuff.project_item_assignment_path(@project.number, item.id),
54
+ method: :delete,
50
55
  local: true,
51
56
  html: { style: 'display: inline' },
52
57
  ) do |form|
@@ -61,7 +66,7 @@
61
66
 
62
67
  <%=
63
68
  form_with(
64
- url: plan_my_stuff.assign_project_item_path(@project.number, item.id),
69
+ url: plan_my_stuff.project_item_assignment_path(@project.number, item.id),
65
70
  method: :patch,
66
71
  local: true,
67
72
  ) do |form|
@@ -0,0 +1,12 @@
1
+ <h1>Add Item to <%= @project.title %></h1>
2
+
3
+ <% if flash[:error].present? %>
4
+ <p style="color: red;"><%= flash[:error] %></p>
5
+ <% end %>
6
+
7
+ <%=
8
+ render({
9
+ partial: 'plan_my_stuff/testing_projects/partials/items/form',
10
+ locals: { project: @project },
11
+ })
12
+ %>
@@ -0,0 +1,22 @@
1
+ <h1>Fail Item</h1>
2
+
3
+ <% if flash[:error].present? %>
4
+ <p style="color: red;"><%= flash[:error] %></p>
5
+ <% end %>
6
+
7
+ <%= form_with(
8
+ url: plan_my_stuff.testing_project_item_result_path(@project_number, @item_id),
9
+ method: :post,
10
+ local: true,
11
+ ) do |form| %>
12
+ <%= form.hidden_field(:result, value: 'fail') %>
13
+
14
+ <div>
15
+ <%= form.label(:result_notes, 'Result Notes') %>
16
+ <%= form.text_area(:result_notes, rows: 5, required: true) %>
17
+ </div>
18
+
19
+ <div>
20
+ <%= form.submit('Submit Failure') %>
21
+ </div>
22
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <h1>Edit Testing Project #<%= @project.number %></h1>
2
+
3
+ <% if flash[:error].present? %>
4
+ <p style="color: red;"><%= flash[:error] %></p>
5
+ <% end %>
6
+
7
+ <%= render({ partial: 'plan_my_stuff/testing_projects/partials/form', locals: { project: @project } }) %>
@@ -0,0 +1,7 @@
1
+ <h1>New Testing Project</h1>
2
+
3
+ <% if flash[:error].present? %>
4
+ <p style="color: red;"><%= flash[:error] %></p>
5
+ <% end %>
6
+
7
+ <%= render({ partial: 'plan_my_stuff/testing_projects/partials/form', locals: { project: @project } }) %>
@@ -0,0 +1,39 @@
1
+ <%
2
+ persisted = project.persisted?
3
+ url =
4
+ if persisted
5
+ plan_my_stuff.testing_project_path(project.number)
6
+ else
7
+ plan_my_stuff.testing_projects_path
8
+ end
9
+ %>
10
+ <%= form_with(url: url, method: persisted ? :patch : :post, scope: :testing_project) do |form| %>
11
+ <div>
12
+ <%= form.label(:title, 'Title') %>
13
+ <%= form.text_field(:title, value: project.title, required: true) %>
14
+ </div>
15
+
16
+ <div>
17
+ <%= form.label(:description, 'Description') %>
18
+ <%= form.text_field(:description, value: project.description) %>
19
+ </div>
20
+
21
+ <div>
22
+ <%= form.label(:subject_urls, 'Subject URLs (one per line)') %>
23
+ <%= form.text_area(:subject_urls, rows: 4, value: project.metadata.subject_urls.join("\n")) %>
24
+ </div>
25
+
26
+ <div>
27
+ <%= form.label(:due_date, 'Due Date') %>
28
+ <%= form.date_field(:due_date, value: project.metadata.due_date) %>
29
+ </div>
30
+
31
+ <div>
32
+ <%= form.label(:deadline_miss_reason, 'Deadline Miss Reason') %>
33
+ <%= form.text_field(:deadline_miss_reason, value: project.metadata.deadline_miss_reason) %>
34
+ </div>
35
+
36
+ <div>
37
+ <%= form.submit(persisted ? 'Update Testing Project' : 'Create Testing Project') %>
38
+ </div>
39
+ <% end %>
@@ -0,0 +1,51 @@
1
+ <div style="border: 1px solid black; margin: 1em; padding: 0.5em">
2
+ <% if item.draft? %>
3
+ <strong><%= item.title %></strong>
4
+ <% else %>
5
+ <strong><%= link_to(item.title, plan_my_stuff.issue_path(item.number, repo: item.repo.full_name)) %></strong>
6
+ <small>#<%= item.number %></small>
7
+ <% end %>
8
+
9
+ <%=
10
+ form_with(
11
+ url: plan_my_stuff.testing_project_item_status_path(project.number, item.id),
12
+ method: :patch,
13
+ local: true,
14
+ ) do |form|
15
+ %>
16
+ <%= form.select(:status, statuses, { selected: item.status }, { onchange: 'this.form.requestSubmit();' }) %>
17
+ <% end %>
18
+
19
+ <% if item.field_values['Testers'].present? %>
20
+ <div><strong>Testers:</strong> <%= item.field_values['Testers'] %></div>
21
+ <% end %>
22
+
23
+ <% if item.field_values['Watchers'].present? %>
24
+ <div><strong>Watchers:</strong> <%= item.field_values['Watchers'] %></div>
25
+ <% end %>
26
+
27
+ <% if item.field_values['Due Date'].present? %>
28
+ <div><strong>Due:</strong> <%= item.field_values['Due Date'] %></div>
29
+ <% end %>
30
+
31
+ <% if item.field_values['Result Notes'].present? %>
32
+ <div><strong>Notes:</strong> <%= item.field_values['Result Notes'] %></div>
33
+ <% end %>
34
+
35
+ <% if item.field_values['Passed At'].present? %>
36
+ <div><strong>Passed at:</strong> <%= item.field_values['Passed At'] %></div>
37
+ <% end %>
38
+
39
+ <div>
40
+ <%=
41
+ button_to(
42
+ 'Pass',
43
+ plan_my_stuff.testing_project_item_result_path(project.number, item.id),
44
+ method: :post,
45
+ params: { result: 'pass' },
46
+ )
47
+ %>
48
+
49
+ <%= link_to('Fail', plan_my_stuff.new_testing_project_item_result_path(project.number, item.id)) %>
50
+ </div>
51
+ </div>
@@ -0,0 +1,35 @@
1
+ <%= form_with(url: plan_my_stuff.testing_project_items_path(project.number), method: :post, local: true) do |form| %>
2
+ <div>
3
+ <%= form.label(:title, 'Title') %>
4
+ <%= form.text_field(:title, required: true) %>
5
+ </div>
6
+
7
+ <div>
8
+ <%= form.label(:body, 'Body') %>
9
+ <%= form.text_area(:body, rows: 4) %>
10
+ </div>
11
+
12
+ <div>
13
+ <%= form.label(:testers, 'Testers (user ids, comma separated)') %>
14
+ <%= form.text_field(:testers) %>
15
+ </div>
16
+
17
+ <div>
18
+ <%= form.label(:watchers, 'Watchers (user ids, comma separated)') %>
19
+ <%= form.text_field(:watchers) %>
20
+ </div>
21
+
22
+ <div>
23
+ <%= form.label(:pass_mode, 'Pass Mode') %>
24
+ <%= form.select(:pass_mode, [['All testers must pass', 'all'], ['Any tester can pass', 'any']], { selected: 'all' }) %>
25
+ </div>
26
+
27
+ <div>
28
+ <%= form.label(:due_date, 'Due Date') %>
29
+ <%= form.date_field(:due_date) %>
30
+ </div>
31
+
32
+ <div>
33
+ <%= form.submit('Add Item') %>
34
+ </div>
35
+ <% end %>
@@ -0,0 +1,65 @@
1
+ <h1><%= @project.title %></h1>
2
+
3
+ <p>
4
+ <%= link_to('Edit', plan_my_stuff.edit_testing_project_path(@project.number)) %>
5
+ <% if @support_user && @project.url.present? %>
6
+ <%= link_to('View on GitHub', @project.url, target: '_blank', rel: 'noopener') %>
7
+ <% end %>
8
+ </p>
9
+
10
+ <% if @support_user && @project.metadata.subject_urls.any? %>
11
+ <p>
12
+ <strong>Subject URLs:</strong>
13
+ <% @project.metadata.subject_urls.each do |url| %>
14
+ <%= link_to(url, url, target: '_blank', rel: 'noopener') %>
15
+ <% end %>
16
+ </p>
17
+ <% end %>
18
+
19
+ <% if @project.metadata.due_date.present? %>
20
+ <p><strong>Due:</strong> <%= @project.metadata.due_date %></p>
21
+ <% end %>
22
+
23
+ <% if @statuses.any? %>
24
+ <table>
25
+ <thead>
26
+ <tr>
27
+ <% @statuses.each do |status| %>
28
+ <th><%= status %></th>
29
+ <% end %>
30
+ </tr>
31
+ </thead>
32
+ <tbody>
33
+ <tr>
34
+ <% @statuses.each do |status| %>
35
+ <td>
36
+ <% items = @items_by_status[status] || [] %>
37
+ <% items.each do |item| %>
38
+ <%= render({
39
+ partial: 'plan_my_stuff/testing_projects/partials/item',
40
+ locals: { item: item, project: @project, statuses: @statuses },
41
+ }) %>
42
+ <% end %>
43
+ <% if items.empty? %>
44
+ <em>No items</em>
45
+ <% end %>
46
+ </td>
47
+ <% end %>
48
+ </tr>
49
+ </tbody>
50
+ </table>
51
+ <% else %>
52
+ <p>No statuses configured for this project.</p>
53
+ <% end %>
54
+
55
+ <h2>Add Item</h2>
56
+
57
+ <p><%= link_to('Add item with details', plan_my_stuff.new_testing_project_item_path(@project.number)) %></p>
58
+
59
+ <%= form_with(url: plan_my_stuff.testing_project_items_path(@project.number), method: :post, local: true) do |form| %>
60
+ <%= form.label(:title, 'Title') %>
61
+ <%= form.text_field(:title, required: true) %>
62
+ <%= form.label(:body, 'Body') %>
63
+ <%= form.text_area(:body) %>
64
+ <%= form.submit('Add Item') %>
65
+ <% end %>
data/config/routes.rb CHANGED
@@ -1,24 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  PlanMyStuff::Engine.routes.draw do
4
- resources :issues, except: %i[destroy] do
5
- member do
6
- patch :close
7
- patch :reopen
8
- post :add_viewers
9
- delete :remove_viewer
4
+ config = PlanMyStuff.configuration
5
+ mount_groups = config.mount_groups
6
+
7
+ if mount_groups.fetch(:issues, true)
8
+ resources :issues, except: %i[destroy], controller: config.controller_for(:issues) do
9
+ resource :closure, only: %i[create destroy], controller: config.controller_for(:'issues/closures')
10
+ resource :waiting, only: %i[create destroy], controller: config.controller_for(:'issues/waitings')
11
+ resources :viewers, only: %i[create destroy], controller: config.controller_for(:'issues/viewers')
12
+ if config.pipeline_enabled
13
+ resource(
14
+ :take,
15
+ only: :create,
16
+ controller: config.controller_for(:'issues/takes'),
17
+ )
18
+ end
19
+ resources :comments, only: %i[create edit update], controller: config.controller_for(:comments)
20
+ resources :labels, only: %i[create destroy], controller: config.controller_for(:labels)
21
+ resources :links, only: %i[create destroy], controller: config.controller_for(:'issues/links')
22
+ resources :approvals, only: %i[create update destroy], controller: config.controller_for(:'issues/approvals')
23
+ end
24
+ end
25
+
26
+ if mount_groups.fetch(:webhooks, true) && config.pipeline_enabled
27
+ namespace :webhooks do
28
+ resource :github, only: %i[create], controller: config.controller_for(:'webhooks/github')
29
+ resource :aws, only: %i[create], controller: config.controller_for(:'webhooks/aws')
10
30
  end
11
- resources :comments, only: %i[create edit update]
12
- post 'labels', to: 'labels#add_to_issue', as: :add_label
13
- delete 'labels/:name', to: 'labels#remove_from_issue', as: :remove_label
14
31
  end
15
32
 
16
- resources :projects, except: %i[destroy] do
17
- resources :items, only: %i[create], controller: 'project_items' do
18
- member do
19
- patch :move
20
- patch :assign
21
- patch :unassign
33
+ if mount_groups.fetch(:projects, true)
34
+ resources :projects, except: %i[destroy], controller: config.controller_for(:projects) do
35
+ resources :items, only: %i[create], controller: config.controller_for(:project_items) do
36
+ resource :status, only: %i[update], controller: config.controller_for(:'project_items/statuses')
37
+ resource :assignment, only: %i[update destroy], controller: config.controller_for(:'project_items/assignments')
38
+ end
39
+ end
40
+
41
+ resources :testing_projects, except: %i[destroy index], controller: config.controller_for(:testing_projects) do
42
+ resources :items, only: %i[new create], controller: config.controller_for(:testing_project_items) do
43
+ resource :status, only: %i[update], controller: config.controller_for(:'project_items/statuses')
44
+ resource :result, only: %i[new create], controller: config.controller_for(:'testing_project_items/results')
22
45
  end
23
46
  end
24
47
  end
@@ -26,6 +26,13 @@ PMS.configure do |config|
26
26
  # Default GitHub Projects V2 number for add_to_project calls.
27
27
  # config.default_project_number = 14
28
28
 
29
+ # Template project to clone when creating new Testing Projects.
30
+ # When set, TestingProject.create! copies this project (preserving its
31
+ # custom fields and board layout) instead of bootstrapping fields from scratch.
32
+ # The template should be a pre-configured testing project with the correct
33
+ # fields and board view already set up in the GitHub UI.
34
+ # config.testing_template_project_number = 42
35
+
29
36
  # --------------------------------------------------------------------------
30
37
  # App identity
31
38
  # --------------------------------------------------------------------------
@@ -49,6 +56,14 @@ PMS.configure do |config|
49
56
  # config.support_method = :support?
50
57
  # config.support_method = ->(user) { user.role.in?(%w[support admin]) }
51
58
 
59
+ # Map of app user id (whatever `user_id_method` returns) to GitHub login.
60
+ # Used by the "Take" UI flow to assign the GitHub user when a support
61
+ # user claims an issue.
62
+ # config.github_login_for = {
63
+ # 1 => 'some_username',
64
+ # 2 => 'octocat',
65
+ # }
66
+
52
67
  # --------------------------------------------------------------------------
53
68
  # Engine authentication
54
69
  # --------------------------------------------------------------------------
@@ -65,6 +80,16 @@ PMS.configure do |config|
65
80
  # :commonmarker (default) or :redcarpet -- the chosen gem must be in your Gemfile.
66
81
  # config.markdown_renderer = :commonmarker
67
82
 
83
+ # Default options passed to the markdown renderer. Per-call options merge on top.
84
+ # For :commonmarker -- passed as `options:` to `Commonmarker.to_html`:
85
+ # config.markdown_options = { render: { hardbreaks: true } }
86
+ # For :redcarpet -- :render_options and :renderer are extracted for the HTML
87
+ # renderer; remaining keys are extensions passed to `Redcarpet::Markdown.new`:
88
+ # config.markdown_options = {
89
+ # render_options: { hard_wrap: true, no_styles: true },
90
+ # autolink: true,
91
+ # }
92
+
68
93
  # --------------------------------------------------------------------------
69
94
  # URL prefix
70
95
  # --------------------------------------------------------------------------
@@ -85,11 +110,9 @@ PMS.configure do |config|
85
110
  # update_status: 'PmsUpdateStatusJob'
86
111
  # }
87
112
 
88
- # Custom notifier for deferred requests (proc/class), or nil to use
89
- # the built-in DeferredMailer.
90
- # config.deferred_notifier = nil
91
- # config.deferred_email_from = 'noreply@example.com'
92
- # config.deferred_email_to = 'it-support@example.com'
113
+ # Fallback actor for notification events (plan_my_stuff.*) when a caller
114
+ # does not pass an explicit user: kwarg. Proc/lambda called at event time.
115
+ # config.current_user = -> { Current.user }
93
116
 
94
117
  # --------------------------------------------------------------------------
95
118
  # Custom fields
@@ -112,4 +135,148 @@ PMS.configure do |config|
112
135
 
113
136
  # Comment-only fields (merged on top of shared, context wins on conflicts):
114
137
  # config.comment_custom_fields = {}
138
+
139
+ # Project-only fields (merged on top of shared, context wins on conflicts):
140
+ # config.project_custom_fields = {}
141
+
142
+ # Testing-project-only fields (merged on top of shared, context wins on conflicts):
143
+ # config.testing_custom_fields = {}
144
+
145
+ # --------------------------------------------------------------------------
146
+ # Release pipeline
147
+ # --------------------------------------------------------------------------
148
+ # config.pipeline_enabled = true
149
+ # config.pipeline_project_number = 14
150
+
151
+ # GitHub webhook HMAC-SHA256 secret (required when webhook routes are mounted).
152
+ # config.webhook_secret = Rails.application.credentials.dig(:plan_my_stuff, :webhook_secret)
153
+
154
+ # Configurable display aliases for pipeline statuses.
155
+ # config.pipeline_statuses = {
156
+ # 'Submitted' => 'Triaged',
157
+ # 'Completed' => 'Done',
158
+ # }
159
+
160
+ # config.main_branch = 'main'
161
+ # config.production_branch = 'production'
162
+
163
+ # --------------------------------------------------------------------------
164
+ # Follow-up reminders
165
+ # --------------------------------------------------------------------------
166
+ # Daily sweep that fires `plan_my_stuff.issue.reminder_due` events on
167
+ # waiting issues and auto-closes issues that exceed the inactivity
168
+ # ceiling. Consuming app is responsible for the initial enqueue:
169
+ #
170
+ # # Enqueue one sweep job per configured repo:
171
+ # rake plan_my_stuff:reminders:sweep
172
+ #
173
+ # # Or a single repo:
174
+ # rake plan_my_stuff:reminders:sweep REPO=element
175
+ #
176
+ # Each job self-requeues after perform (default: 6:30am ET next day);
177
+ # running the rake task once on app boot is enough. Override
178
+ # `RemindersSweepJob.next_run` on a subclass to change the cadence.
179
+ #
180
+ # config.reminders_enabled = true
181
+ #
182
+ # Days-since-waiting at which reminders fire. Per-issue override via
183
+ # `issue.metadata.reminder_days = [...]`.
184
+ # config.reminder_days = [1, 3, 7, 10, 14, 18]
185
+ #
186
+ # Days of continuous waiting before the sweep auto-closes the issue
187
+ # (emits `issue.closed_inactive` instead of the regular `issue.closed`).
188
+ # config.inactivity_close_days = 30
189
+ #
190
+ # Label names the gem creates and manages on waiting/inactive issues.
191
+ # config.waiting_on_user_label = 'waiting-on-user'
192
+ # config.waiting_on_approval_label = 'waiting-on-approval'
193
+ # config.user_inactive_label = 'user-inactive'
194
+
195
+ # --------------------------------------------------------------------------
196
+ # Auto-archiving of aged-closed issues
197
+ # --------------------------------------------------------------------------
198
+ # Piggybacks the RemindersSweepJob. For every issue closed more than
199
+ # `archive_closed_after_days` ago (based on GitHub's `closed_at`) the
200
+ # sweep: adds the configured label, locks the conversation, removes
201
+ # the issue from every Projects V2 board, stamps `metadata.archived_at`,
202
+ # and emits `plan_my_stuff.issue.archived` with `reason: :aged_closed`.
203
+ # Issues auto-closed by the inactivity sweep (closed_by_inactivity) are
204
+ # excluded. Non-PMS issues are excluded.
205
+ #
206
+ # config.archiving_enabled = true
207
+ # config.archive_closed_after_days = 90
208
+ # config.archived_label = 'archived'
209
+
210
+ # --------------------------------------------------------------------------
211
+ # AWS webhook (ECS deployments via SNS)
212
+ # --------------------------------------------------------------------------
213
+ # Expected SNS topic ARN for webhook validation.
214
+ # config.sns_topic_arn = 'arn:aws:sns:us-east-1:123456:ecs-deploy-topic'
215
+
216
+ # ECS service identifier - suffix matched against resource ARNs in events.
217
+ # config.aws_service_identifier = 'myapp-production-web'
218
+
219
+ # Commit hash of the currently deploying build. Prefix-matched against
220
+ # issue metadata commit_sha on SERVICE_DEPLOYMENT_COMPLETED events.
221
+ # config.production_commit_sha = Rails.configuration.x.image_tag
222
+
223
+ # Toggle for processing AWS webhook events (default: Rails.env.production?).
224
+ # config.process_aws_webhooks = Rails.env.production?
225
+
226
+ # SNS signature verifier (default: Aws::SNS::MessageVerifier). Must respond
227
+ # to authenticate!(raw_body). Provide aws-sdk-sns in your Gemfile.
228
+ # config.sns_verifier_class = Aws::SNS::MessageVerifier
229
+ # config.sns_verifier_error = Aws::SNS::MessageVerifier::VerificationError
230
+
231
+ # --------------------------------------------------------------------------
232
+ # Caching
233
+ # --------------------------------------------------------------------------
234
+ # ETag-based HTTP caching of GitHub reads via Rails.cache. Defaults to true.
235
+ # config.cache_enabled = true
236
+
237
+ # Opaque version string baked into every PMS cache key. Bump it to invalidate
238
+ # all cached entries from the consuming app's side (e.g. after a deploy).
239
+ # config.cache_version = Rails.configuration.x.image_tag
240
+
241
+ # --------------------------------------------------------------------------
242
+ # Route mounting
243
+ # --------------------------------------------------------------------------
244
+ # Per-group toggles for which engine route groups to mount.
245
+ # config.mount_groups = { webhooks: true, issues: true, projects: true }
246
+
247
+ # --------------------------------------------------------------------------
248
+ # Controller overrides (Devise-style)
249
+ # --------------------------------------------------------------------------
250
+ # Swap in your own controller for any mounted route group. Typical use is
251
+ # to subclass the gem controller and slot the subclass in here:
252
+ #
253
+ # # app/controllers/issues_controller.rb
254
+ # class IssuesController < PlanMyStuff::IssuesController
255
+ # before_action :require_admin
256
+ # end
257
+ #
258
+ # # config/initializers/plan_my_stuff.rb
259
+ # config.controllers = { issues: 'issues' }
260
+ #
261
+ # Unset keys fall back to the gem default.
262
+ #
263
+ # Controllable keys (with gem defaults):
264
+ # :issues => 'plan_my_stuff/issues'
265
+ # :comments => 'plan_my_stuff/comments'
266
+ # :labels => 'plan_my_stuff/labels'
267
+ # :projects => 'plan_my_stuff/projects'
268
+ # :project_items => 'plan_my_stuff/project_items'
269
+ # :testing_projects => 'plan_my_stuff/testing_projects'
270
+ # :testing_project_items => 'plan_my_stuff/testing_project_items'
271
+ # :'issues/closures' => 'plan_my_stuff/issues/closures'
272
+ # :'issues/viewers' => 'plan_my_stuff/issues/viewers'
273
+ # :'issues/takes' => 'plan_my_stuff/issues/takes'
274
+ # :'issues/waitings' => 'plan_my_stuff/issues/waitings'
275
+ # :'issues/links' => 'plan_my_stuff/issues/links'
276
+ # :'issues/approvals' => 'plan_my_stuff/issues/approvals'
277
+ # :'project_items/statuses' => 'plan_my_stuff/project_items/statuses'
278
+ # :'project_items/assignments' => 'plan_my_stuff/project_items/assignments'
279
+ # :'testing_project_items/results' => 'plan_my_stuff/testing_project_items/results'
280
+ # :'webhooks/github' => 'plan_my_stuff/webhooks/github'
281
+ # :'webhooks/aws' => 'plan_my_stuff/webhooks/aws'
115
282
  end