Skip to content

Commit

Permalink
utils/github: rewrite get_workflow_run using GraphQL
Browse files Browse the repository at this point in the history
  • Loading branch information
Bo98 committed Apr 11, 2022
1 parent dec7ac0 commit 6e37d56
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 19 deletions.
2 changes: 2 additions & 0 deletions Library/Homebrew/.rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Metrics/ModuleLength:
Exclude:
# TODO: extract more of the bottling logic
- "dev-cmd/bottle.rb"
# TODO: try break this down
- "utils/github.rb"
- "test/**/*"

Naming/PredicateName:
Expand Down
67 changes: 50 additions & 17 deletions Library/Homebrew/utils/github.rb
Original file line number Diff line number Diff line change
Expand Up @@ -270,41 +270,74 @@ def upload_release_asset(user, repo, id, local_file: nil, remote_file: nil)

def get_workflow_run(user, repo, pr, workflow_id: "tests.yml", artifact_name: "bottles")
scopes = CREATE_ISSUE_FORK_OR_PR_SCOPES
base_url = "#{API_URL}/repos/#{user}/#{repo}"
pr_payload = API.open_rest("#{base_url}/pulls/#{pr}", scopes: scopes)
pr_sha = pr_payload["head"]["sha"]
pr_branch = URI.encode_www_form_component(pr_payload["head"]["ref"])
parameters = "event=pull_request&branch=#{pr_branch}"

workflow = API.open_rest("#{base_url}/actions/workflows/#{workflow_id}/runs?#{parameters}", scopes: scopes)
workflow_run = workflow["workflow_runs"].select do |run|
run["head_sha"] == pr_sha

# GraphQL unfortunately has no way to get the workflow yml name, so we need an extra REST call.
workflow_api_url = "#{API_URL}/repos/#{user}/#{repo}/actions/workflows/#{workflow_id}"
workflow_payload = API.open_rest(workflow_api_url, scopes: scopes)
workflow_id_num = workflow_payload["id"]

query = <<~EOS
query ($user: String!, $repo: String!, $pr: Int!) {
repository(owner: $user, name: $repo) {
pullRequest(number: $pr) {
commits(last: 1) {
nodes {
commit {
checkSuites(first: 100) {
nodes {
status,
workflowRun {
databaseId,
workflow {
databaseId
}
}
}
}
}
}
}
}
}
}
EOS
variables = {
user: user,
repo: repo,
pr: pr,
}
result = API.open_graphql(query, variables: variables, scopes: scopes)

commit_node = result["repository"]["pullRequest"]["commits"]["nodes"].first
return [] if commit_node.blank?

check_suite = commit_node["commit"]["checkSuites"]["nodes"].select do |suite|
suite["workflowRun"]["workflow"]["databaseId"] == workflow_id_num
end

[workflow_run, pr_sha, pr_branch, pr, workflow_id, scopes, artifact_name]
[check_suite, user, repo, pr, workflow_id, scopes, artifact_name]
end

def get_artifact_url(workflow_array)
workflow_run, pr_sha, pr_branch, pr, workflow_id, scopes, artifact_name = *workflow_array
if workflow_run.empty?
check_suite, user, repo, pr, workflow_id, scopes, artifact_name = *workflow_array
if check_suite.empty?
raise API::Error, <<~EOS
No matching workflow run found for these criteria!
Commit SHA: #{pr_sha}
Branch ref: #{pr_branch}
No matching check suite found for these criteria!
Pull request: #{pr}
Workflow: #{workflow_id}
EOS
end

status = workflow_run.first["status"].sub("_", " ")
status = check_suite.first["status"].sub("_", " ").downcase
if status != "completed"
raise API::Error, <<~EOS
The newest workflow run for ##{pr} is still #{status}!
#{Formatter.url workflow_run.first["html_url"]}
EOS
end

artifacts = API.open_rest(workflow_run.first["artifacts_url"], scopes: scopes)
run_id = check_suite.first["workflowRun"]["databaseId"]
artifacts = API.open_rest("#{API_URL}/repos/#{user}/#{repo}/actions/runs/#{run_id}/artifacts", scopes: scopes)

artifact = artifacts["artifacts"].select do |art|
art["name"] == artifact_name
Expand Down
4 changes: 2 additions & 2 deletions Library/Homebrew/utils/github/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,8 @@ def paginate_rest(url, per_page: 100)
end
end

def open_graphql(query, scopes: [].freeze)
data = { query: query }
def open_graphql(query, variables: nil, scopes: [].freeze)
data = { query: query, variables: variables }
result = open_rest("#{API_URL}/graphql", scopes: scopes, data: data, request_method: "POST")

if result["errors"].present?
Expand Down

0 comments on commit 6e37d56

Please sign in to comment.