GitHub Actions' required properties aren't always required

Featured image for sharing metadata for article

Earlier today on Renovate we noticed that our documentation site had not been deploying for a couple of days.

The root cause was down to a quirk of GitHub Actions, where a required property isn't actually always enforced to be required πŸ˜…

To explain this, let's look at the following composite action:

# .github/actions/setup-node/action.yml
name: 'Setup Node and install dependencies'
description: 'Setup Node and install dependencies using cache'
inputs:
  node-version:
    description: 'Node version'
    required: true
  os:
    description: 'Composite actions do not support `runner.os`, so it must be passed in as an input'
    required: true
  save-cache:
    description: 'Save cache when needed'
    required: false
    default: 'false'
runs:
  using: 'composite'
  steps:
    - name: Calculate `CACHE_KEY`
      shell: bash
      run: |
        echo 'CACHE_KEY=node_modules-${{
          inputs.os
        }}-${{
          inputs.node-version
        }}-${{
          hashFiles('pnpm-lock.yaml', 'package.json')
        }}' >> "$GITHUB_ENV"        

     # ...

This is then used as part of our build:

# .github/workflows/build.yml
  build-deploy-docs-site:
    needs: release

    permissions: # ...

    environment: # ...

    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          show-progress: false

      - name: Setup Node.js
        uses: ./.github/actions/setup-node
        with:
          node-version: ${{ needs.setup-build.outputs.node-version }}
          os: ${{ runner.os }}

Can you spot what's wrong here?

You may notice this line:

          node-version: ${{ needs.setup-build.outputs.node-version }}

We're referencing a job, but that wasn't found in our needs definition.

In this case, GitHub Actions is therefore evaluating this statement as the empty string, resolving as node-version: "".

Because there is technically something passed to the node-version argument, required: true isn't flagging any issues.

In my opinion, required: true should error if it's receiving empty input, but maybe this is instead a slightly painful gotcha, but one I'm now going to going to remember going forwards.

We've since added a check in our composite action to fail the build if either required: true options are unset.

It looks like actionlint would have caught this too - so that's on my TODO list to add to our CI pipelines now, too!

Written by Jamie Tanna's profile image Jamie Tanna on , and last updated on .

Content for this article is shared under the terms of the Creative Commons Attribution Non Commercial Share Alike 4.0 International, and code is shared under the GNU Affero General Public License v3.0 only.

#blogumentation #github #github-actions.

This post was filed under articles.

Interactions with this post

Interactions with this post

Below you can find the interactions that this page has had using WebMention.

Have you written a response to this post? Let me know the URL:

Do you not have a website set up with WebMention capabilities? You can use Comment Parade.