1

Context:

  • I have a PR 12345 towards protected branch (master)
  • This branch is set up to require two jobs for merging: one from GitLab CI gitlab/some-required-test, and one from GitHub Action some-required-github-action
  • Apart from that I have a ton of non-required jobs in each GL and GH. I don't care about those.
  • I want to check via GitHub API if the PR has passed all required checks only.

This is similar to Get if pull request passed all required status checks using GitHub API but in particular I want to know if the ones from github-actions have passed which seems very complicated.

The ones from GitLab are easy, by querying https://api.github.com/repos/OWNER/REPO/commits/REFNAME/status I get a reasonably shaped response with all necessary info. But it's only having GitLab check, not GitHub actions.

{
  state: 'pending',
  statuses: [
    {
        state: 'success',
        context: 'gitlab/check-1',
    },
    {
        state: 'pending',
        context: 'gitlab/check-2',
    }
  ]
  ...
}

So, first, I figured that by querying an endpoint for branch protections, I can figure out the required checks. So far so good:

curl https://api.github.com/repos/ORG/REPO/branches/PROTECTED_BRANCH_NAME/protection/required_status_checks 

{
    "url": "https://api.github.com/repos/ORG/REPO/branches/PROTECTED_BRANCH_NAME/protection/required_status_checks",
    "strict": false,
    "contexts": [
      "gitlab/some-required-test",
      "some-required-github-action"
    ],
    "contexts_url": "https://api.github.com/repos/ORG/REPO/branches/PROTECTED_BRANCH_NAME/protection/required_status_checks/contexts",
    "checks": [
      {
        "context": "gitlab/some-required-test",
        "app_id": null
      },
      {
        "context": "some-required-github-action",
        "app_id": 15368
      }
    ]
}

(app_id 15368 corresponds to "GitHub Actions" app).

Let's now check the status of the checks:

curl https://api.github.com/repos/ORG/REPO/commits/PR_BRANCH/check-suites


{
  "total_count": 10,
  "check_suites": [{
      "id": 10271137035,
      "node_id": "CS_kwDOCf2-888AAAACZDUdKQ",
      "head_branch": "BRANCHNAME",
      "head_sha": "936b3031077ba7b71e0233fec23783ca0d3ed93e",
      "status": "completed",
      "conclusion": "success",
      "url": "https://api.github.com/repos/OWNER/REPO/check-suites/10271137065",
      "before": "8e579556a3909a0d25dbdd34e6ff0a9535653848",
      "after": "936b3031077ba7b71e0233fec23783ca0d3ed93e",
      "pull_requests": [...],
      "app": {
        "id": 15368,
        "slug": "github-actions",
        "node_id": "MDM6QXBwMTUzNjg=",
        "owner": {
          "login": "github",
          ...
        },
        "name": "GitHub Actions",
        "description": "Automate your workflow from idea to production",
        "external_url": "https://help.github.com/en/actions",
        "html_url": "https://github.com/apps/github-actions",
        "created_at": "2018-07-30T09:30:17Z",
        "updated_at": "2019-12-10T19:04:12Z",
        "permissions": {
          ...
        },
        "events": [
          ...
        ]
      },
      "created_at": "2023-01-09T21:36:29Z",
      "updated_at": "2023-01-09T21:38:16Z",
      "rerequestable": true,
      "runs_rerequestable": false,
      "latest_check_runs_count": 1,
      "check_runs_url": "https://api.github.com/repos/OWNER/REPO/check-suites/10271137035/check-runs",
      "head_commit": {
        "id": "936b3031077ba7b71e0233fec23783ca0d3ed93e",
        "tree_id": "4f341091f31a419915f6d8b70f42febdd115ee2f",
        "message": "COMMIT MESSAGE",
        "timestamp": "2023-01-09T21:36:12Z",
        "author": {...},
        "committer": {...}
      },
      "repository": {...}
  }, ...]
}

I get a large array of check_suites but the response is only moderately helpful: By checking app.id / app.slug + status / conclusion I can see that some GitHub action has completed, but without details whether it is required, and what is its name.

I figured I can check .latest_check_runs_count and if > 0, check check_runs_url:

curl https://api.github.com/repos/ORG/REPO/check-suites/10271137035/check-runs

{
  "total_count": 1,
  "check_runs": [
    {
      "id": 10536722916,
      "name": "some-required-github-action",
      "node_id": "CR_kwDOCf2-888AAAACdAmh5A",
      "head_sha": "936b3031077ba7b71e0233fec23783ca0d3ed93e",
      "external_id": "373218f8-38be-52de-27db-c87f3616be12",
      "url": "https://api.github.com/repos/ORG/REPO/check-runs/10536722916",
      "html_url": "https://github.com/ORG/REPO/actions/runs/3877963115/jobs/6613591600",
      "details_url": "https://github.com/ORG/REPO/actions/runs/3877963115/jobs/6613591600",
      "status": "completed",
      "conclusion": "success",
      "started_at": "2023-01-09T21:36:38Z",
      "completed_at": "2023-01-09T21:38:14Z",
      "output": {
        "title": null,
        "summary": null,
        "text": null,
        "annotations_count": 0,
        "annotations_url": "https://api.github.com/repos/ORG/REPO/check-runs/10536722916/annotations"
      }
    }
  ]
}

Then I can inspect check_runs[i].name and if it's one of required ones obtained earlier, check check_runs[i].status / check_runs[i].conclusion. (In the example, it's "some-required-github-action" which I was looking for)

But for this I have to do N requests, one for each item in .check_suites from previous step where "app.slug": "github-actions".

This sounds very convoluted. Is there a simpler way?

jakub.g
  • 38,512
  • 12
  • 92
  • 130

0 Answers0