4

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

4

1 回答 1

7

目前无法在调度响应本身中获取与调度 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还可以使用选项(在此处命名)编辑您的工作流程 yaml 文件id。此外,将其作为第一个作业,该作业具有与输入值同名的单个步骤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"
}

该步骤nameid返回您的输入值,因此您可以安全地确认这是由您的调度调用触发的运行

这是此流程在中的实现,它将返回工作流运行 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没有被评估

于 2021-10-08T18:47:13.907 回答