oxsecurity / megalinter

🦙 MegaLinter analyzes 50 languages, 22 formats, 21 tooling formats, excessive copy-pastes, spelling mistakes and security issues in your repository sources with a GitHub Action, other CI tools or locally.
https://megalinter.io
GNU Affero General Public License v3.0
1.82k stars 214 forks source link

Add Support for Actionlint #762

Closed Kurt-von-Laven closed 2 years ago

Kurt-von-Laven commented 2 years ago

actionlint is a static checker for GitHub Actions workflow files.

It can be installed via Docker.

It's worth noting that this would introduce some degree of duplication, because actionlint runs shellcheck. Personally, I feel this is acceptable in exchange for the extreme degree of convenience Mega-Linter offers, but I am curious what others think. It is one of a very small number of linters present in Super-Linter but missing from Mega-Linter.

nvuillam commented 2 years ago

As shellcheck does not run on yml files, this would not be a "doubling stuff", so I'd gladly accept actionlint within Mega-Linter :)

Would you like to make the PR , or let's wait for someone (me or another contributor) to be available to implement it ? :)

Kurt-von-Laven commented 2 years ago

Awesome. I will probably wait for someone to be available on this one.

llaville commented 2 years ago

I'd like to contribute on this new linter. @nvuillam Can you tell me in which flavor should it be installed ?

nvuillam commented 2 years ago

@llaville that's nice ! As any repo can be used on github actions, it should be in all flavors ^^

llaville commented 2 years ago

I've finished to implement the new linter, and have made tests in real condition under one of my repository, and results LGTM

- File extensions: .yaml, .yml
- Excluding regex: (vendor/)
Kept [3] files on [4091] found files
Kept files before applying linter filters:
- /tmp/lint/.github/ISSUE_TEMPLATE/config.yml
- /tmp/lint/.github/workflows/php-tests.yaml
- /tmp/lint/.mega-linter.yml
[Filters] {'name': 'ACTION_ACTIONLINT', 'filter_regex_include': '(php\\-tests\\.yaml)', 'filter_regex_exclude': None, 'files_sub_directory': None, 'lint_all_files': False, 'lint_all_other_linters_files': False, 'file_extensions': ['.yml', '.yaml'], 'file_names_regex': [], 'file_names_not_ends_with': [], 'file_contains_regex': []}
ACTION_ACTIONLINT linter files after applying linter filters:
- /tmp/lint/.github/workflows/php-tests.yaml

+----MATCHING LINTERS-----+------------+----------------+------------+
| Descriptor | Linter     | Criteria   | Matching files | Format/Fix |
+------------+------------+------------+----------------+------------+
| ACTION     | actionlint | .yml|.yaml | 1              | no         |
+------------+------------+------------+----------------+------------+

Mega-Linter flavor is "all", no need to check match with linters
[actionlint] command: ['actionlint', '-verbose', '/tmp/lint/.github/workflows/php-tests.yaml']
[actionlint] CWD: /
[actionlint] result: 0 verbose: Linting tmp/lint/.github/workflows/php-tests.yaml
verbose: Using project at /tmp/lint
verbose: Found 0 parse errors in 1 ms for tmp/lint/.github/workflows/php-tests.yaml
verbose: Found total 0 errors in 21 ms for tmp/lint/.github/workflows/php-tests.yaml

Popen(['git', 'diff', '--abbrev=40', '--full-index', '-M', '--raw', '-z', '--no-color'], cwd=/tmp/lint, universal_newlines=False, shell=None, istream=None)
Popen(['git', 'cat-file', '--batch-check'], cwd=/tmp/lint, universal_newlines=False, shell=None, istream=<valid stream>)
Linter version command: ['actionlint', '-version']
Linter version result: 0 v1.6.4
installed by building from source
built with go1.15.15 compiler for linux/amd64

### Processed [ACTION] files
- Using [actionlint v1.6.4] https://rhysd.github.io/actionlint/
- Mega-Linter key: [ACTION_ACTIONLINT]
- Rules config: identified by [actionlint]
[actionlint] .github/workflows/php-tests.yaml
✅ Linted [ACTION] files with [actionlint] successfully - (0.06s)
Skipped post of Github Status for ACTION with actionlint
[Text Reporter] Generated TEXT report: /tmp/lint/report/linters_logs/SUCCESS-ACTION_ACTIONLINT.log
[Post] No commands declared in user configuration

+----SUMMARY-+------------+-------+-------+--------+--------------+
| Descriptor | Linter     | Files | Fixed | Errors | Elapsed time |
+------------+------------+-------+-------+--------+--------------+
| ✅ ACTION  | actionlint |     1 |       |      0 |        0.06s |
+------------+------------+-------+-------+--------+--------------+
llaville commented 2 years ago

LGTM also with yaml test files added for automation (tested in real condition)

### Processed [ACTION] files
- Using [actionlint v1.6.4] https://rhysd.github.io/actionlint/
- Mega-Linter key: [ACTION_ACTIONLINT]
- Rules config: identified by [actionlint]
[actionlint] data/actionlint_bad_1.yml
[actionlint] data/actionlint_good_1.yaml
--Error detail:
verbose: Linting 2 files
verbose: Linting tmp/lint/data/actionlint_good_1.yaml
verbose: Using project at /tmp/lint
verbose: Linting tmp/lint/data/actionlint_bad_1.yml
verbose: Using project at /tmp/lint
verbose: Found 0 parse errors in 0 ms for tmp/lint/data/actionlint_good_1.yaml
verbose: Found 1 parse errors in 0 ms for tmp/lint/data/actionlint_bad_1.yml
verbose: Found total 7 errors in 16 ms for tmp/lint/data/actionlint_bad_1.yml
verbose: Found total 0 errors in 17 ms for tmp/lint/data/actionlint_good_1.yaml
tmp/lint/data/actionlint_bad_1.yml:3:5: unexpected key "branch" for "push" section. expected one of "branches", "branches-ignore", "paths", "paths-ignore", "tags", "tags-ignore", "types", "workflows" [syntax-check]
  |
3 |     branch: main
  |     ^~~~~~~
tmp/lint/data/actionlint_bad_1.yml:5:11: character '\' is invalid for branch and tag names. only special characters [, ?, +, *, \ ! can be escaped with \. see `man git-check-ref-format` for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet [glob]
  |
5 |       - 'v\d+'
  |           ^~~~
tmp/lint/data/actionlint_bad_1.yml:10:28: label "linux-latest" is unknown. available labels are "windows-latest", "windows-2019", "windows-2016", "ubuntu-latest", "ubuntu-20.04", "ubuntu-18.04", "ubuntu-16.04", "macos-latest", "macos-11", "macos-11.0", "macos-10.15", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file [runner-label]
   |
10 |         os: [macos-latest, linux-latest]
   |                            ^~~~~~~~~~~~~
tmp/lint/data/actionlint_bad_1.yml:13:41: "github.event.head_commit.message" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions for more details [expression]
   |
13 |       - run: echo "Checking commit '${{ github.event.head_commit.message }}'"
   |                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tmp/lint/data/actionlint_bad_1.yml:17:11: input "node_version" is not defined in action "actions/setup-node@v2". available inputs are "always-auth", "architecture", "cache", "cache-dependency-path", "check-latest", "node-version", "registry-url", "scope", "token", "version" [action]
   |
17 |           node_version: 16.x
   |           ^~~~~~~~~~~~~
tmp/lint/data/actionlint_bad_1.yml:21:20: property "platform" is not defined in object type {os: string} [expression]
   |
21 |           key: ${{ matrix.platform }}-node-${{ hashFiles('**/package-lock.json') }}
   |                    ^~~~~~~~~~~~~~~
tmp/lint/data/actionlint_bad_1.yml:22:17: receiver of object dereference "permissions" must be type of object but got "string" [expression]
   |
22 |         if: ${{ github.repository.permissions.admin == true }}
   |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
verbose: Found 7 errors in 2 files

❌ Linted [ACTION] files with [actionlint]: Found 1 error(s) - (0.06s)
Skipped post of Github Status for ACTION with actionlint
[Text Reporter] Generated TEXT report: /tmp/lint/report/linters_logs/ERROR-ACTION_ACTIONLINT.log
[Post] No commands declared in user configuration

+----SUMMARY-+------------+-------+-------+--------+--------------+
| Descriptor | Linter     | Files | Fixed | Errors | Elapsed time |
+------------+------------+-------+-------+--------+--------------+
| ❌ ACTION  | actionlint |     2 |       |      1 |        0.06s |
+------------+------------+-------+-------+--------+--------------+
llaville commented 2 years ago

@nvuillam I've a strange behavior when I run build.sh, new linter in all_flavors is removed (for ci_light flavor only) each time I run the build.sh script And I don't understand why

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   megalinter/descriptors/all_flavors.json

(venv) llaville@DESKTOP-83207V7:~/devilbox_data/backups/github/my-mega-linter$ git diff megalinter/descriptors/all_flavors.json
diff --git a/megalinter/descriptors/all_flavors.json b/megalinter/descriptors/all_flavors.json
index c4a8f853..75f14735 100644
--- a/megalinter/descriptors/all_flavors.json
+++ b/megalinter/descriptors/all_flavors.json
@@ -5,7 +5,6 @@
         ],
         "label": "Optimized for CI items (Dockerfile, Jenkinsfile, JSON/YAML schemas,XML",
         "linters": [
-            "ACTION_ACTIONLINT",
             "DOCKERFILE_DOCKERFILELINT",
             "DOCKERFILE_HADOLINT",
             "ENV_DOTENV_LINTER",

BTW, I'll propose the PR as draft, and you can have time to make your code review

llaville commented 2 years ago

Hope I've well followed the add new linter process. Waiting your feedbacks

nvuillam commented 2 years ago

@llaville seems nice, i have a look :)

About your question: this is the code of build.py about dispatching linters in flavors use 'all' instead of 'all_flavors' :)

image