Normally, we fill the `workflow_job` data of the `GithubRunner` object when the `workflow_job.in_progress` webhook event is delivered. [^1] We use the `head_branch` value from this data at runtime endpoints to validate the scope cache. When this data is missing, we try to retrieve it from the GitHub API. Since this operation can be costly, it's a good idea to persist the result if the same job needs the same data before the webhook is delivered. [^2] Since the GitHub API doesn't have proper filtering, we fetch all jobs of the workflow run and try to find the corresponding runner using the `runner_name` property. As another improvement, we can update the `workflow_job` column of the all jobs we've already fetched. We can use code similar to this, but I need to think more about it. It's not good practice to update resources other than the prog's subject, so we should also prevent to overwrite existing data. ```ruby jobs.each do |job| GithubRunner.where(id: UBID.to_uuid(job[:runner_name]), workflow_job: nil).update(workflow_job: Sequel.pg_jsonb(job.except("steps"))) end ``` [^1]:d4c19c2bec/routes/webhook/github.rb (L90)
[^2]:d4c19c2bec/routes/runtime/github.rb (L28)
38 lines
1.4 KiB
Ruby
38 lines
1.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Clover < Roda
|
|
def get_runtime_jwt_payload
|
|
return unless (v = request.env["HTTP_AUTHORIZATION"])
|
|
jwt_token = v.sub(%r{\ABearer:?\s+}, "")
|
|
begin
|
|
JWT.decode(jwt_token, Config.clover_runtime_token_secret, true, {algorithm: "HS256"})[0]
|
|
rescue JWT::DecodeError
|
|
end
|
|
end
|
|
|
|
def get_scope_from_github(runner, run_id)
|
|
log_context = {runner_ubid: runner.ubid, repository_ubid: runner.repository.ubid, run_id: run_id}
|
|
if run_id.nil? || run_id.empty?
|
|
Clog.emit("The run_id is blank") { {runner_scope_failure: log_context} }
|
|
return
|
|
end
|
|
|
|
Clog.emit("Get runner scope from GitHub API") { {get_runner_scope: log_context} }
|
|
begin
|
|
client = Github.installation_client(runner.installation.installation_id)
|
|
jobs = client.workflow_run_jobs(runner.repository_name, run_id)[:jobs]
|
|
rescue Octokit::ClientError, Octokit::ServerError, Faraday::ConnectionFailed, Faraday::TimeoutError => ex
|
|
log_context[:expection] = Util.exception_to_hash(ex)
|
|
Clog.emit("Could not list the jobs of the workflow run ") { {runner_scope_failure: log_context} }
|
|
return
|
|
end
|
|
if (job = jobs.find { it[:runner_name] == runner.ubid })
|
|
runner.this.update(workflow_job: Sequel.pg_jsonb(job.except("steps")))
|
|
job[:head_branch]
|
|
else
|
|
Clog.emit("The workflow run does not have given runner") { {runner_scope_failure: log_context} }
|
|
nil
|
|
end
|
|
end
|
|
end
|