superlint/lib/functions/detectFiles.sh
cicdguy 94279fc4ed
No fatal error on R package installation (#4705)
Co-authored-by: Zack Koppert <zkoppert@github.com>
2023-10-15 05:10:37 +00:00

536 lines
17 KiB
Bash
Executable file

#!/usr/bin/env bash
################################################################################
################################################################################
########### Super-Linter linting Functions @admiralawkbar ######################
################################################################################
################################################################################
########################## FUNCTION CALLS BELOW ################################
################################################################################
#### Function DetectActions ####################################################
DetectActions() {
FILE="${1}"
debug "Checking if ${FILE} is a GitHub Actions file..."
# Check if in the users .github, or the super linter test suite
if [[ "$(dirname "${FILE}")" == *".github/workflows"* ]] || [[ "$(dirname "${FILE}")" == *".automation/test/github_actions"* ]]; then
debug "${FILE} is GitHub Actions file."
return 0
else
debug "${FILE} is NOT GitHub Actions file."
return 1
fi
}
################################################################################
#### Function DetectOpenAPIFile ################################################
DetectOpenAPIFile() {
################
# Pull in vars #
################
FILE="${1}"
debug "Checking if ${FILE} is an OpenAPI file..."
###############################
# Check the file for keywords #
###############################
grep -E '"openapi":|"swagger":|^openapi:|^swagger:' "${FILE}" >/dev/null
#######################
# Load the error code #
#######################
ERROR_CODE=$?
##############################
# Check the shell for errors #
##############################
if [ ${ERROR_CODE} -eq 0 ]; then
debug "${FILE} is an OpenAPI descriptor"
return 0
else
debug "${FILE} is NOT an OpenAPI descriptor"
return 1
fi
}
################################################################################
#### Function DetectTektonFile #################################################
DetectTektonFile() {
################
# Pull in vars #
################
FILE="${1}"
debug "Checking if ${FILE} is a Tekton file..."
###############################
# Check the file for keywords #
###############################
grep -q -E 'apiVersion: tekton' "${FILE}" >/dev/null
#######################
# Load the error code #
#######################
ERROR_CODE=$?
##############################
# Check the shell for errors #
##############################
if [ ${ERROR_CODE} -eq 0 ]; then
########################
# Found string in file #
########################
return 0
else
###################
# No string match #
###################
return 1
fi
}
################################################################################
#### Function DetectARMFile ####################################################
DetectARMFile() {
################
# Pull in vars #
################
FILE="${1}" # Name of the file/path we are validating
debug "Checking if ${FILE} is an ARM file..."
###############################
# Check the file for keywords #
###############################
grep -E 'schema.management.azure.com' "${FILE}" >/dev/null
#######################
# Load the error code #
#######################
ERROR_CODE=$?
##############################
# Check the shell for errors #
##############################
if [ ${ERROR_CODE} -eq 0 ]; then
########################
# Found string in file #
########################
return 0
else
###################
# No string match #
###################
return 1
fi
}
################################################################################
#### Function DetectCloudFormationFile #########################################
DetectCloudFormationFile() {
################
# Pull in Vars #
################
FILE="${1}" # File that we need to validate
debug "Checking if ${FILE} is a Cloud Formation file..."
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-formats.html
# AWSTemplateFormatVersion is optional
#######################################
# Check if file has AWS Template info #
#######################################
if grep -q 'AWSTemplateFormatVersion' "${FILE}" >/dev/null; then
# Found it
return 0
fi
#####################################
# See if it contains AWS References #
#####################################
if grep -q -E '(AWS|Alexa|Custom)::' "${FILE}" >/dev/null; then
# Found it
return 0
fi
#####################################################
# No identifiers of a CLOUDFORMATION template found #
#####################################################
return 1
}
################################################################################
#### Function DetectKubernetesFile #########################################
DetectKubernetesFile() {
################
# Pull in Vars #
################
FILE="${1}" # File that we need to validate
debug "Checking if ${FILE} is a Kubernetes descriptor..."
if grep -q -v 'kustomize.config.k8s.io' "${FILE}" &&
grep -q -v "tekton" "${FILE}" &&
grep -q -E '(^apiVersion):' "${FILE}" &&
grep -q -E '(^kind):' "${FILE}"; then
debug "${FILE} is a Kubernetes descriptor"
return 0
fi
debug "${FILE} is NOT a Kubernetes descriptor"
return 1
}
################################################################################
#### Function DetectAWSStatesFIle ##############################################
DetectAWSStatesFIle() {
################
# Pull in Vars #
################
FILE="${1}" # File that we need to validate
debug "Checking if ${FILE} is a AWS states descriptor..."
# https://states-language.net/spec.html#example
###############################
# check if file has resources #
###############################
if grep -q '"Resource": *"arn' "${FILE}" &&
grep -q '"States"' "${FILE}"; then
# Found it
return 0
fi
#################################################
# No identifiers of a AWS States Language found #
#################################################
return 1
}
################################################################################
#### Function CheckInArray #####################################################
CheckInArray() {
###############
# Pull in Var #
###############
NEEDLE="$1" # Language we need to match
######################################
# Check if Language was in the array #
######################################
for LANG in "${UNIQUE_LINTED_ARRAY[@]}"; do
if [[ "${LANG}" == "${NEEDLE}" ]]; then
############
# Found it #
############
return 0
fi
done
###################
# Did not find it #
###################
return 1
}
################################################################################
#### Function GetFileType ######################################################
function GetFileType() {
# Need to run the file through the 'file' exec to help determine
# The type of file being parsed
################
# Pull in Vars #
################
FILE="$1"
##################
# Check the file #
##################
GET_FILE_TYPE_CMD=$(file "${FILE}" 2>&1)
echo "${GET_FILE_TYPE_CMD}"
}
################################################################################
#### Function CheckFileType ####################################################
function CheckFileType() {
# Need to run the file through the 'file' exec to help determine
# The type of file being parsed
################
# Pull in Vars #
################
FILE="$1"
#################
# Get file type #
#################
GET_FILE_TYPE_CMD="$(GetFileType "$FILE")"
if [[ ${GET_FILE_TYPE_CMD} == *"Ruby script"* ]]; then
if [ "${SUPPRESS_FILE_TYPE_WARN}" == "false" ]; then
#######################
# It is a Ruby script #
#######################
warn "Found ruby script without extension:[.rb]"
info "Please update file with proper extensions."
fi
################################
# Append the file to the array #
################################
FILE_ARRAY_JSCPD+=("${FILE}")
FILE_ARRAY_RUBY+=("${FILE}")
elif [[ ${GET_FILE_TYPE_CMD} == *"Python script"* ]]; then
if [ "${SUPPRESS_FILE_TYPE_WARN}" == "false" ]; then
#########################
# It is a Python script #
#########################
warn "Found Python script without extension:[.py]"
info "Please update file with proper extensions."
fi
################################
# Append the file to the array #
################################
FILE_ARRAY_JSCPD+=("${FILE}")
FILE_ARRAY_PYTHON+=("${FILE}")
elif [[ ${GET_FILE_TYPE_CMD} == *"Perl script"* ]]; then
if [ "${SUPPRESS_FILE_TYPE_WARN}" == "false" ]; then
#######################
# It is a Perl script #
#######################
warn "Found Perl script without extension:[.pl]"
info "Please update file with proper extensions."
fi
################################
# Append the file to the array #
################################
FILE_ARRAY_JSCPD+=("${FILE}")
FILE_ARRAY_PERL+=("${FILE}")
else
############################
# Extension was not found! #
############################
debug "Failed to get filetype for:[${FILE}]!"
fi
}
################################################################################
#### Function GetFileExtension ###############################################
function GetFileExtension() {
################
# Pull in Vars #
################
FILE="$1"
###########################
# Get the files extension #
###########################
# Extract just the file extension
FILE_TYPE=${FILE##*.}
# To lowercase
FILE_TYPE=${FILE_TYPE,,}
echo "$FILE_TYPE"
}
################################################################################
#### Function IsValidShellScript ###############################################
function IsValidShellScript() {
################
# Pull in Vars #
################
FILE="$1"
#################
# Get file type #
#################
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" ] ||
[ "${FILE_EXTENSION}" == "bats" ] ||
[ "${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
}
################################################################################
#### Function IsGenerated ######################################################
function IsGenerated() {
# Pull in Vars #
################
FILE="$1"
##############################
# Check the file for keyword #
##############################
grep -q "@generated" "$FILE"
#######################
# Load the error code #
#######################
ERROR_CODE=$?
if [ ${ERROR_CODE} -ne 0 ]; then
trace "File:[${FILE}] is not generated, because it doesn't have @generated marker"
return 1
fi
##############################
# Check the file for keyword #
##############################
grep -q "@not-generated" "$FILE"
#######################
# Load the error code #
#######################
ERROR_CODE=$?
if [ ${ERROR_CODE} -eq 0 ]; then
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
}
################################################################################
#### Function RunAdditionalInstalls ############################################
function RunAdditionalInstalls() {
##################################
# Run installs for Psalm and PHP #
##################################
if [ "${VALIDATE_PHP_PSALM}" == "true" ] && [ "${#FILE_ARRAY_PHP_PSALM[@]}" -ne 0 ]; then
# 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)
debug "COMPOSER_FILE_ARRAY contents:[${COMPOSER_FILE_ARRAY[*]}]"
############################################
# Check if we found the file in the system #
############################################
if [ "${#COMPOSER_FILE_ARRAY[@]}" -ne 0 ]; then
for LINE in "${COMPOSER_FILE_ARRAY[@]}"; do
COMPOSER_PATH=$(dirname "${LINE}" 2>&1)
info "Found [composer.json] at:[${LINE}]"
COMPOSER_CMD=$(
cd "${COMPOSER_PATH}" || exit 1
composer install --no-progress -q 2>&1
)
##############
# Error code #
##############
ERROR_CODE=$?
##############################
# Check the shell for errors #
##############################
if [ "${ERROR_CODE}" -ne 0 ]; then
# Error
error "ERROR! Failed to run composer install at location:[${COMPOSER_PATH}]"
fatal "ERROR:[${COMPOSER_CMD}]"
else
# Success
info "Successfully ran:[composer install] for PHP validation"
fi
done
fi
fi
###############################
# Run installs for R language #
###############################
if [ "${VALIDATE_R}" == "true" ] && [ "${#FILE_ARRAY_R[@]}" -ne 0 ]; then
info "Detected R Language files to lint."
info "Trying to install the R package inside:[${WORKSPACE_PATH}]"
#########################
# Run the build command #
#########################
BUILD_CMD=$(R CMD build "${WORKSPACE_PATH}" 2>&1)
##############
# Error code #
##############
ERROR_CODE=$?
##############################
# Check the shell for errors #
##############################
if [ "${ERROR_CODE}" -ne 0 ]; then
# Error
warn "ERROR! Failed to run:[R CMD build] at location:[${WORKSPACE_PATH}]"
warn "BUILD_CMD:[${BUILD_CMD}]"
else
# Get the build package
BUILD_PKG=$(
cd "${WORKSPACE_PATH}" || exit 0
echo *.tar.gz 2>&1
)
##############################
# Install the build packages #
##############################
INSTALL_CMD=$(
cd "${WORKSPACE_PATH}" || exit 0
R -e "install.packages('remotes', repos = 'https://cloud.r-project.org/')" 2>&1
R -e "remotes::install_local('.', dependencies=T)" 2>&1
)
##############
# Error code #
##############
ERROR_CODE=$?
##############################
# Check the shell for errors #
##############################
debug "INSTALL_CMD:[${INSTALL_CMD}]"
if [ "${ERROR_CODE}" -ne 0 ]; then
warn "ERROR: Failed to install the build package at:[${BUILD_PKG}]"
fi
fi
fi
####################################
# Run installs for TFLINT language #
####################################
if [ "${VALIDATE_TERRAFORM_TFLINT}" == "true" ] && [ "${#FILE_ARRAY_TERRAFORM_TFLINT[@]}" -ne 0 ]; then
info "Detected TFLint Language files to lint."
info "Trying to install the TFLint init inside:[${WORKSPACE_PATH}]"
# Set the log level
TF_LOG_LEVEL="info"
if [ "${ACTIONS_RUNNER_DEBUG}" = "true" ]; then
TF_LOG_LEVEL="debug"
fi
debug "Set the tflint log level to: ${TF_LOG_LEVEL}"
#########################
# Run the build command #
#########################
BUILD_CMD=$(
cd "${WORKSPACE_PATH}" || exit 0
TFLINT_LOG="${TF_LOG_LEVEL}" tflint --init -c "${TERRAFORM_TFLINT_LINTER_RULES}" 2>&1
)
##############
# Error code #
##############
ERROR_CODE=$?
##############################
# Check the shell for errors #
##############################
if [ "${ERROR_CODE}" -ne 0 ]; then
fatal "ERROR! Failed to run:[tflint --init] at location:[${WORKSPACE_PATH}]. BUILD_CMD:[${BUILD_CMD}]"
else
info "Successfully ran:[tflint --init] in workspace:[${WORKSPACE_PATH}]"
debug "BUILD_CMD:[${BUILD_CMD}]"
fi
fi
}