2020-11-12 12:27:34 -05:00
#!/usr/bin/env bash
2021-07-19 10:28:49 -04:00
DetectActions( ) {
FILE = " ${ 1 } "
2024-01-06 12:39:39 -05:00
if [ " ${ VALIDATE_GITHUB_ACTIONS } " = = "false" ] ; then
debug " Don't check if ${ FILE } is a GitHub Actions file because VALIDATE_GITHUB_ACTIONS is: ${ VALIDATE_GITHUB_ACTIONS } "
return 1
fi
2021-07-19 10:28:49 -04:00
debug " Checking if ${ FILE } is a GitHub Actions file... "
# Check if in the users .github, or the super linter test suite
2023-12-15 03:50:35 -05:00
if [ [ " $( dirname " ${ FILE } " ) " = = *".github/workflows" * ] ] || [ [ " $( dirname " ${ FILE } " ) " = = *" ${ TEST_CASE_FOLDER } /github_actions " * ] ] ; then
2021-07-19 10:28:49 -04:00
debug " ${ FILE } is GitHub Actions file. "
return 0
else
debug " ${ FILE } is NOT GitHub Actions file. "
return 1
fi
}
2024-01-06 12:39:39 -05:00
2020-11-12 12:27:34 -05:00
DetectOpenAPIFile( ) {
FILE = " ${ 1 } "
2024-01-06 12:39:39 -05:00
if [ " ${ VALIDATE_OPENAPI } " = = "false" ] ; then
debug " Don't check if ${ FILE } is an OpenAPI file because VALIDATE_OPENAPI is: ${ VALIDATE_OPENAPI } "
return 1
fi
2020-11-12 12:27:34 -05:00
2024-01-06 12:39:39 -05:00
debug " Checking if ${ FILE } is an OpenAPI file... "
2020-11-12 12:27:34 -05:00
2024-01-06 12:39:39 -05:00
if grep -E '"openapi":|"swagger":|^openapi:|^swagger:' " ${ FILE } " >/dev/null; then
2021-01-27 14:47:34 -05:00
debug " ${ FILE } is an OpenAPI descriptor "
2020-11-12 12:27:34 -05:00
return 0
else
2021-01-27 14:47:34 -05:00
debug " ${ FILE } is NOT an OpenAPI descriptor "
2020-11-12 12:27:34 -05:00
return 1
fi
}
2024-01-06 12:39:39 -05:00
2020-11-12 12:27:34 -05:00
DetectTektonFile( ) {
FILE = " ${ 1 } "
2024-01-06 12:39:39 -05:00
if [ " ${ VALIDATE_TEKTON } " = = "false" ] ; then
debug " Don't check if ${ FILE } is a Tekton file because VALIDATE_TEKTON is: ${ VALIDATE_TEKTON } "
return 1
fi
2020-11-12 12:27:34 -05:00
debug " Checking if ${ FILE } is a Tekton file... "
2024-01-06 12:39:39 -05:00
if grep -q -E 'apiVersion: tekton' " ${ FILE } " >/dev/null; then
2020-11-12 12:27:34 -05:00
return 0
else
return 1
fi
}
2024-01-06 12:39:39 -05:00
2020-11-12 12:27:34 -05:00
DetectARMFile( ) {
2024-01-06 12:39:39 -05:00
FILE = " ${ 1 } "
if [ " ${ VALIDATE_ARM } " = = "false" ] ; then
debug " Don't check if ${ FILE } is an ARM file because VALIDATE_ARM is: ${ VALIDATE_ARM } "
return 1
fi
2020-11-12 12:27:34 -05:00
debug " Checking if ${ FILE } is an ARM file... "
2024-01-06 12:39:39 -05:00
if grep -E 'schema.management.azure.com' " ${ FILE } " >/dev/null; then
2020-11-12 12:27:34 -05:00
return 0
else
return 1
fi
}
2024-01-06 12:39:39 -05:00
2020-11-12 12:27:34 -05:00
DetectCloudFormationFile( ) {
2024-01-06 12:39:39 -05:00
FILE = " ${ 1 } "
if [ " ${ VALIDATE_CLOUDFORMATION } " = = "false" ] ; then
debug " Don't check if ${ FILE } is a CloudFormation file because VALIDATE_CLOUDFORMATION is: ${ VALIDATE_CLOUDFORMATION } "
return 1
fi
2020-11-12 12:27:34 -05:00
debug " Checking if ${ FILE } is a Cloud Formation file... "
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-formats.html
# AWSTemplateFormatVersion is optional
2024-01-06 12:39:39 -05:00
# Check if file has AWS Template info
2020-11-12 12:27:34 -05:00
if grep -q 'AWSTemplateFormatVersion' " ${ FILE } " >/dev/null; then
return 0
fi
2024-01-06 12:39:39 -05:00
# See if it contains AWS References
2020-11-12 12:27:34 -05:00
if grep -q -E '(AWS|Alexa|Custom)::' " ${ FILE } " >/dev/null; then
return 0
fi
return 1
}
2024-01-06 12:39:39 -05:00
2020-11-12 12:27:34 -05:00
DetectKubernetesFile( ) {
2024-01-06 12:39:39 -05:00
FILE = " ${ 1 } "
if [ " ${ VALIDATE_KUBERNETES_KUBECONFORM } " = = "false" ] ; then
debug " Don't check if ${ FILE } is a Kubernetes file because VALIDATE_KUBERNETES_KUBECONFORM is: ${ VALIDATE_KUBERNETES_KUBECONFORM } "
return 1
fi
2020-11-12 12:27:34 -05:00
debug " Checking if ${ FILE } is a Kubernetes descriptor... "
2022-03-14 10:22:58 -04:00
if grep -q -v 'kustomize.config.k8s.io' " ${ FILE } " &&
grep -q -v "tekton" " ${ FILE } " &&
2023-06-20 15:27:03 -04:00
grep -q -E '(^apiVersion):' " ${ FILE } " &&
grep -q -E '(^kind):' " ${ FILE } " ; then
2020-11-12 12:27:34 -05:00
debug " ${ FILE } is a Kubernetes descriptor "
return 0
fi
debug " ${ FILE } is NOT a Kubernetes descriptor "
return 1
}
2024-01-06 12:39:39 -05:00
2020-11-12 12:27:34 -05:00
DetectAWSStatesFIle( ) {
2024-01-06 12:39:39 -05:00
FILE = " ${ 1 } "
if [ " ${ VALIDATE_STATES } " = = "false" ] ; then
debug " Don't check if ${ FILE } is an AWS states file because VALIDATE_STATES is: ${ VALIDATE_STATES } "
return 1
fi
2020-11-12 12:27:34 -05:00
debug " Checking if ${ FILE } is a AWS states descriptor... "
# https://states-language.net/spec.html#example
2021-09-09 14:03:41 -04:00
if grep -q '"Resource": *"arn' " ${ FILE } " &&
grep -q '"States"' " ${ FILE } " ; then
2020-11-12 12:27:34 -05:00
return 0
fi
return 1
}
2024-01-06 12:39:39 -05:00
2020-11-12 12:27:34 -05:00
function GetFileType( ) {
# Need to run the file through the 'file' exec to help determine
# The type of file being parsed
FILE = " $1 "
GET_FILE_TYPE_CMD = $( file " ${ FILE } " 2>& 1)
echo " ${ GET_FILE_TYPE_CMD } "
}
2024-01-06 12:39:39 -05:00
2020-11-12 12:27:34 -05:00
function CheckFileType( ) {
# Need to run the file through the 'file' exec to help determine
# The type of file being parsed
2024-01-30 14:24:55 -05:00
local FILE
2020-11-12 12:27:34 -05:00
FILE = " $1 "
2024-01-30 14:24:55 -05:00
local GET_FILE_TYPE_CMD
2020-11-12 12:27:34 -05:00
GET_FILE_TYPE_CMD = " $( GetFileType " $FILE " ) "
2024-01-11 14:44:16 -05:00
local FILE_TYPE_MESSAGE
2020-11-12 12:27:34 -05:00
if [ [ ${ GET_FILE_TYPE_CMD } = = *"Ruby script" * ] ] ; then
2024-01-11 14:44:16 -05:00
FILE_TYPE_MESSAGE = " Found Ruby script without extension ( ${ FILE } ). Rename the file with proper extension for Ruby files. "
2024-01-30 14:24:55 -05:00
echo " ${ FILE } " >>" ${ FILE_ARRAYS_DIRECTORY_PATH } /file-array-RUBY "
2022-01-19 12:09:26 -05:00
elif [ [ ${ GET_FILE_TYPE_CMD } = = *"Python script" * ] ] ; then
2024-01-11 14:44:16 -05:00
FILE_TYPE_MESSAGE = " Found Python script without extension ( ${ FILE } ). Rename the file with proper extension for Python files. "
2024-01-30 14:24:55 -05:00
echo " ${ FILE } " >>" ${ FILE_ARRAYS_DIRECTORY_PATH } /file-array-PYTHON "
2022-01-19 12:09:26 -05:00
elif [ [ ${ GET_FILE_TYPE_CMD } = = *"Perl script" * ] ] ; then
2024-01-11 14:44:16 -05:00
FILE_TYPE_MESSAGE = " Found Perl script without extension ( ${ FILE } ). Rename the file with proper extension for Perl files. "
2024-01-30 14:24:55 -05:00
echo " ${ FILE } " >>" ${ FILE_ARRAYS_DIRECTORY_PATH } /file-array-PERL "
2020-11-12 12:27:34 -05:00
else
2024-01-11 14:44:16 -05:00
FILE_TYPE_MESSAGE = " Failed to get file type for: ${ FILE } "
fi
if [ " ${ SUPPRESS_FILE_TYPE_WARN } " = = "false" ] ; then
warn " ${ FILE_TYPE_MESSAGE } "
else
debug " ${ FILE_TYPE_MESSAGE } "
2020-11-12 12:27:34 -05:00
fi
}
2024-01-06 12:39:39 -05:00
2020-11-12 12:27:34 -05:00
function GetFileExtension( ) {
FILE = " $1 "
2024-01-11 15:30:00 -05:00
# We want a lowercase value
local -l FILE_TYPE
# Extract the file extension
2020-11-12 12:27:34 -05:00
FILE_TYPE = ${ FILE ##*. }
echo " $FILE_TYPE "
}
2024-01-06 12:39:39 -05:00
2020-11-12 12:27:34 -05:00
function IsValidShellScript( ) {
FILE = " $1 "
2024-01-06 12:39:39 -05:00
if [ " ${ VALIDATE_BASH } " = = "false" ] && [ " ${ VALIDATE_BASH_EXEC } " = = "false" ] && [ " ${ VALIDATE_SHELL_SHFMT } " = = "false" ] ; then
debug " Don't check if ${ FILE } is a shell script because VALIDATE_BASH, VALIDATE_BASH_EXEC, and VALIDATE_SHELL_SHFMT are set to: ${ VALIDATE_BASH } , ${ VALIDATE_BASH_EXEC } , ${ VALIDATE_SHELL_SHFMT } "
return 1
fi
2020-11-12 12:27:34 -05:00
FILE_EXTENSION = " $( GetFileExtension " $FILE " ) "
GET_FILE_TYPE_CMD = " $( GetFileType " $FILE " ) "
trace " File:[ ${ FILE } ], File extension:[ ${ FILE_EXTENSION } ], File type: [ ${ GET_FILE_TYPE_CMD } ] "
if [ [ " ${ FILE_EXTENSION } " = = "zsh" ] ] ||
[ [ ${ GET_FILE_TYPE_CMD } = = *"zsh script" * ] ] ; then
warn " $FILE is a ZSH script. Skipping... "
return 1
fi
if [ " ${ FILE_EXTENSION } " = = "sh" ] ||
[ " ${ FILE_EXTENSION } " = = "bash" ] ||
2021-07-19 10:30:44 -04:00
[ " ${ FILE_EXTENSION } " = = "bats" ] ||
2020-11-12 12:27:34 -05:00
[ " ${ FILE_EXTENSION } " = = "dash" ] ||
[ " ${ FILE_EXTENSION } " = = "ksh" ] ; then
debug " $FILE is a valid shell script (has a valid extension: ${ FILE_EXTENSION } ) "
return 0
fi
if [ [ " ${ GET_FILE_TYPE_CMD } " = = *"POSIX shell script" * ] ] ||
[ [ ${ GET_FILE_TYPE_CMD } = = *"Bourne-Again shell script" * ] ] ||
[ [ ${ GET_FILE_TYPE_CMD } = = *"dash script" * ] ] ||
[ [ ${ GET_FILE_TYPE_CMD } = = *"ksh script" * ] ] ||
[ [ ${ GET_FILE_TYPE_CMD } = = *"/usr/bin/env sh script" * ] ] ; then
debug " $FILE is a valid shell script (has a valid file type: ${ GET_FILE_TYPE_CMD } ) "
return 0
fi
trace " $FILE is NOT a supported shell script. Skipping "
return 1
}
2024-01-06 12:39:39 -05:00
2021-06-28 08:59:11 -04:00
function IsGenerated( ) {
FILE = " $1 "
2024-01-06 12:39:39 -05:00
if [ " ${ IGNORE_GENERATED_FILES } " = = "false" ] ; then
debug " Don't check if ${ FILE } is generated because IGNORE_GENERATED_FILES is: ${ IGNORE_GENERATED_FILES } "
return 1
fi
2021-06-28 08:59:11 -04:00
2024-01-06 12:39:39 -05:00
if ! grep -q "@generated" " $FILE " ; then
2021-06-28 08:59:11 -04:00
trace " File:[ ${ FILE } ] is not generated, because it doesn't have @generated marker "
return 1
fi
2024-01-06 12:39:39 -05:00
if grep -q "@not-generated" " $FILE " ; then
2021-06-28 08:59:11 -04:00
trace " File:[ ${ FILE } ] is not-generated because it has @not-generated marker "
return 1
else
trace " File:[ ${ FILE } ] is generated because it has @generated marker "
return 0
fi
}
2024-01-06 12:39:39 -05:00
2024-01-30 14:24:55 -05:00
# We need these functions when building the file list with paralle
export -f CheckFileType
export -f DetectActions
export -f DetectARMFile
export -f DetectAWSStatesFIle
export -f DetectCloudFormationFile
export -f DetectKubernetesFile
export -f DetectOpenAPIFile
export -f DetectTektonFile
export -f GetFileExtension
export -f GetFileType
export -f IsValidShellScript
export -f IsGenerated
2021-09-10 10:43:20 -04:00
function RunAdditionalInstalls( ) {
2024-01-30 14:24:55 -05:00
if [ -z " ${ FILE_ARRAYS_DIRECTORY_PATH } " ] || [ ! -d " ${ FILE_ARRAYS_DIRECTORY_PATH } " ] ; then
fatal " FILE_ARRAYS_DIRECTORY_PATH (set to ${ FILE_ARRAYS_DIRECTORY_PATH } ) is empty or doesn't exist "
fi
2021-09-10 10:43:20 -04:00
##################################
# Run installs for Psalm and PHP #
##################################
2024-01-30 14:24:55 -05:00
if [ " ${ VALIDATE_PHP_PSALM } " = = "true" ] && [ -e " ${ FILE_ARRAYS_DIRECTORY_PATH } /file-array-PHP_PSALM " ] ; then
2021-09-10 10:43:20 -04:00
# found PHP files and were validating it, need to composer install
info "Found PHP files to validate, and [VALIDATE_PHP_PSALM] set to true, need to run composer install"
info "looking for composer.json in the users repository..."
mapfile -t COMPOSER_FILE_ARRAY < <( find / -name composer.json 2>& 1)
2021-10-01 13:41:13 -04:00
debug " COMPOSER_FILE_ARRAY contents:[ ${ COMPOSER_FILE_ARRAY [*] } ] "
2021-09-10 10:43:20 -04:00
############################################
# Check if we found the file in the system #
############################################
if [ " ${# COMPOSER_FILE_ARRAY [@] } " -ne 0 ] ; then
for LINE in " ${ COMPOSER_FILE_ARRAY [@] } " ; do
2022-03-23 12:43:28 -04:00
COMPOSER_PATH = $( dirname " ${ LINE } " 2>& 1)
2021-09-10 10:43:20 -04:00
info " Found [composer.json] at:[ ${ LINE } ] "
COMPOSER_CMD = $(
2022-03-23 12:43:28 -04:00
cd " ${ COMPOSER_PATH } " || exit 1
2021-10-01 13:41:13 -04:00
composer install --no-progress -q 2>& 1
2021-09-10 10:43:20 -04:00
)
##############
# Error code #
##############
ERROR_CODE = $?
##############################
# Check the shell for errors #
##############################
if [ " ${ ERROR_CODE } " -ne 0 ] ; then
# Error
2022-03-23 12:43:28 -04:00
error " ERROR! Failed to run composer install at location:[ ${ COMPOSER_PATH } ] "
2021-09-10 10:43:20 -04:00
fatal " ERROR:[ ${ COMPOSER_CMD } ] "
else
# Success
info "Successfully ran:[composer install] for PHP validation"
fi
done
fi
fi
2021-10-05 09:46:38 -04:00
###############################
# Run installs for R language #
###############################
2024-01-30 14:24:55 -05:00
if [ " ${ VALIDATE_R } " = = "true" ] && [ -e " ${ FILE_ARRAYS_DIRECTORY_PATH } /file-array-R " ] ; then
2021-10-05 09:46:38 -04:00
info "Detected R Language files to lint."
2024-01-30 14:24:55 -05:00
info " Trying to install the R package inside:[ ${ GITHUB_WORKSPACE } ] "
2021-10-05 09:46:38 -04:00
#########################
# Run the build command #
#########################
2024-01-30 14:24:55 -05:00
BUILD_CMD = $( R CMD build " ${ GITHUB_WORKSPACE } " 2>& 1)
2021-10-05 09:46:38 -04:00
##############
# Error code #
##############
ERROR_CODE = $?
##############################
# Check the shell for errors #
##############################
if [ " ${ ERROR_CODE } " -ne 0 ] ; then
# Error
2024-01-30 14:24:55 -05:00
warn " ERROR! Failed to run:[R CMD build] at location:[ ${ GITHUB_WORKSPACE } ] "
2021-10-05 09:46:38 -04:00
warn " BUILD_CMD:[ ${ BUILD_CMD } ] "
else
# Get the build package
BUILD_PKG = $(
2024-01-30 14:24:55 -05:00
cd " ${ GITHUB_WORKSPACE } " || exit 0
2021-10-05 09:46:38 -04:00
echo *.tar.gz 2>& 1
)
##############################
# Install the build packages #
##############################
INSTALL_CMD = $(
2024-01-30 14:24:55 -05:00
cd " ${ GITHUB_WORKSPACE } " || exit 0
2022-10-28 13:41:13 -04:00
R -e "remotes::install_local('.', dependencies=T)" 2>& 1
2021-11-09 15:35:36 -05:00
)
2021-10-05 09:46:38 -04:00
##############
# Error code #
##############
ERROR_CODE = $?
##############################
# Check the shell for errors #
##############################
2023-01-16 13:28:56 -05:00
debug " INSTALL_CMD:[ ${ INSTALL_CMD } ] "
2021-10-05 09:46:38 -04:00
if [ " ${ ERROR_CODE } " -ne 0 ] ; then
2023-10-15 01:10:37 -04:00
warn " ERROR: Failed to install the build package at:[ ${ BUILD_PKG } ] "
2021-10-05 09:46:38 -04:00
fi
fi
2024-01-30 14:24:55 -05:00
if [ ! -f " ${ R_RULES_FILE_PATH_IN_ROOT } " ] ; then
info "No .lintr configuration file found, using defaults."
cp " $R_LINTER_RULES " " $GITHUB_WORKSPACE "
# shellcheck disable=SC2034
SUPER_LINTER_COPIED_R_LINTER_RULES_FILE = "true"
fi
2021-10-05 09:46:38 -04:00
fi
2022-03-28 14:32:04 -04:00
####################################
# Run installs for TFLINT language #
####################################
2024-01-30 14:24:55 -05:00
if [ " ${ VALIDATE_TERRAFORM_TFLINT } " = = "true" ] && [ -e " ${ FILE_ARRAYS_DIRECTORY_PATH } /file-array-TERRAFORM_TFLINT " ] ; then
2022-03-28 14:32:04 -04:00
info "Detected TFLint Language files to lint."
2024-01-30 14:24:55 -05:00
info " Trying to install the TFLint init inside:[ ${ GITHUB_WORKSPACE } ] "
2022-03-28 14:32:04 -04:00
#########################
# Run the build command #
#########################
BUILD_CMD = $(
2024-01-30 14:24:55 -05:00
cd " ${ GITHUB_WORKSPACE } " || exit 0
2023-12-15 04:29:34 -05:00
tflint --init -c " ${ TERRAFORM_TFLINT_LINTER_RULES } " 2>& 1
2022-03-28 14:32:04 -04:00
)
##############
# Error code #
##############
ERROR_CODE = $?
##############################
# Check the shell for errors #
##############################
if [ " ${ ERROR_CODE } " -ne 0 ] ; then
2023-12-15 04:29:34 -05:00
fatal " ERROR! Failed to initialize tflint with the ${ TERRAFORM_TFLINT_LINTER_RULES } config file: ${ BUILD_CMD } "
2022-03-28 14:32:04 -04:00
else
2023-12-15 04:29:34 -05:00
info " Successfully initialized tflint with the ${ TERRAFORM_TFLINT_LINTER_RULES } config file "
debug " Tflint output: ${ BUILD_CMD } "
2022-03-28 14:32:04 -04:00
fi
2024-01-30 14:24:55 -05:00
# Array to track directories where tflint was run
local -A TFLINT_SEEN_DIRS
TFLINT_SEEN_DIRS = ( )
for FILE in " ${ FILE_ARRAY_TERRAFORM_TFLINT [@] } " ; do
local DIR_NAME
DIR_NAME = $( dirname " ${ FILE } " 2>& 1)
debug " DIR_NAME for ${ FILE } : ${ DIR_NAME } "
# Check the cache to see if we've already prepped this directory for tflint
if [ [ ! -v " TFLINT_SEEN_DIRS[ ${ DIR_NAME } ] " ] ] ; then
debug " Configuring Terraform data directory for ${ DIR_NAME } "
# Define the path to an empty Terraform data directory
# (def: https://developer.hashicorp.com/terraform/cli/config/environment-variables#tf_data_dir)
# in case the user has a Terraform data directory already, and we don't
# want to modify it.
# TFlint considers this variable as well.
# Ref: https://github.com/terraform-linters/tflint/blob/master/docs/user-guide/compatibility.md#environment-variables
TF_DATA_DIR = " /tmp/.terraform- ${ TERRAFORM_TFLINT } - ${ DIR_NAME } "
# Fetch Terraform modules
debug " Fetch Terraform modules for ${ FILE } in ${ DIR_NAME } in ${ TF_DATA_DIR } "
local FETCH_TERRAFORM_MODULES_CMD
if ! FETCH_TERRAFORM_MODULES_CMD = " $( terraform get) " ; then
fatal " Error when fetching Terraform modules while linting ${ FILE } . Command output: ${ FETCH_TERRAFORM_MODULES_CMD } "
fi
debug " Fetch Terraform modules command for ${ FILE } output: ${ FETCH_TERRAFORM_MODULES_CMD } "
# Let the cache know we've seen this before
# Set the value to an arbitrary non-empty string.
TFLINT_SEEN_DIRS[ ${ DIR_NAME } ] = "false"
else
debug " Skip fetching Terraform modules for ${ FILE } because we already did that for ${ DIR_NAME } "
fi
done
fi
# Check if there's local configuration for the Raku linter
if [ -e " ${ GITHUB_WORKSPACE } /META6.json " ] ; then
cd " ${ GITHUB_WORKSPACE } " && zef install --deps-only --/test .
2022-03-28 14:32:04 -04:00
fi
2021-09-10 10:43:20 -04:00
}