superlint/test/inspec/super-linter/controls/super_linter.rb
Marco Ferrari d465382ed5
Update documentation (#4981)
* Update documentation

* Fix typos

* Update security policy

* Remove outdated instructions

* Fix list

* Add more info to config load step

* Don't test linter.yml

* Point to the cd workflow in README

* Move badge up

* Add info about Make help

---------

Co-authored-by: Zack Koppert <zkoppert@github.com>
2023-12-11 21:35:20 +00:00

439 lines
13 KiB
Ruby

# frozen_string_literal: true
# PUll in env vars passed
image = ENV["IMAGE"]
##################################################
# Check to see all system packages are installed #
##################################################
control "super-linter-installed-packages" do
impact 1
title "Super-Linter installed packages check"
desc "Check that packages that Super-Linter needs are installed."
packages = [
"bash",
"ca-certificates",
"coreutils",
"curl",
"gcc",
"git-lfs",
"git",
"glibc",
"gnupg",
"go",
"icu-libs",
"jq",
"krb5-libs",
"libc-dev",
"libcurl",
"libffi-dev",
"libgcc",
"libintl",
"libssl1.1",
"libstdc++",
"libxml2-dev",
"libxml2-utils",
"linux-headers",
"lttng-ust-dev",
"make",
"musl-dev",
"npm",
"nodejs-current",
"openjdk17-jre",
"openssl-dev",
"perl-dev",
"perl",
"py3-pyflakes",
"py3-setuptools",
"python3-dev",
"rakudo",
"R-dev",
"R-doc",
"R",
"readline-dev",
"ruby-bundler",
"ruby-dev",
"ruby-rdoc",
"ruby",
"rustup",
"zef",
"zlib-dev",
"zlib"
]
# Removed linters from slim image
SLIM_IMAGE_REMOVED_PACKAGES=%w(
rustup
)
packages.each do |item|
if (image == "slim" && SLIM_IMAGE_REMOVED_PACKAGES.include?(item))
next
else
describe package(item) do
it { should be_installed }
end
end
end
end
###########################################
# Check to see all binaries are installed #
###########################################
control "super-linter-installed-commands" do
impact 1
title "Super-Linter installed commands check"
desc "Check that commands that Super-Linter needs are installed."
default_version_option = "--version"
default_version_expected_exit_status = 0
default_expected_stdout_regex = /(.*?)/s
linters = [
{ linter_name: "actionlint"},
{ linter_name: "ansible-lint", expected_stdout_regex: /(.*)/},
{ linter_name: "arm-ttk", version_command: "grep -iE 'version' '/usr/bin/arm-ttk' | xargs"},
{ linter_name: "asl-validator", expected_exit_status: 0},
{ linter_name: "bash-exec", expected_exit_status: 1}, # expect a return code = 1 because this linter doesn't support a "get linter version" command
{ linter_name: "black"},
{ linter_name: "clang-format"},
{ linter_name: "cfn-lint"},
{ linter_name: "checkstyle", version_command: "java -jar /usr/bin/checkstyle --version"},
{ linter_name: "google-java-format", version_command: "java -jar /usr/bin/google-java-format --version"},
{ linter_name: "chktex"},
{ linter_name: "clippy", linter_command: "clippy", version_command: "cargo-clippy --version"},
{ linter_name: "clj-kondo"},
{ linter_name: "coffeelint"},
{ linter_name: "cpplint"},
{ linter_name: "dart"},
{ linter_name: "dotnet"},
{ linter_name: "dotenv-linter"},
{ linter_name: "editorconfig-checker", version_option: "-version"},
{ linter_name: "eslint"},
{ linter_name: "flake8"},
{ linter_name: "gherkin-lint", expected_exit_status: 1}, # expect a return code = 1 because this linter doesn't support a "get linter version" command
{ linter_name: "golangci-lint"},
{ linter_name: "hadolint"},
{ linter_name: "htmlhint"},
{ linter_name: "isort"},
{ linter_name: "jscpd"},
{ linter_name: "ktlint"},
{ linter_name: "kubeconform", version_option: "-v"},
{ linter_name: "lua", version_option: "-v"},
{ linter_name: "markdownlint"},
{ linter_name: "mypy"},
{ linter_name: "npm-groovy-lint"},
{ linter_name: "perl"},
{ linter_name: "php"},
{ linter_name: "phpcs"},
{ linter_name: "phpstan"},
{ linter_name: "protolint", version_option: "version"},
{ linter_name: "psalm"},
{ linter_name: "pwsh"},
{ linter_name: "pylint"},
{ linter_name: "R", version_command: "R --slave -e \"r_ver <- R.Version()\\$version.string; \
lintr_ver <- packageVersion('lintr'); \
glue::glue('lintr { lintr_ver } on { r_ver }')\""},
{ linter_name: "raku", version_command: "raku --version | strings -n 8"},
{ linter_name: "rubocop"},
{ linter_name: "rustfmt"},
{ linter_name: "scalafmt"},
{ linter_name: "shellcheck"},
{ linter_name: "shfmt"},
{ linter_name: "snakefmt"},
{ linter_name: "snakemake"},
{ linter_name: "spectral"},
{ linter_name: "sql-lint"},
{ linter_name: "sqlfluff"},
{ linter_name: "standard"},
{ linter_name: "stylelint"},
{ linter_name: "tekton-lint"},
{ linter_name: "terraform"},
{ linter_name: "terragrunt"},
{ linter_name: "terrascan", version_option: "version"},
{ linter_name: "tflint"},
{ linter_name: "xmllint"},
{ linter_name: "yamllint"},
]
# Removed linters from slim image
SLIM_IMAGE_REMOVED_LINTERS=%w(
arm-ttk
clippy
dotnet
dotenv-linter
pwsh
rustfmt
)
linters.each do |linter|
# If we didn't specify a linter command, use the linter name as a linter
# command because the vast majority of linters have name == command
linter_command = ""
if (image == "slim" && SLIM_IMAGE_REMOVED_LINTERS.include?(linter[:linter_name]))
next
else
if (linter.key?(:linter_command))
linter_command = linter[:linter_command]
else
linter_command = linter[:linter_name]
end
describe command("command -v #{linter_command}") do
its("exit_status") { should eq 0 }
end
# A few linters have a command that it's different than linter_command
if (linter.key?(:version_command))
version_command = linter[:version_command]
else
# Check if the linter needs an option that is different from the one that
# the vast majority of linters use to get the version
if (linter.key?(:version_option))
version_option = linter[:version_option]
else
version_option = default_version_option
end
version_command = "#{linter_command} #{version_option}"
if (linter.key?(:expected_exit_status))
expected_exit_status = linter[:expected_exit_status]
else
expected_exit_status = default_version_expected_exit_status
end
if (linter.key?(:expected_stdout_regex))
expected_stdout_regex = linter[:expected_stdout_regex]
else
expected_stdout_regex = default_expected_stdout_regex
end
##########################################################
# Being able to run the command `linter --version` helps #
# achieve that the linter is installed, ini PATH, and #
# has the libraries needed to be able to basically run #
##########################################################
describe command(version_command) do
its("exit_status") { should eq expected_exit_status }
its("stdout") { should match (expected_stdout_regex) }
end
end
end
end
end
###################################
# Linters with no version command #
# protolint editorconfig-checker #
# bash-exec gherkin-lint #
###################################
############################################
# Check to see all Ruby Gems are installed #
############################################
control "super-linter-installed-ruby-gems" do
impact 1
title "Super-Linter installed Ruby gems check"
desc "Check that Ruby gems that Super-Linter needs are installed."
gems = [
"rubocop",
"rubocop-github",
"rubocop-performance",
"rubocop-rails",
"rubocop-rspec"
]
gems.each do |item|
describe gem(item) do
it { should be_installed }
end
end
end
###############################################
# Check to see all NPM packages are installed #
###############################################
control "super-linter-installed-npm-packages" do
impact 1
title "Super-Linter installed NPM packages check"
desc "Check that NPM packages that Super-Linter needs are installed."
packages = [
"@babel/eslint-parser",
"@babel/preset-react",
"@babel/preset-typescript",
"@coffeelint/cli",
"@stoplight/spectral-cli",
"@typescript-eslint/eslint-plugin",
"@typescript-eslint/parser",
"asl-validator",
#"axios",
#"eslint",
"eslint-config-airbnb",
"eslint-config-prettier",
"eslint-plugin-jest",
"eslint-plugin-json",
"eslint-plugin-jsonc",
"eslint-plugin-jsx-a11y",
"eslint-plugin-prettier",
"gherkin-lint",
"htmlhint",
#"immer",
#"ini",
"jscpd",
#"lodash",
"markdownlint-cli",
#"node-fetch",
"npm-groovy-lint",
"prettier",
"prettyjson",
#"pug",
"sql-lint",
"standard",
"stylelint",
"stylelint-config-sass-guidelines",
"stylelint-config-standard",
#"stylelint-scss",
"tekton-lint",
"typescript"
]
packages.each do |item|
describe npm(item, path: "/") do
it { should be_installed }
end
end
end
#####################################
# Check to see if directories exist #
#####################################
control "super-linter-validate-directories" do
impact 1
title "Super-Linter check for directories"
desc "Check that directories that Super-Linter needs are installed."
dirs = [
"/home/r-library",
"/node_modules",
"/action/lib",
"/action/lib/functions",
"/action/lib/.automation",
"/usr/local/lib/",
"/usr/local/share/"
]
# Removed linters from slim image
SLIM_IMAGE_REMOVED_DIRS=%w(
/home/r-library
)
dirs.each do |item|
if (image == "slim" && SLIM_IMAGE_REMOVED_DIRS.include?(item))
next
else
describe directory(item) do
it { should exist }
it { should be_directory }
end
end
end
end
###############################
# Check to see if files exist #
###############################
control "super-linter-validate-files" do
impact 1
title "Super-Linter check for files"
desc "Check that files that Super-Linter needs are installed."
files = [
"/action/lib/linter.sh",
"/action/lib/functions/buildFileList.sh",
"/action/lib/functions/detectFiles.sh",
"/action/lib/functions/linterRules.sh",
"/action/lib/functions/linterVersions.sh",
"/action/lib/functions/linterVersions.txt",
"/action/lib/functions/log.sh",
"/action/lib/functions/possum.sh",
"/action/lib/functions/updateSSL.sh",
"/action/lib/functions/validation.sh",
"/action/lib/functions/worker.sh",
"/action/lib/.automation/actionlint.yml",
"/action/lib/.automation/.ansible-lint.yml",
"/action/lib/.automation/.arm-ttk.psd1",
"/action/lib/.automation/.cfnlintrc.yml",
"/action/lib/.automation/.chktexrc",
"/action/lib/.automation/.clj-kondo",
"/action/lib/.automation/.coffee-lint.json",
"/action/lib/.automation/.ecrc",
"/action/lib/.automation/.eslintrc.yml",
"/action/lib/.automation/.flake8",
"/action/lib/.automation/.gherkin-lintrc",
"/action/lib/.automation/.golangci.yml",
"/action/lib/.automation/.groovylintrc.json",
"/action/lib/.automation/.hadolint.yaml",
"/action/lib/.automation/.htmlhintrc",
"/action/lib/.automation/.isort.cfg",
"/action/lib/.automation/.jscpd.json",
"/action/lib/.automation/.lintr",
"/action/lib/.automation/.luacheckrc",
"/action/lib/.automation/.markdown-lint.yml",
"/action/lib/.automation/.mypy.ini",
"/action/lib/.automation/.openapirc.yml",
"/action/lib/.automation/.perlcriticrc",
"/action/lib/.automation/.powershell-psscriptanalyzer.psd1",
"/action/lib/.automation/.protolintrc.yml",
"/action/lib/.automation/.python-black",
"/action/lib/.automation/.python-lint",
"/action/lib/.automation/.ruby-lint.yml",
"/action/lib/.automation/.scalafmt.conf",
"/action/lib/.automation/.snakefmt.toml",
"/action/lib/.automation/.sql-config.json",
"/action/lib/.automation/.sqlfluff",
"/action/lib/.automation/.stylelintrc.json",
"/action/lib/.automation/.tflint.hcl",
"/action/lib/.automation/.yaml-lint.yml",
"/action/lib/.automation/analysis_options.yml",
"/action/lib/.automation/phpcs.xml",
"/action/lib/.automation/phpstan.neon",
"/action/lib/.automation/psalm.xml",
"/action/lib/.automation/sun_checks.xml"
]
files.each do |item|
describe file(item) do
it { should exist }
end
end
end
###############################
# Validate powershell modules #
###############################
control "super-linter-validate-powershell-modules" do
impact 1
title "Super-Linter validate Powershell Modules"
desc "Check that Powershell modules that Super-Linter needs are installed."
if (image == "slim")
next
else
describe command("pwsh -c \"(Get-Module -Name PSScriptAnalyzer -ListAvailable | Select-Object -First 1).Name\" 2>&1") do
its("exit_status") { should eq 0 }
its("stdout") { should eq "PSScriptAnalyzer\n" }
end
describe command("pwsh -c \"(Get-Command Invoke-ScriptAnalyzer | Select-Object -First 1).Name\" 2>&1") do
its("exit_status") { should eq 0 }
its("stdout") { should eq "Invoke-ScriptAnalyzer\n" }
end
end
end