Skip to content

Commit 00dcabd

Browse files
committed
Support scanning for any completed run, not only successful.
Fixes #14
1 parent e484830 commit 00dcabd

File tree

4 files changed

+48
-11
lines changed

4 files changed

+48
-11
lines changed

spec/main_spec.cr

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ describe "dash_by_branch" do
175175
assert_nofollow
176176
end
177177

178+
test "bad request" do
179+
resp, body = serve("/UserName/RepoName/workflows/SomeWorkflow/SomeBranch?status=foo")
180+
assert resp.status == HTTP::Status::BAD_REQUEST
181+
end
182+
178183
describe "private" do
179184
test "without password" do
180185
resp, body = serve("/#{PRIVATE_REPO}/workflows/SomeWorkflow/SomeBranch")
@@ -310,6 +315,18 @@ describe "by_branch" do
310315
assert_nofollow
311316
end
312317

318+
test "completed" do
319+
WebMock.stub(:get, "https://api.github.com/repos/username/reponame/actions/workflows/SomeWorkflow.yml/runs?per_page=1&branch=SomeBranch&event=push&status=completed").to_return(
320+
body: %({"workflow_runs":[
321+
{"id":#{RUN_1},"event":"push","workflow_id":#{WORKFLOW_1},"check_suite_url":"https://api.github.com/repos/UserName/RepoName/check-suites/#{CHECK_SUITE_1}","updated_at":"2020-12-19T22:22:22Z","repository":{"full_name":"UserName/RepoName","private":false,"fork":false}}]}))
322+
WebMock.stub(:get, "https://api.github.com/repos/username/reponame/actions/workflows/SomeWorkflow.yml/runs?per_page=1&branch=SomeBranch&event=schedule&status=completed").to_return(
323+
body: %({"workflow_runs":[
324+
{"id":#{RUN_2},"event":"schedule","workflow_id":#{WORKFLOW_1},"check_suite_url":"https://api.github.com/repos/UserName/RepoName/check-suites/#{CHECK_SUITE_1}","updated_at":"2021-02-07T07:15:00Z","repository":{"full_name":"UserName/RepoName","private":false,"fork":false}}]}))
325+
326+
resp, body = serve("/UserName/RepoName/workflows/SomeWorkflow/SomeBranch/SomeArtifact?status=completed")
327+
assert_canonical "https://nightly.link/UserName/RepoName/workflows/SomeWorkflow/SomeBranch/SomeArtifact"
328+
end
329+
313330
test "redirect" do
314331
resp, body = serve("/UserName/RepoName/workflows/SomeWorkflow/SomeBranch/SomeArtifact.zip")
315332
assert_redirect "http://example.org/download1"

src/github_api.cr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,14 @@ struct WorkflowRuns
233233
property workflow_runs : Array(WorkflowRun)
234234

235235
cached_array def self.for_workflow(
236-
repo_owner : DowncaseString, repo_name : DowncaseString, workflow : String, branch : String, event : String,
236+
repo_owner : DowncaseString, repo_name : DowncaseString, workflow : String,
237+
branch : String, event : String, status : String,
237238
token : InstallationToken | UserToken, max_items : Int32, & : WorkflowRun ->
238239
)
239240
# https://docs.github.com/v3/actions#list-workflow-runs
240241
get_json_list(
241242
WorkflowRuns, "repos/#{repo_owner}/#{repo_name}/actions/workflows/#{workflow}/runs",
242-
params: {branch: branch, event: event, status: "success"},
243+
params: {branch: branch, event: event, status: status},
243244
headers: {Authorization: token}, max_items: max_items
244245
)
245246
end

src/nightly_link.cr

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,12 @@ private def github_run_link(repo_owner : String, repo_name : String, run_id : In
136136
"https://github.com" + GitHubRoutes.gen_run(repo_owner: repo_owner, repo_name: repo_name, run_id: run_id) + "#artifacts"
137137
end
138138

139-
private def github_actions_link(repo_owner : String, repo_name : String, *, event : String, branch : String) : String
139+
private def github_actions_link(
140+
repo_owner : String, repo_name : String, *,
141+
event : String, branch : String, status : String
142+
) : String
140143
"https://github.com/#{repo_owner}/#{repo_name}/actions?" + HTTP::Params.encode({
141-
query: "event:#{event} is:success branch:#{branch}",
144+
query: "event:#{event} is:#{status} branch:#{branch}",
142145
})
143146
end
144147

@@ -228,7 +231,10 @@ class NightlyLink
228231

229232
run, artifact = @@examples_cache.fetch(example_workflow) do
230233
token = GitHubApp.token(FALLBACK_INSTALL_ID)
231-
run_ = get_latest_run(args[:repo_owner], args[:repo_name], args[:workflow] + ".yml", args[:branch], token)
234+
run_ = get_latest_run(
235+
args[:repo_owner], args[:repo_name],
236+
workflow: args[:workflow] + ".yml", branch: args[:branch], status: "success", token: token
237+
)
232238
artifact_ = Artifacts.for_run(args[:repo_owner], args[:repo_name], run_.id, token, expires_in: 3.hours).first
233239
{run_, artifact_}
234240
end
@@ -301,8 +307,12 @@ class NightlyLink
301307
unless workflow.to_i64?(whitespace: false) || workflow.ends_with?(".yml") || workflow.ends_with?(".yaml")
302308
workflow += ".yml"
303309
end
310+
status = ctx.request.query_params.fetch("status", "success")
311+
if !status.in?("success", "completed")
312+
raise HTTPException.new(:BadRequest, "?status must be 'success' (default) or 'completed'")
313+
end
304314

305-
run = get_latest_run(repo_owner, repo_name, workflow, branch, token)
315+
run = get_latest_run(repo_owner, repo_name, workflow: workflow, branch: branch, status: status, token: token)
306316
repo_owner, repo_name = run.repository.owner, run.repository.name
307317
if run.updated_at < 90.days.ago
308318
message = "Warning: the latest successful run is older than 90 days, and its artifacts likely expired."
@@ -384,12 +394,15 @@ class NightlyLink
384394
ECR.embed("templates/artifact_list.html", ctx.response)
385395
end
386396

387-
private def get_latest_run(repo_owner : String, repo_name : String, workflow : String, branch : String, token : InstallationToken)
397+
private def get_latest_run(
398+
repo_owner : String, repo_name : String,
399+
workflow : String, branch : String, status : String, token : InstallationToken
400+
)
388401
futures = [{"push", 5.minutes}, {"schedule", 1.hour}].map do |(event, expires_in)|
389402
future do
390403
begin
391404
WorkflowRuns.for_workflow(
392-
repo_owner, repo_name, workflow, branch: branch, event: event,
405+
repo_owner, repo_name, workflow, branch: branch, event: event, status: status,
393406
token: token, max_items: 1, expires_in: expires_in
394407
)
395408
rescue e : Halite::Exception::ClientError
@@ -405,7 +418,7 @@ class NightlyLink
405418
end
406419
runs = futures.map(&.get.first?).compact
407420
if runs.empty?
408-
gh_link = github_actions_link(repo_owner, repo_name, event: "push", branch: branch)
421+
gh_link = github_actions_link(repo_owner, repo_name, event: "push", branch: branch, status: status)
409422
raise HTTPException.new(:NotFound,
410423
"No successful runs found for workflow '#{workflow}' and branch '#{branch}'.\n" +
411424
"Check on GitHub: <#{gh_link}>"
@@ -439,13 +452,18 @@ class NightlyLink
439452
unless workflow.to_i64?(whitespace: false) || workflow.ends_with?(".yml") || workflow.ends_with?(".yaml")
440453
workflow += ".yml"
441454
end
442-
run = get_latest_run(repo_owner, repo_name, workflow, branch, token)
455+
status = ctx.request.query_params.fetch("status", "success")
456+
if !status.in?("success", "completed")
457+
raise HTTPException.new(:BadRequest, "?status must be 'success' (default) or 'completed'")
458+
end
459+
460+
run = get_latest_run(repo_owner, repo_name, workflow: workflow, branch: branch, status: status, token: token)
443461
repo_owner, repo_name = run.repository.owner, run.repository.name
444462

445463
links = by_run(nil, repo_owner, repo_name, run.id, artifact, run.check_suite_id, h, zip: zip)
446464
title = {"Repository #{repo_owner}/#{repo_name}", "Workflow #{workflow} | Branch #{branch} | Artifact #{artifact}"}
447465
links << ArtifactLink.new(
448-
github_actions_link(repo_owner, repo_name, event: run.event, branch: branch),
466+
github_actions_link(repo_owner, repo_name, event: run.event, branch: branch, status: status),
449467
"Browse workflow runs on branch '#{branch}'", ext: true
450468
)
451469
canonical = abs_url(NightlyLink.gen_by_branch(

templates/controls.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ <h2>Paste a GitHub link, get a nightly.link!</h2>
2929
Note that the <i>branch</i> which you're on also matters.</p>
3030
<p>Following this form (and having selected the "<%= example_art %>" artifact), you will end up at<br><a rel="nofollow" href="<%= example_dest %>"><%= example_dest %></a> [<a rel="nofollow" href="<%= example_dest %>.zip">.zip</a>]<br>
3131
which is a link that always downloads the latest artifact from a <u>succeeding</u> run on that <u>repo</u>+<u>workflow</u>+<u>branch</u>.</p>
32+
<p>To allow <u>any finished</u> workflow runs, not only successful ones, append <code>?status=success</code> to the URL.
3233
<p>If you have several workflows or branches, you can adapt the URL by hand in a predictable way.</p>
3334
</details>
3435

0 commit comments

Comments
 (0)