Skip to content

Commit

Permalink
add tests for checking invalid keys under runs in action.yml
Browse files Browse the repository at this point in the history
  • Loading branch information
rhysd committed Mar 13, 2024
1 parent 5243827 commit 98ca3cf
Show file tree
Hide file tree
Showing 31 changed files with 192 additions and 30 deletions.
6 changes: 3 additions & 3 deletions action_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ type ActionMetadataRuns struct {
// PostIf is `post-if` configuration of action.yaml for JavaScript action.
PostIf string `yaml:"post-if"`
// Steps is `steps` configuration of action.yaml for Composite action.
Steps []yaml.Node `yaml:"steps"`
Steps []any `yaml:"steps"`
// Image is `image` of action.yaml for Docker action.
Image string `yaml:"image"`
// PreEntrypoint is `pre-entrypoint` of action.yaml for Docker action.
Expand All @@ -116,9 +116,9 @@ type ActionMetadataRuns struct {
// PostEntrypoint is `post-entrypoint` of action.yaml for Docker action.
PostEntrypoint string `yaml:"post-entrypoint"`
// Args is `args` of action.yaml for Docker action.
Args []*yaml.Node `yaml:"args"`
Args []any `yaml:"args"`
// Env is `env` of action.yaml for Docker action.
Env map[string]*yaml.Node `yaml:"env"`
Env map[string]any `yaml:"env"`
}

// ActionMetadata represents structure of action.yaml.
Expand Down
34 changes: 15 additions & 19 deletions rule_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,19 +109,15 @@ 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) invalidRunnerName(pos *Pos, name, action, path string) {
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) missingRunnerProp(pos *Pos, prop, ty, action, path string) {
rule.Errorf(pos, `%q is required at "runs" section for %s action in local action %q defined at %q`, prop, ty, 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)
}

func (rule *RuleAction) invalidRunnerProp(pos *Pos, prop, ty, action, path string) {
rule.Errorf(pos, `%q is not allowed at "runs" section for %s action in local action %q defined at %q`, prop, ty, action, path)
}

func (rule *RuleAction) checkInvalidRunnerProps(pos *Pos, r *ActionMetadataRuns, ty, action, path string, props []string) {
func (rule *RuleAction) checkInvalidRunsProps(pos *Pos, r *ActionMetadataRuns, ty, action, path string, props []string) {
for _, prop := range props {
invalid := prop == "main" && r.Main != "" ||
prop == "pre" && r.Pre != "" ||
Expand All @@ -137,15 +133,15 @@ func (rule *RuleAction) checkInvalidRunnerProps(pos *Pos, r *ActionMetadataRuns,
prop == "env" && r.Env != nil

if invalid {
rule.Errorf(pos, `%q is not allowed at "runs" section because %q is a %s action. it is defined at %q`, prop, action, ty, path)
rule.Errorf(pos, `%q is not allowed in "runs" section because %q is a %s action. the action is defined at %q`, prop, action, ty, path)
}
}
}

// https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-javascript-actions
// https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-docker-container-actions
// https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-composite-actions
func (rule *RuleAction) checkLocalActionRunner(path string, meta *ActionMetadata, pos *Pos) {
func (rule *RuleAction) checkLocalActionRuns(path string, meta *ActionMetadata, pos *Pos) {
r := &meta.Runs
u := r.Using
if u == "" {
Expand All @@ -155,28 +151,28 @@ func (rule *RuleAction) checkLocalActionRunner(path string, meta *ActionMetadata

if u == "docker" {
if r.Image == "" {
rule.missingRunnerProp(pos, "image", "Docker", meta.Name, path)
rule.missingRunsProp(pos, "image", "Docker", meta.Name, path)
}
rule.checkInvalidRunnerProps(pos, r, "Docker", meta.Name, path, []string{"main", "pre", "pre-if", "post", "post-if", "steps"})
rule.checkInvalidRunsProps(pos, r, "Docker", meta.Name, path, []string{"main", "pre", "pre-if", "post", "post-if", "steps"})
return
}

if u == "composite" {
if len(r.Steps) == 0 {
rule.missingRunnerProp(pos, "steps", "Composite", meta.Name, path)
rule.missingRunsProp(pos, "steps", "Composite", meta.Name, path)
}
rule.checkInvalidRunnerProps(pos, r, "Composite", meta.Name, path, []string{"main", "pre", "pre-if", "post", "post-if", "image", "pre-entrypoint", "entrypoint", "post-entrypoint", "args", "env"})
rule.checkInvalidRunsProps(pos, r, "Composite", meta.Name, path, []string{"main", "pre", "pre-if", "post", "post-if", "image", "pre-entrypoint", "entrypoint", "post-entrypoint", "args", "env"})
return
}

if !strings.HasPrefix(u, "node") {
rule.invalidRunnerName(pos, u, meta.Name, path)
rule.invalidRunsName(pos, u, meta.Name, path)
return
}

v, err := strconv.ParseUint(u[len("node"):], 10, 0)
if err != nil {
rule.invalidRunnerName(pos, u, meta.Name, path)
rule.invalidRunsName(pos, u, meta.Name, path)
return
}
if v < MinimumNodeRunnerVersion {
Expand All @@ -191,9 +187,9 @@ func (rule *RuleAction) checkLocalActionRunner(path string, meta *ActionMetadata
)
}
if r.Main == "" {
rule.missingRunnerProp(pos, "main", "JavaScript", meta.Name, path)
rule.missingRunsProp(pos, "main", "JavaScript", meta.Name, path)
}
rule.checkInvalidRunnerProps(pos, r, "JavaScript", meta.Name, path, []string{"steps", "image", "pre-entrypoint", "entrypoint", "post-entrypoint", "args", "env"})
rule.checkInvalidRunsProps(pos, r, "JavaScript", meta.Name, path, []string{"steps", "image", "pre-entrypoint", "entrypoint", "post-entrypoint", "args", "env"})
}

// https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#example-using-the-github-packages-container-registry
Expand Down Expand Up @@ -237,7 +233,7 @@ func (rule *RuleAction) checkLocalAction(path string, action *ExecAction) {

if !cached {
rule.Debug("Checking runner metadata of %s action %q at %q", meta.Runs, meta.Name, path)
rule.checkLocalActionRunner(path, meta, action.Uses.Pos)
rule.checkLocalActionRuns(path, meta, action.Uses.Pos)
}

rule.checkAction(meta, action, func(m *ActionMetadata) string {
Expand Down
7 changes: 4 additions & 3 deletions testdata/projects/local_action_invalid_runners.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/workflows/test\.yaml:7:15: "node14" runner at "runs.using" is unavailable since the Node\.js version is too old \(14 < 16\) in local action "Old Node\.js" defined at "\./old_node"\. see https://.+ \[action\]/
/workflows/test\.yaml:8:15: "runs\.using" is missing in local action "Missing runner name" defined at "\./missing_runner" \[action\]/
/workflows/test\.yaml:9:15: invalid runner name "what-is-this-runner" at runs\.using in local action "Unknown runner name" defined at "\./unknown_runner"\. see https://.+ to know valid runner names \[action\]/
/workflows/test\.yaml:10:15: invalid runner name "nodenext" at runs\.using in local action "Invalid node version" defined at "\./invalid_node_version"\. see https://.+ to know valid runner names \[action\]/
workflows/test.yaml:8:15: "runs.using" is missing in local action "Missing runner name" defined at "./missing_runs" [action]
workflows/test.yaml:9:15: "runs.using" is missing in local action "No using" defined at "./missing_using" [action]
/workflows/test\.yaml:10:15: invalid runner name "what-is-this-runner" at runs\.using in local action "Unknown runner name" defined at "\./unknown_runner"\. see https://.+ to know valid runner names \[action\]/
/workflows/test\.yaml:11:15: invalid runner name "nodenext" at runs\.using in local action "Invalid node version" defined at "\./invalid_node_version"\. see https://.+ to know valid runner names \[action\]/
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: 'No using'
author: 'rhysd <https://rhysd.github.io>'
description: '"using" is required'

runs:
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: ./old_node
- uses: ./missing_runner
- uses: ./missing_runs
- uses: ./missing_using
- uses: ./unknown_runner
- uses: ./invalid_node_version
- uses: ./ok_node
- uses: ./ok_composite
- uses: ./ok_docker
# ...
# Check using same invalid action twice does not duplicate the errors
- uses: ./old_node
12 changes: 12 additions & 0 deletions testdata/projects/local_composite_action.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
workflows/test.yaml:8:15: "steps" is required in "runs" section because "Composite action" is a Composite action. the action is defined at "./missing_steps" [action]
workflows/test.yaml:9:15: "main" is not allowed in "runs" section because "Composite action" is a Composite action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:9:15: "pre" is not allowed in "runs" section because "Composite action" is a Composite action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:9:15: "pre-if" is not allowed in "runs" section because "Composite action" is a Composite action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:9:15: "post" is not allowed in "runs" section because "Composite action" is a Composite action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:9:15: "post-if" is not allowed in "runs" section because "Composite action" is a Composite action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:9:15: "image" is not allowed in "runs" section because "Composite action" is a Composite action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:9:15: "pre-entrypoint" is not allowed in "runs" section because "Composite action" is a Composite action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:9:15: "entrypoint" is not allowed in "runs" section because "Composite action" is a Composite action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:9:15: "post-entrypoint" is not allowed in "runs" section because "Composite action" is a Composite action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:9:15: "args" is not allowed in "runs" section because "Composite action" is a Composite action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:9:15: "env" is not allowed in "runs" section because "Composite action" is a Composite action. the action is defined at "./all_invalid_keys" [action]
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: 'Composite action'
author: 'rhysd <https://rhysd.github.io>'
description: 'Correct composite action'

runs:
using: 'composite'
steps:
- run: echo hello
main: index.js
pre: pre.js
pre-if: true
post: post.js
post-if: true
image: 'docker://debian:stretch-slim'
pre-entrypoint: pre.sh
entrypoint: main.sh
post-entrypoint: post.sh
args: [foo, bar]
env:
FOO: BAR
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: 'Composite action'
author: 'rhysd <https://rhysd.github.io>'
description: 'Correct composite action'

runs:
using: 'composite'
9 changes: 9 additions & 0 deletions testdata/projects/local_composite_action/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
on: push

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: ./ok
- uses: ./missing_steps
- uses: ./all_invalid_keys
7 changes: 7 additions & 0 deletions testdata/projects/local_docker_action.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
workflows/test.yaml:10:15: "image" is required in "runs" section because "Docker action" is a Docker action. the action is defined at "./missing_image" [action]
workflows/test.yaml:11:15: "main" is not allowed in "runs" section because "Docker action" is a Docker action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:11:15: "pre" is not allowed in "runs" section because "Docker action" is a Docker action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:11:15: "pre-if" is not allowed in "runs" section because "Docker action" is a Docker action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:11:15: "post" is not allowed in "runs" section because "Docker action" is a Docker action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:11:15: "post-if" is not allowed in "runs" section because "Docker action" is a Docker action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:11:15: "steps" is not allowed in "runs" section because "Docker action" is a Docker action. the action is defined at "./all_invalid_keys" [action]
14 changes: 14 additions & 0 deletions testdata/projects/local_docker_action/all_invalid_keys/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: 'Docker action'
author: 'rhysd <https://rhysd.github.io>'
description: 'Correct Docker action'

runs:
using: 'docker'
image: 'docker://debian:stretch-slim'
main: index.js
pre: pre.js
pre-if: true
post: post.js
post-if: true
steps:
- run: echo hello
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: 'Docker action'
author: 'rhysd <https://rhysd.github.io>'
description: 'Correct Docker action'

runs:
using: 'docker'
13 changes: 13 additions & 0 deletions testdata/projects/local_docker_action/ok_all_keys/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: 'Docker action'
author: 'rhysd <https://rhysd.github.io>'
description: 'Correct Docker action'

runs:
using: 'docker'
image: 'Dockerfile'
pre-entrypoint: pre.sh
entrypoint: main.sh
post-entrypoint: post.sh
args: [foo, bar]
env:
FOO: BAR
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FROM alpine:latest
7 changes: 7 additions & 0 deletions testdata/projects/local_docker_action/ok_registry/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: 'Docker action'
author: 'rhysd <https://rhysd.github.io>'
description: 'Correct Docker action'

runs:
using: 'docker'
image: 'docker://debian:stretch-slim'
11 changes: 11 additions & 0 deletions testdata/projects/local_docker_action/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
on: push

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: ./ok_dockerfile
- uses: ./ok_registry
- uses: ./ok_all_keys
- uses: ./missing_image
- uses: ./all_invalid_keys
9 changes: 9 additions & 0 deletions testdata/projects/local_javascript_action.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
workflows/test.yaml:9:15: "main" is required in "runs" section because "JavaScript action" is a JavaScript action. the action is defined at "./missing_main" [action]
workflows/test.yaml:9:15: "main" is required in "runs" section because "JavaScript action" is a JavaScript action. the action is defined at "./missing_main" [action]
workflows/test.yaml:10:15: "steps" is not allowed in "runs" section because "Composite action" is a JavaScript action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:10:15: "image" is not allowed in "runs" section because "Composite action" is a JavaScript action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:10:15: "pre-entrypoint" is not allowed in "runs" section because "Composite action" is a JavaScript action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:10:15: "entrypoint" is not allowed in "runs" section because "Composite action" is a JavaScript action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:10:15: "post-entrypoint" is not allowed in "runs" section because "Composite action" is a JavaScript action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:10:15: "args" is not allowed in "runs" section because "Composite action" is a JavaScript action. the action is defined at "./all_invalid_keys" [action]
workflows/test.yaml:10:15: "env" is not allowed in "runs" section because "Composite action" is a JavaScript action. the action is defined at "./all_invalid_keys" [action]
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: 'Composite action'
author: 'rhysd <https://rhysd.github.io>'
description: 'Correct composite action'

runs:
using: node20
main: index.js
steps:
- run: echo hello
image: 'docker://debian:stretch-slim'
pre-entrypoint: pre.sh
entrypoint: main.sh
post-entrypoint: post.sh
args: [foo, bar]
env:
FOO: BAR
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: 'JavaScript action'
author: 'rhysd <https://rhysd.github.io>'
description: 'Correct JavaScript action'

runs:
using: node20
1 change: 1 addition & 0 deletions testdata/projects/local_javascript_action/ok/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: 'JavaScript action'
author: 'rhysd <https://rhysd.github.io>'
description: 'Correct JavaScript action'

runs:
using: node20
main: index.js
pre: pre.js
pre-if: true
post: pre.js
post-if: true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

10 changes: 10 additions & 0 deletions testdata/projects/local_javascript_action/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
on: push

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: ./ok
- uses: ./ok_all_optional
- uses: ./missing_main
- uses: ./all_invalid_keys

0 comments on commit 98ca3cf

Please sign in to comment.