plan_my_stuff 0.10.2 → 0.10.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35e23ebdd170bd3c29874da833e2fed058b04319ce5d0441daf0e7837e9ef2d7
4
- data.tar.gz: 5f1387007a2be2ef848420257f7ba9887dc6118a358b8aefd6ce36fb146057f0
3
+ metadata.gz: ce0e2f02e6063ab2fe3238671d06182fc5447f428e6dc01d336ba6e00379e86a
4
+ data.tar.gz: f80f58ce32e19ea6e7b8aca34a62110379e6ea65f10c943fd108c409ec50a669
5
5
  SHA512:
6
- metadata.gz: 69f11b3b68728cc78cc32b0f9abe0516daae40f888c4feba2bd5b813e4fcb5501f2d628548ae6413da2712dd00007a278c215a18d1ce360150e8ca99a56014ff
7
- data.tar.gz: 3d490025bd4edc8179868b6cb88adaf2a6c3c555f342532f4db603c37d1d397f89133a470871b7807b53875c5b737cb0bcc1b64a7e8bb5ad38ddc19e775c588d
6
+ metadata.gz: 3aaf1478091d45cbf8caa72a8a0f14b6cc445c5ec7c17382b92d50bb593d36b04ab00ade2973b2e8c67e19b3dfe1b7841022a9f336da2fe7ba3d27ea6c6b7eb5
7
+ data.tar.gz: 680bbb80160eaa20b20c05d4585e167e143c5be6c4735869bf8d138605cd11a52bacc1f3564cc6b8ea57e772b13aa22bdc7cd720c8254f5cf576c3207b15826e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.10.5
4
+
5
+ ### Added
6
+
7
+ - `config.parent_controller` (default `'::ApplicationController'`) lets consuming apps that don't use the
8
+ `ApplicationController` name (e.g. `ActionController::Base`, `RawrApplicationController`) tell the engine
9
+ what to inherit from. The `plan_my_stuff:verify` rake task now reports whether the configured class
10
+ resolves.
11
+
12
+ ### Fixed
13
+
14
+ - Example config option showed `url_options = Rails.application.config.action_mailer.default_url_options`. Now it shows
15
+ `url_options = Rails.application.routes.default_url_options`
16
+
17
+ ## 0.10.4
18
+
19
+ ### Changed
20
+
21
+ - Internal: unit specs now use VCR cassettes against `BrandsInsurance/ubiquitous-adventure` instead of
22
+ `instance_double(Octokit::Client)`. No effect on consuming apps.
23
+
24
+ ### Removed
25
+
26
+ - ETag caching on `Issue.list`. The cache key included `state`, `labels`, `page`, and `per_page`,
27
+ so an etag stored under one combo never matched a request with different params - the cache wrote
28
+ on every call and effectively never hit. `Issue.list` now always issues a fresh GitHub request.
29
+ `Comment.list` keeps ETag caching (param surface is just `issue` + `pms_only`).
30
+ `PlanMyStuff::Cache.read_list` / `write_list` remain available for `Comment.list`.
31
+
32
+ ## 0.10.3
33
+
34
+ ### Added
35
+
36
+ - `BaseProjectItem#assignees` returns the GitHub logins of users assigned to the underlying Issue,
37
+ PullRequest, or DraftIssue. Populated from the `FIND_PROJECT` GraphQL response (the query was extended
38
+ with `assignees(first: 10)` on each content fragment).
39
+
3
40
  ## 0.10.2
4
41
 
5
42
  ### Changed
data/CONFIGURATION.md CHANGED
@@ -67,7 +67,7 @@ config.testing_template_project_number = 42
67
67
  ```ruby
68
68
  config.app_name = 'MyApp'
69
69
 
70
- url_options = Rails.application.config.action_mailer.default_url_options
70
+ url_options = Rails.application.routes.default_url_options
71
71
  config.issues_url_prefix = "#{url_options[:protocol] || 'http'}://#{url_options[:host]}/issues"
72
72
  ```
73
73
 
@@ -349,3 +349,16 @@ Controllable keys (with gem defaults):
349
349
  | `:'testing_project_items/results'` | `plan_my_stuff/testing_project_items/results` |
350
350
  | `:'webhooks/github'` | `plan_my_stuff/webhooks/github` |
351
351
  | `:'webhooks/aws'` | `plan_my_stuff/webhooks/aws` |
352
+
353
+ ### Parent controller
354
+
355
+ | Option | Type | Default | Description |
356
+ |---|---|---|---|
357
+ | `parent_controller` | `String` | `'::ApplicationController'` | Parent of `PlanMyStuff::ApplicationController`. |
358
+
359
+ Set this in `config/initializers/plan_my_stuff.rb`; Rails resolves the superclass once at class definition, so the
360
+ value must be set before the engine's controllers load.
361
+
362
+ ```ruby
363
+ config.parent_controller = 'RawrApplicationController'
364
+ ```
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PlanMyStuff
4
- class ApplicationController < ::ApplicationController
4
+ class ApplicationController < PlanMyStuff.configuration.parent_controller.constantize
5
5
  protect_from_forgery with: :exception
6
6
  helper Rails.application.routes.url_helpers
7
7
 
@@ -101,7 +101,7 @@ PlanMyStuff.configure do |config|
101
101
  # number is appended to form `Issue#user_link`, which the gem also
102
102
  # writes as the visible body of the GitHub issue.
103
103
  # Recommended default:
104
- # url_options = Rails.application.config.action_mailer.default_url_options
104
+ # url_options = Rails.application.routes.default_url_options
105
105
  # config.issues_url_prefix =
106
106
  # "#{url_options[:protocol] || 'http'}://#{url_options[:host]}/issues"
107
107
 
@@ -321,4 +321,11 @@ PlanMyStuff.configure do |config|
321
321
  # :'testing_project_items/results' => 'plan_my_stuff/testing_project_items/results'
322
322
  # :'webhooks/github' => 'plan_my_stuff/webhooks/github'
323
323
  # :'webhooks/aws' => 'plan_my_stuff/webhooks/aws'
324
+
325
+ # --------------------------------------------------------------------------
326
+ # Parent controller
327
+ # --------------------------------------------------------------------------
328
+ # Parent class for PlanMyStuff::ApplicationController. Override when the
329
+ # consuming app does not use the `ApplicationController` name.
330
+ # config.parent_controller = 'MyOtherApplicationController'
324
331
  end
@@ -129,6 +129,7 @@ module PlanMyStuff
129
129
  content = item[:content] || {}
130
130
  field_values = item.dig(:fieldValues, :nodes) || []
131
131
  repo_name = content.dig(:repository, :nameWithOwner)
132
+ assignee_nodes = content.dig(:assignees, :nodes) || []
132
133
 
133
134
  {
134
135
  id: item[:id],
@@ -142,6 +143,7 @@ module PlanMyStuff
142
143
  repo: repo_name.present? ? PlanMyStuff::Repo.resolve!(repo_name) : nil,
143
144
  status: extract_item_status(field_values),
144
145
  field_values: parse_field_values(field_values),
146
+ assignees: assignee_nodes.pluck(:login).compact,
145
147
  updated_at: item[:updatedAt],
146
148
  github_response: item,
147
149
  }
@@ -168,7 +170,7 @@ module PlanMyStuff
168
170
  field_name = fv.dig(:field, :name)
169
171
  next unless field_name
170
172
 
171
- value = fv[:name] || fv[:text]
173
+ value = fv[:name] || fv[:text] || fv[:date]&.to_date
172
174
  users_node = fv[:users]
173
175
  if users_node
174
176
  value = (users_node[:nodes] || []).map { |u| u[:login] }
@@ -46,6 +46,8 @@ module PlanMyStuff
46
46
  attribute :updated_at, :datetime
47
47
  # @return [Hash]
48
48
  attribute :field_values, default: -> { {} }
49
+ # @return [Array<String>] GitHub logins assigned to the underlying Issue, PullRequest, or DraftIssue
50
+ attribute :assignees, default: -> { [] }
49
51
  # @return [PlanMyStuff::BaseProject, nil]
50
52
  attribute :project
51
53
  # @return [PlanMyStuff::Issue, nil] linked issue (nil for draft items)
@@ -75,6 +77,7 @@ module PlanMyStuff
75
77
  status: item_hash[:status],
76
78
  updated_at: item_hash[:updated_at],
77
79
  field_values: item_hash[:field_values] || {},
80
+ assignees: item_hash[:assignees] || [],
78
81
  project: project,
79
82
  )
80
83
 
@@ -227,6 +227,16 @@ module PlanMyStuff
227
227
  #
228
228
  attr_accessor :controllers
229
229
 
230
+ # Parent class string for +PlanMyStuff::ApplicationController+. Defaults to +'::ApplicationController'+. Override
231
+ # when the consuming app does not use the +ApplicationController+ name (e.g. +'ActionController::Base'+,
232
+ # +'RawrApplicationController'+). Must be set before the gem's controllers load - the standard
233
+ # +config/initializers/plan_my_stuff.rb+ location is correct, since Rails resolves the superclass once at class
234
+ # definition time.
235
+ #
236
+ # @return [String]
237
+ #
238
+ attr_accessor :parent_controller
239
+
230
240
  # Whether to use Rails.cache for ETag-based HTTP caching of GitHub reads. Defaults to true; set to false to bypass
231
241
  # the cache entirely.
232
242
  #
@@ -361,6 +371,7 @@ module PlanMyStuff
361
371
  @production_branch = 'production'
362
372
  @mount_groups = { webhooks: true, issues: true, projects: true }
363
373
  @controllers = {}
374
+ @parent_controller = '::ApplicationController'
364
375
  @cache_enabled = true
365
376
  @github_login_for = {}
366
377
  @reminders_enabled = true
@@ -63,7 +63,7 @@ module PlanMyStuff
63
63
  }
64
64
  GRAPHQL
65
65
 
66
- FIND_PROJECT = <<~GRAPHQL
66
+ FIND_PROJECT = <<~GRAPHQL.freeze
67
67
  query($org: String!, $number: Int!, $cursor: String) {
68
68
  organization(login: $org) {
69
69
  projectV2(number: $number) {
@@ -95,7 +95,7 @@ module PlanMyStuff
95
95
  }
96
96
  }
97
97
  }
98
- items(first: 100, after: $cursor) {
98
+ items(first: #{PlanMyStuff::BaseProject::ITEMS_PER_PAGE}, after: $cursor) {
99
99
  pageInfo {
100
100
  hasNextPage
101
101
  endCursor
@@ -112,6 +112,7 @@ module PlanMyStuff
112
112
  url
113
113
  state
114
114
  repository { nameWithOwner }
115
+ assignees(first: 10) { nodes { login } }
115
116
  }
116
117
  ... on PullRequest {
117
118
  id
@@ -120,11 +121,13 @@ module PlanMyStuff
120
121
  url
121
122
  state
122
123
  repository { nameWithOwner }
124
+ assignees(first: 10) { nodes { login } }
123
125
  }
124
126
  ... on DraftIssue {
125
127
  id
126
128
  title
127
129
  body
130
+ assignees(first: 10) { nodes { login } }
128
131
  }
129
132
  }
130
133
  fieldValues(first: 20) {
@@ -145,6 +148,14 @@ module PlanMyStuff
145
148
  }
146
149
  }
147
150
  }
151
+ ... on ProjectV2ItemFieldDateValue {
152
+ date
153
+ field {
154
+ ... on ProjectV2Field {
155
+ name
156
+ }
157
+ }
158
+ }
148
159
  ... on ProjectV2ItemFieldUserValue {
149
160
  users(first: 10) {
150
161
  nodes {
@@ -290,17 +290,8 @@ module PlanMyStuff
290
290
  params = { state: state.to_s, page: page, per_page: per_page }
291
291
  params[:labels] = labels.sort.join(',') if labels.present?
292
292
 
293
- cached = PlanMyStuff::Cache.read_list(:issue, resolved_repo, params)
294
- request_options = cached ? params.merge(headers: { 'If-None-Match' => cached[:etag] }) : params
295
-
296
- github_issues = client.rest(:list_issues, resolved_repo, **request_options)
297
-
298
- if cached && not_modified?(client)
299
- return cached[:body].map { |gi| build(gi, repo: resolved_repo) }
300
- end
301
-
293
+ github_issues = client.rest(:list_issues, resolved_repo, **params)
302
294
  filtered = github_issues.reject { |gi| gi.respond_to?(:pull_request) && gi.pull_request }
303
- store_list_etag_to_cache(client, :issue, resolved_repo, params, filtered)
304
295
  filtered.map { |gi| build(gi, repo: resolved_repo) }
305
296
  end
306
297
 
@@ -3,17 +3,25 @@
3
3
  require 'plan_my_stuff'
4
4
 
5
5
  module PlanMyStuff
6
- # Test support for consuming apps. Provides:
6
+ # Test support for apps that *consume* PlanMyStuff. Provides:
7
7
  # - `PlanMyStuff.test_mode!` to stub all API calls
8
8
  # - Factory-style builders: `build_issue`, `build_comment`, `build_project`
9
9
  # - RSpec matchers: `expect_pms_issue_created`, `expect_pms_comment_created`, `expect_pms_item_moved`
10
10
  #
11
- # Usage:
11
+ # Usage (in a consuming Rails app):
12
12
  # require 'plan_my_stuff/test_helpers'
13
13
  #
14
14
  # RSpec.configure do |config|
15
15
  # config.include PlanMyStuff::TestHelpers
16
16
  # end
17
+ #
18
+ # Not the harness for PlanMyStuff's own unit specs. Gem-internal specs go
19
+ # through VCR cassettes against a real GitHub sandbox (see `spec/support/vcr.rb`
20
+ # and the `:pms_vcr_configured` shared context). Calling `PlanMyStuff.test_mode!`
21
+ # inside the gem would monkey-patch the very class methods the cassettes were
22
+ # recorded against, defeating the VCR coverage. The builder utilities
23
+ # (`build_issue`, `build_comment`, `build_project`, `stub_approvals`) are safe
24
+ # to use inside the gem as plain factories - they don't replace any methods.
17
25
  module TestHelpers
18
26
  # Recorded actions during test mode, keyed by type:
19
27
  # :issue_created, :comment_created, :item_moved
@@ -23,6 +23,7 @@ module PlanMyStuff
23
23
  check_organization
24
24
  check_repos
25
25
  check_default_project
26
+ check_parent_controller
26
27
  self
27
28
  end
28
29
 
@@ -80,6 +81,15 @@ module PlanMyStuff
80
81
  @results << Result.new("Repo :#{key}", false, "#{full_name}: #{e.message}")
81
82
  end
82
83
 
84
+ # @return [void]
85
+ def check_parent_controller
86
+ parent = PlanMyStuff.configuration.parent_controller.to_s
87
+ klass = parent.constantize
88
+ @results << Result.new('Parent controller', true, "#{parent} resolved to #{klass}")
89
+ rescue NameError => e
90
+ @results << Result.new('Parent controller', false, "#{parent.inspect}: #{e.message}")
91
+ end
92
+
83
93
  # @return [void]
84
94
  def check_default_project
85
95
  project_number = PlanMyStuff.configuration.default_project_number
@@ -4,7 +4,7 @@ module PlanMyStuff
4
4
  module VERSION
5
5
  MAJOR = 0
6
6
  MINOR = 10
7
- TINY = 2
7
+ TINY = 5
8
8
 
9
9
  # Set PRE to nil unless it's a pre-release (beta, rc, etc.)
10
10
  PRE = nil
@@ -193,6 +193,32 @@ namespace :plan_my_stuff do
193
193
  end
194
194
  end
195
195
 
196
+ desc 'Print all GitHub primary rate-limit buckets for the configured token. ' \
197
+ 'Note: secondary/abuse limits and content-creation limits are NOT surfaced by GitHub ' \
198
+ 'until you hit them, so a healthy report here does not guarantee writes will succeed.'
199
+ task rate_limit: :environment do
200
+ data = PlanMyStuff.client.rest(:get, '/rate_limit').to_h
201
+ resources = data[:resources] || {}
202
+
203
+ width = resources.keys.map { |k| k.to_s.length }.max || 0
204
+ resources.sort.each do |name, bucket|
205
+ next if bucket[:used].zero?
206
+
207
+ reset_at = Time.at(bucket[:reset]).utc
208
+ reset_in = [bucket[:reset] - Time.now.to_i, 0].max
209
+ puts(format(
210
+ '%-*s used=%-5d remaining=%-5d limit=%-5d resets_at=%s (in %ds)',
211
+ width,
212
+ name,
213
+ bucket[:used],
214
+ bucket[:remaining],
215
+ bucket[:limit],
216
+ reset_at.iso8601,
217
+ reset_in,
218
+ ))
219
+ end
220
+ end
221
+
196
222
  desc 'Verify PlanMyStuff configuration: token, org, repos, and project access'
197
223
  task verify: :environment do
198
224
  require 'plan_my_stuff/verifier'
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plan_my_stuff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ version: 0.10.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brands Insurance
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2026-05-13 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: rails
@@ -43,6 +44,7 @@ dependencies:
43
44
  - - "~>"
44
45
  - !ruby/object:Gem::Version
45
46
  version: 10.0.0
47
+ description:
46
48
  email:
47
49
  - documents@brandsinsurance.com
48
50
  executables: []
@@ -206,7 +208,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
206
208
  - !ruby/object:Gem::Version
207
209
  version: '0'
208
210
  requirements: []
209
- rubygems_version: 4.0.6
211
+ rubygems_version: 3.5.11
212
+ signing_key:
210
213
  specification_version: 4
211
214
  summary: Shared PMS
212
215
  test_files: []