At first glance GitHub’s API docs are fairly extensive, but they make a mistake I see very commonly in API documentation which is providing zero or no examples for values that are technically unformatted, but reference something very specific. In this case it’s the contexts key for required status checks. You can set these via the web interface with handy autocompletion, but that doesn’t show you what the value it uses behind the scenes actually is. This is something that can be queried through the API but only from a full GitHub app, not personal API tokens dramatically increasing the friction in seeing what is currently set.

Best practices for managing infrastructure (and yes that includes your GitHub repository config) is via versioned config files. GitHub Settings App allows you to do this inside the repository itself by creating a .github/settings.yml file in your repository. A current limitation of this approach is there isn’t a way to test your changes within the repo you’re making the change in (it only applies what is in your main branch). You can use other tools such as Terraform to manage your repositories, but this is convenient, simple, and keeps the config close to infrastructure you’re managing.

I hit this annoying lack of documentation when I was trying to enforce GitHub workflows passing before allowing PRs to be merged (aka branch protection rules). Searching online for the solution led to a lot of complaints about the limitations of GitHub actions and similar issues without a published solution. Let’s start with a concrete example of a workflow I want to enforce on a Rust repository, specifically checking for security advisories and validating license and dependencies match our configured policies before accepting changes into our codebase. This workflow file for me lives at .github/workflows/audits.yml:

name: Dependency Security & License Audit
on:
  - pull_request
jobs:
  cargo-deny:
    runs-on: ubuntu-22.04
    strategy:
      matrix:
        checks:
          - advisories
          - bans licenses sources
    continue-on-error: ${{ matrix.checks == 'advisories' }}
    steps:
    - uses: actions/checkout@v3
    - uses: EmbarkStudios/cargo-deny-action@v1
      with:
        command: check ${{ matrix.checks }}
        arguments: --all-features

The only example given for status checks is the useful very string “continuous-integration/travis-ci”. In GitHub’s defense, these status strings can be used from any third party app our utility and when used this way are entirely unformatted. With GitHub actions though, that string should be predictable and documented somewhere. It’s probably the most common use case for required status checks and entirely ignored by their documentation. Based off various posted questions and issues I was able to find I gave the following strings a try:

  • audits, audits.yml: The filename of the workflow
  • Dependency Security & License Audit: The name of the workflow
  • cargo-deny: The name of the job
  • audits/cargo-deny: The workflow filename/job name.
  • github-actions-audits-cargo-deny: A string that was uselessly recommended by ChatGPT
  • Dependency Security & License Audit (advisories), Dependency Security & License Audit (bans licenses sources): The two titles that show up in PRs when the workflow (there is a 2 entry matrix for this workflow).

I finally figured it out by inspecting an individual workflow run which had the job names cargo-deny (advisories) and cargo-deny (bans licenses sources). If you’re not using a matrix in your workflow, the name of the job appears to be the value you’re looking for (cargo-deny in this case) but if you’re also using matrixes you need to include their value in parens after the name. If this isn’t working for you, they might be interacting with another feature in an unknown way but you should be able to figure out the correct value by following these steps:

  1. Allow the workflow job to run at least once
  2. Navigate to your GitHub repository page
  3. Click on the “Actions” tab
  4. Select the relevant workflow from the left hand side (Dependency Security & License Audit in my case)
  5. Click into one of the workflow runs (success or failure of the run doesn’t matter here)
  6. Check the names on the left hand side under the Jobs section, these are what you’re looking for

For completeness, my final working example is:

branches:
  - name: master
    protection:
      required_pull_request_reviews:
        required_approving_review_count: 1
        dismiss_stale_reviews: true
      required_status_checks:
        strict: true
        contexts:
          - "cargo-deny (advisories)"
          - "cargo-deny (bans licenses sources)"
      enforce_admins: true
      restrictions: null
      required_linear_history: false

The null value on that restrictions key is due to an unrelated bug in the GitHub Settings App and how the GitHub.

Don’t be like GitHub. Provide examples with your documentations, don’t blindly trust API doc generation tools and assume the types alone are sufficient, especially if you’re integrating with your own tools.