entitlements-github-plugin 1.0.0 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 693affbe3d5a82f2de418c8d892e3348543de2b11ade01021c5d70e1604e7737
4
- data.tar.gz: a1275a50c6e8c02b9394b4198f88aeb8a2fe5916182e02784c32ea81ef095a97
3
+ metadata.gz: 4907f4cd71ba69a500d3d7da6bd1e27407d55777e1e83ec1bc9ab7278fdaa744
4
+ data.tar.gz: 8cd6c1023daa722e97c0d54ccba07568ff9e86749be83089da54077c0a94ba70
5
5
  SHA512:
6
- metadata.gz: 1a1da49e107045a502174d53e751fba158fe76712d2f777027b12648f9587cdfef265fcfef65228a03f7ce426d0ceaa6d10b58d74628ed2f2f7f9b07f6cdf483
7
- data.tar.gz: 98bf9fbf07473e4cf09da1a2d44433ff7801a52fd7073e8e5042a33fb15438f11a88647d1c71fbb4c893a0219ae209d4089d621e48619d4839562057af9ba0de
6
+ metadata.gz: fab3df5745d25dfc4d89b4c9ee78fb9a0a320b23b3ae6d009ed0efa13b7298118b5ee588c11133396487a477dc94cbe5ddd495fa03e94678e9080c18d3f64990
7
+ data.tar.gz: c2e481dbb6807564dc7fc7619ecf31b5adf9fd245e54ed7613d8418b90ca83f98080a6be1a4d7d4060ea3af6c1696575cadd2f08237ab7c4a6ada4880e695268
@@ -46,7 +46,9 @@ module Entitlements
46
46
  Entitlements.logger.debug "#{identifier} add_user_to_organization(user=#{user}, org=#{org}, role=#{role})"
47
47
 
48
48
  begin
49
- new_membership = octokit.update_organization_membership(org, user:, role:)
49
+ new_membership = Retryable.with_context(:default, not: [Octokit::NotFound]) do
50
+ octokit.update_organization_membership(org, user:, role:)
51
+ end
50
52
  rescue Octokit::NotFound => e
51
53
  raise e unless ignore_not_found
52
54
 
@@ -78,7 +80,10 @@ module Entitlements
78
80
  Contract String => C::Bool
79
81
  def remove_user_from_organization(user)
80
82
  Entitlements.logger.debug "#{identifier} remove_user_from_organization(user=#{user}, org=#{org})"
81
- result = octokit.remove_organization_membership(org, user:)
83
+
84
+ result = Retryable.with_context(:default) do
85
+ octokit.remove_organization_membership(org, user:)
86
+ end
82
87
 
83
88
  # If we removed the user, remove them from the cache of members, so that any GitHub team
84
89
  # operations in this organization will ignore this user.
@@ -24,3 +24,5 @@ end
24
24
  require_relative "github_org/controller"
25
25
  require_relative "github_org/provider"
26
26
  require_relative "github_org/service"
27
+ require_relative "../config/retry"
28
+ Retry.setup!
@@ -279,10 +279,12 @@ module Entitlements
279
279
  team_options[:parent_team_id] = parent_team_data[:team_id]
280
280
  rescue TeamNotFound
281
281
  # if the parent team does not exist, create it (think `mkdir -p` logic here)
282
- result = octokit.create_team(
283
- org,
284
- { name: entitlement_metadata["parent_team_name"], repo_names: [], privacy: "closed" }
285
- )
282
+ result = Retryable.with_context(:default, not: [Octokit::UnprocessableEntity]) do
283
+ octokit.create_team(
284
+ org,
285
+ { name: entitlement_metadata["parent_team_name"], repo_names: [], privacy: "closed" }
286
+ )
287
+ end
286
288
 
287
289
  Entitlements.logger.debug "created parent team #{entitlement_metadata["parent_team_name"]} with id #{result[:id]}"
288
290
 
@@ -296,7 +298,11 @@ module Entitlements
296
298
  end
297
299
 
298
300
  Entitlements.logger.debug "create_team(team=#{team_name})"
299
- result = octokit.create_team(org, team_options)
301
+
302
+ result = Retryable.with_context(:default, not: [Octokit::UnprocessableEntity]) do
303
+ octokit.create_team(org, team_options)
304
+ end
305
+
300
306
  Entitlements.logger.debug "created team #{team_name} with id #{result[:id]}"
301
307
  true
302
308
  rescue Octokit::UnprocessableEntity => e
@@ -317,7 +323,10 @@ module Entitlements
317
323
  Entitlements.logger.debug "update_team(team=#{team.team_name})"
318
324
  options = { name: team.team_name, repo_names: [], privacy: "closed",
319
325
  parent_team_id: metadata[:parent_team_id] }
320
- octokit.update_team(team.team_id, options)
326
+ Retryable.with_context(:default, not: [Octokit::UnprocessableEntity]) do
327
+ octokit.update_team(team.team_id, options)
328
+ end
329
+
321
330
  true
322
331
  rescue Octokit::UnprocessableEntity => e
323
332
  Entitlements.logger.debug "update_team(team=#{team.team_name}) ERROR - #{e.message}"
@@ -334,7 +343,9 @@ module Entitlements
334
343
  team_name: String
335
344
  ] => Sawyer::Resource
336
345
  def team_by_name(org_name:, team_name:)
337
- octokit.team_by_name(org_name, team_name)
346
+ Retryable.with_context(:default) do
347
+ octokit.team_by_name(org_name, team_name)
348
+ end
338
349
  end
339
350
 
340
351
  private
@@ -426,7 +437,10 @@ module Entitlements
426
437
  @validation_cache ||= {}
427
438
  @validation_cache[team_id] ||= begin
428
439
  Entitlements.logger.debug "validate_team_id_and_slug!(#{team_id}, #{team_slug.inspect})"
429
- team_data = octokit.team(team_id)
440
+ team_data = Retryable.with_context(:default) do
441
+ octokit.team(team_id)
442
+ end
443
+
430
444
  team_data[:slug]
431
445
  end
432
446
  return if @validation_cache[team_id] == team_slug
@@ -457,8 +471,16 @@ module Entitlements
457
471
  validate_team_id_and_slug!(team.team_id, team.team_name)
458
472
 
459
473
  begin
460
- result = octokit.add_team_membership(team.team_id, user, role:)
474
+ result = Retryable.with_context(:default, not: [Octokit::UnprocessableEntity, Octokit::NotFound]) do
475
+ octokit.add_team_membership(team.team_id, user, role:)
476
+ end
477
+
461
478
  result[:state] == "active" || result[:state] == "pending"
479
+ rescue Octokit::UnprocessableEntity => e
480
+ raise e unless ignore_not_found && e.message =~ /Enterprise Managed Users must be part of the organization to be assigned to the team/
481
+
482
+ Entitlements.logger.warn "User #{user} not found in organization #{org}, ignoring."
483
+ false
462
484
  rescue Octokit::NotFound => e
463
485
  raise e unless ignore_not_found
464
486
 
@@ -482,7 +504,10 @@ module Entitlements
482
504
 
483
505
  Entitlements.logger.debug "#{identifier} remove_user_from_team(user=#{user}, org=#{org}, team_id=#{team.team_id})"
484
506
  validate_team_id_and_slug!(team.team_id, team.team_name)
485
- octokit.remove_team_membership(team.team_id, user)
507
+
508
+ Retryable.with_context(:default) do
509
+ octokit.remove_team_membership(team.team_id, user)
510
+ end
486
511
  end
487
512
  end
488
513
  end
@@ -4,3 +4,5 @@ require_relative "github_team/controller"
4
4
  require_relative "github_team/models/team"
5
5
  require_relative "github_team/provider"
6
6
  require_relative "github_team/service"
7
+ require_relative "../config/retry"
8
+ Retry.setup!
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "retryable"
4
+
5
+ module Retry
6
+ # This method should be called as early as possible in the startup of your application
7
+ # It sets up the Retryable gem with custom contexts and passes through a few options
8
+ # Should the number of retries be reached without success, the last exception will be raised
9
+ def self.setup!
10
+ ######## Retryable Configuration ########
11
+ # All defaults available here:
12
+ # https://github.com/nfedyashev/retryable/blob/6a04027e61607de559e15e48f281f3ccaa9750e8/lib/retryable/configuration.rb#L22-L33
13
+ Retryable.configure do |config|
14
+ config.contexts[:default] = {
15
+ on: [StandardError],
16
+ sleep: 1,
17
+ tries: 3
18
+ }
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../config/retry"
4
+
3
5
  require "net/http"
4
6
  require "octokit"
5
7
  require "uri"
@@ -36,6 +38,9 @@ module Entitlements
36
38
  ignore_not_found: C::Maybe[C::Bool],
37
39
  ] => C::Any
38
40
  def initialize(addr: nil, org:, token:, ou:, ignore_not_found: false)
41
+ # init the retry module
42
+ Retry.setup!
43
+
39
44
  # Save some parameters for the connection but don't actually connect yet.
40
45
  @addr = addr
41
46
  @org = org
@@ -94,7 +99,10 @@ module Entitlements
94
99
  # Returns true if the github instance is an enterprise server instance
95
100
  Contract C::None => C::Bool
96
101
  def enterprise?
97
- meta = octokit.github_meta
102
+ meta = Retryable.with_context(:default) do
103
+ octokit.github_meta
104
+ end
105
+
98
106
  meta.key? :installed_version
99
107
  end
100
108
 
@@ -163,6 +171,7 @@ module Entitlements
163
171
  client = Octokit::Client.new(access_token: token)
164
172
  client.api_endpoint = addr if addr
165
173
  client.auto_paginate = true
174
+ client.per_page = 100
166
175
  Entitlements.logger.debug "Setting up GitHub API connection to #{client.api_endpoint}"
167
176
  client
168
177
  end
@@ -246,11 +255,22 @@ module Entitlements
246
255
  def members_and_roles_from_rest
247
256
  Entitlements.logger.debug "Loading organization members and roles for #{org}"
248
257
  result = {}
249
- members = octokit.organization_members(org, { role: "admin" })
250
- members.each do |member|
258
+
259
+ # fetch all the admin members from the org
260
+ admin_members = Retryable.with_context(:default) do
261
+ octokit.organization_members(org, { role: "admin" })
262
+ end
263
+
264
+ # fetch all the regular members from the org
265
+ regular_members = Retryable.with_context(:default) do
266
+ octokit.organization_members(org, { role: "member" })
267
+ end
268
+
269
+ admin_members.each do |member|
251
270
  result[member[:login].downcase] = "ADMIN"
252
271
  end
253
- octokit.organization_members(org, { role: "member" }).each do |member|
272
+
273
+ regular_members.each do |member|
254
274
  result[member[:login].downcase] = "MEMBER"
255
275
  end
256
276
 
data/lib/version.rb CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Entitlements
4
4
  module Version
5
- VERSION = "1.0.0"
5
+ VERSION = "1.2.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: entitlements-github-plugin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub, Inc. Security Ops
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-30 00:00:00.000000000 Z
11
+ date: 2025-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: contracts
@@ -66,6 +66,26 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '4.25'
69
+ - !ruby/object:Gem::Dependency
70
+ name: retryable
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 3.0.5
79
+ type: :runtime
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: '3.0'
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 3.0.5
69
89
  - !ruby/object:Gem::Dependency
70
90
  name: entitlements-app
71
91
  requirement: !ruby/object:Gem::Requirement
@@ -106,14 +126,14 @@ dependencies:
106
126
  requirements:
107
127
  - - '='
108
128
  - !ruby/object:Gem::Version
109
- version: 3.8.0
129
+ version: 3.13.0
110
130
  type: :development
111
131
  prerelease: false
112
132
  version_requirements: !ruby/object:Gem::Requirement
113
133
  requirements:
114
134
  - - '='
115
135
  - !ruby/object:Gem::Version
116
- version: 3.8.0
136
+ version: 3.13.0
117
137
  - !ruby/object:Gem::Dependency
118
138
  name: rubocop
119
139
  requirement: !ruby/object:Gem::Requirement
@@ -162,14 +182,14 @@ dependencies:
162
182
  requirements:
163
183
  - - "~>"
164
184
  - !ruby/object:Gem::Version
165
- version: 0.16.7
185
+ version: 0.19.1
166
186
  type: :development
167
187
  prerelease: false
168
188
  version_requirements: !ruby/object:Gem::Requirement
169
189
  requirements:
170
190
  - - "~>"
171
191
  - !ruby/object:Gem::Version
172
- version: 0.16.7
192
+ version: 0.19.1
173
193
  - !ruby/object:Gem::Dependency
174
194
  name: rugged
175
195
  requirement: !ruby/object:Gem::Requirement
@@ -273,13 +293,14 @@ files:
273
293
  - lib/entitlements/backend/github_team/models/team.rb
274
294
  - lib/entitlements/backend/github_team/provider.rb
275
295
  - lib/entitlements/backend/github_team/service.rb
296
+ - lib/entitlements/config/retry.rb
276
297
  - lib/entitlements/service/github.rb
277
298
  - lib/version.rb
278
299
  homepage: https://github.com/github/entitlements-github-plugin
279
300
  licenses:
280
301
  - MIT
281
302
  metadata: {}
282
- post_install_message:
303
+ post_install_message:
283
304
  rdoc_options: []
284
305
  require_paths:
285
306
  - lib
@@ -294,8 +315,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
294
315
  - !ruby/object:Gem::Version
295
316
  version: '0'
296
317
  requirements: []
297
- rubygems_version: 3.5.9
298
- signing_key:
318
+ rubygems_version: 3.5.22
319
+ signing_key:
299
320
  specification_version: 4
300
321
  summary: GitHub dotcom provider for entitlements-app
301
322
  test_files: []