Skipping Jobs in GitHub Actions when Secrets are Unavailable

Jim King

Jim King

How to Securely Inject Configuration Secrets into GitHub

CloudTruth’s configure-action for GitHub allows you securely inject configuration secrets into GitHub with this addition to the GitHub Actions workflow files. The build process for the action has a few jobs that require a secret to demonstrate the behavior. For security reasons, GitHub normally restricts secrets from being used in a pull request that comes from a fork. This becomes obvious very quickly when pull requests from Dependabot are failing some build steps because secrets were not available.

We added recording to our unit tests using a very nice wrapper around polly.js called @scaleleap/jest-polly so that they could run even from a fork. We were still left with a few build jobs that demonstrate the action behavior which still require a secret. Our first attempt to fix this was to make certain GitHub Actions’ jobs were conditional based on the presence of a secret:

jobs:
  demo:
    runs-on: ubuntu-latest
    if: ${{ secrets.CLOUDTRUTH_API_KEY != null }}
    steps:
      - ...

Unfortunately, this did not work – fortunately, the error message is pretty clear:

The workflow is not valid. .github/workflows/demo.yml (Line: 4, Col: 9): 
  Unrecognized named-value: 'secrets'. 
  Located at position 1 within expression: secrets.CLOUDTRUTH_API_KEY != null

The GitHub documentation about this conditional is vague, stating that only supported contexts can be used, but it does not specify which ones are supported. Sadly, it looks like secrets are one of the unsupported contexts. 😞

Fortunately, needs is supported in job conditionals, and though it is more verbose than one might like, it does correctly limit job execution to situations where secrets are available. The secrets-gate job runs a step that checks whether secret content is available, and sets the output of the job for other jobs to check:

jobs:
  secrets-gate:
    runs-on: ubuntu-latest
    outputs:
      ok: ${{ steps.check-secrets.outputs.ok }}
    steps:
      - name: check for secrets needed to run demo
        id: check-secrets
        run: |
          if [ ! -z "${{ secrets.CLOUDTRUTH_API_KEY }}" ]; then
            echo "::set-output name=ok::true"
          fi

  demo:
    needs:
      - secrets-gate
    if: ${{ needs.secrets-gate.outputs.ok == 'true' }}
    runs-on: ubuntu-latest
    steps:
      - ...

With this addition to the GitHub Actions workflow files, we were able to make certain jobs conditional on the presence of secrets. This allows our own pull requests and pushes into the main branch to run everything, while pull requests from forks are able to complete all the steps that do not require secrets – namely the unit tests and code security sweep.

Try using CloudTruth for GitHub to securely inject configuration secrets into GitHub.


About the Author: Jim King is a software engineer, architect, startup founder, and has contributed to a number of open-source projects including Apache Thrift and Boost.