From 9c36f48549f5a86c3b1f6c9b683b3f5149e80aab Mon Sep 17 00:00:00 2001 From: rhysd Date: Tue, 19 Mar 2024 21:01:24 +0900 Subject: [PATCH] describe action metadata checks in document --- docs/checks.md | 74 +++++++++++++++++++ rule_action.go | 4 - .../actions/my-invalid-action/action.yml | 14 ++++ .../action_metadata_syntax_validation.out | 4 + .../action_metadata_syntax_validation.yaml | 8 ++ 5 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 testdata/examples/.github/actions/my-invalid-action/action.yml create mode 100644 testdata/examples/action_metadata_syntax_validation.out create mode 100644 testdata/examples/action_metadata_syntax_validation.yaml diff --git a/docs/checks.md b/docs/checks.md index a8f8f6666..a863c4143 100644 --- a/docs/checks.md +++ b/docs/checks.md @@ -38,6 +38,7 @@ List of checks: - [Contexts and special functions availability](#ctx-spfunc-availability) - [Deprecated workflow commands](#check-deprecated-workflow-commands) - [Conditions always evaluated to true at `if:`](#if-cond-always-true) +- [Action metadata syntax validation](#action-metadata-syntax) Note that actionlint focuses on catching mistakes in workflow files. If you want some general code style checks, please consider using a general YAML checker like [yamllint][]. @@ -2657,6 +2658,78 @@ works as intended. actionlint checks all `if:` conditions in workflow and reports error when some condition is always evaluated to true due to extra characters around `${{ }}`. + +## Action metadata syntax validation + +Example workflow input: + +```yaml +on: push + +jobs: + test: + runs-on: ubuntu-latest + steps: + # actionlint checks an action when it is actually used in a workflow + - uses: ./.github/actions/my-invalid-action +``` + +Example action metadata: + +```yaml +# .github/actions/some-action/action.yml + +name: 'My action' +author: '...' +# ERROR: 'description' section is required + +runs: + # ERROR: Node.js runtime version is too old + using: 'node14' + # ERROR: The source file being run by this action does not exist + main: 'this-file-does-not-exist.js' + # ERROR: 'env' configuration is only allowed for Docker actions + env: + SOME_VAR: SOME_VALUE +``` + +Output: + +``` +test.yaml:8:15: description is required in metadata of "My action" action at "path/to/.github/actions/my-invalid-action/action.yml" [action] + | +8 | - uses: ./.github/actions/my-invalid-action + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +test.yaml:8:15: "node14" runner at "runs.using" is unavailable since the Node.js version is too old (14 < 16) in local action "My action" defined at "path/to/.github/actions/my-invalid-action". see https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-javascript-actions [action] + | +8 | - uses: ./.github/actions/my-invalid-action + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +test.yaml:8:15: file "this-file-does-not-exist.js" does not exist in "path/to/.github/actions/my-invalid-action". it is specified at "main" key in "runs" section in "My action" action [action] + | +8 | - uses: ./.github/actions/my-invalid-action + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +test.yaml:8:15: "env" is not allowed in "runs" section because "My action" is a JavaScript action. the action is defined at "path/to/.github/actions/my-invalid-action" [action] + | +8 | - uses: ./.github/actions/my-invalid-action + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``` + +All actions require a metadata file `action.yml` or `aciton.yaml`. The syntax is defined in [the official document][action-metadata-doc]. + +actionlint checks metadata files used in workflows and reports errors when they are not following the syntax. + +- `name:`, `description:`, `runs:` sections are required +- Runner name at `using:` is one of `composite`, `docker`, `node16`, `node20` +- Keys under `runs:` section are correct. Required/Valid keys are different depending on the type of action; Docker action or + Composite action or JavaScript action (e.g. `image:` is required for Docker action). +- Files specified in some keys under `runs` are existing. For example, JavaScript action defines a script file path for + entrypoint at `main:`. + +actionlint checks action metadata files which are used by workflows. Currently it is not supported to specify `action.yml` +directly via command line arguments. + +Note that `steps` in Composite action's metadata is not checked at this point. It will be supported in the future. + --- [Installation](install.md) | [Usage](usage.md) | [Configuration](config.md) | [Go API](api.md) | [References](reference.md) @@ -2710,3 +2783,4 @@ characters around `${{ }}`. [deprecate-set-output-save-state]: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ [deprecate-set-env-add-path]: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/ [workflow-commands-doc]: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions +[action-metadata-doc]: https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions diff --git a/rule_action.go b/rule_action.go index bb374ab2a..43b9d0cf9 100644 --- a/rule_action.go +++ b/rule_action.go @@ -105,10 +105,6 @@ func (rule *RuleAction) invalidActionFormat(pos *Pos, spec string, why string) { rule.Errorf(pos, "specifying action %q in invalid format because %s. available formats are \"{owner}/{repo}@{ref}\" or \"{owner}/{repo}/{path}@{ref}\"", spec, why) } -func (rule *RuleAction) invalidRunsName(pos *Pos, name, action, path string) { - rule.Errorf(pos, "invalid runner name %q at runs.using in local action %q defined at %q. see https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs to know valid runner names", name, action, path) -} - func (rule *RuleAction) missingRunsProp(pos *Pos, prop, ty, action, path string) { rule.Errorf(pos, `%q is required in "runs" section because %q is a %s action. the action is defined at %q`, prop, action, ty, path) } diff --git a/testdata/examples/.github/actions/my-invalid-action/action.yml b/testdata/examples/.github/actions/my-invalid-action/action.yml new file mode 100644 index 000000000..8cc05fc5a --- /dev/null +++ b/testdata/examples/.github/actions/my-invalid-action/action.yml @@ -0,0 +1,14 @@ +# .github/actions/some-action/action.yml + +name: 'My action' +author: '...' +# ERROR: 'description' section is required + +runs: + # ERROR: Node.js runtime version is too old + using: 'node14' + # ERROR: The source file being run by this action does not exist + main: 'this-file-does-not-exist.js' + # ERROR: 'env' configuration is only allowed for Docker actions + env: + SOME_VAR: SOME_VALUE diff --git a/testdata/examples/action_metadata_syntax_validation.out b/testdata/examples/action_metadata_syntax_validation.out new file mode 100644 index 000000000..00cc1bc8c --- /dev/null +++ b/testdata/examples/action_metadata_syntax_validation.out @@ -0,0 +1,4 @@ +/test\.yaml:8:15: description is required in metadata of "My action" action at ".+(\\\\|/)my-invalid-action(\\\\|/)action\.yml" \[action\]/ +/test\.yaml:8:15: invalid runner name \"node14\" at runs\.using in \"My action\" action defined at \".+(\\\\|/)actions(\\\\|/)my-invalid-action\"\. valid runners are \"composite\", \"docker\", \"node16\", and \"node20\"\. see https://.+ \[action\]/ +/test\.yaml:8:15: file "this-file-does-not-exist\.js" does not exist in ".+(\\\\|/)my-invalid-action"\. it is specified at "main" key in "runs" section in "My action" action \[action\]/ +/test\.yaml:8:15: "env" is not allowed in "runs" section because "My action" is a JavaScript action\. the action is defined at ".+(\\\\|/)my-invalid-action" \[action\]/ diff --git a/testdata/examples/action_metadata_syntax_validation.yaml b/testdata/examples/action_metadata_syntax_validation.yaml new file mode 100644 index 000000000..733bcfb7b --- /dev/null +++ b/testdata/examples/action_metadata_syntax_validation.yaml @@ -0,0 +1,8 @@ +on: push + +jobs: + test: + runs-on: ubuntu-latest + steps: + # actionlint checks an action when it is actually used in a workflow + - uses: ./.github/actions/my-invalid-action