Skip to content

Use webhooks to trigger automations

Rather than running a pipeline every 5 minutes, it'd be great if an access request could trigger the pipeline only when needed (we could always run a scheduled pipeline every few hours to pick up any stragglers)

Initial investigation into the group members webhooks identified that there are currently no hooks for requesting access, but it shouldn't be too hard to modify them to support this.

I played around a bit:

diff --git a/app/models/member.rb b/app/models/member.rb
index 04039e2724c6..f92841696da6 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -307,13 +307,13 @@ class Member < ApplicationRecord
 
   after_create :send_invite, if: :invite?, unless: :importing?
   after_create :create_notification_setting, unless: [:pending?, :importing?]
-  after_create :post_create_hook, unless: [:pending?, :importing?], if: :hook_prerequisites_met?
+  after_create :post_create_hook, unless: [:importing?], if: :hook_prerequisites_met?
   after_create :update_two_factor_requirement, unless: :invite?
   after_create :create_organization_user_record
   after_update :post_update_hook, unless: [:pending?, :importing?], if: :hook_prerequisites_met?
   after_update :create_organization_user_record, if: :saved_change_to_user_id? # only occurs on invite acceptance
   after_destroy :destroy_notification_setting
-  after_destroy :post_destroy_hook, unless: :pending?, if: :hook_prerequisites_met?
+  after_destroy :post_destroy_hook, if: :hook_prerequisites_met?
   after_destroy :update_two_factor_requirement, unless: :invite?
   after_save :log_invitation_token_cleanup
 
@@ -620,7 +620,8 @@ def post_create_hook
       run_after_commit_or_now { notification_service.new_member(self) }
     end
 
-    system_hook_service.execute_hooks_for(self, :create)
+    event_name = pending? ? :request : :create
+    system_hook_service.execute_hooks_for(self, event_name)
   end
 
   def post_update_hook
@@ -636,7 +637,8 @@ def post_update_hook
   end
 
   def post_destroy_hook
-    system_hook_service.execute_hooks_for(self, :destroy)
+    event_name = pending? ? :reject : :destroy
+    system_hook_service.execute_hooks_for(self, event_name)
   end
 
   # Refreshes authorizations of the current member.
diff --git a/ee/app/models/ee/group_member.rb b/ee/app/models/ee/group_member.rb
index d6897d445f2f..da76a329faba 100644
--- a/ee/app/models/ee/group_member.rb
+++ b/ee/app/models/ee/group_member.rb
@@ -118,7 +118,8 @@ def access_level_inclusion
     def post_destroy_hook
       super
 
-      execute_hooks_for(:destroy)
+      event_name = pending? ? :reject : :destroy
+      execute_hooks_for(event_name)
     end
 
     override :seat_available
diff --git a/ee/app/models/ee/member.rb b/ee/app/models/ee/member.rb
index 5f4584e26eaa..7f9ddcce00cf 100644
--- a/ee/app/models/ee/member.rb
+++ b/ee/app/models/ee/member.rb
@@ -308,7 +308,8 @@ def post_update_hook
     def post_create_hook
       super
 
-      execute_hooks_for(:create)
+      event_name = pending? ? :request : :create
+      execute_hooks_for(event_name)
     end
 
     def execute_hooks_for(event)
diff --git a/lib/gitlab/hook_data/group_member_builder.rb b/lib/gitlab/hook_data/group_member_builder.rb
index d70885018e94..d51f28c48db3 100644
--- a/lib/gitlab/hook_data/group_member_builder.rb
+++ b/lib/gitlab/hook_data/group_member_builder.rb
@@ -54,6 +54,12 @@ def event_data(event)
                         'user_remove_from_group'
                       when :update
                         'user_update_for_group'
+                      when :request
+                        'user_access_request_to_group'
+                      when :accept
+                        'user_access_request_approved_for_group'
+                      when :reject
+                        'user_access_request_rejected_for_group'
                       end
 
         { event_name: event_name }