Skip to content

Commit 398d90b

Browse files
dawidd6claude
andauthored
fix: do not rely on API workflow run ordering (#429)
The runs endpoint is documented nowhere as newest-first and has twice returned otherwise (#95, #424), making the action pick a stale run whose artifacts have expired. Sort candidate runs newest-first ourselves and fetch 100 per page, so a misordered page cannot select an old run. Stop counting expired artifacts towards check_artifacts and search_artifacts: an expired artifact is not downloadable, so a run that only has those is not a usable candidate. Also read dry_run with getBooleanInput, as the string "false" was truthy and silently enabled dry run mode. Refs #428 Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent b9a309f commit 398d90b

3 files changed

Lines changed: 8 additions & 6 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ On GitHub Enterprise Server, use `use_unzip: true` for large artifacts so extrac
9393

9494
### API usage
9595

96-
Workflow, branch, event and commit/ref filters are sent to GitHub's API. `workflow_conclusion`, `run_number`, fork filtering, `check_artifacts` and `search_artifacts` are evaluated by this action; artifact checks may require an additional paginated API request for every candidate workflow run.
96+
Workflow, branch, event and commit/ref filters are sent to GitHub's API. `workflow_conclusion`, `run_number`, fork filtering, `check_artifacts` and `search_artifacts` are evaluated by this action; artifact checks may require an additional paginated API request for every candidate workflow run. Expired artifacts do not satisfy `check_artifacts` or `search_artifacts`, so runs whose artifacts are gone are skipped. Candidate runs are sorted newest first by this action rather than relying on the order the API returns them in.
9797

9898
## Troubleshooting
9999

‎action.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ inputs:
6464
default: false
6565
dry_run:
6666
description: Check the existence of artifact(s) without downloading
67+
default: false
6768
if_no_artifact_found:
6869
description: |
6970
Choose how to exit the action if no artifact is found

‎main.js‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ async function main() {
3333
let checkArtifacts = core.getBooleanInput("check_artifacts")
3434
let searchArtifacts = core.getBooleanInput("search_artifacts")
3535
const allowForks = core.getBooleanInput("allow_forks")
36-
let dryRun = core.getInput("dry_run")
36+
let dryRun = core.getBooleanInput("dry_run")
3737

3838
const client = github.getOctokit(token)
3939
const artifactClient = new artifact.DefaultArtifactClient()
@@ -114,17 +114,18 @@ async function main() {
114114

115115
if (!runID) {
116116
const runGetter = workflow ? client.rest.actions.listWorkflowRuns : client.rest.actions.listWorkflowRunsForRepo
117-
// Note that the runs are returned in most recent first order.
118117
for await (const runs of client.paginate.iterator(runGetter, {
119118
owner: owner,
120119
repo: repo,
120+
per_page: 100,
121121
...(workflow ? { workflow_id: workflow } : {}),
122122
...(branch ? { branch } : {}),
123123
...(event ? { event } : {}),
124124
...(commit ? { head_sha: commit } : {}),
125125
}
126126
)) {
127-
for (const run of runs.data) {
127+
// Do not rely on the API returning runs in most recent first order, it sometimes does not.
128+
for (const run of runs.data.sort((a, b) => b.id - a.id)) {
128129
if (runNumber && run.run_number != runNumber) {
129130
continue
130131
}
@@ -136,11 +137,11 @@ async function main() {
136137
continue
137138
}
138139
if (checkArtifacts || searchArtifacts) {
139-
const artifacts = await client.paginate(client.rest.actions.listWorkflowRunArtifacts, {
140+
const artifacts = (await client.paginate(client.rest.actions.listWorkflowRunArtifacts, {
140141
owner: owner,
141142
repo: repo,
142143
run_id: run.id,
143-
})
144+
})).filter(artifact => !artifact.expired)
144145
if (artifacts.length === 0 || (searchArtifacts && !artifacts.some(matchesName))) continue
145146
}
146147

0 commit comments

Comments
 (0)