我使用GitHub-Action进行构建,它会生成多个带有不同名称的构件。
是否有一种方法可以预测最后一次成功构建的构件URL? 不需要知道sha1,只需要知道构件的名称和仓库?
我使用GitHub-Action进行构建,它会生成多个带有不同名称的构件。
是否有一种方法可以预测最后一次成功构建的构件URL? 不需要知道sha1,只需要知道构件的名称和仓库?
https://nightly.link/
https://github.com/oprypin/nightly.link
https://api.github.com/repos/:owner/:repo/actions/workflows/someworkflow.yml/runs?per_page=1&branch=master&event=push&status=success
https://api.github.com/repos/:owner/:repo/actions/runs/123456789/artifacts?per_page=100
https://api.github.com/repos/:owner/:repo/actions/artifacts/87654321/zip
最后一个链接会将您重定向到一个短暂的直接下载URL。
请注意,需要进行身份验证。对于OAuth,这是public_repo
(如果适用,则为repo
)。对于GitHub应用程序,这是“Actions”/“只读”。
upload-artifact
操作可能会改变这一点。因此,您可以接收JSON回复并遍历“artifacts”数组以获取相应的“archive_download_url”。 工作流可以像这样填写URL:
GET /repos/:owner/:repo/actions/runs/:run_id/artifacts
/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts
curl -s https://api.github.com/repos/<OWNER>/<REPO_NAME>/actions/artifacts\?per_page\=<NUMBER_OF_ARTIFACTS_PER_BUILD> | jq '[.artifacts[] | {name : .name, archive_download_url : .archive_download_url}]' | jq -r '.[] | select (.name == "<NAME_OF_THE_ARTIFACT>") | .archive_download_url'
curl -s https://api.github.com/repos/ballerina-platform/ballerina-distribution/actions/artifacts\?per_page\=9 | jq '[.artifacts[] | {name : .name, archive_download_url : .archive_download_url}]' | jq -r '.[] | select (.name == "Linux Installer deb") | .archive_download_url'
这里,curl -s https://api.github.com/repos/<OWNER>/<REPO_NAME>/actions/artifacts\?per_page\=<NUMBER_OF_ARTIFACTS_PER_BUILD>
返回与最新构建相关的工件数组。
jq '[.artifacts[] | {name : .name, archive_download_url : .archive_download_url}]'
提取工件数组并过滤所需数据。
jq -r '.[] | select (.name == "<NAME_OF_THE_ARTIFACT>") | .archive_download_url'
选择给定工件名称的url。
per_page\=9
替换为 per_page\=1
。需要注意的是,这要求返回的构件按时间顺序降序排序,但似乎情况确实如此。 - BallpointBen最近我遇到了一个类似的用例,目的是通过单击提交状态(虽然需要用户登录github.com)使给定GitHub Actions工作流的构建产物更加可见。
正如@geoff-hutchison在他的答案中所指出的:
不过:
archive_download_url
URL似乎不太实用(它们是GitHub API URL,重定向到临时 URL)。幸运的是:
https://github.com/${{ github.repository }}/suites/${check_suite_id}/artifacts/${artifact_id}
,并且这些URL是静态的(尽管仅对已登录用户和最多90天的工件过期时间有效)。因此,我开发了以下通用代码(根据MIT许可证)来将给定工作流的所有工件固定在提交状态中(只需替换3个TODO字符串
):
.github/workflows/pin-artifacts.yml:
name: Pin artifacts
on:
workflow_run:
workflows:
- "TODO-Name Of Existing Workflow"
types: ["completed"]
jobs:
# Make artifacts links more visible for the upstream project
pin-artifacts:
permissions:
statuses: write
name: Add artifacts links to commit statuses
if: ${{ github.event.workflow_run.conclusion == 'success' && github.repository == 'TODO-orga/TODO-repo' }}
runs-on: ubuntu-latest
steps:
- name: Add artifacts links to commit status
run: |
set -x
workflow_id=${{ github.event.workflow_run.workflow_id }}
run_id=${{ github.event.workflow_run.id }} # instead of ${{ github.run_id }}
run_number=${{ github.event.workflow_run.run_number }}
head_branch=${{ github.event.workflow_run.head_branch }}
head_sha=${{ github.event.workflow_run.head_sha }} # instead of ${{ github.event.pull_request.head.sha }} (or ${{ github.sha }})
check_suite_id=${{ github.event.workflow_run.check_suite_id }}
set +x
curl \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/actions/runs/${run_id}/artifacts" \
| jq '[.artifacts | .[] | {"id": .id, "name": .name, "created_at": .created_at, "expires_at": .expires_at, "archive_download_url": .archive_download_url}] | sort_by(.name)' \
> artifacts.json
cat artifacts.json
< artifacts.json jq -r ".[] | \
.name + \"§\" + \
( .id | tostring | \"https://github.com/${{ github.repository }}/suites/${check_suite_id}/artifacts/\" + . ) + \"§\" + \
( \"Link to \" + .name + \".zip [\" + ( .created_at | sub(\"T.*\"; \"→\") ) + ( .expires_at | sub(\"T.*\"; \"] (you must be logged)\" ) ) )" \
| while IFS="§" read name url descr; do
curl \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ github.token }}" \
"https://api.github.com/repos/${{ github.repository }}/statuses/${head_sha}" \
-d "$( printf '{"state":"%s","target_url":"%s","description":"%s","context":"%s"}' "${{ github.event.workflow_run.conclusion }}" "$url" "$descr" "$name (artifact)" )"
done
(如有需要,还可以查看我的PR ocaml-sf/learn-ocaml#501以查看实现示例和此GHA工作流程的屏幕截图。)
我不是GitHub和jq大师。可能有更优化的解决方案。
jq playground链接:https://jqplay.org/s/Gm0kRcv63C - 用于测试我的解决方案和其他可能的想法。我删除了一些无关的字段以缩小示例JSON的大小(例如:node_id,size_in_bytes,created_at...)下面的代码示例中有更多详细信息。
####### You can get the max date of your artifacts.
####### Then you need to choose the artifact entry by this date.
#######
####### NOTE: I just pre-formatted the first command "line".
####### 2nd "line" has a very similar, but simplified structure.
####### (at least easy to copy-paste into jq playground)
####### NOTE: ASSUMPTION:
####### First "page" of json response contains the most recent entries
####### AND includes artifact(s) with that specific name.
#######
####### (if other artifacts flood your API response, you can increase
####### the page size of it or do iteration on pages as a workaround)
bash$ cat artifact_response.json | \
jq '
(
[
.artifacts[]
| select(.name == "my-artifact" and .expired == false)
| .updated_at
]
| max
) as $max_date
| { $max_date }'
####### output
{ "max_date": "2021-04-29T11:22:20Z" }
另一种方式:
####### Latest ID of non-expired artifacts with a specific name.
####### Probably this is better solution than the above since you
####### can use the "id" instantly in your download url construction:
#######
####### "https://api.github.com/repos/blabla.../actions/artifacts/92394368/zip"
#######
####### ASSUMPTION: higher "id" means higher "update date" in your workflow
####### (there is no post-update of artifacts aka creation and
####### update dates are identical for an artifact)
cat artifact_response.json | \
jq '[ .artifacts[] | select(.name == "my-artifact" and .expired == false) | .id ] | max'
####### output
92394368
####### no full command line, just jq filter string
#######
####### no "max" function, only pick the first element by index
#######
'[ .artifacts[] | select(.name == "my-artifact" and .expired == false) | .id ][0]'