Class: PlanMyStuff::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/plan_my_stuff/configuration.rb

Constant Summary collapse

DEFAULT_CONTROLLERS =

Default controller for each controllable route group. Consuming apps override by assigning values into controllers; lookups go through controller_for which falls back to this table.

Returns:

  • (Hash{Symbol => String})
{
  'issues': 'plan_my_stuff/issues',
  'comments': 'plan_my_stuff/comments',
  'labels': 'plan_my_stuff/labels',
  'projects': 'plan_my_stuff/projects',
  'project_items': 'plan_my_stuff/project_items',
  'testing_projects': 'plan_my_stuff/testing_projects',
  'testing_project_items': 'plan_my_stuff/testing_project_items',
  'issues/closures': 'plan_my_stuff/issues/closures',
  'issues/viewers': 'plan_my_stuff/issues/viewers',
  'issues/takes': 'plan_my_stuff/issues/takes',
  'issues/waitings': 'plan_my_stuff/issues/waitings',
  'issues/links': 'plan_my_stuff/issues/links',
  'issues/approvals': 'plan_my_stuff/issues/approvals',
  'project_items/statuses': 'plan_my_stuff/project_items/statuses',
  'project_items/assignments': 'plan_my_stuff/project_items/assignments',
  'testing_project_items/results': 'plan_my_stuff/testing_project_items/results',
  'webhooks/github': 'plan_my_stuff/webhooks/github',
  'webhooks/aws': 'plan_my_stuff/webhooks/aws',
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfiguration



310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/plan_my_stuff/configuration.rb', line 310

def initialize
  @repos = {}
  @user_class = 'User'
  @display_name_method = :to_s
  @user_id_method = :id
  @support_method = :support?
  @markdown_renderer = :commonmarker
  @markdown_options = {}
  @job_classes = {}
  @custom_fields = {}
  @issue_custom_fields = {}
  @comment_custom_fields = {}
  @project_custom_fields = {}
  @testing_custom_fields = {}
  @pipeline_enabled = true
  @pipeline_statuses = {}
  @main_branch = 'main'
  @production_branch = 'production'
  @mount_groups = { webhooks: true, issues: true, projects: true }
  @controllers = {}
  @cache_enabled = true
  @github_login_for = {}
  @reminders_enabled = true
  @reminder_days = [1, 3, 7, 10, 14, 18].freeze
  @inactivity_close_days = 30
  @waiting_on_user_label = 'waiting-on-user'
  @waiting_on_approval_label = 'waiting-on-approval'
  @user_inactive_label = 'user-inactive'
  @archiving_enabled = true
  @archive_closed_after_days = 90
  @archived_label = 'archived'
  @process_aws_webhooks = Rails.env.production?
  @sns_verifier_class = ::Aws::SNS::MessageVerifier if defined?(::Aws::SNS::MessageVerifier)
  @sns_verifier_error =
    if defined?(::Aws::SNS::MessageVerifier::VerificationError)
      ::Aws::SNS::MessageVerifier::VerificationError
    end
end

Instance Attribute Details

#access_tokenString

Returns GitHub PAT with repo and project scopes. Required.

Returns:

  • (String)

    GitHub PAT with repo and project scopes. Required.



33
34
35
# File 'lib/plan_my_stuff/configuration.rb', line 33

def access_token
  @access_token
end

#app_nameString?

Returns name of the consuming app, stored in metadata (e.g. “Atlas”).

Returns:

  • (String, nil)

    name of the consuming app, stored in metadata (e.g. “Atlas”)



146
147
148
# File 'lib/plan_my_stuff/configuration.rb', line 146

def app_name
  @app_name
end

#archive_closed_after_daysInteger

Days after closed_at at which a non-inactive-closed issue becomes an archive candidate.

Returns:

  • (Integer)


275
276
277
# File 'lib/plan_my_stuff/configuration.rb', line 275

def archive_closed_after_days
  @archive_closed_after_days
end

#archived_labelString

Label name added to archived issues. Also used by the sweep as a skip marker to avoid re-archiving the same issue.

Returns:

  • (String)


282
283
284
# File 'lib/plan_my_stuff/configuration.rb', line 282

def archived_label
  @archived_label
end

#archiving_enabledBoolean

Whether the archive sweep performs any work. Defaults to true. Set to false in apps that don’t want auto-archiving of aged-closed issues.

Returns:

  • (Boolean)


268
269
270
# File 'lib/plan_my_stuff/configuration.rb', line 268

def archiving_enabled
  @archiving_enabled
end

#aws_service_identifierString?

Returns suffix matched against ECS event resource ARNs (e.g. ‘rawr-production-2-web’).

Returns:

  • (String, nil)

    suffix matched against ECS event resource ARNs (e.g. ‘rawr-production-2-web’)



161
162
163
# File 'lib/plan_my_stuff/configuration.rb', line 161

def aws_service_identifier
  @aws_service_identifier
end

#cache_enabledBoolean

Whether to use Rails.cache for ETag-based HTTP caching of GitHub reads. Defaults to true; set to false to bypass the cache entirely.

Returns:

  • (Boolean)


212
213
214
# File 'lib/plan_my_stuff/configuration.rb', line 212

def cache_enabled
  @cache_enabled
end

#cache_versionString?

Opaque app-supplied version string embedded in every PMS cache key. Bumping this string invalidates all cached entries from the consuming app’s side (e.g. after a deploy or schema change). Defaults to nil.

Returns:

  • (String, nil)


220
221
222
# File 'lib/plan_my_stuff/configuration.rb', line 220

def cache_version
  @cache_version
end

#comment_custom_fieldsHash{Symbol => Hash}

Comment-only field definitions, deep-merged on top of shared custom_fields. Context-specific config wins on key conflicts.

Returns:

  • (Hash{Symbol => Hash})


126
127
128
# File 'lib/plan_my_stuff/configuration.rb', line 126

def comment_custom_fields
  @comment_custom_fields
end

#controllersHash{Symbol => String}

Per-route controller overrides. Keys are the controllable route symbols defined in DEFAULT_CONTROLLERS; values are fully-qualified controller paths (e.g. ‘my_app/issues’). Unset keys fall back to the gem default. Consuming apps typically subclass the gem controller to add before_actions or tweak responses, then swap their subclass in here.

Returns:

  • (Hash{Symbol => String})


205
206
207
# File 'lib/plan_my_stuff/configuration.rb', line 205

def controllers
  @controllers
end

#current_userProc?

Fallback actor for notification events when a caller does not pass user:. Set to a proc/lambda that returns the current request user.

Example: config.current_user = -> { Current.user }

Returns:

  • (Proc, nil)


104
105
106
# File 'lib/plan_my_stuff/configuration.rb', line 104

def current_user
  @current_user
end

#custom_fieldsHash{Symbol => Hash}

Shared field definitions stored in issue/comment metadata. Keys are field names, values are hashes with :type and :required. These fields apply to both issues and comments.

Returns:

  • (Hash{Symbol => Hash})


112
113
114
# File 'lib/plan_my_stuff/configuration.rb', line 112

def custom_fields
  @custom_fields
end

#default_project_numberInteger?

Returns default GitHub Projects V2 number for add_to_project calls.

Returns:

  • (Integer, nil)

    default GitHub Projects V2 number for add_to_project calls



42
43
44
# File 'lib/plan_my_stuff/configuration.rb', line 42

def default_project_number
  @default_project_number
end

#default_repoSymbol?

Returns default repo key used when callers omit repo: param.

Returns:

  • (Symbol, nil)

    default repo key used when callers omit repo: param



39
40
41
# File 'lib/plan_my_stuff/configuration.rb', line 39

def default_repo
  @default_repo
end

#display_name_methodSymbol

Returns method called on user object to get display name for comment headers.

Returns:

  • (Symbol)

    method called on user object to get display name for comment headers



54
55
56
# File 'lib/plan_my_stuff/configuration.rb', line 54

def display_name_method
  @display_name_method
end

#github_login_forHash{Object => String}

Hash mapping consuming-app user id to GitHub login. Used by the “Take” UI flow to assign the GitHub user when a support user claims an issue. Keys are whatever config.user_id_method returns on the current user.

Example: config.github_login_for = { 1 => ‘some_username’, 2 => ‘octocat’ }

Returns:

  • (Hash{Object => String})


188
189
190
# File 'lib/plan_my_stuff/configuration.rb', line 188

def 
  @github_login_for
end

#inactivity_close_daysInteger

Days of inactivity after which the sweep auto-closes a waiting issue.

Returns:

  • (Integer)


241
242
243
# File 'lib/plan_my_stuff/configuration.rb', line 241

def inactivity_close_days
  @inactivity_close_days
end

#issue_custom_fieldsHash{Symbol => Hash}

Issue-only field definitions, deep-merged on top of shared custom_fields. Context-specific config wins on key conflicts.

Returns:

  • (Hash{Symbol => Hash})


119
120
121
# File 'lib/plan_my_stuff/configuration.rb', line 119

def issue_custom_fields
  @issue_custom_fields
end

#issues_url_prefixString?

Returns URL prefix for building user-facing ticket URLs in the consuming app.

Returns:

  • (String, nil)

    URL prefix for building user-facing ticket URLs in the consuming app



143
144
145
# File 'lib/plan_my_stuff/configuration.rb', line 143

def issues_url_prefix
  @issues_url_prefix
end

#job_classesHash{Symbol => String}

Map of action type to job class name for deferred requests. Keys: :create_ticket, :post_comment, :update_status.

Returns:

  • (Hash{Symbol => String})


95
96
97
# File 'lib/plan_my_stuff/configuration.rb', line 95

def job_classes
  @job_classes
end

#main_branchString

Returns branch name that PRs merge into for “Ready for release” transition.

Returns:

  • (String)

    branch name that PRs merge into for “Ready for release” transition



174
175
176
# File 'lib/plan_my_stuff/configuration.rb', line 174

def main_branch
  @main_branch
end

#markdown_optionsHash

Default options passed to the markdown renderer. Per-call options in Markdown.render merge on top of these.

For :commonmarker - passed as ‘options:` to `Commonmarker.to_html`

e.g. `{ render: { hardbreaks: true } }`

For :redcarpet - :render_options and :renderer are extracted for the HTML renderer;

remaining keys are passed as extensions to `Redcarpet::Markdown.new`
e.g. `{ render_options: { hard_wrap: true, no_styles: true }, autolink: true }`

Returns:

  • (Hash)


81
82
83
# File 'lib/plan_my_stuff/configuration.rb', line 81

def markdown_options
  @markdown_options
end

#markdown_rendererSymbol

Returns which markdown gem to use: :commonmarker or :redcarpet.

Returns:

  • (Symbol)

    which markdown gem to use: :commonmarker or :redcarpet



67
68
69
# File 'lib/plan_my_stuff/configuration.rb', line 67

def markdown_renderer
  @markdown_renderer
end

#mount_groupsHash{Symbol => Boolean}

Per-group route mounting toggles. Keys: :webhooks, :issues, :projects. Set a key to false to skip mounting that route group.

Returns:

  • (Hash{Symbol => Boolean})


195
196
197
# File 'lib/plan_my_stuff/configuration.rb', line 195

def mount_groups
  @mount_groups
end

#organizationString

Returns GitHub organization name. Required.

Returns:

  • (String)

    GitHub organization name. Required.



36
37
38
# File 'lib/plan_my_stuff/configuration.rb', line 36

def organization
  @organization
end

#pipeline_enabledBoolean

Returns whether the release pipeline feature is enabled.

Returns:

  • (Boolean)

    whether the release pipeline feature is enabled



149
150
151
# File 'lib/plan_my_stuff/configuration.rb', line 149

def pipeline_enabled
  @pipeline_enabled
end

#pipeline_project_numberInteger?

Returns GitHub Projects V2 number for the pipeline board (falls back to default_project_number).

Returns:

  • (Integer, nil)

    GitHub Projects V2 number for the pipeline board (falls back to default_project_number)



152
153
154
# File 'lib/plan_my_stuff/configuration.rb', line 152

def pipeline_project_number
  @pipeline_project_number
end

#pipeline_statusesHash{String => String}

Canonical status name to display alias map. Allows consuming apps to rename pipeline statuses (e.g. “Submitted” to “Triaged”).

Returns:

  • (Hash{String => String})


171
172
173
# File 'lib/plan_my_stuff/configuration.rb', line 171

def pipeline_statuses
  @pipeline_statuses
end

#process_aws_webhooksBoolean

Whether to process incoming AWS webhook events. Defaults to Rails.env.production?.

Returns:

  • (Boolean)


288
289
290
# File 'lib/plan_my_stuff/configuration.rb', line 288

def process_aws_webhooks
  @process_aws_webhooks
end

#production_branchString

Returns branch name that triggers deployment when a PR merges.

Returns:

  • (String)

    branch name that triggers deployment when a PR merges



177
178
179
# File 'lib/plan_my_stuff/configuration.rb', line 177

def production_branch
  @production_branch
end

#production_commit_shaString?

Returns commit hash of the deploying build, prefix-matched against issue metadata commit_sha.

Returns:

  • (String, nil)

    commit hash of the deploying build, prefix-matched against issue metadata commit_sha



164
165
166
# File 'lib/plan_my_stuff/configuration.rb', line 164

def production_commit_sha
  @production_commit_sha
end

#project_custom_fieldsHash{Symbol => Hash}

Project-only field definitions, deep-merged on top of shared custom_fields. Context-specific config wins on key conflicts.

Returns:

  • (Hash{Symbol => Hash})


133
134
135
# File 'lib/plan_my_stuff/configuration.rb', line 133

def project_custom_fields
  @project_custom_fields
end

#reminder_daysArray<Integer>

Days-since-waiting at which reminder events fire. Per-issue override via metadata.reminder_days.

Returns:

  • (Array<Integer>)


235
236
237
# File 'lib/plan_my_stuff/configuration.rb', line 235

def reminder_days
  @reminder_days
end

#reminders_enabledBoolean

Whether the reminders sweep performs any work. Defaults to true. Set to false in apps that don’t want follow-up reminders or inactivity auto-close.

Returns:

  • (Boolean)


228
229
230
# File 'lib/plan_my_stuff/configuration.rb', line 228

def reminders_enabled
  @reminders_enabled
end

#reposHash{Symbol => String} (readonly)

Named repo configs. Set via config.repos = ‘BrandsInsurance/Element’.

Returns:

  • (Hash{Symbol => String})


307
308
309
# File 'lib/plan_my_stuff/configuration.rb', line 307

def repos
  @repos
end

#should_send_requestProc?

Proc returning boolean, or nil (always send). When it returns false the request is deferred to a background job instead of hitting GitHub.

Returns:

  • (Proc, nil)


88
89
90
# File 'lib/plan_my_stuff/configuration.rb', line 88

def should_send_request
  @should_send_request
end

#sns_topic_arnString?

Returns expected SNS topic ARN for AWS webhook validation.

Returns:

  • (String, nil)

    expected SNS topic ARN for AWS webhook validation



158
159
160
# File 'lib/plan_my_stuff/configuration.rb', line 158

def sns_topic_arn
  @sns_topic_arn
end

#sns_verifier_classClass

Class instantiated per request for SNS signature verification. Must respond to authenticate!(raw_body).

Returns:

  • (Class)


295
296
297
# File 'lib/plan_my_stuff/configuration.rb', line 295

def sns_verifier_class
  @sns_verifier_class
end

#sns_verifier_errorClass

Exception class rescued during SNS signature verification.

Returns:

  • (Class)


301
302
303
# File 'lib/plan_my_stuff/configuration.rb', line 301

def sns_verifier_error
  @sns_verifier_error
end

#support_methodSymbol, Proc

Determines if a user is support staff. Symbol (method name on user) or Proc that receives the user object and returns boolean.

Returns:

  • (Symbol, Proc)


64
65
66
# File 'lib/plan_my_stuff/configuration.rb', line 64

def support_method
  @support_method
end

#testing_custom_fieldsHash{Symbol => Hash}

Testing-project-only field definitions, deep-merged on top of shared custom_fields. Context-specific config wins on key conflicts.

Returns:

  • (Hash{Symbol => Hash})


140
141
142
# File 'lib/plan_my_stuff/configuration.rb', line 140

def testing_custom_fields
  @testing_custom_fields
end

#testing_template_project_numberInteger?

when creating new TestingProjects. When set, TestingProject.create! copies the template (preserving its fields and board layout) instead of bootstrapping fields from scratch. Leave nil to use the default bootstrap-fields path.

Returns:

  • (Integer, nil)

    GitHub Projects V2 number of the template project to clone



48
49
50
# File 'lib/plan_my_stuff/configuration.rb', line 48

def testing_template_project_number
  @testing_template_project_number
end

#user_classString

Returns consuming app’s user model class name, constantized for lookups.

Returns:

  • (String)

    consuming app’s user model class name, constantized for lookups



51
52
53
# File 'lib/plan_my_stuff/configuration.rb', line 51

def user_class
  @user_class
end

#user_id_methodSymbol

Returns method called on user object to extract the app-side user ID.

Returns:

  • (Symbol)

    method called on user object to extract the app-side user ID



57
58
59
# File 'lib/plan_my_stuff/configuration.rb', line 57

def user_id_method
  @user_id_method
end

#user_inactive_labelString

Label name applied to issues auto-closed by the inactivity sweep. Removed when an issue is auto-reopened via a user reply.

Returns:

  • (String)


260
261
262
# File 'lib/plan_my_stuff/configuration.rb', line 260

def user_inactive_label
  @user_inactive_label
end

#waiting_on_approval_labelString

Label name used to flag issues waiting on pending approvals.

Returns:

  • (String)


253
254
255
# File 'lib/plan_my_stuff/configuration.rb', line 253

def waiting_on_approval_label
  @waiting_on_approval_label
end

#waiting_on_user_labelString

Label name used to flag issues waiting on an end-user reply.

Returns:

  • (String)


247
248
249
# File 'lib/plan_my_stuff/configuration.rb', line 247

def waiting_on_user_label
  @waiting_on_user_label
end

#webhook_secretString?

Returns HMAC secret for GitHub webhook signature verification (required when webhooks mounted).

Returns:

  • (String, nil)

    HMAC secret for GitHub webhook signature verification (required when webhooks mounted)



155
156
157
# File 'lib/plan_my_stuff/configuration.rb', line 155

def webhook_secret
  @webhook_secret
end

Instance Method Details

#authenticate_with(&block) ⇒ void

This method returns an undefined value.

Sets the authentication block for engine controllers.



353
354
355
356
357
358
359
# File 'lib/plan_my_stuff/configuration.rb', line 353

def authenticate_with(&block)
  if block
    @authenticate_with = block
  else
    @authenticate_with
  end
end

#controller_for(key) ⇒ String

Returns the controller path for the given route group, preferring a consuming-app override from controllers and falling back to the gem default from DEFAULT_CONTROLLERS. The returned value always begins with ‘/’ so the isolated engine does not re-prefix it with plan_my_stuff/.

Parameters:

  • key (Symbol)

Returns:

  • (String)

Raises:

  • (KeyError)

    if key is not a controllable route group



412
413
414
415
# File 'lib/plan_my_stuff/configuration.rb', line 412

def controller_for(key)
  path = controllers[key] || DEFAULT_CONTROLLERS.fetch(key)
  path.start_with?('/') ? path : "/#{path}"
end

#custom_fields_for(context) ⇒ Hash{Symbol => Hash}

Returns the merged custom fields schema for the given context. Context-specific fields deep-merge on top of shared fields.

Parameters:

  • context (Symbol)

    :issue or :comment

Returns:

  • (Hash{Symbol => Hash})


387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/plan_my_stuff/configuration.rb', line 387

def custom_fields_for(context)
  context_fields =
    case context
    when :issue then issue_custom_fields
    when :comment then comment_custom_fields
    when :project then project_custom_fields
    when :testing then testing_custom_fields
    else {}
    end

  custom_fields.deep_merge(context_fields)
end

#validate!void

This method returns an undefined value.

Validates that required configuration options are set.

Raises:



367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/plan_my_stuff/configuration.rb', line 367

def validate!
  missing = []
  missing << 'access_token' if access_token.nil? || access_token.to_s.strip.empty?
  missing << 'organization' if organization.nil? || organization.to_s.strip.empty?

  return if missing.empty?

  raise(
    ConfigurationError,
    "Missing required PlanMyStuff configuration: #{missing.join(', ')}",
  )
end