entitlements-github-plugin 1.2.6 → 1.2.8

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: e8b4641323dd4da38ecb87c7f94eacecdfc20508dfdeb0e1b02030c31fe67ab7
4
- data.tar.gz: c9180370314b8e80b776ecc554fba1310cc690a246ddc1ac99509263dbb01547
3
+ metadata.gz: 41951a6ab48f3605dd85973777867619620b508e2a7ac1f1ec78451dbcf42170
4
+ data.tar.gz: 400ab0cb03e6b8dfda7945a07eb51a1d5665615ea0bb535598a35b920c857dca
5
5
  SHA512:
6
- metadata.gz: a0311bcc81ebeac4a1ea1852962bf5a7b592771e2ed11ab1955e199bf5d935d5117e7632167d6bcda55d6b979167faa1cba79744282e55957e011975816b8417
7
- data.tar.gz: 6de304801162205be96002493fedff35431cc37823fdc0b6f80933731fd89ae7ce15cf820be1a8e82dbb77a607e50a0900cba9604872566fac8b829d01c58fc2
6
+ metadata.gz: c32214124e1949acc3679157620d7dddc795a3951cbc1935626a17a9295ecb5b2ef3e4784450b3b8bd2afd3d1a910e952df298867520c452ac7aa0d1c2f637ba
7
+ data.tar.gz: bb1a5adacf8ad4fed75717a3a09d020297c4941ff3d518c62772a7e6139990352984732f4bcf607fb77d9295b3e447620b15135bb63c641e5f40a55535434707
@@ -46,7 +46,7 @@ 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 = Retryable.with_context(:default, not: [Octokit::NotFound]) do
49
+ new_membership = Retryable.with_context(:default, not: [Octokit::NotFound, Octokit::Forbidden]) do
50
50
  octokit.update_organization_membership(org, user:, role:)
51
51
  end
52
52
  rescue Octokit::NotFound => e
@@ -54,9 +54,12 @@ module Entitlements
54
54
 
55
55
  Entitlements.logger.warn "User #{user} not found in GitHub instance #{identifier}, ignoring."
56
56
  return false
57
- rescue Octokit::UnprocessableEntity => e
57
+ rescue Octokit::UnprocessableEntity => e # code 422
58
58
  Entitlements.logger.warn "Unprocessable entity when adding #{user} to organization #{org} with role #{role}: #{e.message}. This likely means the user blocked the invite, so we're ignoring them, but someone should check it."
59
59
  return false
60
+ rescue Octokit::Forbidden => e # code 403
61
+ Entitlements.logger.warn "Forbidden from adding #{user} to organization #{org} with role #{role}: #{e.message}."
62
+ return false
60
63
  end
61
64
 
62
65
  # Happy path
@@ -363,12 +363,14 @@ module Entitlements
363
363
  def graphql_team_data(team_slug)
364
364
  cursor = nil
365
365
  team_id = nil
366
+ parent_team_name = nil
366
367
  result = []
367
368
  roles = {}
368
369
  sanity_counter = 0
369
370
 
370
- while sanity_counter < 100
371
+ loop do
371
372
  sanity_counter += 1
373
+ raise_if_too_many_pages(sanity_counter, "members of team #{org}/#{team_slug}")
372
374
  first_str = cursor.nil? ? "first: #{max_graphql_results}" : "first: #{max_graphql_results}, after: \"#{cursor}\""
373
375
  query = "{
374
376
  organization(login: \"#{org}\") {
@@ -15,6 +15,7 @@ module Entitlements
15
15
 
16
16
  # This is a limitation of the GitHub API
17
17
  MAX_GRAPHQL_RESULTS = 100
18
+ MAX_GRAPHQL_PAGES = 100
18
19
 
19
20
  # Retries to smooth over transient network blips
20
21
  MAX_GRAPHQL_RETRIES = 3
@@ -193,7 +194,7 @@ module Entitlements
193
194
  member_from_cache = Entitlements::Data::Groups::Cached.members("cn=member,#{ou}")
194
195
 
195
196
  # If we do not have *both* admins and members, we need to call the API
196
- return [members_and_roles_from_rest, false] unless admin_from_cache && member_from_cache
197
+ return [members_and_roles_from_graphql, false] unless admin_from_cache && member_from_cache
197
198
 
198
199
  # Convert the Sets of strings into the expected hash structure.
199
200
  Entitlements.logger.debug "Loading organization members and roles for #{org} from cache"
@@ -215,8 +216,9 @@ module Entitlements
215
216
  result = {}
216
217
  sanity_counter = 0
217
218
 
218
- while sanity_counter < 100
219
+ loop do
219
220
  sanity_counter += 1
221
+ raise_if_too_many_pages(sanity_counter, "organization members of #{org}")
220
222
  first_str = cursor.nil? ? "first: #{max_graphql_results}" : "first: #{max_graphql_results}, after: \"#{cursor}\""
221
223
  query = "{
222
224
  organization(login: \"#{org}\") {
@@ -294,8 +296,9 @@ module Entitlements
294
296
  result = Set.new
295
297
  sanity_counter = 0
296
298
 
297
- while sanity_counter < 100
299
+ loop do
298
300
  sanity_counter += 1
301
+ raise_if_too_many_pages(sanity_counter, "pending members of #{org}")
299
302
  first_str = cursor.nil? ? "first: #{max_graphql_results}" : "first: #{max_graphql_results}, after: \"#{cursor}\""
300
303
  query = "{
301
304
  organization(login: \"#{org}\") {
@@ -378,6 +381,8 @@ module Entitlements
378
381
  request = Net::HTTP::Post.new(uri)
379
382
  request.add_field("Authorization", "bearer #{token}")
380
383
  request.add_field("Content-Type", "application/json")
384
+ # Lets a proxy such as entitlements-caches tie each request to a CI run.
385
+ request.add_field("X-Entitlements-Run-Id", ENV["GITHUB_RUN_ID"]) if ENV["GITHUB_RUN_ID"]
381
386
  request.body = JSON.generate("query" => query)
382
387
 
383
388
  begin
@@ -476,6 +481,35 @@ module Entitlements
476
481
  MAX_GRAPHQL_RESULTS
477
482
  end
478
483
  # :nocov:
484
+
485
+ # Helper method: Determine the maximum number of pages to read from a paginated
486
+ # GraphQL query. Stubbed in tests.
487
+ #
488
+ # Takes no arguments.
489
+ #
490
+ # Returns an Integer.
491
+ # :nocov:
492
+ Contract C::None => Integer
493
+ def max_graphql_pages
494
+ MAX_GRAPHQL_PAGES
495
+ end
496
+ # :nocov:
497
+
498
+ # Helper method: Raise rather than return a truncated result when a paginated
499
+ # GraphQL query needs more pages than allowed. A partial list of members would
500
+ # cause entitlements to skip removals for anyone not returned.
501
+ #
502
+ # page - Integer number of the page about to be requested.
503
+ # what - String describing what is being read, for the error message.
504
+ #
505
+ # Returns nothing.
506
+ Contract Integer, String => nil
507
+ def raise_if_too_many_pages(page, what)
508
+ return if page <= max_graphql_pages
509
+
510
+ Entitlements.logger.fatal "Abort reading #{what}: more than #{max_graphql_pages} pages of results"
511
+ raise "GraphQL pagination limit exceeded"
512
+ end
479
513
  end
480
514
  end
481
515
  end
data/lib/version.rb CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Entitlements
4
4
  module Version
5
- VERSION = "1.2.6"
5
+ VERSION = "1.2.8"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: entitlements-github-plugin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.6
4
+ version: 1.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub, Inc. Security Ops
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-10-13 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: contracts
@@ -314,7 +313,6 @@ homepage: https://github.com/github/entitlements-github-plugin
314
313
  licenses:
315
314
  - MIT
316
315
  metadata: {}
317
- post_install_message:
318
316
  rdoc_options: []
319
317
  require_paths:
320
318
  - lib
@@ -329,8 +327,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
329
327
  - !ruby/object:Gem::Version
330
328
  version: '0'
331
329
  requirements: []
332
- rubygems_version: 3.5.22
333
- signing_key:
330
+ rubygems_version: 3.6.9
334
331
  specification_version: 4
335
332
  summary: GitHub dotcom provider for entitlements-app
336
333
  test_files: []