我正在通过 github 的 REST API 触发工作流程运行。但 github 不会在响应正文中发送任何数据 (204)。 如何获取触发请求的运行 ID? 我知道
getRunsList
api,它会返回工作流 ID 的运行,然后我可以获得最新的运行,但是当几乎同时提交两个请求时,这可能会导致问题。
目前无法在调度响应本身中获取与调度 API 调用关联的 run_id,但如果您可以稍微编辑一下 woflow 文件,就有办法找到它。
您需要使用
input
来调度工作流程,如下所示:
curl "https://api.github.com/repos/$OWNER/$REPO/actions/workflows/$WORKFLOW/dispatches" -s \
-H "Authorization: Token $TOKEN" \
-d '{
"ref":"master",
"inputs":{
"id":"12345678"
}
}'
还可以使用可选的
input
(此处名为 id
)编辑工作流程 yaml 文件。另外,将其作为第一个作业,该作业具有与输入 id
值同名的单个步骤(这就是我们使用 API 取回 id 的方式!):
name: ID Example
on:
workflow_dispatch:
inputs:
id:
description: 'run identifier'
required: false
jobs:
id:
name: Workflow ID Provider
runs-on: ubuntu-latest
steps:
- name: ${{github.event.inputs.id}}
run: echo run identifier ${{ inputs.id }}
这里的技巧是使用
name: ${{github.event.inputs.id}}
https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#inputs
那么流程如下:
运行调度 API 调用以及名为
input
的 id
,在本例中使用随机值
POST https://api.github.com/repos/$OWNER/$REPO/actions/workflows/$WORKFLOW/dispatches
在循环中获取自现在减去 5 分钟以来创建的运行(增量是为了避免任何计时问题):
GET https://api.github.com/repos/$OWNER/$REPO/actions/runs?created=>$run_date_filter
在运行 API 响应中,您将获得一个
jobs_url
,您将调用它:
GET https://api.github.com/repos/$OWNER/$REPO/actions/runs/[RUN_ID]/jobs
上面的作业 API 调用返回作业列表,因为您已将
id
作业声明为第一个作业,它将位于第一个位置。它还为您提供 steps
以及步骤的 name
。像这样的东西:
{
"id": 3840520726,
"run_id": 1321007088,
"run_url": "https://api.github.com/repos/$OWNER/$REPO/actions/runs/1321007088",
"run_attempt": 1,
"node_id": "CR_kwDOEi1ZxM7k6bIW",
"head_sha": "4687a9bb5090b0aadddb69cc335b7d9e80a1601d",
"url": "https://api.github.com/repos/$OWNER/$REPO/actions/jobs/3840520726",
"html_url": "https://github.com/$OWNER/$REPO/runs/3840520726",
"status": "completed",
"conclusion": "success",
"started_at": "2021-10-08T15:54:40Z",
"completed_at": "2021-10-08T15:54:43Z",
"name": "Hello world",
"steps": [
{
"name": "Set up job",
"status": "completed",
"conclusion": "success",
"number": 1,
"started_at": "2021-10-08T17:54:40.000+02:00",
"completed_at": "2021-10-08T17:54:42.000+02:00"
},
{
"name": "12345678", <=============== HERE
"status": "completed",
"conclusion": "success",
"number": 2,
"started_at": "2021-10-08T17:54:42.000+02:00",
"completed_at": "2021-10-08T17:54:43.000+02:00"
},
{
"name": "Complete job",
"status": "completed",
"conclusion": "success",
"number": 3,
"started_at": "2021-10-08T17:54:43.000+02:00",
"completed_at": "2021-10-08T17:54:43.000+02:00"
}
],
"check_run_url": "https://api.github.com/repos/$OWNER/$REPO/check-runs/3840520726",
"labels": [
"ubuntu-latest"
],
"runner_id": 1,
"runner_name": "Hosted Agent",
"runner_group_id": 2,
"runner_group_name": "GitHub Actions"
}
name
步骤的id
正在返回您的输入值,因此您可以安全地确认这次运行是由您的调度调用触发的
这是此流程在 python 中的实现,它将返回工作流程运行 id:
import random
import string
import datetime
import requests
import time
# edit the following variables
owner = "YOUR_ORG"
repo = "YOUR_REPO"
workflow = "dispatch.yaml"
token = "YOUR_TOKEN"
authHeader = { "Authorization": f"Token {token}" }
# generate a random id
run_identifier = ''.join(random.choices(string.ascii_uppercase + string.digits, k=15))
# filter runs that were created after this date minus 5 minutes
delta_time = datetime.timedelta(minutes=5)
run_date_filter = (datetime.datetime.utcnow()-delta_time).strftime("%Y-%m-%dT%H:%M")
r = requests.post(f"https://api.github.com/repos/{owner}/{repo}/actions/workflows/{workflow}/dispatches",
headers= authHeader,
json= {
"ref":"master",
"inputs":{
"id": run_identifier
}
})
print(f"dispatch workflow status: {r.status_code} | workflow identifier: {run_identifier}")
workflow_id = ""
while workflow_id == "":
r = requests.get(f"https://api.github.com/repos/{owner}/{repo}/actions/runs?created=%3E{run_date_filter}",
headers = authHeader)
runs = r.json()["workflow_runs"]
if len(runs) > 0:
for workflow in runs:
jobs_url = workflow["jobs_url"]
print(f"get jobs_url {jobs_url}")
r = requests.get(jobs_url, headers= authHeader)
jobs = r.json()["jobs"]
if len(jobs) > 0:
# we only take the first job, edit this if you need multiple jobs
job = jobs[0]
steps = job["steps"]
if len(steps) >= 2:
second_step = steps[1] # if you have position the run_identifier step at 1st position
if second_step["name"] == run_identifier:
workflow_id = job["run_id"]
else:
print("waiting for steps to be executed...")
time.sleep(3)
else:
print("waiting for jobs to popup...")
time.sleep(3)
else:
print("waiting for workflows to popup...")
time.sleep(3)
print(f"workflow_id: {workflow_id}")
样本输出
$ python3 github_action_dispatch_runid.py
dispatch workflow status: 204 | workflow identifier: Z7YPF6DD1YP2PTM
get jobs_url https://api.github.com/repos/OWNER/REPO/actions/runs/1321463229/jobs
get jobs_url https://api.github.com/repos/OWNER/REPO/actions/runs/1321463229/jobs
get jobs_url https://api.github.com/repos/OWNER/REPO/actions/runs/1321463229/jobs
get jobs_url https://api.github.com/repos/OWNER/REPO/actions/runs/1321475221/jobs
waiting for steps to be executed...
get jobs_url https://api.github.com/repos/OWNER/REPO/actions/runs/1321463229/jobs
get jobs_url https://api.github.com/repos/OWNER/REPO/actions/runs/1321475221/jobs
waiting for steps to be executed...
get jobs_url https://api.github.com/repos/OWNER/REPO/actions/runs/1321463229/jobs
get jobs_url https://api.github.com/repos/OWNER/REPO/actions/runs/1321475221/jobs
waiting for steps to be executed...
get jobs_url https://api.github.com/repos/OWNER/REPO/actions/runs/1321463229/jobs
get jobs_url https://api.github.com/repos/OWNER/REPO/actions/runs/1321475221/jobs
get jobs_url https://api.github.com/repos/OWNER/REPO/actions/runs/1321463229/jobs
workflow_id: 1321475221
如果有一种方法可以通过 API 检索工作流程输入,那就更容易了,但目前还没有办法做到这一点
请注意,在工作流程文件中,我使用
${{github.event.inputs.id}}
,因为 ${{inputs.id}}
不起作用。当我们使用它作为步骤名称时,似乎 inputs
没有被评估
获取工作流ID
gh workflow list --repo <repo-name>
触发workflow_dispatch类型的工作流
gh workflow run $WORKFLOWID --repo <repo-name>
它不返回获取执行状态所需的run-id
获取最新的运行ID WORKFLOW_RUNID
gh run list -w $WORKFLOWID --repo <repo> -L 1 --json databaseId | jq '.[]| .databaseId'
获取工作流程运行详细信息
gh run view --repo <repo> $WORKFLOW_RUNID
这是我们所做的解决方法。它并不完美,但应该可以工作。
受到上面评论的启发,制作了一个 /bin/bash 脚本来获取你的 $run_id
name: ID Example
on:
workflow_dispatch:
inputs:
id:
description: 'run identifier'
required: false
jobs:
id:
name: Workflow ID Provider
runs-on: ubuntu-latest
steps:
- name: ${{github.event.inputs.id}}
run: echo run identifier ${{ inputs.id }}
workflow_id=生成一个随机的8位数字
现在,稍后,date_filter=用于时间过滤器,现在 - 5 分钟 \
TOKEN="" \
GH_USER="" \
REPO="" \
REF=""
WORKFLOW_ID=$(tr -dc '0-9' </dev/urandom | head -c 8) \
NOW=$(date +"%Y-%m-%dT%H:%M") \
LATER=$(date -d "-5 minutes" +"%Y-%m-%dT%H:%M") \
DATE_FILTER=$(echo "$NOW-$LATER") \
JSON=$(cat <<-EOF
{"ref":"$REF","inputs":{"id":"$WORKFLOW_ID"}}
EOF
) && \
curl -s \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $TOKEN" \
"https://api.github.com/repos/$GH_USER/$REPO/actions/workflows/main.yml/dispatches" \
-d $JSON && \
INFO="null" \
COUNT=1 \
ATTEMPTS=10 && \
until [[ $CHECK -eq $WORKFLOW_ID ]] || [[ $COUNT -eq $ATTEMPTS ]];do
echo -e "$(( COUNT++ ))..."
INFO=$(curl -s \
-X GET \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $TOKEN" \
"https://api.github.com/repos/$GH_USER/$REPO/actions/runs?created:<$DATE_FILTER" | jq -r '.workflow_runs[].id' | grep -m1 "")
CHECK=$(curl -s \
-X GET \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $TOKEN" \
"https://api.github.com/repos/$GH_USER/$REPO/actions/runs/$INFO/jobs" | jq -r '.jobs[].steps[].name' | grep -o '[[:digit:]]*')
sleep 5s
done
echo "Your run_id is $CHECK"
输出:
1...
2...
3...
Your run_id is 67530050
我建议使用确信/触发工作流程并等待操作:
- name: Example
uses: convictional/[email protected]
with:
owner: my-org
repo: other-repo
workflow_file_name: other-workflow.yaml
github_token: ${{ secrets.GH_TOKEN }}
client_payload: '{"key1": "value1", "key2": "value2"}'
这负责等待其他作业并根据其他工作流程是成功还是失败返回成功或失败。它以一种强大的方式来处理几乎同时触发的多个运行。
如果您正在寻找一种可靠的方法来在分派工作流程后获取运行 ID,请查看 return-dispatch GitHub Action。它简化了流程并提供了简单的解决方案。
简单使用-
- name: Dispatch an action and get the run ID
uses: codex-/return-dispatch@v1
id: return_dispatch
with:
token: ${{ secrets.ACCESS_TOKEN }} # Note this is NOT GITHUB_TOKEN but a PAT
ref: githubActions_iOS/build # or refs/heads/target_branch
repo: feature
owner: mr-x
workflow: shared.yml
workflow_inputs: '{ "distinct_id": "123" }' # Optional
workflow_timeout_seconds: 120 # Default: 300
接下来你可以读取run_id
- name: Use the output run ID
run: echo ${{steps.return_dispatch.outputs.run_id}}
lasith-kg/dispatch-workflow@v1
的 GitHub Action,它使用 repository_dispatch
或 workflow_dispatch
事件分派工作流程,并具有可选标志 discover: true
。启用此标志后,它会将唯一的 UUID 注入工作流运行名称,以便它可以与初始调度事件相关联。发现工作流程后,即可从步骤输出中获取运行 ID 和运行 URL。
steps:
- uses: lasith-kg/dispatch-workflow@v1
id: dispatch-with-discovery
name: "Dispatch Workflow With Discovery"
with:
dispacth-method: workflow_dispatch | repository_dispatch
...
discover: true
discover-timeout-seconds: 30 # Optional: Default to 30 seconds
- id: echo-run-id-url
name: "Echo Run ID and Run URL"
run: |
echo "${{ steps.dispatch-with-discovery.outputs.run-id }}"
echo "${{ steps.dispatch-with-discovery.outputs.run-url }}"
当然,需要修改接收工作流程以在
run-name
[参考] 中拦截此 UUID
整个想法是知道调度了哪个运行,当建议在调度时使用 id 时,预计可以在对此 url“actions/runs”的 GET 调用的响应中找到该 id,因此现在用户能够识别正确运行以进行监控。注入的 id 不是响应的一部分,因此提取另一个 url 来查找您的 id 没有帮助,因为这是 id 需要识别运行以进行监控的点