#!/usr/bin/env bash ################################################################################ ################################################################################ ########### Super-Linter (Lint all the code) @admiralawkbar #################### ################################################################################ ################################################################################ ######################### # Source Function Files # ######################### # shellcheck source=/dev/null source /action/lib/termColors.sh # Source the function script(s) # shellcheck source=/dev/null source /action/lib/buildFileList.sh # Source the function script(s) # shellcheck source=/dev/null source /action/lib/validation.sh # Source the function script(s) # shellcheck source=/dev/null source /action/lib/worker.sh # Source the function script(s) ########### # GLOBALS # ########### # Ansible Vars ANSIBLE_FILE_NAME='.ansible-lint.yml' # Name of the file ANSIBLE_LINTER_RULES="${DEFAULT_RULES_LOCATION}/${ANSIBLE_FILE_NAME}" # Path to the Ansible lint rules # Azure Resource Manager Vars ARM_FILE_NAME='.arm-ttk.psd1' # Name of the file ARM_LINTER_RULES="${DEFAULT_RULES_LOCATION}/${ARM_FILE_NAME}" # Path to the ARM lint rules # Cloudformation Vars CFN_FILE_NAME='.cfnlintrc.yml' # Name of the file CFN_LINTER_RULES="$DEFAULT_RULES_LOCATION/$CFN_FILE_NAME" # Path to the cloudformation lint rules # Clojure Vars CLOJURE_FILE_NAME='.clj-kondo/config.edn' # Name of the file CLOJURE_LINTER_RULES="$DEFAULT_RULES_LOCATION/$CLOJURE_FILE_NAME" # Path to the Clojure lint rules # Coffee Vars COFFEESCRIPT_LINTER_RULES="$DEFAULT_RULES_LOCATION/$COFFEE_FILE_NAME" # Path to the coffeescript lint rules COFFEE_FILE_NAME='.coffee-lint.json' # Name of the file # CSS Vars CSS_FILE_NAME='.stylelintrc.json' # Name of the file CSS_LINTER_RULES="$DEFAULT_RULES_LOCATION/$CSS_FILE_NAME" # Path to the CSS lint rules # Dart Vars DART_FILE_NAME='analysis_options.yaml' # Name of the file DART_LINTER_RULES="$DEFAULT_RULES_LOCATION/$DART_FILE_NAME" # Path to the DART lint rules # Default Vars DEFAULT_RULES_LOCATION='/action/lib/.automation' # Default rules files location # Docker Vars DOCKER_FILE_NAME='.dockerfilelintrc' # Name of the file DOCKER_LINTER_RULES="$DEFAULT_RULES_LOCATION/$DOCKER_FILE_NAME" # Path to the Docker lint rules # Golang Vars GO_FILE_NAME='.golangci.yml' # Name of the file GO_LINTER_RULES="$DEFAULT_RULES_LOCATION/$GO_FILE_NAME" # Path to the Go lint rules # HTML Vars HTML_FILE_NAME='.htmlhintrc' # Name of the file HTML_LINTER_RULES="$DEFAULT_RULES_LOCATION/$HTML_FILE_NAME" # Path to the CSS lint rules # Javascript Vars JAVASCRIPT_FILE_NAME="${JAVASCRIPT_ES_CONFIG_FILE:-.eslintrc.yml}" # Name of the file JAVASCRIPT_LINTER_RULES="$DEFAULT_RULES_LOCATION/$JAVASCRIPT_FILE_NAME" # Path to the Javascript lint rules JAVASCRIPT_STANDARD_LINTER_RULES='' # ENV string to pass when running js standard # Default linter path LINTER_RULES_PATH="${LINTER_RULES_PATH:-.github/linters}" # Linter Path Directory # MD Vars MARKDOWN_FILE_NAME='.markdown-lint.yml' # Name of the file MARKDOWN_LINTER_RULES="$DEFAULT_RULES_LOCATION/$MARKDOWN_FILE_NAME" # Path to the markdown lint rules # OpenAPI Vars OPENAPI_FILE_NAME='.openapirc.yml' # Name of the file OPENAPI_LINTER_RULES="$DEFAULT_RULES_LOCATION/$OPENAPI_FILE_NAME" # Path to the OpenAPI lint rules # Powershell Vars POWERSHELL_FILE_NAME='.powershell-psscriptanalyzer.psd1' # Name of the file POWERSHELL_LINTER_RULES="$DEFAULT_RULES_LOCATION/$POWERSHELL_FILE_NAME" # Path to the Powershell lint rules # Protocol Buffers Vars PROTOBUF_FILE_NAME='.protolintrc.yml' # Name of the file PROTOBUF_LINTER_RULES="$DEFAULT_RULES_LOCATION/$PROTOBUF_FILE_NAME" # Path to the Protocol Buffers lint rules # Python Vars PYTHON_FILE_NAME='.python-lint' # Name of the file PYTHON_LINTER_RULES="$DEFAULT_RULES_LOCATION/$PYTHON_FILE_NAME" # Path to the python lint rules # Ruby Vars RUBY_FILE_NAME="${RUBY_CONFIG_FILE:-.ruby-lint.yml}" # Name of the file RUBY_LINTER_RULES="$DEFAULT_RULES_LOCATION/$RUBY_FILE_NAME" # Path to the ruby lint rules # Terraform Vars TERRAFORM_FILE_NAME='.tflint.hcl' # Name of the file TERRAFORM_LINTER_RULES="$DEFAULT_RULES_LOCATION/$TERRAFORM_FILE_NAME" # Path to the Terraform lint rules # Typescript Vars TYPESCRIPT_FILE_NAME="${TYPESCRIPT_ES_CONFIG_FILE:-.eslintrc.yml}" # Name of the file TYPESCRIPT_LINTER_RULES="$DEFAULT_RULES_LOCATION/$TYPESCRIPT_FILE_NAME" # Path to the Typescript lint rules TYPESCRIPT_STANDARD_LINTER_RULES='' # ENV string to pass when running js standard # YAML Vars YAML_FILE_NAME='.yaml-lint.yml' # Name of the file YAML_LINTER_RULES="$DEFAULT_RULES_LOCATION/$YAML_FILE_NAME" # Path to the yaml lint rules ####################################### # Linter array for information prints # ####################################### LINTER_ARRAY=('ansible-lint' 'arm-ttk' 'asl-validator' 'cfn-lint' 'clj-kondo' 'coffeelint' 'dart' 'dockerfilelint' 'dotenv-linter' 'eslint' 'golangci-lint' 'htmlhint' 'jsonlint' 'ktlint' 'markdownlint' 'perl' 'protolint' 'pwsh' 'pylint' 'raku' 'rubocop' 'shellcheck' 'spectral' 'standard' 'stylelint' 'tflint' 'xmllint' 'yamllint') ############################# # Language array for prints # ############################# LANGUAGE_ARRAY=('ANSIBLE' 'ARM' 'BASH' 'CFN' 'CLOJURE' 'COFFEESCRIPT' 'CSS' 'DART' 'DOCKER' 'ENV' 'GO' 'HTML' 'JAVASCRIPT_ES' 'JAVASCRIPT_STANDARD' 'JSON' 'JSX' 'KOTLIN' 'MARKDOWN' 'OPENAPI' 'PERL' 'PHP' 'POWERSHELL' 'PROTOBUF' 'PYTHON' 'RAKU' 'RUBY' 'STATES' 'TERRAFORM' 'TSX' 'TYPESCRIPT_ES' 'TYPESCRIPT_STANDARD' 'XML' 'YML') ############################################ # Array for all languages that were linted # ############################################ LINTED_LANGUAGES_ARRAY=() # Will be filled at run time with all languages that were linted ################### # GitHub ENV Vars # ################### ANSIBLE_DIRECTORY="${ANSIBLE_DIRECTORY}" # Ansible Directory DEFAULT_BRANCH="${DEFAULT_BRANCH:-master}" # Default Git Branch to use (master by default) DISABLE_ERRORS="${DISABLE_ERRORS}" # Boolean to enable warning-only output without throwing errors GITHUB_EVENT_PATH="${GITHUB_EVENT_PATH}" # Github Event Path GITHUB_REPOSITORY="${GITHUB_REPOSITORY}" # GitHub Org/Repo passed from system GITHUB_RUN_ID="${GITHUB_RUN_ID}" # GitHub RUn ID to point to logs GITHUB_SHA="${GITHUB_SHA}" # GitHub sha from the commit GITHUB_TOKEN="${GITHUB_TOKEN}" # GitHub Token passed from environment GITHUB_WORKSPACE="${GITHUB_WORKSPACE}" # Github Workspace MULTI_STATUS="${MULTI_STATUS:-true}" # Multiple status are created for each check ran TEST_CASE_RUN="${TEST_CASE_RUN}" # Boolean to validate only test cases VALIDATE_ALL_CODEBASE="${VALIDATE_ALL_CODEBASE}" # Boolean to validate all files VALIDATE_ANSIBLE="${VALIDATE_ANSIBLE}" # Boolean to validate language VALIDATE_ARM="${VALIDATE_ARM}" # Boolean to validate language VALIDATE_BASH="${VALIDATE_BASH}" # Boolean to validate language VALIDATE_CFN="${VALIDATE_CLOUDFORMATION}" # Boolean to validate language VALIDATE_CLOJURE="${VALIDATE_CLOJURE}" # Boolean to validate language VALIDATE_COFFEE="${VALIDATE_COFFEE}" # Boolean to validate language VALIDATE_CSS="${VALIDATE_CSS}" # Boolean to validate language VALIDATE_DART="${VALIDATE_DART}" # Boolean to validate language VALIDATE_DOCKER="${VALIDATE_DOCKER}" # Boolean to validate language VALIDATE_EDITORCONFIG="${VALIDATE_EDITORCONFIG}" # Boolean to validate files with editorconfig VALIDATE_ENV="${VALIDATE_ENV}" # Boolean to validate language VALIDATE_GO="${VALIDATE_GO}" # Boolean to validate language VALIDATE_HTML="${VALIDATE_HTML}" # Boolean to validate language VALIDATE_JAVASCRIPT_ES="${VALIDATE_JAVASCRIPT_ES}" # Boolean to validate language VALIDATE_JAVASCRIPT_STANDARD="${VALIDATE_JAVASCRIPT_STANDARD}" # Boolean to validate language VALIDATE_JSON="${VALIDATE_JSON}" # Boolean to validate language VALIDATE_JSX="${VALIDATE_JSX}" # Boolean to validate language VALIDATE_KOTLIN="${VALIDATE_KOTLIN}" # Boolean to validate language VALIDATE_MARKDOWN="${VALIDATE_MD:-}" # Boolean to validate language VALIDATE_OPENAPI="${VALIDATE_OPENAPI}" # Boolean to validate language VALIDATE_PERL="${VALIDATE_PERL}" # Boolean to validate language VALIDATE_PHP="${VALIDATE_PHP}" # Boolean to validate language VALIDATE_POWERSHELL="${VALIDATE_POWERSHELL}" # Boolean to validate language VALIDATE_PYTHON="${VALIDATE_PYTHON}" # Boolean to validate language VALIDATE_RAKU="${VALIDATE_RAKU}" # Boolean to validate language VALIDATE_RUBY="${VALIDATE_RUBY}" # Boolean to validate language VALIDATE_STATES="${VALIDATE_STATES}" # Boolean to validate language VALIDATE_TERRAFORM="${VALIDATE_TERRAFORM}" # Boolean to validate language VALIDATE_TSX="${VALIDATE_TSX}" # Boolean to validate language VALIDATE_TYPESCRIPT_ES="${VALIDATE_TYPESCRIPT_ES}" # Boolean to validate language VALIDATE_TYPESCRIPT_STANDARD="${VALIDATE_TYPESCRIPT_STANDARD}" # Boolean to validate language VALIDATE_XML="${VALIDATE_XML}" # Boolean to validate language VALIDATE_YAML="${VALIDATE_YAML}" # Boolean to validate language ############## # Debug Vars # ############## RUN_LOCAL="${RUN_LOCAL}" # Boolean to see if we are running locally ACTIONS_RUNNER_DEBUG="${ACTIONS_RUNNER_DEBUG:-false}" # Boolean to see even more info (debug) ################ # Default Vars # ################ DEFAULT_VALIDATE_ALL_CODEBASE='true' # Default value for validate all files DEFAULT_WORKSPACE="${DEFAULT_WORKSPACE:-/tmp/lint}" # Default workspace if running locally DEFAULT_RUN_LOCAL='false' # Default value for debugging locally DEFAULT_TEST_CASE_RUN='false' # Flag to tell code to run only test cases DEFAULT_IFS="$IFS" # Get the Default IFS for updating ############################################################### # Default Vars that are called in Subs and need to be ignored # ############################################################### DEFAULT_DISABLE_ERRORS='false' # Default to enabling errors echo "${DEFAULT_DISABLE_ERRORS}" > /dev/null 2>&1 || true # Workaround SC2034 RAW_FILE_ARRAY=() # Array of all files that were changed echo "${RAW_FILE_ARRAY[*]}" > /dev/null 2>&1 || true # Workaround SC2034 READ_ONLY_CHANGE_FLAG=0 # Flag set to 1 if files changed are not txt or md echo "${READ_ONLY_CHANGE_FLAG}" > /dev/null 2>&1 || true # Workaround SC2034 TEST_CASE_FOLDER='.automation/test' # Folder for test cases we should always ignore echo "${TEST_CASE_FOLDER}" > /dev/null 2>&1 || true # Workaround SC2034 DEFAULT_ANSIBLE_DIRECTORY="$GITHUB_WORKSPACE/ansible" # Default Ansible Directory echo "${DEFAULT_ANSIBLE_DIRECTORY}" > /dev/null 2>&1 || true # Workaround SC2034 WARNING_ARRAY_TEST=() # Array of warning linters that did not have an expected test result. echo "${WARNING_ARRAY_TEST[*]}" > /dev/null 2>&1 || true # Workaround SC2034 ############## # Format # ############## OUTPUT_FORMAT="${OUTPUT_FORMAT}" # Output format to be generated. Default none OUTPUT_FOLDER="${OUTPUT_FOLDER:-super-linter.report}" # Folder where the reports are generated. Default super-linter.report OUTPUT_DETAILS="${OUTPUT_DETAILS:-simpler}" # What level of details. (simpler or detailed). Default simpler REPORT_OUTPUT_FOLDER="${DEFAULT_WORKSPACE}/${OUTPUT_FOLDER}" ########################## # Array of changed files # ########################## FILE_ARRAY_ARM=() # Array of files to check FILE_ARRAY_BASH=() # Array of files to check FILE_ARRAY_CFN=() # Array of files to check FILE_ARRAY_CLOJURE=() # Array of files to check FILE_ARRAY_COFFEESCRIPT=() # Array of files to check FILE_ARRAY_CSS=() # Array of files to check FILE_ARRAY_DART=() # Array of files to check FILE_ARRAY_DOCKER=() # Array of files to check FILE_ARRAY_ENV=() # Array of files to check FILE_ARRAY_GO=() # Array of files to check FILE_ARRAY_HTML=() # Array of files to check FILE_ARRAY_JAVASCRIPT_ES=() # Array of files to check FILE_ARRAY_JAVASCRIPT_STANDARD=() # Array of files to check FILE_ARRAY_JSON=() # Array of files to check FILE_ARRAY_JSX=() # Array of files to check FILE_ARRAY_KOTLIN=() # Array of files to check FILE_ARRAY_MARKDOWN=() # Array of files to check FILE_ARRAY_OPENAPI=() # Array of files to check FILE_ARRAY_PERL=() # Array of files to check FILE_ARRAY_PHP=() # Array of files to check FILE_ARRAY_POWERSHELL=() # Array of files to check FILE_ARRAY_PROTOBUF=() # Array of files to check FILE_ARRAY_PYTHON=() # Array of files to check FILE_ARRAY_RAKU=() # Array of files to check FILE_ARRAY_RUBY=() # Array of files to check FILE_ARRAY_STATES=() # Array of files to check FILE_ARRAY_TERRAFORM=() # Array of files to check FILE_ARRAY_TSX=() # Array of files to check FILE_ARRAY_TYPESCRIPT_ES=() # Array of files to check FILE_ARRAY_TYPESCRIPT_STANDARD=() # Array of files to check FILE_ARRAY_XML=() # Array of files to check FILE_ARRAY_YML=() # Array of files to check ############ # Counters # ############ ERRORS_FOUND_ANSIBLE=0 # Count of errors found ERRORS_FOUND_ARM=0 # Count of errors found ERRORS_FOUND_BASH=0 # Count of errors found ERRORS_FOUND_CFN=0 # Count of errors found ERRORS_FOUND_CLOJURE=0 # Count of errors found ERRORS_FOUND_CSS=0 # Count of errors found ERRORS_FOUND_COFFEESCRIPT=0 # Count of errors found ERRORS_FOUND_DART=0 # Count of errors found ERRORS_FOUND_DOCKER=0 # Count of errors found ERRORS_FOUND_ENV=0 # Count of errors found ERRORS_FOUND_GO=0 # Count of errors found ERRORS_FOUND_HTML=0 # Count of errors found ERRORS_FOUND_JAVASCRIPT_STANDARD=0 # Count of errors found ERRORS_FOUND_JAVASCRIPT_ES=0 # Count of errors found ERRORS_FOUND_JSON=0 # Count of errors found ERRORS_FOUND_JSX=0 # Count of errors found ERRORS_FOUND_KOTLIN=0 # Count of errors found ERRORS_FOUND_MARKDOWN=0 # Count of errors found ERRORS_FOUND_OPENAPI=0 # Count of errors found ERRORS_FOUND_PERL=0 # Count of errors found ERRORS_FOUND_PHP=0 # Count of errors found ERRORS_FOUND_POWERSHELL=0 # Count of errors found ERRORS_FOUND_PROTOBUF=0 # Count of errors found ERRORS_FOUND_PYTHON=0 # Count of errors found ERRORS_FOUND_RAKU=0 # Count of errors found ERRORS_FOUND_RUBY=0 # Count of errors found ERRORS_FOUND_STATES=0 # Count of errors found ERRORS_FOUND_TERRAFORM=0 # Count of errors found ERRORS_FOUND_TSX=0 # Count of errors found ERRORS_FOUND_TYPESCRIPT_STANDARD=0 # Count of errors found ERRORS_FOUND_TYPESCRIPT_ES=0 # Count of errors found ERRORS_FOUND_XML=0 # Count of errors found ERRORS_FOUND_YML=0 # Count of errors found ################################################################################ ########################## FUNCTIONS BELOW ##################################### ################################################################################ ################################################################################ #### Function Header ########################################################### Header() { ############################### # Give them the possum action # ############################### /bin/bash /action/lib/possum.sh ########## # Prints # ########## echo "" echo "---------------------------------------------" echo "--- GitHub Actions Multi Language Linter ----" echo "---------------------------------------------" echo "" echo "---------------------------------------------" echo "The Super-Linter source code can be found at:" echo " - https://github.com/github/super-linter" echo "---------------------------------------------" } ################################################################################ #### Function GetLinterVersions ################################################ GetLinterVersions() { ######################### # Print version headers # ######################### echo "" echo "---------------------------------------------" echo "Linter Version Info:" ########################################################## # Go through the array of linters and print version info # ########################################################## for LINTER in "${LINTER_ARRAY[@]}"; do ################### # Get the version # ################### if [[ "$LINTER" == "arm-ttk" ]]; then # Need specific command for ARM mapfile -t GET_VERSION_CMD < <(grep -iE 'version' "$ARM_TTK_PSD1" | xargs 2>&1) elif [[ "$LINTER" == "protolint" ]]; then # Need specific command for Protolint mapfile -t GET_VERSION_CMD < <(echo "--version not supported") else # Standard version command mapfile -t GET_VERSION_CMD < <("$LINTER" --version 2>&1) fi ####################### # Load the error code # ####################### ERROR_CODE=$? ############################## # Check the shell for errors # ############################## if [ $ERROR_CODE -ne 0 ] || [ -z "${GET_VERSION_CMD[*]}" ]; then echo -e "${NC}[$LINTER]: ${F[Y]}WARN!${NC} Failed to get version info for:${NC}" else ########################## # Print the version info # ########################## echo -e "${NC}${F[B]}Successfully found version for ${F[W]}[$LINTER]${F[B]}: ${F[W]}${GET_VERSION_CMD[*]}${NC}" fi done ######################### # Print version footers # ######################### echo "---------------------------------------------" echo "" } ################################################################################ #### Function GetLinterRules ################################################### GetLinterRules() { # Need to validate the rules files exist ################ # Pull in vars # ################ LANGUAGE_NAME="$1" # Name of the language were looking for ####################################################### # Need to create the variables for the real variables # ####################################################### LANGUAGE_FILE_NAME="${LANGUAGE_NAME}_FILE_NAME" LANGUAGE_LINTER_RULES="${LANGUAGE_NAME}_LINTER_RULES" ##################################### # Validate we have the linter rules # ##################################### if [ -f "$GITHUB_WORKSPACE/$LINTER_RULES_PATH/${!LANGUAGE_FILE_NAME}" ]; then echo "----------------------------------------------" echo "User provided file:[${!LANGUAGE_FILE_NAME}], setting rules file..." ######################################## # Update the path to the file location # ######################################## eval "${LANGUAGE_LINTER_RULES}=$GITHUB_WORKSPACE/$LINTER_RULES_PATH/${!LANGUAGE_FILE_NAME}" else ######################################################## # No user default provided, using the template default # ######################################################## if [[ $ACTIONS_RUNNER_DEBUG == "true" ]]; then echo " -> Codebase does NOT have file:[$LINTER_RULES_PATH/${!LANGUAGE_FILE_NAME}], using Default rules at:[${!LANGUAGE_LINTER_RULES}]" fi fi } ################################################################################ #### Function GetStandardRules ################################################# GetStandardRules() { ################ # Pull In Vars # ################ LINTER="$1" # Type: javascript | typescript ######################################################################### # Need to get the ENV vars from the linter rules to run in command line # ######################################################################### # Copy orig IFS to var ORIG_IFS="$IFS" # Set the IFS to newline IFS=$'\n' ######################################### # Get list of all environment variables # ######################################### # Only env vars that are marked as true GET_ENV_ARRAY=() if [[ $LINTER == "javascript" ]]; then mapfile -t GET_ENV_ARRAY < <(yq .env "$JAVASCRIPT_LINTER_RULES" | grep true) elif [[ $LINTER == "typescript" ]]; then mapfile -t GET_ENV_ARRAY < <(yq .env "$TYPESCRIPT_LINTER_RULES" | grep true) fi ####################### # Load the error code # ####################### ERROR_CODE=$? ############################## # Check the shell for errors # ############################## if [ $ERROR_CODE -ne 0 ]; then # ERROR echo -e "${NC}${B[R]}${F[W]}ERROR!${NC} Failed to gain list of ENV vars to load!${NC}" echo -e "${NC}${B[R]}${F[W]}ERROR:${NC}[${GET_ENV_ARRAY[*]}]${NC}" exit 1 fi ########################## # Set IFS back to normal # ########################## # Set IFS back to Orig IFS="$ORIG_IFS" ###################### # Set the env string # ###################### ENV_STRING='' ############################# # Pull out the envs to load # ############################# for ENV in "${GET_ENV_ARRAY[@]}"; do ############################# # remove spaces from return # ############################# ENV="$(echo -e "${ENV}" | tr -d '[:space:]')" ################################ # Get the env to add to string # ################################ ENV="$(echo "${ENV}" | cut -d'"' -f2)" # echo "ENV:[$ENV]" ENV_STRING+="--env ${ENV} " done ######################################### # Remove trailing and ending whitespace # ######################################### if [[ $LINTER == "javascript" ]]; then JAVASCRIPT_STANDARD_LINTER_RULES="$(echo -e "${ENV_STRING}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" elif [[ $LINTER == "typescript" ]]; then TYPESCRIPT_STANDARD_LINTER_RULES="$(echo -e "${ENV_STRING}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" fi } ################################################################################ #### Function DetectOpenAPIFile ################################################ DetectOpenAPIFile() { ################ # Pull in vars # ################ FILE="$1" ############################### # 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 ######################## # 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 ############################### # 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 # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-formats.html # AWSTemplateFormatVersion is optional ####################################### # Check if file has AWS Template info # ####################################### if grep 'AWSTemplateFormatVersion' "$FILE" > /dev/null; then # Found it return 0 fi ################################################### # Check if file has AWSTemplateFormatVersion info # ################################################### if shyaml --quiet get-type AWSTemplateFormatVersion > /dev/null < "$FILE"; then # Found it return 0 fi ############################### # check if file has resources # ############################### if jq -e 'has("Resources")' > /dev/null 2>&1 < "$FILE"; then # Check if AWS Alexa or custom if jq ".Resources[].Type" 2> /dev/null | grep -q -E "(AWS|Alexa|Custom)" < "$FILE"; then # Found it return 0 fi fi ################################ # See if it contains resources # ################################ if shyaml values-0 Resources 2> /dev/null | grep -q -E "Type: (AWS|Alexa|Custom)" < "$FILE"; then # Found it return 0 fi ########################################## # No identifiers of a CFN template found # ########################################## return 1 } ################################################################################ #### Function DetectAWSStatesFIle ############################################## DetectAWSStatesFIle() { ################ # Pull in Vars # ################ FILE="$1" # File that we need to validate # https://states-language.net/spec.html#example ############################### # check if file has resources # ############################### if grep '"Resource": *"arn"*' "$FILE"; then # Found it return 0 fi ################################################# # No identifiers of a AWS States Language found # ################################################# return 1 } ################################################################################ #### Function GetGitHubVars #################################################### GetGitHubVars() { ########## # Prints # ########## echo "--------------------------------------------" echo "Gathering GitHub information..." ############################### # Get the Run test cases flag # ############################### if [ -z "$TEST_CASE_RUN" ]; then ################################## # No flag passed, set to default # ################################## TEST_CASE_RUN="$DEFAULT_TEST_CASE_RUN" fi ############################### # Convert string to lowercase # ############################### TEST_CASE_RUN="${TEST_CASE_RUN,,}" ########################## # Get the run local flag # ########################## if [ -z "$RUN_LOCAL" ]; then ################################## # No flag passed, set to default # ################################## RUN_LOCAL="$DEFAULT_RUN_LOCAL" fi ############################### # Convert string to lowercase # ############################### RUN_LOCAL="${RUN_LOCAL,,}" ################################# # Check if were running locally # ################################# if [[ $RUN_LOCAL != "false" ]]; then ########################################## # We are running locally for a debug run # ########################################## echo "NOTE: ENV VAR [RUN_LOCAL] has been set to:[true]" echo "bypassing GitHub Actions variables..." ############################ # Set the GITHUB_WORKSPACE # ############################ if [ -z "$GITHUB_WORKSPACE" ]; then GITHUB_WORKSPACE="$DEFAULT_WORKSPACE" fi if [ ! -d "$GITHUB_WORKSPACE" ]; then echo -e "${NC}${B[R]}${F[W]}ERROR:${NC} Provided volume is not a directory!${NC}" exit 1 fi echo "Linting all files in mapped directory:[$DEFAULT_WORKSPACE]" # No need to touch or set the GITHUB_SHA # No need to touch or set the GITHUB_EVENT_PATH # No need to touch or set the GITHUB_ORG # No need to touch or set the GITHUB_REPO ################################# # Set the VALIDATE_ALL_CODEBASE # ################################# VALIDATE_ALL_CODEBASE="$DEFAULT_VALIDATE_ALL_CODEBASE" else ############################ # Validate we have a value # ############################ if [ -z "$GITHUB_SHA" ]; then echo -e "${NC}${B[R]}${F[W]}ERROR!${NC} Failed to get [GITHUB_SHA]!${NC}" echo -e "${NC}${B[R]}${F[W]}ERROR:${NC}[$GITHUB_SHA]${NC}" exit 1 else echo -e "${NC}${F[B]}Successfully found:${F[W]}[GITHUB_SHA]${F[B]}, value:${F[W]}[$GITHUB_SHA]${NC}" fi ############################ # Validate we have a value # ############################ if [ -z "$GITHUB_WORKSPACE" ]; then echo -e "${NC}${B[R]}${F[W]}ERROR!${NC} Failed to get [GITHUB_WORKSPACE]!${NC}" echo -e "${NC}${B[R]}${F[W]}ERROR:${NC}[$GITHUB_WORKSPACE]${NC}" exit 1 else echo -e "${NC}${F[B]}Successfully found:${F[W]}[GITHUB_WORKSPACE]${F[B]}, value:${F[W]}[$GITHUB_WORKSPACE]${NC}" fi ############################ # Validate we have a value # ############################ if [ -z "$GITHUB_EVENT_PATH" ]; then echo -e "${NC}${B[R]}${F[W]}ERROR!${NC} Failed to get [GITHUB_EVENT_PATH]!${NC}" echo -e "${NC}${B[R]}${F[W]}ERROR:${NC}[$GITHUB_EVENT_PATH]${NC}" exit 1 else echo -e "${NC}${F[B]}Successfully found:${F[W]}[GITHUB_EVENT_PATH]${F[B]}, value:${F[W]}[$GITHUB_EVENT_PATH]${F[B]}${NC}" fi ################################################## # Need to pull the GitHub Vars from the env file # ################################################## ###################### # Get the GitHub Org # ###################### GITHUB_ORG=$(jq -r '.repository.owner.login' < "$GITHUB_EVENT_PATH") ############################ # Validate we have a value # ############################ if [ -z "$GITHUB_ORG" ]; then echo -e "${NC}${B[R]}${F[W]}ERROR!${NC} Failed to get [GITHUB_ORG]!${NC}" echo -e "${NC}${B[R]}${F[W]}ERROR:${NC}[$GITHUB_ORG]${NC}" exit 1 else echo -e "${NC}${F[B]}Successfully found:${F[W]}[GITHUB_ORG]${F[B]}, value:${F[W]}[$GITHUB_ORG]${NC}" fi ####################### # Get the GitHub Repo # ####################### GITHUB_REPO=$(jq -r '.repository.name' < "$GITHUB_EVENT_PATH") ############################ # Validate we have a value # ############################ if [ -z "$GITHUB_REPO" ]; then echo -e "${NC}${B[R]}${F[W]}ERROR!${NC} Failed to get [GITHUB_REPO]!${NC}" echo -e "${NC}${B[R]}${F[W]}ERROR:${NC}[$GITHUB_REPO]${NC}" exit 1 else echo -e "${NC}${F[B]}Successfully found:${F[W]}[GITHUB_REPO]${F[B]}, value:${F[W]}[$GITHUB_REPO]${NC}" fi fi ############################ # Validate we have a value # ############################ if [ -z "$GITHUB_TOKEN" ]; then echo -e "${NC}${B[R]}${F[W]}ERROR!${NC} Failed to get [GITHUB_TOKEN]!${NC}" echo -e "${NC}${B[R]}${F[W]}ERROR:${NC}[$GITHUB_TOKEN]${NC}" echo -e "${NC}${B[R]}${F[W]}ERROR!${NC} Please set a [GITHUB_TOKEN] from the main workflow environment to take advantage of multiple status reports!${NC}" ################################################################################ # Need to set MULTI_STATUS to false as we cant hit API endpoints without token # ################################################################################ MULTI_STATUS='false' else echo -e "${NC}${F[B]}Successfully found:${F[W]}[GITHUB_TOKEN]${NC}" fi ############################### # Convert string to lowercase # ############################### MULTI_STATUS="${MULTI_STATUS,,}" ####################################################################### # Check to see if the multi status is set, and we have a token to use # ####################################################################### if [ "$MULTI_STATUS" == "true" ] && [ -n "$GITHUB_TOKEN" ]; then ############################ # Validate we have a value # ############################ if [ -z "$GITHUB_REPOSITORY" ]; then echo -e "${NC}${B[R]}${F[W]}ERROR!${NC} Failed to get [GITHUB_REPOSITORY]!${NC}" echo -e "${NC}${B[R]}${F[W]}ERROR:${NC}[$GITHUB_REPOSITORY]${NC}" exit 1 else echo -e "${NC}${F[B]}Successfully found:${F[W]}[GITHUB_REPOSITORY]${F[B]}, value:${F[W]}[$GITHUB_REPOSITORY]${NC}" fi ############################ # Validate we have a value # ############################ if [ -z "$GITHUB_RUN_ID" ]; then echo -e "${NC}${B[R]}${F[W]}ERROR!${NC} Failed to get [GITHUB_RUN_ID]!${NC}" echo -e "${NC}${B[R]}${F[W]}ERROR:${NC}[$GITHUB_RUN_ID]${NC}" exit 1 else echo -e "${NC}${F[B]}Successfully found:${F[W]}[GITHUB_RUN_ID]${F[B]}, value:${F[W]}[$GITHUB_RUN_ID]${NC}" fi fi } ################################################################################ #### Function ValidatePowershellModules ######################################## function ValidatePowershellModules() { VALIDATE_PSSA_MODULE=$(pwsh -c "(Get-Module -Name PSScriptAnalyzer -ListAvailable | Select-Object -First 1).Name" 2>&1) # If module found, ensure Invoke-ScriptAnalyzer command is available if [[ $VALIDATE_PSSA_MODULE == "PSScriptAnalyzer" ]]; then VALIDATE_PSSA_CMD=$(pwsh -c "(Get-Command Invoke-ScriptAnalyzer | Select-Object -First 1).Name" 2>&1) else # Failed to find module exit 1 fi ######################################### # validate we found the script analyzer # ######################################### if [[ $VALIDATE_PSSA_CMD != "Invoke-ScriptAnalyzer" ]]; then # Failed to find module exit 1 fi ####################### # Load the error code # ####################### ERROR_CODE=$? ############################## # Check the shell for errors # ############################## if [ $ERROR_CODE -ne 0 ]; then # Failed echo -e "${NC}${B[R]}${F[W]}ERROR!${NC} Failed find module [PSScriptAnalyzer] for [$LINTER_NAME] in system!${NC}" echo -e "${NC}${B[R]}${F[W]}ERROR:${NC}[PSSA_MODULE $VALIDATE_PSSA_MODULE] [PSSA_CMD $VALIDATE_PSSA_CMD]${NC}" exit 1 else # Success if [[ $ACTIONS_RUNNER_DEBUG == "true" ]]; then echo -e "${NC}${F[B]}Successfully found module ${F[W]}[$VALIDATE_PSSA_MODULE]${F[B]} in system${NC}" echo -e "${NC}${F[B]}Successfully found command ${F[W]}[$VALIDATE_PSSA_CMD]${F[B]} in system${NC}" fi fi } ################################################################################ #### Function CallStatusAPI #################################################### CallStatusAPI() { #################### # Pull in the vars # #################### LANGUAGE="$1" # langauge that was validated STATUS="$2" # success | error SUCCESS_MSG='No errors were found in the linting process' FAIL_MSG='Errors were detected, please view logs' MESSAGE='' # Message to send to status API ###################################### # Check the status to create message # ###################################### if [ "$STATUS" == "success" ]; then # Success MESSAGE="$SUCCESS_MSG" else # Failure MESSAGE="$FAIL_MSG" fi ########################################################## # Check to see if were enabled for multi Status mesaages # ########################################################## if [ "$MULTI_STATUS" == "true" ]; then ############################################## # Call the status API to create status check # ############################################## SEND_STATUS_CMD=$(curl -f -s -X POST \ --url "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/statuses/$GITHUB_SHA" \ -H 'accept: application/vnd.github.v3+json' \ -H "authorization: Bearer $GITHUB_TOKEN" \ -H 'content-type: application/json' \ -d "{ \"state\": \"$STATUS\", \"target_url\": \"https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\", \"description\": \"$MESSAGE\", \"context\": \"--> Linted: $LANGUAGE\" }" 2>&1) ####################### # Load the error code # ####################### ERROR_CODE=$? ############################## # Check the shell for errors # ############################## if [ "$ERROR_CODE" -ne 0 ]; then # ERROR echo "ERROR! Failed to call GitHub Status API!" echo "ERROR:[$SEND_STATUS_CMD]" # Not going to fail the script on this yet... fi fi } ################################################################################ #### Function Footer ########################################################### Footer() { echo "" echo "----------------------------------------------" echo "----------------------------------------------" echo "The script has completed" echo "----------------------------------------------" echo "----------------------------------------------" echo "" ################################### # Prints output report if enabled # ################################### if [ -z "${FORMAT_REPORT}" ] ; then echo "Reports generated in folder ${REPORT_OUTPUT_FOLDER}" fi #################################################### # Need to clean up the lanuage array of duplicates # #################################################### mapfile -t UNIQUE_LINTED_ARRAY < <(echo "${LINTED_LANGUAGES_ARRAY[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ') ############################## # Prints for errors if found # ############################## for LANGUAGE in "${LANGUAGE_ARRAY[@]}"; do ########################### # Build the error counter # ########################### ERROR_COUNTER="ERRORS_FOUND_$LANGUAGE" ################## # Print if not 0 # ################## if [ "${!ERROR_COUNTER}" -ne 0 ]; then # We found errors in the language ################### # Print the goods # ################### echo -e "${NC}${B[R]}${F[W]}ERRORS FOUND${NC} in $LANGUAGE:[${!ERROR_COUNTER}]${NC}" ######################################### # Create status API for Failed language # ######################################### CallStatusAPI "$LANGUAGE" "error" else # No errors found when linting the language ###################################### # Check if we validated the langauge # ###################################### if [[ "${UNIQUE_LINTED_ARRAY[*]}" =~ ${LANGUAGE} ]]; then CallStatusAPI "$LANGUAGE" "success" fi fi done ################################ # Prints for warnings if found # ################################ for TEST in "${WARNING_ARRAY_TEST[@]}"; do echo -e "${NC}${F[Y]}WARN!${NC} Expected file to compare with was not found for ${TEST}${NC}" done ################################## # Exit with 0 if errors disabled # ################################## if [ "$DISABLE_ERRORS" == "true" ]; then echo -e "${NC}${F[Y]}WARN!${NC} Exiting with exit code:[0] as:[DISABLE_ERRORS] was set to:[$DISABLE_ERRORS]${NC}" exit 0 ############################### # Exit with 1 if errors found # ############################### elif [ "$ERRORS_FOUND_ANSIBLE" -ne 0 ] || [ "$ERRORS_FOUND_ARM" -ne 0 ] || [ "$ERRORS_FOUND_BASH" -ne 0 ] || [ "$ERRORS_FOUND_CFN" -ne 0 ] || [ "$ERRORS_FOUND_CLOJURE" -ne 0 ] || [ "$ERRORS_FOUND_COFFEESCRIPT" -ne 0 ] || [ "$ERRORS_FOUND_CSS" -ne 0 ] || [ "$ERRORS_FOUND_DART" -ne 0 ] || [ "$ERRORS_FOUND_DOCKER" -ne 0 ] || [ "$ERRORS_FOUND_ENV" -ne 0 ] || [ "$ERRORS_FOUND_GO" -ne 0 ] || [ "$ERRORS_FOUND_HTML" -ne 0 ] || [ "$ERRORS_FOUND_JAVASCRIPT_ES" -ne 0 ] || [ "$ERRORS_FOUND_JAVASCRIPT_STANDARD" -ne 0 ] || [ "$ERRORS_FOUND_JSON" -ne 0 ] || [ "$ERRORS_FOUND_JSX" -ne 0 ] || [ "$ERRORS_FOUND_KOTLIN" -ne 0 ] || [ "$ERRORS_FOUND_MARKDOWN" -ne 0 ] || [ "$ERRORS_FOUND_OPENAPI" -ne 0 ] || [ "$ERRORS_FOUND_PERL" -ne 0 ] || [ "$ERRORS_FOUND_PHP" -ne 0 ] || [ "$ERRORS_FOUND_POWERSHELL" -ne 0 ] || [ "$ERRORS_FOUND_PROTOBUF" -ne 0 ] || [ "$ERRORS_FOUND_PYTHON" -ne 0 ] || [ "$ERRORS_FOUND_RAKU" -ne 0 ] || [ "$ERRORS_FOUND_RUBY" -ne 0 ] || [ "$ERRORS_FOUND_STATES" -ne 0 ] || [ "$ERRORS_FOUND_TERRAFORM" -ne 0 ] || [ "$ERRORS_FOUND_TSX" -ne 0 ] || [ "$ERRORS_FOUND_TYPESCRIPT_ES" -ne 0 ] || [ "$ERRORS_FOUND_TYPESCRIPT_STANDARD" -ne 0 ] || [ "$ERRORS_FOUND_XML" -ne 0 ] || [ "$ERRORS_FOUND_YML" -ne 0 ]; then # Failed exit echo -e "${NC}${F[R]}Exiting with errors found!${NC}" exit 1 else ################# # Footer prints # ################# echo "" echo -e "${NC}${F[G]}All file(s) linted successfully with no errors detected${NC}" echo "----------------------------------------------" echo "" # Successful exit exit 0 fi } ################################################################################ ############################### MAIN ########################################### ################################################################################ ########## # Header # ########## Header ############################################################## # check flag for validating the report folder does not exist # ############################################################## if [ -n "${OUTPUT_FORMAT}" ]; then if [ -d "${REPORT_OUTPUT_FOLDER}" ] ; then echo "ERROR! Found ${REPORT_OUTPUT_FOLDER}" echo "Please remove the folder and try again." exit 1 fi fi ####################### # Get GitHub Env Vars # ####################### # Need to pull in all the GitHub variables # needed to connect back and update checks GetGitHubVars ######################################### # Get the languages we need to validate # ######################################### GetValidationInfo ######################## # Get the linter rules # ######################## # Get YML rules GetLinterRules "YAML" # Get Markdown rules GetLinterRules "MARKDOWN" # Get Python rules GetLinterRules "PYTHON" # Get Ruby rules GetLinterRules "RUBY" # Get Coffeescript rules GetLinterRules "COFFEESCRIPT" # Get Ansible rules GetLinterRules "ANSIBLE" # Get JavaScript rules GetLinterRules "JAVASCRIPT" # Get TypeScript rules GetLinterRules "TYPESCRIPT" # Get Golang rules GetLinterRules "GO" # Get Docker rules GetLinterRules "DOCKER" # Get Terraform rules GetLinterRules "TERRAFORM" # Get PowerShell rules GetLinterRules "POWERSHELL" # Get ARM rules GetLinterRules "ARM" # Get CSS rules GetLinterRules "CSS" # Get CFN rules GetLinterRules "CFN" # Get DART rules GetLinterRules "DART" # Get HTML rules GetLinterRules "HTML" ################################# # Check if were in verbose mode # ################################# if [[ $ACTIONS_RUNNER_DEBUG == "true" ]]; then ################################## # Get and print all version info # ################################## GetLinterVersions fi ########################################### # Check to see if this is a test case run # ########################################### if [[ $TEST_CASE_RUN != "false" ]]; then ############################################# # Set the multi status to off for test runs # ############################################# MULTI_STATUS='false' ########################### # Run only the test cases # ########################### # Code will exit from inside this loop RunTestCases fi ############################################# # check flag for validation of all codebase # ############################################# if [ "$VALIDATE_ALL_CODEBASE" == "false" ]; then ######################################## # Get list of files changed if env set # ######################################## BuildFileList fi ############### # YML LINTING # ############### if [ "$VALIDATE_YAML" == "true" ]; then ###################### # Lint the Yml Files # ###################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "YML" "yamllint" "yamllint -c $YAML_LINTER_RULES" ".*\.\(yml\|yaml\)\$" "${FILE_ARRAY_YML[@]}" fi ################ # JSON LINTING # ################ if [ "$VALIDATE_JSON" == "true" ]; then ####################### # Lint the json files # ####################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "JSON" "jsonlint" "jsonlint" ".*\.\(json\)\$" "${FILE_ARRAY_JSON[@]}" fi ############### # XML LINTING # ############### if [ "$VALIDATE_XML" == "true" ]; then ###################### # Lint the XML Files # ###################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "XML" "xmllint" "xmllint" ".*\.\(xml\)\$" "${FILE_ARRAY_XML[@]}" fi #################### # MARKDOWN LINTING # #################### if [ "$VALIDATE_MARKDOWN" == "true" ]; then ########################### # Lint the Markdown Files # ########################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "MARKDOWN" "markdownlint" "markdownlint -c $MARKDOWN_LINTER_RULES" ".*\.\(md\)\$" "${FILE_ARRAY_MARKDOWN[@]}" fi ################ # BASH LINTING # ################ if [ "$VALIDATE_BASH" == "true" ]; then ####################### # Lint the bash files # ####################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "BASH" "shellcheck" "shellcheck --color" ".*\.\(sh\|bash\|dash\|ksh\)\$" "${FILE_ARRAY_BASH[@]}" fi ################## # PYTHON LINTING # ################## if [ "$VALIDATE_PYTHON" == "true" ]; then ######################### # Lint the python files # ######################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "PYTHON" "pylint" "pylint --rcfile $PYTHON_LINTER_RULES" ".*\.\(py\)\$" "${FILE_ARRAY_PYTHON[@]}" fi ############### # CFN LINTING # ############### if [ "$VALIDATE_CFN" == "true" ]; then ################################# # Lint the CloudFormation files # ################################# # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "CFN" "cfn-lint" "cfn-lint --config-file $CFN_LINTER_RULES" ".*\.\(json\|yml\|yaml\)\$" "${FILE_ARRAY_CFN[@]}" fi ################ # PERL LINTING # ################ if [ "$VALIDATE_PERL" == "true" ]; then ####################### # Lint the perl files # ####################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "PERL" "perl" "perl -Mstrict -cw" ".*\.\(pl\)\$" "${FILE_ARRAY_PERL[@]}" fi ################ # RAKU LINTING # ################ if [ "$VALIDATE_RAKU" == "true" ]; then ####################### # Lint the raku files # ####################### echo "$GITHUB_WORKSPACE/META6.json" if [ -e "$GITHUB_WORKSPACE/META6.json" ]; then cd "$GITHUB_WORKSPACE" && zef install --deps-only --/test . fi # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "RAKU" "raku" "raku -I $GITHUB_WORKSPACE/lib -c" ".*\.\(raku\|rakumod\|rakutest\|pm6\|pl6\|p6\)\$" "${FILE_ARRAY_RAKU[@]}" fi ################ # PHP LINTING # ################ if [ "$VALIDATE_PHP" == "true" ]; then ####################### # Lint the PHP files # ####################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "PHP" "php" "php -l" ".*\.\(php\)\$" "${FILE_ARRAY_PHP[@]}" fi ################ # RUBY LINTING # ################ if [ "$VALIDATE_RUBY" == "true" ]; then ####################### # Lint the ruby files # ####################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "RUBY" "rubocop" "rubocop -c $RUBY_LINTER_RULES --force-exclusion" ".*\.\(rb\)\$" "${FILE_ARRAY_RUBY[@]}" fi ######################## # COFFEESCRIPT LINTING # ######################## if [ "$VALIDATE_COFFEE" == "true" ]; then ######################### # Lint the coffee files # ######################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "COFFEESCRIPT" "coffeelint" "coffeelint -f $COFFEESCRIPT_LINTER_RULES" ".*\.\(coffee\)\$" "${FILE_ARRAY_COFFEESCRIPT[@]}" fi ################## # GOLANG LINTING # ################## if [ "$VALIDATE_GO" == "true" ]; then ######################### # Lint the golang files # ######################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "GO" "golangci-lint" "golangci-lint run -c $GO_LINTER_RULES" ".*\.\(go\)\$" "${FILE_ARRAY_GO[@]}" fi ##################### # TERRAFORM LINTING # ##################### if [ "$VALIDATE_TERRAFORM" == "true" ]; then ############################ # Lint the Terraform files # ############################ # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "TERRAFORM" "tflint" "tflint -c $TERRAFORM_LINTER_RULES" ".*\.\(tf\)\$" "${FILE_ARRAY_TERRAFORM[@]}" fi ################### # ANSIBLE LINTING # ################### if [ "$VALIDATE_ANSIBLE" == "true" ]; then ########################## # Lint the Ansible files # ########################## # Due to the nature of how we want to validate Ansible, we cannot use the # standard loop, since it looks for an ansible folder, excludes certain # files, and looks for additional changes, it should be an outlier LintAnsibleFiles "$ANSIBLE_LINTER_RULES" # Passing rules but not needed, dont want to exclude unused var fi ###################### # JAVASCRIPT LINTING # ###################### if [ "$VALIDATE_JAVASCRIPT_ES" == "true" ]; then ############################# # Lint the Javascript files # ############################# # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "JAVASCRIPT_ES" "eslint" "eslint --no-eslintrc -c $JAVASCRIPT_LINTER_RULES" ".*\.\(js\)\$" "${FILE_ARRAY_JAVASCRIPT_ES[@]}" fi ###################### # JAVASCRIPT LINTING # ###################### if [ "$VALIDATE_JAVASCRIPT_STANDARD" == "true" ]; then ################################# # Get Javascript standard rules # ################################# GetStandardRules "javascript" ############################# # Lint the Javascript files # ############################# # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "JAVASCRIPT_STANDARD" "standard" "standard $JAVASCRIPT_STANDARD_LINTER_RULES" ".*\.\(js\)\$" "${FILE_ARRAY_JAVASCRIPT_STANDARD[@]}" fi ###################### # JSX LINTING # ###################### if [ "$VALIDATE_JSX" == "true" ]; then ############################# # Lint the JSX files # ############################# # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "JSX" "eslint" "eslint --no-eslintrc -c $JAVASCRIPT_LINTER_RULES" ".*\.\(jsx\)\$" "${FILE_ARRAY_JSX[@]}" fi ###################### # TSX LINTING # ###################### if [ "$VALIDATE_TSX" == "true" ]; then ############################# # Lint the TSX files # ############################# LintCodebase "TSX" "eslint" "eslint --no-eslintrc -c $TYPESCRIPT_LINTER_RULES" ".*\.\(tsx\)\$" "${FILE_ARRAY_TSX[@]}" fi ###################### # TYPESCRIPT LINTING # ###################### if [ "$VALIDATE_TYPESCRIPT_ES" == "true" ]; then ############################# # Lint the Typescript files # ############################# LintCodebase "TYPESCRIPT_ES" "eslint" "eslint --no-eslintrc -c $TYPESCRIPT_LINTER_RULES" ".*\.\(ts\)\$" "${FILE_ARRAY_TYPESCRIPT_ES[@]}" fi ###################### # TYPESCRIPT LINTING # ###################### if [ "$VALIDATE_TYPESCRIPT_STANDARD" == "true" ]; then ################################# # Get Typescript standard rules # ################################# GetStandardRules "typescript" ############################# # Lint the Typescript files # ############################# LintCodebase "TYPESCRIPT_STANDARD" "standard" "standard --parser @typescript-eslint/parser --plugin @typescript-eslint/eslint-plugin $TYPESCRIPT_STANDARD_LINTER_RULES" ".*\.\(ts\)\$" "${FILE_ARRAY_TYPESCRIPT_STANDARD[@]}" fi ############### # CSS LINTING # ############### if [ "$VALIDATE_CSS" == "true" ]; then ################################# # Get CSS standard rules # ################################# GetStandardRules "stylelint" ############################# # Lint the CSS files # ############################# LintCodebase "CSS" "stylelint" "stylelint --config $CSS_LINTER_RULES" ".*\.\(css\)\$" "${FILE_ARRAY_CSS[@]}" fi ############### # ENV LINTING # ############### if [ "$VALIDATE_ENV" == "true" ]; then ####################### # Lint the env files # ####################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "ENV" "dotenv-linter" "dotenv-linter" ".*\.\(env\).*\$" "${FILE_ARRAY_ENV[@]}" fi ################## # KOTLIN LINTING # ################## if [ "$VALIDATE_KOTLIN" == "true" ]; then ####################### # Lint the Kotlin files # ####################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "KOTLIN" "ktlint" "ktlint" ".*\.\(kt\|kts\)\$" "${FILE_ARRAY_KOTLIN[@]}" fi ######################## # EDITORCONFIG LINTING # ######################## if [ "$VALIDATE_EDITORCONFIG" == "true" ]; then #################################### # Lint the files with editorconfig # #################################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "EDITORCONFIG" "editorconfig-checker" "editorconfig-checker" "^.*$" "${FILE_ARRAY_ENV[@]}" fi ################## # DART LINTING # ################## if [ "$VALIDATE_DART" == "true" ]; then ####################### # Lint the Dart files # ####################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "DART" "dart" "pub get || true && dartanalyzer --fatal-infos --fatal-warnings --options $DART_LINTER_RULES" ".*\.\(dart\)\$" "${FILE_ARRAY_DART[@]}" fi ################## # DOCKER LINTING # ################## if [ "$VALIDATE_DOCKER" == "true" ]; then ######################### # Lint the docker files # ######################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" # NOTE: dockerfilelint's "-c" option expects the folder *containing* the DOCKER_LINTER_RULES file LintCodebase "DOCKER" "dockerfilelint" "dockerfilelint -c $(dirname $DOCKER_LINTER_RULES)" ".*\(Dockerfile\)\$" "${FILE_ARRAY_DOCKER[@]}" fi ################### # CLOJURE LINTING # ################### if [ "$VALIDATE_CLOJURE" == "true" ]; then ################################# # Get Clojure standard rules # ################################# GetStandardRules "clj-kondo" ######################### # Lint the Clojure files # ######################### LintCodebase "CLOJURE" "clj-kondo" "clj-kondo --config $CLOJURE_LINTER_RULES --lint" ".*\.\(clj\|cljs\|cljc\|edn\)\$" "${FILE_ARRAY_CLOJURE[@]}" fi ################## # PROTOBUF LINTING # ################## if [ "$VALIDATE_PROTOBUF" == "true" ]; then ####################### # Lint the Protocol Buffers files # ####################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "PROTOBUF" "protolint" "protolint lint --config_path $PROTOBUF_LINTER_RULES" ".*\.\(proto\)\$" "${FILE_ARRAY_PROTOBUF[@]}" fi ###################### # POWERSHELL LINTING # ###################### if [ "$VALIDATE_POWERSHELL" == "true" ]; then ############################################################### # For POWERSHELL, ensure PSScriptAnalyzer module is available # ############################################################### ValidatePowershellModules ############################# # Lint the powershell files # ############################# # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "POWERSHELL" "pwsh" "Invoke-ScriptAnalyzer -EnableExit -Settings $POWERSHELL_LINTER_RULES -Path" ".*\.\(ps1\|psm1\|psd1\|ps1xml\|pssc\|psrc\|cdxml\)\$" "${FILE_ARRAY_POWERSHELL[@]}" fi ######################## # ARM Template LINTING # ######################## if [ "$VALIDATE_ARM" == "true" ]; then ############################### # Lint the ARM Template files # ############################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "ARM" "arm-ttk" "Import-Module $ARM_TTK_PSD1 ; \$config = \$(Import-PowerShellDataFile -Path $ARM_LINTER_RULES) ; Test-AzTemplate @config -TemplatePath" ".*\.\(json\)\$" "${FILE_ARRAY_ARM[@]}" fi ################### # OPENAPI LINTING # ################### if [ "$VALIDATE_OPENAPI" == "true" ]; then # If we are validating all codebase we need to build file list because not every yml/json file is an OpenAPI file if [ "$VALIDATE_ALL_CODEBASE" == "true" ]; then ############################################################################### # Set the file seperator to newline to allow for grabbing objects with spaces # ############################################################################### IFS=$'\n' mapfile -t LIST_FILES < <(find "$GITHUB_WORKSPACE" -type f -regex ".*\.\(yml\|yaml\|json\)\$" 2>&1) for FILE in "${LIST_FILES[@]}"; do if DetectOpenAPIFile "$FILE"; then FILE_ARRAY_OPENAPI+=("$FILE") fi done ########################### # Set IFS back to default # ########################### IFS="$DEFAULT_IFS" fi ########################## # Lint the OpenAPI files # ########################## # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" LintCodebase "OPENAPI" "spectral" "spectral lint -r $OPENAPI_LINTER_RULES" "disabledfileext" "${FILE_ARRAY_OPENAPI[@]}" fi ################ # HTML LINTING # ################ if [ "$VALIDATE_HTML" == "true" ]; then ################################# # Get HTML standard rules # ################################# GetStandardRules "htmlhint" ############################# # Lint the HTML files # ############################# LintCodebase "HTML" "htmlhint" "htmlhint --config $HTML_LINTER_RULES" ".*\.\(html\)\$" "${FILE_ARRAY_HTML[@]}" fi ###################### # AWS STATES LINTING # ###################### if [ "$VALIDATE_STATES" == "true" ]; then ######################### # Lint the STATES files # ######################### LintCodebase "STATES" "asl-validator" "asl-validator --json-path" ".*\.\(json\)\$" "${FILE_ARRAY_STATES[@]}" fi ########## # Footer # ########## Footer