触发 github 工作流调度事件后获取 运行 id

Get run id after triggering a github workflow dispatch event

我正在通过 github 的其余部分 api 触发工作流 运行。但是 github 不会在响应正文 (204) 中发送任何数据。 我如何获得触发请求的 运行 id? 我知道 getRunsList api,它将 return 运行s 作为工作流 ID,然后我可以获得最新的 运行,但这可能会导致问题当几乎同时提交两个请求时。

目前无法在调度响应本身中获取与调度 API 调用关联的 run_id,但是如果您可以编辑您的 worflow 文件,则有一种方法可以找到它有一点。

您需要像这样 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

那么流程如下:

  • 运行 dispatch API 调用以及名为 idinput 在这种情况下具有随机值

    POST https://api.github.com/repos/$OWNER/$REPO/actions/workflows/$WORKFLOW/dispatches
    
  • 在循环中获取自现在减去 5 分钟后创建的 运行s(增量是为了避免任何时间问题):

    GET https://api.github.com/repos/$OWNER/$REPO/actions/runs?created=>$run_date_filter
    

example

  • 在 运行 API 响应中,您将得到一个 jobs_url,您将调用:

    GET https://api.github.com/repos/$OWNER/$REPO/actions/runs/[RUN_ID]/jobs
    
  • 作业 API 在上面调用 returns 作业列表,因为您已将 id 作业声明为第一个作业,它将位于第一个位置.它还为您提供 stepsname 的步骤。像这样:

{
  "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"
}

id 步骤的 name 正在 returning 您的输入值,因此您可以放心地确认是由您的 dispatch 触发的 运行打电话

这是 中此流程的一个实现,它将 return 工作流 运行 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}")

gist link

示例输出

$ 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 检索工作流输入,那会更容易,但目前无法做到这一点

请注意,在 worflow 文件中,我使用 ${{github.event.inputs.id}},因为 ${{inputs.id}} 不起作用。当我们使用它作为步骤名称时,似乎 inputs 没有被评估

获取 WORKFLOWID

gh workflow list --repo <repo-name>

workflow_dispatch

类型的触发器工作流
gh workflow run $WORKFLOWID --repo <repo-name>

return需要run-id得到执行状态

获取最新的run-idWORKFLOW_RUNID

gh run list -w $WORKFLOWID --repo <repo> -L 1 --json databaseId | jq '.[]| .databaseId'

获取工作流程运行详细信息

gh run view --repo <repo> $WORKFLOW_RUNID

这是我们所做的解决方法。它并不完美,但应该可以。

整个想法是知道哪个 运行 被调度,当 id 被建议在调度时使用时,这个 id 应该在对这个 url 的 GET 调用的响应中找到“actions/runs”所以现在用户能够识别正确的 运行 监视器。注入的 ID 不是响应的一部分,因此提取另一个 url 来查找您的 ID 没有帮助,因为这是识别 运行 以进行监控

所需的点