Merge pull request #13124 from Bo98/get_workflow_run

utils/github: rewrite get_workflow_run using GraphQL
This commit is contained in:
Michka Popoff 2022-04-11 22:16:30 +02:00 committed by GitHub
commit e5e02f8705
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 21 deletions

View File

@ -39,6 +39,8 @@ Metrics/ModuleLength:
Exclude: Exclude:
# TODO: extract more of the bottling logic # TODO: extract more of the bottling logic
- "dev-cmd/bottle.rb" - "dev-cmd/bottle.rb"
# TODO: try break this down
- "utils/github.rb"
- "test/**/*" - "test/**/*"
Naming/PredicateName: Naming/PredicateName:

View File

@ -71,7 +71,7 @@ describe GitHub do
described_class.get_artifact_url( described_class.get_artifact_url(
described_class.get_workflow_run("Homebrew", "homebrew-core", 1), described_class.get_workflow_run("Homebrew", "homebrew-core", 1),
) )
}.to raise_error(/No matching workflow run found/) }.to raise_error(/No matching check suite found/)
end end
it "fails to find artifacts that don't exist" do it "fails to find artifacts that don't exist" do

View File

@ -270,41 +270,77 @@ module GitHub
def get_workflow_run(user, repo, pr, workflow_id: "tests.yml", artifact_name: "bottles") def get_workflow_run(user, repo, pr, workflow_id: "tests.yml", artifact_name: "bottles")
scopes = CREATE_ISSUE_FORK_OR_PR_SCOPES 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) # GraphQL unfortunately has no way to get the workflow yml name, so we need an extra REST call.
workflow_run = workflow["workflow_runs"].select do |run| workflow_api_url = "#{API_URL}/repos/#{user}/#{repo}/actions/workflows/#{workflow_id}"
run["head_sha"] == pr_sha 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,
url,
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
check_suite = if commit_node.present?
commit_node["commit"]["checkSuites"]["nodes"].select do |suite|
suite["workflowRun"]["workflow"]["databaseId"] == workflow_id_num
end
else
[]
end end
[workflow_run, pr_sha, pr_branch, pr, workflow_id, scopes, artifact_name] [check_suite, user, repo, pr, workflow_id, scopes, artifact_name]
end end
def get_artifact_url(workflow_array) def get_artifact_url(workflow_array)
workflow_run, pr_sha, pr_branch, pr, workflow_id, scopes, artifact_name = *workflow_array check_suite, user, repo, pr, workflow_id, scopes, artifact_name = *workflow_array
if workflow_run.empty? if check_suite.empty?
raise API::Error, <<~EOS raise API::Error, <<~EOS
No matching workflow run found for these criteria! No matching check suite found for these criteria!
Commit SHA: #{pr_sha}
Branch ref: #{pr_branch}
Pull request: #{pr} Pull request: #{pr}
Workflow: #{workflow_id} Workflow: #{workflow_id}
EOS EOS
end end
status = workflow_run.first["status"].sub("_", " ") status = check_suite.first["status"].sub("_", " ").downcase
if status != "completed" if status != "completed"
raise API::Error, <<~EOS raise API::Error, <<~EOS
The newest workflow run for ##{pr} is still #{status}! The newest workflow run for ##{pr} is still #{status}!
#{Formatter.url workflow_run.first["html_url"]} #{Formatter.url check_suite.first["workflowRun"]["url"]}
EOS EOS
end 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| artifact = artifacts["artifacts"].select do |art|
art["name"] == artifact_name art["name"] == artifact_name
@ -313,7 +349,7 @@ module GitHub
if artifact.empty? if artifact.empty?
raise API::Error, <<~EOS raise API::Error, <<~EOS
No artifact with the name `#{artifact_name}` was found! No artifact with the name `#{artifact_name}` was found!
#{Formatter.url workflow_run.first["html_url"]} #{Formatter.url check_suite.first["workflowRun"]["url"]}
EOS EOS
end end

View File

@ -253,8 +253,8 @@ module GitHub
end end
end end
def open_graphql(query, scopes: [].freeze) def open_graphql(query, variables: nil, scopes: [].freeze)
data = { query: query } data = { query: query, variables: variables }
result = open_rest("#{API_URL}/graphql", scopes: scopes, data: data, request_method: "POST") result = open_rest("#{API_URL}/graphql", scopes: scopes, data: data, request_method: "POST")
if result["errors"].present? if result["errors"].present?