From 0ef8931302c3560f64c7b78c03036ad395493fe3 Mon Sep 17 00:00:00 2001 From: nobe4 Date: Wed, 28 Oct 2026 21:50:40 +0100 Subject: [PATCH 1/5] feat(service): catch 403 when someone blocks the invitation This happened just now, and should only warn, but not fail. --- .../backend/github_org/service.rb | 7 ++++-- lib/version.rb | 2 +- .../backend/github_org/service_spec.rb | 22 +++++++++++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/entitlements/backend/github_org/service.rb b/lib/entitlements/backend/github_org/service.rb index 17062e0..7ba89ec 100644 --- a/lib/entitlements/backend/github_org/service.rb +++ b/lib/entitlements/backend/github_org/service.rb @@ -46,7 +46,7 @@ def add_user_to_organization(user, role) Entitlements.logger.debug "#{identifier} add_user_to_organization(user=#{user}, org=#{org}, role=#{role})" begin - new_membership = Retryable.with_context(:default, not: [Octokit::NotFound]) do + new_membership = Retryable.with_context(:default, not: [Octokit::NotFound, Octokit::Forbidden]) do octokit.update_organization_membership(org, user:, role:) end rescue Octokit::NotFound => e @@ -54,9 +54,12 @@ def add_user_to_organization(user, role) Entitlements.logger.warn "User #{user} not found in GitHub instance #{identifier}, ignoring." return false - rescue Octokit::UnprocessableEntity => e + rescue Octokit::UnprocessableEntity => e # code 422 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." return false + rescue Octokit::Forbidden => e # code 403 + Entitlements.logger.warn "Forbidden from adding #{user} to organization #{org} with role #{role}: #{e.message}." + return false end # Happy path diff --git a/lib/version.rb b/lib/version.rb index 7f933cc..9bc799e 100644 --- a/lib/version.rb +++ b/lib/version.rb @@ -2,6 +2,6 @@ module Entitlements module Version - VERSION = "1.2.6" + VERSION = "1.2.7" end end diff --git a/spec/unit/entitlements/backend/github_org/service_spec.rb b/spec/unit/entitlements/backend/github_org/service_spec.rb index 05c8a99..5d4824a 100644 --- a/spec/unit/entitlements/backend/github_org/service_spec.rb +++ b/spec/unit/entitlements/backend/github_org/service_spec.rb @@ -223,6 +223,28 @@ expect(result).to eq(false) end end + + context "when the API returns a forbidden error" do + it "warns and returns false" do + expect(logger).to receive(:debug).with("github.fake add_user_to_organization(user=bob, org=kittensinc, role=admin)") + expect(logger).to receive(:debug).with("Setting up GitHub API connection to https://github.fake/api/v3/") + expect(logger).to receive(:warn).with(/Forbidden from adding bob to organization kittensinc with role admin/) + + stub_request(:put, "https://github.fake/api/v3/orgs/kittensinc/memberships/bob").to_return( + status: 403, + headers: { + "Content-type" => "application/json" + }, + body: JSON.generate({ + "message" => "Forbidden", + "documentation_url" => "https://docs.github.com/rest" + }) + ) + + result = subject.send(:add_user_to_organization, "bob", "admin") + expect(result).to eq(false) + end + end end end From b18e329564989e84ee58b023d142db313d3b6905 Mon Sep 17 00:00:00 2001 From: nobe4 Date: Wed, 28 Oct 2026 21:55:10 +0100 Subject: [PATCH 2/5] fix: bump version --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e5e595e..e44c0a6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - entitlements-github-plugin (1.2.6) + entitlements-github-plugin (1.2.7) contracts (~> 0.17.0) faraday (~> 2.0) faraday-net_http_persistent (~> 2.3) @@ -186,4 +186,4 @@ DEPENDENCIES webmock (~> 3.23, >= 3.23.1) BUNDLED WITH - 2.5.9 + 2.7.2 From aadea5bac7d104be9685f1554f1a367f5ea83f95 Mon Sep 17 00:00:00 2001 From: nobe4 Date: Thu, 29 Oct 2026 10:17:00 +0100 Subject: [PATCH 3/5] fix: bump ruby to 3.4.0 --- .ruby-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ruby-version b/.ruby-version index 9c25013..1809198 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.3.6 +3.4.0 From c5c7c9a3f0668a5e3cddc05edbced9bd8c7ea4bc Mon Sep 17 00:00:00 2001 From: nobe4 Date: Thu, 29 Oct 2026 10:17:34 +0100 Subject: [PATCH 4/5] fix: bump ruby to 3.4.9 to match the main repo --- .ruby-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ruby-version b/.ruby-version index 1809198..7bcbb38 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.4.0 +3.4.9 From cb50e9040e9d504487e25783d40e3e747b82d121 Mon Sep 17 00:00:00 2001 From: nobe4 Date: Thu, 29 Oct 2026 10:20:55 +0100 Subject: [PATCH 5/5] fix(test): update matrix with only valid ruby versions --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2b0e653..e5afa80 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - ruby: [ '3.1.2', '3.1.4', '3.2.2', '3.2.3', '3.3.0', '3.3.1' ] + ruby: ["3.3.0", "3.3.1", "3.4.9"] steps: - name: checkout