1818require_relative '../helpers/configuration'
1919
2020module Github
21+ # Class responsible for interacting with GitHub's Check API.
22+ #
23+ # This class provides methods to authenticate with GitHub, fetch pull request information,
24+ # manage check runs, and handle comments and reactions on pull requests.
25+ #
26+ # @attr_reader [Object] app the authenticated GitHub app client.
27+ # @attr_reader [Object] check_suite the check suite associated with the pull request.
2128 class Check
2229 attr_reader :app , :check_suite
2330
31+ # Initializes a new Github::Check object.
32+ #
33+ # @param check_suite [Object] the check suite associated with the pull request.
2434 def initialize ( check_suite )
2535 @check_suite = check_suite
2636 @config = GitHubApp ::Configuration . instance . config
@@ -29,10 +39,21 @@ def initialize(check_suite)
2939 authenticate_app
3040 end
3141
42+ # Fetches information about a pull request.
43+ #
44+ # @param pr_id [Integer] the pull request ID.
45+ # @param repo [String] the repository name.
46+ # @return [Hash] the pull request information.
3247 def pull_request_info ( pr_id , repo )
3348 @app . pull_request ( repo , pr_id ) . to_h
3449 end
3550
51+ # Fetches commits associated with a pull request.
52+ #
53+ # @param pr_id [Integer] the pull request ID.
54+ # @param repo [String] the repository name.
55+ # @param page [Integer] the page number for pagination.
56+ # @return [Array<Hash>] the list of commits.
3657 def fetch_pull_request_commits ( pr_id , repo , page )
3758 @app . pull_request_commits (
3859 repo ,
@@ -42,6 +63,12 @@ def fetch_pull_request_commits(pr_id, repo, page)
4263 )
4364 end
4465
66+ # Adds a comment to a pull request.
67+ #
68+ # @param pr_id [Integer] the pull request ID.
69+ # @param comment [String] the comment text.
70+ # @param repo [String] the repository name.
71+ # @return [Hash] the added comment information.
4572 def add_comment ( pr_id , comment , repo )
4673 @app . add_comment (
4774 repo ,
@@ -50,18 +77,36 @@ def add_comment(pr_id, comment, repo)
5077 ) . to_h
5178 end
5279
80+ # Adds a thumbs-up reaction to a comment.
81+ #
82+ # @param repo [String] the repository name.
83+ # @param comment_id [Integer] the comment ID.
5384 def comment_reaction_thumb_up ( repo , comment_id )
5485 @app . create_issue_comment_reaction ( repo , comment_id , '+1' )
5586 end
5687
88+ # Adds a thumbs-down reaction to a comment.
89+ #
90+ # @param repo [String] the repository name.
91+ # @param comment_id [Integer] the comment ID.
5792 def comment_reaction_thumb_down ( repo , comment_id )
5893 @app . create_issue_comment_reaction ( repo , comment_id , '-1' )
5994 end
6095
96+ # Fetches check runs for a specific commit SHA.
97+ #
98+ # @param repo [String] the repository name.
99+ # @param sha [String] the commit SHA.
100+ # @param status [String] the status of the check runs to fetch.
101+ # @return [Array<Hash>] the list of check runs.
61102 def check_runs_for_ref ( repo , sha , status : 'queued' )
62103 @app . check_runs_for_ref ( repo , sha , status : status )
63104 end
64105
106+ # Creates a new check run.
107+ #
108+ # @param name [String] the name of the check run.
109+ # @return [Hash] the created check run information.
65110 def create ( name )
66111 @app . create_check_run (
67112 @check_suite . pull_request . repository ,
@@ -70,30 +115,64 @@ def create(name)
70115 )
71116 end
72117
118+ # Updates the status of a check run to 'queued'.
119+ #
120+ # @param check_ref [Integer] the check run reference ID.
121+ # @param output [Hash] the output information for the check run.
122+ # @return [Hash] the updated check run information.
73123 def queued ( check_ref , output = { } )
74124 basic_status ( check_ref , 'queued' , output )
75125 end
76126
127+ # Updates the status of a check run to 'in_progress'.
128+ #
129+ # @param check_ref [Integer] the check run reference ID.
130+ # @param output [Hash] the output information for the check run.
131+ # @return [Hash] the updated check run information.
77132 def in_progress ( check_ref , output = { } )
78133 basic_status ( check_ref , 'in_progress' , output )
79134 end
80135
136+ # Updates the status of a check run to 'cancelled'.
137+ #
138+ # @param check_ref [Integer] the check run reference ID.
139+ # @param output [Hash] the output information for the check run.
140+ # @return [Hash] the updated check run information.
81141 def cancelled ( check_ref , output = { } )
82142 completed ( check_ref , 'completed' , 'cancelled' , output )
83143 end
84144
145+ # Updates the status of a check run to 'success'.
146+ #
147+ # @param check_ref [Integer] the check run reference ID.
148+ # @param output [Hash] the output information for the check run.
149+ # @return [Hash] the updated check run information.
85150 def success ( check_ref , output = { } )
86151 completed ( check_ref , 'completed' , 'success' , output )
87152 end
88153
154+ # Updates the status of a check run to 'failure'.
155+ #
156+ # @param check_ref [Integer] the check run reference ID.
157+ # @param output [Hash] the output information for the check run.
158+ # @return [Hash] the updated check run information.
89159 def failure ( check_ref , output = { } )
90160 completed ( check_ref , 'completed' , 'failure' , output )
91161 end
92162
163+ # Updates the status of a check run to 'skipped'.
164+ #
165+ # @param check_ref [Integer] the check run reference ID.
166+ # @param output [Hash] the output information for the check run.
167+ # @return [Hash] the updated check run information.
93168 def skipped ( check_ref , output = { } )
94169 completed ( check_ref , 'completed' , 'skipped' , output )
95170 end
96171
172+ # Fetches a specific check run.
173+ #
174+ # @param check_ref [Integer] the check run reference ID.
175+ # @return [Hash] the check run information.
97176 def get_check_run ( check_ref )
98177 @app . check_run ( @check_suite . pull_request . repository , check_ref ) . to_h
99178 end
@@ -106,6 +185,10 @@ def signature
106185 @config . dig ( 'auth_signature' , 'password' )
107186 end
108187
188+ # Fetches the username associated with a GitHub user.
189+ #
190+ # @param username [String] the GitHub username.
191+ # @return [Hash, false] the user information if found, otherwise false.
109192 def fetch_username ( username )
110193 @app . user ( username )
111194 rescue StandardError
@@ -114,6 +197,12 @@ def fetch_username(username)
114197
115198 private
116199
200+ # Updates the status of a check run.
201+ #
202+ # @param check_ref [Integer] the check run reference ID.
203+ # @param status [String] the status of the check run.
204+ # @param output [Hash] the output information for the check run.
205+ # @return [Hash] the updated check run information.
117206 def basic_status ( check_ref , status , output )
118207 opts = {
119208 status : status
@@ -133,6 +222,13 @@ def basic_status(check_ref, status, output)
133222 resp
134223 end
135224
225+ # Completes a check run with a specific conclusion.
226+ #
227+ # @param check_ref [Integer] the check run reference ID.
228+ # @param status [String] the status of the check run.
229+ # @param conclusion [String] the conclusion of the check run.
230+ # @param output [Hash] the output information for the check run.
231+ # @return [Hash] the updated check run information.
136232 # PS: Conclusion and status are the same name from GitHub Check doc.
137233 # https://docs.github.com/en/rest/checks/runs?apiVersion=2022-11-28#update-a-check-run
138234 def completed ( check_ref , status , conclusion , output )
@@ -163,26 +259,68 @@ def completed(check_ref, status, conclusion, output)
163259 end
164260 end
165261
262+ # Authenticates the GitHub app.
263+ #
264+ # This method attempts to authenticate the GitHub app by repository. If the
265+ # authentication by repository fails or the check suite is nil, it falls back
266+ # to authenticating the default GitHub app.
267+ #
268+ # @raise [RuntimeError] if the GitHub authentication fails.
166269 def authenticate_app
167- @config [ 'github_apps' ] . each do |app |
168- payload = generate_payload ( app )
270+ github_app_by_repo
271+
272+ github_default_app if @check_suite . nil? or @app . nil?
273+ end
169274
170- rsa = OpenSSL ::PKey ::RSA . new ( File . read ( app [ 'cert' ] ) )
275+ # Authenticates the GitHub app by repository.
276+ #
277+ # This method finds the GitHub app configuration for the repository associated
278+ # with the check suite and creates a GitHub app client using that configuration.
279+ def github_app_by_repo
280+ app =
281+ @config [ 'github_apps' ] . find do |entry |
282+ entry . key? 'repo' and entry [ 'repo' ] == @check_suite . pull_request . repository
283+ end
171284
172- jwt = JWT . encode ( payload , rsa , 'RS256' )
285+ @logger . info ( "github_app_by_repo: #{ app . inspect } " )
173286
174- authenticate ( jwt )
287+ create_app ( app ) unless app . nil?
288+ end
289+
290+ def github_default_app
291+ @config [ 'github_apps' ] . each do |app |
292+ create_app ( app )
175293
176294 break unless @app . nil?
177295 end
178296
179297 raise 'Github Authentication Failed' if @app . nil?
180298 end
181299
300+ # Creates a GitHub app client.
301+ #
302+ # @param app [Hash] the app configuration.
303+ def create_app ( app )
304+ payload = generate_payload ( app )
305+
306+ rsa = OpenSSL ::PKey ::RSA . new ( File . read ( app [ 'cert' ] ) )
307+
308+ jwt = JWT . encode ( payload , rsa , 'RS256' )
309+
310+ authenticate ( jwt )
311+ end
312+
313+ # Generates a payload for authentication.
314+ #
315+ # @param app [Hash] the app configuration.
316+ # @return [Hash] the generated payload.
182317 def generate_payload ( app )
183318 { iat : Time . now . to_i , exp : Time . now . to_i + ( 10 * 60 ) - 30 , iss : app [ 'login' ] }
184319 end
185320
321+ # Authenticates the GitHub app with a JWT.
322+ #
323+ # @param jwt [String] the JWT token.
186324 def authenticate ( jwt )
187325 @authenticate_app = Octokit ::Client . new ( bearer_token : jwt )
188326
@@ -195,6 +333,12 @@ def authenticate(jwt)
195333 @app = Octokit ::Client . new ( bearer_token : token )
196334 end
197335
336+ # Sends an update to GitHub for a check run.
337+ #
338+ # @param check_ref [Integer] the check run reference ID.
339+ # @param opts [Hash] the options for the update.
340+ # @param conclusion [String] the conclusion of the check run.
341+ # @return [Hash] the updated check run information.
198342 def send_update ( check_ref , opts , conclusion )
199343 resp =
200344 @app . update_check_run (
0 commit comments