Skip to content

Commit

Permalink
Merge branch 'outdated-action'
Browse files Browse the repository at this point in the history
  • Loading branch information
rhysd committed Apr 27, 2024
2 parents 420085b + c49afc5 commit ad005b6
Show file tree
Hide file tree
Showing 15 changed files with 201 additions and 11 deletions.
43 changes: 40 additions & 3 deletions docs/checks.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ List of checks:
- [Action format in `uses:`](#check-action-format)
- [Local action inputs validation at `with:`](#check-local-action-inputs)
- [Popular action inputs validation at `with:`](#check-popular-action-inputs)
- [Outdated popular actions detection at `with:`](#detect-outdated-popular-actions)
- [Shell name validation at `shell:`](#check-shell-names)
- [Job ID and step ID uniqueness](#check-job-step-ids)
- [Hardcoded credentials](#check-hardcoded-credentials)
Expand Down Expand Up @@ -938,12 +939,12 @@ jobs:
- name: Print pull request title
# ERROR: Using the potentially untrusted input can cause script injection
run: echo '${{ github.event.pull_request.title }}'
- uses: actions/stale@v4
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.TOKEN }}
# This is OK because action input is not evaluated by shell
stale-pr-message: ${{ github.event.pull_request.title }} was closed
- uses: actions/github-script@v4
- uses: actions/github-script@v7
with:
# ERROR: Using the potentially untrusted input can cause script injection
script: console.log('${{ github.event.head_commit.author.name }}')
Expand All @@ -969,7 +970,7 @@ test.yaml:22:31: object filter extracts potentially untrusted properties "github
| ^~~~~~~~~~~~~~~~~~~~
```
[Playground](https://rhysd.github.io/actionlint#eJyFkUFLAzEQhe/9FXMQ2gqJF085eRFBoRXsvWSzQ3drNrNmJi1S+t9NdkupSvUUknnzvcdLsB0aWCHLhIKBPnm/jviRysNkSxWbCYDkWzkBYgqsijBVKUhS3pbZMGLBnkcVgIIwgF9jG2SgwokK0orHk2wAGkDXEExvDgfYtNKkSuMOg+jLMHpYg+NxenZIjGzAOmkp8B2L9fiwuz+T9xllzrfshD0poXfMhsWK0UUU1qvly+Migy+kA0v1UXXIbDc4LvyfDfaWwXlirK+kHBmKXWx7+SvtqDDg8hZ51J42s98NNWjrtaOua0XbJA1FXXovNc1//MQTChRlXuNr7Qs9vy0Xs28Wt7qi+nNekF/IR69F)
[Playground](https://rhysd.github.io/actionlint#eJyFkUFLAzEQhe/9FXMQ2gqJRzGnXkRQaAV7L9ns0F3NZtbMpEVK/7vJbilVKZ5CMm++93gJtkMDa2SZUDDQJ+83ET9TeZi8U8VmAiD5Vk6AmAKrIkxVCpKUt2U2jFiw51EFoCAM4NfYBhmocKKCtOLxJBuABtA1BNObwwG2rTSp0rjDIPoyjB7W4Hicnh0SIxuwTloKfMdiPS52D2fyPqPM+ZadsCcl9IHZsFgxuojCer16eVxm8IV0YKk+qg6Z7RbHhf+zwd4yOE+M9ZWUI0Oxi20vi9391bSjwoDLW+RRe9rO/jbUoK03jrquFW2TNBR16b3UNP/1E08oUJR5ja+1L/T8tlrOfljc6orqr3lBfgPRHa9N)
Since `${{ }}` placeholders are evaluated and replaced directly by GitHub Actions runtime, you need to use them carefully in
inline scripts at `run:`. For example, if we have step as follows,
Expand Down Expand Up @@ -1740,6 +1741,41 @@ So far, actionlint supports more than 100 popular actions The data set is embedd
and were automatically collected by [a script][generate-popular-actions]. If you want more checks for other actions, please
make a request [as an issue][issue-form].

<a name="detect-outdated-popular-actions"></a>
## Outdated popular actions detection at `with:`

Example input:

```yaml
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
# ERROR: actions/checkout@v2 is using the outdated runner 'node12'
- uses: actions/checkout@v2
```

Output:

```
test.yaml:8:15: the runner of "actions/checkout@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue [action]
|
8 | - uses: actions/checkout@v2
| ^~~~~~~~~~~~~~~~~~~
```

[Playground](https://rhysd.github.io/actionlint#eJwlyjkOwCAMRNGeU8wFUKSUVLkKICSyyEYZO+fPVv3ifZWE4ewhbFqYAmCN9hY4XRj1Gby4mMcjv/YRrQ3+FxDhbEzI1VYVTrW3uqvbcs03dIgdzQ==)

In addition to the checks for inputs of actions described in [the previous section](#check-popular-action-inputs), actionlint
reports an error when a popular action is 'outdated'. An action is outdated when the runner used by the action is no longer
supported by GitHub Actions runtime. For example, `node12` is no longer available so any actions can use `node12` runner.

Note that this check doesn't report that the action version is up-to-date. For example, even if you use `actions/checkout@v3` and
newer version `actions/checkout@v4` is available, actionlint reports no error as long as `actions/checkout@v3` is not outdated.
If you want to keep actions used by your workflows up-to-date, consider to use [Dependabot][dependabot-doc].

<a name="check-shell-names"></a>
## Shell name validation at `shell:`

Expand Down Expand Up @@ -2778,6 +2814,7 @@ Note that `steps` in Composite action's metadata is not checked at this point. I
[gh-hosted-runner]: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners
[self-hosted-runner]: https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners
[action-uses-doc]: https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepsuses
[dependabot-doc]: https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
[credentials-doc]: https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#jobsjob_idcontainercredentials
[actions-cache]: https://github.com/actions/cache
[permissions-doc]: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
Expand Down
92 changes: 92 additions & 0 deletions popular_actions.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions rule_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ func (rule *RuleAction) checkRepoAction(spec string, exec *ExecAction) {

meta, ok := PopularActions[spec]
if !ok {
if _, ok := OutdatedPopularActionSpecs[spec]; ok {
rule.Errorf(exec.Uses.Pos, "the runner of %q action is too old to run on GitHub Actions. update the action's version to fix this issue", spec)
return
}
rule.Debug("This action is not found in popular actions data set: %s", spec)
return
}
Expand Down
24 changes: 19 additions & 5 deletions scripts/generate-popular-actions/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,6 @@ func (g *gen) fetchRemote() (map[string]*actionlint.ActionMetadata, error) {
close(done)
return nil, f.err
}
if isOutdatedRunner(f.meta.Runs.Using) {
g.log.Printf("Ignore outdated action %q since runner is %q", f.spec, f.meta.Runs.Using)
continue
}
ret[f.spec] = f.meta
}

Expand All @@ -194,6 +190,10 @@ func (g *gen) fetchRemote() (map[string]*actionlint.ActionMetadata, error) {
func (g *gen) writeJSONL(out io.Writer, actions map[string]*actionlint.ActionMetadata) error {
enc := json.NewEncoder(out)
for spec, meta := range actions {
if isOutdatedRunner(meta.Runs.Using) {
g.log.Printf("Ignore outdated action %q since runner is %q", spec, meta.Runs.Using)
continue
}
j := actionOutput{spec, meta}
if err := enc.Encode(&j); err != nil {
return fmt.Errorf("could not encode action %q data into JSON: %w", spec, err)
Expand All @@ -220,8 +220,14 @@ var PopularActions = map[string]*ActionMetadata{
}
sort.Strings(specs)

outdated := []string{}
for _, spec := range specs {
meta := actions[spec]
if isOutdatedRunner(meta.Runs.Using) {
outdated = append(outdated, spec)
continue
}

fmt.Fprintf(b, "%q: {\n", spec)
fmt.Fprintf(b, "Name: %q,\n", meta.Name)

Expand Down Expand Up @@ -268,6 +274,14 @@ var PopularActions = map[string]*ActionMetadata{

fmt.Fprintln(b, "}")

fmt.Fprintln(b, `// OutdatedPopularActionSpecs is a spec set of known outdated popular actions. The word 'outdated'
// means that the runner used by the action is no longer available such as "node12".
var OutdatedPopularActionSpecs = map[string]struct{}{`)
for _, s := range outdated {
fmt.Fprintf(b, "%q: {},\n", s)
}
fmt.Fprintln(b, "}")

// Format the generated source with checking Go syntax
gen := b.Bytes()
src, err := format.Source(gen)
Expand All @@ -279,7 +293,7 @@ var PopularActions = map[string]*ActionMetadata{
return fmt.Errorf("could not output generated Go source to stdout: %w", err)
}

g.log.Printf("Wrote %d action metadata as Go", len(actions))
g.log.Printf("Wrote %d action metadata and %d outdated action specs as Go", len(actions)-len(outdated), len(outdated))
return nil
}

Expand Down
4 changes: 4 additions & 0 deletions scripts/generate-popular-actions/testdata/go/fetched.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions scripts/generate-popular-actions/testdata/go/outdated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions scripts/generate-popular-actions/testdata/go/want.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion testdata/err/github_script_untrusted_input.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
comment:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v4
- uses: actions/github-script@v7
with:
script: |
github.issues.createComment({
Expand Down
2 changes: 2 additions & 0 deletions testdata/err/outdated_popular_action.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
test.yaml:8:15: the runner of "actions/checkout@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue [action]
test.yaml:10:15: the runner of "actions/stale@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue [action]
10 changes: 10 additions & 0 deletions testdata/err/outdated_popular_action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
on: push

jobs:
test:
runs-on: ubuntu-latest
steps:
# ERROR: This version is outdated
- uses: actions/checkout@v2
# ERROR: This version is outdated
- uses: actions/stale@v4
1 change: 1 addition & 0 deletions testdata/examples/detect_outdated_popular_actions.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test.yaml:8:15: the runner of "actions/checkout@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue [action]
8 changes: 8 additions & 0 deletions testdata/examples/detect_outdated_popular_actions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
on: push

jobs:
test:
runs-on: ubuntu-latest
steps:
# ERROR: actions/checkout@v2 is using the outdated runner 'node12'
- uses: actions/checkout@v2
4 changes: 2 additions & 2 deletions testdata/examples/untrusted_input.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ jobs:
- name: Print pull request title
# ERROR: Using the potentially untrusted input can cause script injection
run: echo '${{ github.event.pull_request.title }}'
- uses: actions/stale@v4
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.TOKEN }}
# This is OK because action input is not evaluated by shell
stale-pr-message: ${{ github.event.pull_request.title }} was closed
- uses: actions/github-script@v4
- uses: actions/github-script@v7
with:
# ERROR: Using the potentially untrusted input can cause script injection
script: console.log('${{ github.event.head_commit.author.name }}')
Expand Down

0 comments on commit ad005b6

Please sign in to comment.