actionlint

repository·main·Indexed 23 days ago

https://github.com/rhysd/actionlint

A static checker for GitHub Actions workflow files designed to catch syntax errors, type mismatches in expressions, incorrect action usage, and security vulnerabilities. It provides strong type checking for ${{ }} expressions, validates reusable workflows, and integrates with shellcheck and pyflakes for scripts within run: blocks. actionlint can be used as a CLI tool, via Docker, in an online playground, or integrated as a Go library.

Tokens
34.2K
Snippets
80
Records
243
Agent score
85%

What's inside actionlint

  1. Overview of actionlint features

    main

    actionlint is a static checker for GitHub Actions workflow files that provides the following checks:

    • Syntax check: Validates workflow files for unexpected or missing keys.
    • Strong type check for ${{ }} expressions: Catches semantic errors like accessing non-existent properties or type mismatches.
    • Actions usage check: Verifies that with: inputs and steps.{id}.outputs are correct for used actions.
    • Reusable workflow check: Validates inputs, outputs, and secrets for reusable workflows and workflow calls.
    • Script integration: Integrates shellcheck and pyflakes for scripts within run: blocks.
    • Security checks: Detects potential script injection from untrusted inputs and hard-coded credentials.
    • Other checks: Validates glob syntax, needs: dependencies, runner labels, and cron syntax.
  2. Run actionlint to check workflows

    main

    To check your GitHub Actions workflow files, run the actionlint command in your repository. The tool automatically detects workflow files and checks for errors such as syntax mistakes, type mismatches in expressions, incorrect action inputs, and security vulnerabilities.

    Alternatively, you can use the online playground to run actionlint in your browser via WebAssembly.

    actionlint
  3. Validate Runner labels in `runs-on`

    main

    The actionlint tool checks that the labels provided in the runs-on: section are valid. This includes validating GitHub-hosted runner labels and resolving expressions (like ${{ matrix.runner }}) to check their possible values.

    Key Features:

    • Label Validation: Detects unknown or deprecated labels (e.g., macos-10.13).
    • Custom Labels: For self-hosted runners with custom labels, you must define these labels in your actionlint.yaml configuration file so actionlint can recognize them.
    • Conflict Detection: Detects conflicting label combinations in an array (e.g., [ubuntu-latest, windows-latest]). To run on multiple runners, use a matrix instead of an array in runs-on.

    Correct usage for multiple runners:

    jobs:
      test:
        strategy:
          matrix:
            os: [ubuntu-latest, windows-latest]
        runs-on: ${{ matrix.os }}
  4. How actionlint handles YAML anchors and aliases

    main

    actionlint supports GitHub Actions YAML anchors and aliases. When an alias node references an anchor, actionlint validates the content as if the alias were replaced by the anchor node itself.

    Key behaviors:

    • Multiple Reports: Because one anchor may be used in multiple places, actionlint may report similar errors at the same source location for every alias that references that anchor.
    • Recursive Aliases: actionlint detects and reports errors for recursive alias references.
    • Unused Anchors: actionlint reports errors when an anchor is defined but never used.
    • Dangling Aliases: actionlint detects and reports syntax errors for aliases that reference undefined anchors (though error positioning may currently be inaccurate due to the underlying go-yaml library).
    on: push
    
    jobs:
      test:
        services:
          nginx:
            image: nginx:latest
            credentials: &credentials
              username: my-user-name
              password: P@ssw0rd
              # ERROR: Unexpected key 'email'
              email: me@example.com
          redis:
            image: redis:latest
            credentials: *credentials
        runs-on: ubuntu-latest
        steps:
          - run: ./do_something.sh
  5. Install actionlint on Windows

    main

    You can install actionlint on Windows using several package managers:

    • Chocolatey: Use choco install actionlint.
    • Scoop: Use scoop install actionlint.
    • Winget: Use winget install actionlint.
    # Chocolatey
    choco install actionlint
    
    # Scoop
    scoop install actionlint
    
    # Winget
    winget install actionlint
  6. Validate Local action inputs at `with:`

    main

    When using a local action (defined via ./path/to/action), actionlint reads the action.yml (or action.yaml) file in that directory to validate the inputs provided in the with: block of your workflow.

    What is checked:

    • Missing Required Inputs: Ensures all inputs marked as required: true in the action's definition are provided.
    • Unexpected Inputs: Ensures no extra keys are passed to the with: block that are not defined in the action's inputs section.
    # In workflow file
    steps:
      - uses: ./.github/actions/my-action
        with:
          name: rhysd
          message: hello
  7. Follow ID naming conventions for jobs and steps

    main

    GitHub Actions IDs (for jobs and steps) must follow specific naming rules. actionlint enforces these to prevent workflow errors.

    Rules:

    • Must start with a letter or _.
    • Can only contain alphanumeric characters, -, or _.
    • Cannot start with numbers or -.
    • Cannot contain spaces or special characters like ..
  8. Validate reusable workflow input definitions

    main

    When defining a reusable workflow using the workflow_call event, actionlint validates the inputs configuration.

    Key validation rules:

    • Type requirement: Unlike standard actions, reusable workflow inputs must specify a type: field.
    • Supported types: The type must be one of boolean, number, or string.
    • Default value matching: The default value must be compatible with the specified type (e.g., a number type cannot have a string default like ':1234').
    • Required vs Default: If an input is marked as required: true, providing a default value will trigger an error because the default is never used.
    on:
      workflow_call:
        inputs:
          scheme:
            description: Scheme of URL
            default: https
            type: string
          port:
            description: Port of URL
            # ERROR: Type is number but default value is string
            default: ':1234'
            type: number
          query:
            description: Query of URL
            # ERROR: Type must be one of number, string, boolean
            type: object
          path:
            description: Path of URL
            required: true
            # ERROR: Default value is never used since this input is required
            default: ''
            type: string
  9. Run actionlint using Docker in GitHub Actions

    main

    Alternatively, you can use the official actionlint Docker image in your workflow steps.

    name: Lint GitHub Actions workflows
    on: [push, pull_request]
    
    jobs:
      actionlint:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v6
          - name: Check workflow files
            uses: docker://rhysd/actionlint:latest
            with:
              args: -color
  10. Install actionlint using the download script

    main

    A download script is available to install the actionlint executable in a single command. This is recommended for use within shell scripts.

    • Latest version: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
    • Specific version: Provide the version as the first argument.
    • Custom directory: Provide the directory path as the second argument.