mirror of
https://github.com/super-linter/super-linter.git
synced 2024-11-06 09:15:49 -05:00
c26430f868
- Support passing an arbitrary path to the shellcheck configuration file with the BASH_CONFIG_FILE_NAME variable. This brings shellcheck in line with other linters that support configuration files. - Enable shellcheck external sources using a directive in the configuration file, so users can eventually override it if not needed. - Export command configuration variables that subprocesses might need. Close #5414
544 lines
16 KiB
Ruby
544 lines
16 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# PUll in env vars passed
|
|
image = ENV["IMAGE"]
|
|
|
|
version_file_path = "/action/linterVersions.txt"
|
|
|
|
control "super-linter-environment-variables" do
|
|
impact 1
|
|
title "Super-Linter environment variables check"
|
|
desc "Check that environment variables that Super-Linter needs are defined."
|
|
|
|
describe os_env("VERSION_FILE") do
|
|
its("content") { should eq version_file_path }
|
|
end
|
|
|
|
describe os_env("IMAGE") do
|
|
its("content") { should match(/^(standard|slim)$/) }
|
|
end
|
|
|
|
if (image == "standard")
|
|
describe os_env("POWERSHELL_TELEMETRY_OPTOUT") do
|
|
its("content") { should eq "1" }
|
|
end
|
|
end
|
|
end
|
|
|
|
##################################################
|
|
# 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",
|
|
"file",
|
|
"gcompat",
|
|
"git-lfs",
|
|
"git",
|
|
"go",
|
|
"jq",
|
|
"libxml2-utils",
|
|
"nodejs-current",
|
|
"npm",
|
|
"openjdk17-jre",
|
|
"openssh-client",
|
|
"parallel",
|
|
"perl",
|
|
"php82",
|
|
"php82-ctype",
|
|
"php82-curl",
|
|
"php82-dom",
|
|
"php82-iconv",
|
|
"php82-mbstring",
|
|
"php82-openssl",
|
|
"php82-phar",
|
|
"php82-simplexml",
|
|
"php82-tokenizer",
|
|
"php82-xmlwriter",
|
|
"R",
|
|
"rakudo",
|
|
"ruby",
|
|
"rust-clippy",
|
|
"rustfmt",
|
|
"tar",
|
|
"zef"
|
|
]
|
|
|
|
# Removed linters from slim image
|
|
SLIM_IMAGE_REMOVED_PACKAGES=%w(
|
|
rust-clippy
|
|
rustfmt
|
|
)
|
|
|
|
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
|
|
|
|
control "super-linter-uninstalled-packages" do
|
|
impact 1
|
|
title "Super-Linter uninstalled packages check"
|
|
desc "Check that packages that Super-Linter doesn't need are not installed."
|
|
|
|
packages = [
|
|
"cmake",
|
|
"clang17-extra-tools",
|
|
"g++",
|
|
"gnupg",
|
|
"libc-dev",
|
|
"libxml2-dev",
|
|
"linux-headers",
|
|
"make",
|
|
"perl-dev",
|
|
"python3-dev",
|
|
"R-dev",
|
|
"R-doc",
|
|
"readline-dev",
|
|
"ruby-bundler",
|
|
"ruby-dev",
|
|
"ruby-rdoc"
|
|
]
|
|
|
|
packages.each do |item|
|
|
describe package(item) do
|
|
it { should_not be_installed }
|
|
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"},
|
|
{ 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: "cfn-lint"},
|
|
{ linter_name: "checkov"},
|
|
{ linter_name: "checkstyle", version_command: "java -jar /usr/bin/checkstyle --version"},
|
|
{ linter_name: "chktex"},
|
|
{ linter_name: "clang-format"},
|
|
{ linter_name: "clippy", linter_command: "clippy", version_command: "cargo-clippy --version"},
|
|
{ linter_name: "clj-kondo"},
|
|
{ linter_name: "coffeelint"},
|
|
{ linter_name: "composer"},
|
|
{ linter_name: "cpplint"},
|
|
{ linter_name: "dart"},
|
|
{ linter_name: "dotenv-linter"},
|
|
{ linter_name: "dotnet"},
|
|
{ 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: "gitleaks", version_option: "version"},
|
|
{ linter_name: "golangci-lint"},
|
|
{ linter_name: "goreleaser"},
|
|
{ linter_name: "google-java-format", version_command: "java -jar /usr/bin/google-java-format --version"},
|
|
{ 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: "prettier"},
|
|
{ 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: "renovate-config-validator", version_command: "renovate --version"},
|
|
{ linter_name: "rubocop"},
|
|
{ linter_name: "ruff"},
|
|
{ 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: "textlint"},
|
|
{ linter_name: "tflint"},
|
|
{ linter_name: "ts-standard"},
|
|
{ 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-minitest",
|
|
"rubocop-performance",
|
|
"rubocop-rails",
|
|
"rubocop-rake",
|
|
"rubocop-rspec",
|
|
"standard"
|
|
]
|
|
|
|
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",
|
|
"@ibm/tekton-lint",
|
|
"@react-native/eslint-config",
|
|
"@react-native/eslint-plugin",
|
|
"@stoplight/spectral-cli",
|
|
"@typescript-eslint/eslint-plugin",
|
|
"@typescript-eslint/parser",
|
|
"asl-validator",
|
|
"eslint",
|
|
"eslint-config-airbnb",
|
|
"eslint-config-prettier",
|
|
"eslint-plugin-jest",
|
|
"eslint-plugin-json",
|
|
"eslint-plugin-jsonc",
|
|
"eslint-plugin-jsx-a11y",
|
|
"eslint-plugin-prettier",
|
|
"eslint-plugin-react",
|
|
"eslint-plugin-react-hooks",
|
|
"eslint-plugin-vue",
|
|
"gherkin-lint",
|
|
"htmlhint",
|
|
"jscpd",
|
|
"markdownlint-cli",
|
|
"next",
|
|
"next-pwa",
|
|
"npm-groovy-lint",
|
|
"postcss-less",
|
|
"prettier",
|
|
"prettyjson",
|
|
"pug",
|
|
"react",
|
|
"react-dom",
|
|
"react-intl",
|
|
"react-redux",
|
|
"react-router-dom",
|
|
"renovate",
|
|
"sql-lint",
|
|
"standard",
|
|
"stylelint",
|
|
"stylelint-config-recommended-scss",
|
|
"stylelint-config-sass-guidelines",
|
|
"stylelint-config-standard",
|
|
"stylelint-config-standard-scss",
|
|
"stylelint-prettier",
|
|
"stylelint-scss",
|
|
"textlint",
|
|
"textlint-filter-rule-allowlist",
|
|
"textlint-filter-rule-comments",
|
|
"textlint-rule-terminology",
|
|
"ts-standard",
|
|
"typescript"
|
|
]
|
|
|
|
packages.each do |item|
|
|
describe npm(item, path: "/") do
|
|
it { should be_installed }
|
|
end
|
|
end
|
|
end
|
|
|
|
###############################################
|
|
# Check to see if PyPi packages are installed #
|
|
###############################################
|
|
control "super-linter-installed-pypi-packages" do
|
|
impact 1
|
|
title "Super-Linter installed PyPi packages check"
|
|
desc "Check that PyPi packages that Super-Linter needs are installed."
|
|
|
|
pypi_packages = [
|
|
"ansible-lint",
|
|
"black",
|
|
"cfn-lint",
|
|
"checkov",
|
|
"cpplint",
|
|
"flake8",
|
|
"isort",
|
|
"mypy",
|
|
"pylint",
|
|
"ruff",
|
|
"snakefmt",
|
|
"snakemake",
|
|
"sqlfluff",
|
|
"yamllint",
|
|
"yq"
|
|
]
|
|
|
|
pypi_packages.each do |item|
|
|
describe pip(item, "/venvs/#{item}/bin/pip") 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 = [
|
|
"/node_modules",
|
|
"/action/lib",
|
|
"/action/lib/functions",
|
|
"/action/lib/.automation",
|
|
"/root/.tflint.d/plugins/github.com/terraform-linters/tflint-ruleset-aws",
|
|
"/root/.tflint.d/plugins/github.com/terraform-linters/tflint-ruleset-azurerm",
|
|
"/root/.tflint.d/plugins/github.com/terraform-linters/tflint-ruleset-google",
|
|
"/usr/local/lib/",
|
|
"/usr/local/share/"
|
|
]
|
|
|
|
# Removed linters from slim image
|
|
SLIM_IMAGE_REMOVED_DIRS=%w(
|
|
)
|
|
|
|
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/githubEvent.sh",
|
|
"/action/lib/functions/linterCommands.sh",
|
|
"/action/lib/functions/linterRules.sh",
|
|
version_file_path,
|
|
"/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/.checkov.yaml",
|
|
"/action/lib/.automation/.chktexrc",
|
|
"/action/lib/.automation/.clang-format",
|
|
"/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/.ruff.toml",
|
|
"/action/lib/.automation/.scalafmt.conf",
|
|
"/action/lib/.automation/.shellcheckrc",
|
|
"/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/phpcs.xml",
|
|
"/action/lib/.automation/phpstan.neon",
|
|
"/action/lib/.automation/psalm.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
|