Skip to content

Latest commit

 

History

History
486 lines (346 loc) · 19.4 KB

usage.md

File metadata and controls

486 lines (346 loc) · 19.4 KB

Usage

This document describes how to use actionlint.

actionlint command

With no argument, actionlint finds all workflow files in the current repository and checks them.

actionlint

When paths to YAML workflow files are given as arguments, actionlint checks them.

actionlint path/to/workflow1.yaml path/to/workflow2.yaml

When - argument is given, actionlint reads inputs from stdin and checks it as workflow source.

cat path/to/workflow.yaml | actionlint -

To know all flags and options, see an output of actionlint -h or the online command manual.

Ignore some errors

To ignore some errors, -ignore option offers to filter errors by messages using regular expression. The option is repeatable. The regular expression syntax is the same as RE2.

actionlint -ignore 'label ".+" is unknown' -ignore '".+" is potentially untrusted'

-shellcheck and -pyflakes specifies file paths of executables. Setting empty string to them disables shellcheck and pyflakes rules. As a bonus, disabling them makes actionlint much faster Since these external linter integrations spawn many processes.

actionlint -shellcheck= -pyflakes=

Format error messages

-format option can flexibly format error messages with Go template syntax.

Before explaining the formatting details, let's see some examples.

Example: Serialized into JSON

actionlint -format '{{json .}}'

Output:

[{"message":"unexpected key \"branch\" for ...

Example: Markdown

actionlint -format '{{range $err := .}}### Error at line {{$err.Line}}, col {{$err.Column}} of `{{$err.Filepath}}`\n\n{{$err.Message}}\n\n```\n{{$err.Snippet}}\n```\n\n{{end}}'

Output:

### Error at line 21, col 20 of `test.yaml`

property "platform" is not defined in object type {os: string}

```
          key: ${{ matrix.platform }}-node-${{ hashFiles('**/package-lock.json') }}
                   ^~~~~~~~~~~~~~~
```

Example: Serialized in JSON Lines

actionlint -format '{{range $err := .}}{{json $err}}{{end}}'

Output:

{"message":"unexpected key \"branch\" for ...
{"message":"character '\\' is invalid for branch ...
{"message":"label \"linux-latest\" is unknown. ...

Example: Error annotation on GitHub Actions

actionlint -format '{{range $err := .}}::error file={{$err.Filepath}},line={{$err.Line}},col={{$err.Column}}::{{$err.Message}}%0A```%0A{{replace $err.Snippet "\\n" "%0A"}}%0A```\n{{end}}' -ignore 'SC2016:'

Output:

annotations on GitHub Actions

To include newlines in the annotation body, it prints %0A. (ref actions/toolkit#193). And it suppresses SC2016 shellcheck rule error since it complains about the template argument.

Basically it is more recommended to use Problem Matchers or reviewdog as explained in 'Tools integration' section below.

Example: SARIF format

The Static Analysis Results Interchange Format (SARIF) is a standardized format for the results of static analysis tools.

Since this practical format is much more complex than the above examples, the template is not written here. Please read the template file in test data.

Outputs are also too large to be written here. Please read the output example in test data.

Formatting syntax

In Go template syntax, . within {{ }} means the target object. Here, the target object is a sequence of error objects.

The sequence can be traversed with range action, which is like for ... = range ... {} in Go.

{{range $err := .}} this part iterates error objects with the iteration variable $err {{end}}

The error object has the following fields.

Field Description Example
{{$err.Message}} Body of error message property "platform" is not defined in object type {os: string}
{{$err.Snippet}} Code snippet to indicate error position node_version: 16.x\n ^~~~~~~~~~~~~
{{$err.Kind}} Name of rule the error belongs to expression
{{$err.Filepath}} Canonical relative file path of the error position .github/workflows/ci.yaml
{{$err.Line}} Line number of the error position (1-based) 9
{{$err.Column}} Column number of the error's start position (1-based) 11
{{$err.EndColumn}} Column number of the error's end position (1-based) 23

Functions called in {{ }} placeholder are template actions. There are many actions defined by Go standard library. In addition, there are a few custom actions defined by actionlint. Most useful action would be json as we already used it in the above JSON example. List of all custom actions are as follows:

Action Description Example usage
json x Serialize x as JSON string followed by newline character {{json $err}}
replace x y z Replace string y with z in x {{replace $err.Filepath "\\" "/"}}
toPascalCase x Convert x into PascalCase (e.g. 'foo-bar' to 'FooBar') {{toPascalCase $err.Kind}}
allKinds Return an array of kind objects. The kind object is explained in the below table {{range $ = allKinds}}{{$.Name}}{{end}}
getVersion Return the version of actionlint as string {{getVersion}}

The kind object returned from allKinds action has the following fields.

Field Description Example
{{$kind.Name}} Name of the kind syntax-check
{{$kind.Description}} Short description of the kind Checks for GitHub Actions workflow syntax

For example, the following simple iteration body

line is {{$err.Line}}, col is {{$err.Column}}, message is {{$err.Message | printf "%q"}}

will produce output like below.

line is 21, col is 20, message is "property \"platform\" is not defined in object type {os: string}"

In {{ }} placeholder, input can be piped and action can be used to transform texts. In above example, the message is piped with | and transformed with printf "%q".

Note that special characters escaped with backslash like \n in the format string are automatically unescaped.

Exit status

actionlint command exits with one of the following exit statuses.

Status Description
0 The command ran successfully and no problem was found
1 The command ran successfully and some problem was found
2 The command failed due to invalid command line option
3 The command failed due to some fatal error

Use actionlint on GitHub Actions

Preparing actionlint executable with the download script is recommended. See the instruction for more details. It sets an absolute file path of downloaded executable to executable output in order to use the executable in the following steps easily.

Here is an example of simple workflow to run actionlint on GitHub Actions. Please ensure shell: bash since the default shell for Windows runners is pwsh.

name: Lint GitHub Actions workflows
on: [push, pull_request]

jobs:
  actionlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Download actionlint
        id: get_actionlint
        run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
        shell: bash
      - name: Check workflow files
        run: ${{ steps.get_actionlint.outputs.executable }} -color
        shell: bash

Or simply download the executable and run it in one step:

- name: Check workflow files
  run: |
    bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
    ./actionlint -color
  shell: bash

The download script allows to specify the version of actionlint and the download directory. Try to give --help argument to the script for more usage details.

If you want to enable shellcheck integration, install shellcheck command. Note that shellcheck is pre-installed on Ubuntu worker.

If you want to annotate errors from actionlint on GitHub, consider using Problem Matchers.

If you prefer Docker image to running a downloaded executable, using actionlint Docker image is another option.

name: Lint GitHub Actions workflows
on: [push, pull_request]

jobs:
  actionlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Check workflow files
        uses: docker://rhysd/actionlint:latest
        with:
          args: -color

Online playground

Thanks to WebAssembly, actionlint playground is available on your browser. It never sends any data to outside your browser.

https://rhysd.github.io/actionlint/

Paste your workflow content to the code editor at left pane. It automatically shows the results at right pane. When editing the workflow content in the code editor, the results will be updated on the fly. Clicking an error message in the results table moves a cursor to position of the error in the code editor.

Docker image

Official Docker image is available. The image contains actionlint executable and all dependencies (shellcheck and pyflakes).

Available tags are:

  • actionlint:latest: Latest stable version of actionlint. This image is recommended.
  • actionlint:{version}: Specific version of actionlint. (e.g. actionlint:1.7.4)

Just run the image with docker run:

docker run --rm rhysd/actionlint:latest -version

To check all workflows in your repository, mount your repository's root directory as a volume and run actionlint in the mounted directory. When you are at a root directory of your repository:

docker run --rm -v $(pwd):/repo --workdir /repo rhysd/actionlint:latest -color

To check a file with actionlint in a Docker container, pass the file content via stdin and use - argument:

cat /path/to/workflow.yml | docker run --rm -i rhysd/actionlint:latest -color -

Or mount the workflows directory and pass the paths as arguments:

docker run --rm -v /path/to/workflows:/workflows rhysd/actionlint:latest -color /workflows/ci.yml

Using actionlint from Go program

Go APIs are available. See the Go API document for more details.

Tools integration

reviewdog

reviewdog is an automated review tool for various code hosting services. It officially supports actionlint. You can check errors from actionlint easily with inline review comments at pull request review.

The usage is easy. Run reviewdog/action-actionlint action in your workflow as follows.

name: reviewdog
on: [pull_request]
jobs:
  actionlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: reviewdog/action-actionlint@v1

Problem Matchers

Problem Matchers is a feature to extract GitHub Actions annotations from terminal outputs of linters.

Copy actionlint-matcher.json to .github/actionlint-matcher.json in your repository.

Then enable the matcher using add-matcher command before running actionlint in the step of your workflow.

- name: Check workflow files
  run: |
    echo "::add-matcher::.github/actionlint-matcher.json"
    bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
    ./actionlint -color
  shell: bash

When you change your workflow and the changed line causes a new error, CI will annotate the diff with the extracted error message.

annotation by Problem Matchers

super-linter

super-linter is a Bash script for a simple combination of various linters, provided by GitHub. It has support for actionlint. Running super-linter in your repository automatically runs actionlint.

To ignore some errors, please add -ignore option by using GITHUB_ACTIONS_COMMAND_ARGS environment variable. Please see super-linter/super-linter#1852 for the discussion.

pre-commit

pre-commit is a framework for managing and maintaining multi-language Git pre-commit hooks. actionlint is available as a pre-commit hook to check workflow files in .github/workflows/ directory.

Add this to your .pre-commit-config.yaml in your repository:

---
repos:
  - repo: https://github.com/rhysd/actionlint
    rev: v1.7.4
    hooks:
      - id: actionlint

As alternatives to actionlint hook, actionlint-docker or actionlint-system hooks are available.

Hook ID Explanation
actionlint Automatically installs actionlint command in isolated $GOPATH directory using Go toolchain.
actionlint-docker Automatically pulls the actionlint Docker image.
actionlint-system Uses system-installed actionlint command. The command is necessary to be installed manually.

VS Code

Linter extension for VS Code is available. The extension automatically detects .github/workflows directory, runs actionlint command, and reports errors in the code editor while editing workflow files.

Emacs

Plugins for both Flycheck and Flymake are available via MELPA.

Their respective repositories are flycheck-actionlint and flymake-actionlint.

Vim and Neovim

nvim-lint supports actionlint on Neovim. The plugin automatically and asynchronously runs actionlint and notifies errors on the fly when you edit GitHub Actions CI workflows. Please read the plugin's documentation for more details.

ALE supports actionlint on Vim and Neovim. Similar to nvim-lint, The plugin automatically and asynchronously runs actionlint and notifies errors on the fly when you edit GitHub Actions CI workflows. Please read the plugin's documentation for more details.

Pulsar Edit

A Linter package for Pulsar Edit is available. The package automatically detects a workflows directory, executes the actionlint command on any detected GitHub Actions files within the directory, and reports returned information in the code editor display tab while editing workflow files.

Nova

Nova.app is a MacOS only editor and IDE. The Actionlint for Nova allows you to get inline feedback while editing actions.

trunk

trunk is an extendable superlinter with a builtin language server and preexisting issue detection. Actionlint is integrated here.

Once you have initialized trunk in your repo, to enable at the latest actionlint version, just run:

trunk check enable actionlint

or if you'd like a specific version:

trunk check enable [email protected]

or modify .trunk/trunk.yaml in your repository to contain:

lint:
  enabled:
    - [email protected]

Then just run:

trunk check

and it will check your modified files via actionlint, if applicable, and show you the results. Trunk also will detect preexisting issues and highlight only the newly added actionlint issues. For more information, check the trunk docs.

You can also see actionlint issues inline in VS Code via the Trunk VS Code extension.


Checks | Installation | Configuration | Go API | References