#!/usr/bin/env bash function ValidateBooleanConfigurationVariables() { ValidateBooleanVariable "ACTIONS_RUNNER_DEBUG" "${ACTIONS_RUNNER_DEBUG}" ValidateBooleanVariable "BASH_EXEC_IGNORE_LIBRARIES" "${BASH_EXEC_IGNORE_LIBRARIES}" ValidateBooleanVariable "CREATE_LOG_FILE" "${CREATE_LOG_FILE}" ValidateBooleanVariable "DISABLE_ERRORS" "${DISABLE_ERRORS}" ValidateBooleanVariable "ENABLE_GITHUB_ACTIONS_GROUP_TITLE" "${ENABLE_GITHUB_ACTIONS_GROUP_TITLE}" ValidateBooleanVariable "ENABLE_GITHUB_ACTIONS_STEP_SUMMARY" "${ENABLE_GITHUB_ACTIONS_STEP_SUMMARY}" ValidateBooleanVariable "FIX_MODE_TEST_CASE_RUN" "${FIX_MODE_TEST_CASE_RUN}" ValidateBooleanVariable "IGNORE_GENERATED_FILES" "${IGNORE_GENERATED_FILES}" ValidateBooleanVariable "IGNORE_GITIGNORED_FILES" "${IGNORE_GITIGNORED_FILES}" ValidateBooleanVariable "LOG_DEBUG" "${LOG_DEBUG}" ValidateBooleanVariable "LOG_ERROR" "${LOG_ERROR}" ValidateBooleanVariable "LOG_NOTICE" "${LOG_NOTICE}" ValidateBooleanVariable "LOG_VERBOSE" "${LOG_VERBOSE}" ValidateBooleanVariable "LOG_WARN" "${LOG_WARN}" ValidateBooleanVariable "MULTI_STATUS" "${MULTI_STATUS}" ValidateBooleanVariable "RUN_LOCAL" "${RUN_LOCAL}" ValidateBooleanVariable "SAVE_SUPER_LINTER_OUTPUT" "${SAVE_SUPER_LINTER_OUTPUT}" ValidateBooleanVariable "SAVE_SUPER_LINTER_SUMMARY" "${SAVE_SUPER_LINTER_SUMMARY}" ValidateBooleanVariable "SSH_INSECURE_NO_VERIFY_GITHUB_KEY" "${SSH_INSECURE_NO_VERIFY_GITHUB_KEY}" ValidateBooleanVariable "SSH_SETUP_GITHUB" "${SSH_SETUP_GITHUB}" ValidateBooleanVariable "SUPPRESS_FILE_TYPE_WARN" "${SUPPRESS_FILE_TYPE_WARN}" ValidateBooleanVariable "SUPPRESS_POSSUM" "${SUPPRESS_POSSUM}" ValidateBooleanVariable "TEST_CASE_RUN" "${TEST_CASE_RUN}" ValidateBooleanVariable "USE_FIND_ALGORITHM" "${USE_FIND_ALGORITHM}" ValidateBooleanVariable "VALIDATE_ALL_CODEBASE" "${VALIDATE_ALL_CODEBASE}" ValidateBooleanVariable "YAML_ERROR_ON_WARNING" "${YAML_ERROR_ON_WARNING}" } function ValidateGitHubWorkspace() { local GITHUB_WORKSPACE GITHUB_WORKSPACE="${1}" if [ -z "${GITHUB_WORKSPACE}" ]; then fatal "Failed to get GITHUB_WORKSPACE: ${GITHUB_WORKSPACE}" fi if [ ! -d "${GITHUB_WORKSPACE}" ]; then fatal "The workspace (${GITHUB_WORKSPACE}) is not a directory!" fi info "Successfully validated GITHUB_WORKSPACE: ${GITHUB_WORKSPACE}" } function ValidateFindMode() { debug "Validating find mode. USE_FIND_ALGORITHM: ${USE_FIND_ALGORITHM}, VALIDATE_ALL_CODEBASE: ${VALIDATE_ALL_CODEBASE}" if [[ "${USE_FIND_ALGORITHM}" == "true" ]] && [[ "${VALIDATE_ALL_CODEBASE}" == "false" ]]; then error "Setting USE_FIND_ALGORITHM to true and VALIDATE_ALL_CODEBASE to false is not supported because super-linter relies on Git to validate changed files." return 1 fi } function ValidateAnsibleDirectory() { if [ -z "${ANSIBLE_DIRECTORY:-}" ]; then ANSIBLE_DIRECTORY="${GITHUB_WORKSPACE}/ansible" debug "Set ANSIBLE_DIRECTORY to the default: ${ANSIBLE_DIRECTORY}" else debug "ANSIBLE_DIRECTORY before considering corner cases: ${ANSIBLE_DIRECTORY}" # Check if first char is '/' if [[ ${ANSIBLE_DIRECTORY:0:1} == "/" ]]; then # Remove first char ANSIBLE_DIRECTORY="${ANSIBLE_DIRECTORY:1}" fi if [ -z "${ANSIBLE_DIRECTORY}" ] || [[ ${ANSIBLE_DIRECTORY} == "." ]]; then # Catches the case where ANSIBLE_DIRECTORY="/" or ANSIBLE_DIRECTORY="." TEMP_ANSIBLE_DIRECTORY="${GITHUB_WORKSPACE}" else # Need to give it full path TEMP_ANSIBLE_DIRECTORY="${GITHUB_WORKSPACE}/${ANSIBLE_DIRECTORY}" fi # Set the value ANSIBLE_DIRECTORY="${TEMP_ANSIBLE_DIRECTORY}" debug "Setting Ansible directory to: ${ANSIBLE_DIRECTORY}" fi export ANSIBLE_DIRECTORY } function ValidateValidationVariables() { ################################################ # Determine if any linters were explicitly set # ################################################ local ANY_SET="false" local ANY_TRUE="false" local ANY_FALSE="false" for LANGUAGE in "${LANGUAGE_ARRAY[@]}"; do debug "Check if configuration provided a custom value to enable or disable ${LANGUAGE}" local VALIDATE_LANGUAGE VALIDATE_LANGUAGE="VALIDATE_${LANGUAGE}" if [ -n "${!VALIDATE_LANGUAGE:-}" ]; then debug "Configuration provided a custom value for ${VALIDATE_LANGUAGE}: ${!VALIDATE_LANGUAGE}" # Validate if user provided a string representing a valid boolean ValidateBooleanVariable "${VALIDATE_LANGUAGE}" "${!VALIDATE_LANGUAGE}" ANY_SET="true" if [ "${!VALIDATE_LANGUAGE}" == "true" ]; then ANY_TRUE="true" # We already checked that VALIDATE_LANGUAGE is either true or false else ANY_FALSE="true" fi else debug "Configuration didn't provide a custom value for ${VALIDATE_LANGUAGE}" fi done debug "ANY_SET: ${ANY_SET}, ANY_TRUE: ${ANY_TRUE}, ANY_FALSE: ${ANY_FALSE}" if [ $ANY_TRUE == "true" ] && [ $ANY_FALSE == "true" ]; then error "Behavior not supported, please either only include (VALIDATE=true) or exclude (VALIDATE=false) linters, but not both" return 1 fi ######################################################### # Validate if we should check/omit individual languages # ######################################################### for LANGUAGE in "${LANGUAGE_ARRAY[@]}"; do local VALIDATE_LANGUAGE VALIDATE_LANGUAGE="VALIDATE_${LANGUAGE}" if [[ ${ANY_SET} == "true" ]]; then debug "Configuration contains at least one custom value to enable or disable linters." if [ -z "${!VALIDATE_LANGUAGE:-}" ]; then # Flag was not set, default to: # - true if the configuration provided any false value -> enable linters that the user didn't explicitly disable # - false if the configuration didn't provid any false value -> disable linters that the user didn't explicitly enable eval "${VALIDATE_LANGUAGE}='$ANY_FALSE'" fi else # The user didn't provide and configuration value -> enable all linters by default eval "${VALIDATE_LANGUAGE}='true'" debug "Configuration doesn't include any custom values to enable or disable linters. Setting VALIDATE variable for ${LANGUAGE} to: ${!VALIDATE_LANGUAGE}" fi if [[ "${!VALIDATE_LANGUAGE}" == "true" ]]; then debug "- Validating [${LANGUAGE}] files in code base..." else debug "- Excluding [$LANGUAGE] files in code base..." fi eval "export ${VALIDATE_LANGUAGE}" done } function ValidateCheckModeAndFixModeVariables() { for LANGUAGE in "${LANGUAGE_ARRAY[@]}"; do local FIX_MODE_OPTIONS_VARIABLE_NAME="${LANGUAGE}_FIX_MODE_OPTIONS" local CHECK_ONLY_MODE_OPTIONS_VARIABLE_NAME="${LANGUAGE}_CHECK_ONLY_MODE_OPTIONS" local FIX_MODE_VARIABLE_NAME="FIX_${LANGUAGE}" debug "Check if ${LANGUAGE} supports fix mode by checking if ${FIX_MODE_OPTIONS_VARIABLE_NAME}, ${CHECK_ONLY_MODE_OPTIONS_VARIABLE_NAME}, or both variables are set." if [[ -v "${FIX_MODE_OPTIONS_VARIABLE_NAME}" ]] || [[ -v "${CHECK_ONLY_MODE_OPTIONS_VARIABLE_NAME}" ]]; then debug "Assuming that ${LANGUAGE} supports fix mode because ${FIX_MODE_OPTIONS_VARIABLE_NAME}, ${CHECK_ONLY_MODE_OPTIONS_VARIABLE_NAME}, or both variables are set." local -n FIX_MODE_REF="${FIX_MODE_VARIABLE_NAME}" if [[ -n "${FIX_MODE_REF:-}" ]]; then debug "The configuration provided a value for ${FIX_MODE_VARIABLE_NAME}: ${FIX_MODE_REF}" else FIX_MODE_REF="false" debug "The configuration didn't provide a value for ${FIX_MODE_VARIABLE_NAME} for ${LANGUAGE}. Setting it to: ${FIX_MODE_REF}" fi # TODO: After refactoring ValidateBooleanVariable to return an error instead # of exiting the whole program, add a test case for when ValidateBooleanVariable fails ValidateBooleanVariable "${!FIX_MODE_REF}" "${FIX_MODE_REF}" local -n VALIDATE_MODE_REF="VALIDATE_${LANGUAGE}" if [[ "${FIX_MODE_REF}" == "true" ]] && [[ "${VALIDATE_MODE_REF}" == "false" ]]; then error "Cannot set ${!FIX_MODE_REF} to ${FIX_MODE_REF} when ${!VALIDATE_MODE_REF} is ${VALIDATE_MODE_REF}" return 1 fi export FIX_MODE_REF else debug "Assuming that ${LANGUAGE} doesn't support fix mode because it doesn't have ${FIX_MODE_OPTIONS_VARIABLE_NAME}, nor ${CHECK_ONLY_MODE_OPTIONS_VARIABLE_NAME} variables defined." if [[ -v "${FIX_MODE_VARIABLE_NAME}" ]]; then error "The configuration provided a value for ${FIX_MODE_VARIABLE_NAME} but it's not supported for ${LANGUAGE}" return 1 else debug "The configuration didn't provide a value for ${FIX_MODE_VARIABLE_NAME} for ${LANGUAGE}" fi fi unset -n FIX_MODE_REF unset -n VALIDATE_MODE_REF done } function CheckIfGitBranchExists() { local BRANCH_NAME="${1}" debug "Check if the ${BRANCH_NAME} branch exists in ${GITHUB_WORKSPACE}" if ! git -C "${GITHUB_WORKSPACE}" rev-parse --quiet --verify "${BRANCH_NAME}"; then info "The ${BRANCH_NAME} branch doesn't exist in ${GITHUB_WORKSPACE}" return 1 else debug "The ${BRANCH_NAME} branch exists in ${GITHUB_WORKSPACE}" return 0 fi } function ValidateBooleanVariable() { local VAR_NAME VAR_NAME="${1}" local VAR_VALUE VAR_VALUE="${2}" if [[ "${VAR_VALUE}" != "true" ]] && [[ "${VAR_VALUE}" != "false" ]]; then fatal "Set ${VAR_NAME} to either true or false. It was set to: ${VAR_VALUE}" else debug "${VAR_NAME} has a valid boolean string value: ${VAR_VALUE}" fi } export -f ValidateBooleanVariable function ValidateLocalGitRepository() { debug "Check if ${GITHUB_WORKSPACE} is a Git repository" if ! git -C "${GITHUB_WORKSPACE}" rev-parse --git-dir; then fatal "${GITHUB_WORKSPACE} is not a Git repository." else debug "${GITHUB_WORKSPACE} is a Git repository" fi debug "Git branches: $(git -C "${GITHUB_WORKSPACE}" branch -a)" } function CheckIfGitRefExists() { local GIT_REF=${1} if git -C "${GITHUB_WORKSPACE}" cat-file -e "${GIT_REF}"; then return 0 else return 1 fi } function IsUnsignedInteger() { case ${1} in '' | *[!0-9]*) return 1 ;; *) return 0 ;; esac } function ValidateGitShaReference() { debug "Git HEAD: $(git -C "${GITHUB_WORKSPACE}" show HEAD --stat)" debug "Validate that the GITHUB_SHA reference (${GITHUB_SHA}) exists in this Git repository." if ! CheckIfGitRefExists "${GITHUB_SHA}"; then IssueHintForFullGitHistory fatal "The GITHUB_SHA reference (${GITHUB_SHA}) doesn't exist in this Git repository" else debug "The GITHUB_SHA reference (${GITHUB_SHA}) exists in this repository" fi } function ValidateGitBeforeShaReference() { debug "Validating GITHUB_BEFORE_SHA: ${GITHUB_BEFORE_SHA}" if [ -z "${GITHUB_BEFORE_SHA}" ] || [ "${GITHUB_BEFORE_SHA}" == "null" ] || [ "${GITHUB_BEFORE_SHA}" == "0000000000000000000000000000000000000000" ]; then fatal "Failed to get GITHUB_BEFORE_SHA: [${GITHUB_BEFORE_SHA}]" fi debug "Validate that the GITHUB_BEFORE_SHA reference (${GITHUB_BEFORE_SHA}) exists in this Git repository." if ! CheckIfGitRefExists "${GITHUB_BEFORE_SHA}"; then fatal "The GITHUB_BEFORE_SHA reference (${GITHUB_BEFORE_SHA}) doesn't exist in this Git repository" else debug "The GITHUB_BEFORE_SHA reference (${GITHUB_BEFORE_SHA}) exists in this repository" fi } function ValidateDefaultGitBranch() { debug "Check if the default branch (${DEFAULT_BRANCH}) exists" if ! CheckIfGitBranchExists "${DEFAULT_BRANCH}"; then REMOTE_DEFAULT_BRANCH="origin/${DEFAULT_BRANCH}" debug "The default branch (${DEFAULT_BRANCH}) doesn't exist in this Git repository. Trying with ${REMOTE_DEFAULT_BRANCH}" if ! CheckIfGitBranchExists "${REMOTE_DEFAULT_BRANCH}"; then fatal "Neither ${DEFAULT_BRANCH}, nor ${REMOTE_DEFAULT_BRANCH} exist in ${GITHUB_WORKSPACE}" else info "${DEFAULT_BRANCH} doesn't exist, however ${REMOTE_DEFAULT_BRANCH} exists. Setting DEFAULT_BRANCH to: ${REMOTE_DEFAULT_BRANCH}" DEFAULT_BRANCH="${REMOTE_DEFAULT_BRANCH}" debug "Updated DEFAULT_BRANCH: ${DEFAULT_BRANCH}" fi else debug "The default branch (${DEFAULT_BRANCH}) exists in this repository" fi } function CheckovConfigurationFileContainsDirectoryOption() { local CHECKOV_LINTER_RULES_PATH="${1}" local CONFIGURATION_OPTION_KEY="directory:" debug "Checking if ${CHECKOV_LINTER_RULES_PATH} contains a '${CONFIGURATION_OPTION_KEY}' configuration option" if [ ! -e "${CHECKOV_LINTER_RULES_PATH}" ]; then fatal "${CHECKOV_LINTER_RULES_PATH} doesn't exist. Cannot check if it contains a '${CONFIGURATION_OPTION_KEY}' configuration option" fi if grep -q "${CONFIGURATION_OPTION_KEY}" "${CHECKOV_LINTER_RULES_PATH}"; then debug "${CHECKOV_LINTER_RULES_PATH} contains a '${CONFIGURATION_OPTION_KEY}' statement" return 0 else debug "${CHECKOV_LINTER_RULES_PATH} doesn't contain a '${CONFIGURATION_OPTION_KEY}' statement" return 1 fi } export -f CheckovConfigurationFileContainsDirectoryOption function ValidateGitHubUrls() { if [[ -z "${DEFAULT_GITHUB_DOMAIN:-}" ]]; then error "DEFAULT_GITHUB_DOMAIN is empty." return 1 fi debug "Default GitHub domain: ${DEFAULT_GITHUB_DOMAIN}" if [[ -z "${GITHUB_DOMAIN:-}" ]]; then error "GITHUB_DOMAIN is empty." return 1 fi debug "GitHub domain: ${GITHUB_DOMAIN}" if [[ "${GITHUB_DOMAIN}" != "${DEFAULT_GITHUB_DOMAIN}" ]]; then debug "GITHUB_DOMAIN (${GITHUB_DOMAIN}) is not set to the default GitHub domain (${DEFAULT_GITHUB_DOMAIN})" if [[ -n "${GITHUB_CUSTOM_API_URL:-}" || -n "${GITHUB_CUSTOM_SERVER_URL:-}" ]]; then error "Cannot set GITHUB_DOMAIN (${GITHUB_DOMAIN}) along with GITHUB_CUSTOM_API_URL (${GITHUB_CUSTOM_API_URL:-}) or with GITHUB_CUSTOM_SERVER_URL (${GITHUB_CUSTOM_SERVER_URL:-})." return 1 fi else debug "GITHUB_DOMAIN (${GITHUB_DOMAIN}) is set to the default GitHub domain (${DEFAULT_GITHUB_DOMAIN})" if [[ -n "${GITHUB_CUSTOM_API_URL:-}" && -z "${GITHUB_CUSTOM_SERVER_URL:-}" ]] || [[ -z "${GITHUB_CUSTOM_API_URL:-}" && -n "${GITHUB_CUSTOM_SERVER_URL:-}" ]]; then error "Configure both GITHUB_CUSTOM_API_URL and GITHUB_CUSTOM_SERVER_URL. Current values: GITHUB_CUSTOM_API_URL: ${GITHUB_CUSTOM_API_URL:-}, GITHUB_CUSTOM_SERVER_URL: ${GITHUB_CUSTOM_SERVER_URL:-}" return 1 fi fi } function ValidateSuperLinterSummaryOutputPath() { debug "Validating SUPER_LINTER_SUMMARY_OUTPUT_PATH" if [[ -z "${SUPER_LINTER_SUMMARY_OUTPUT_PATH:-}" ]]; then error "SUPER_LINTER_SUMMARY_OUTPUT_PATH is not set." return 1 fi debug "SUPER_LINTER_SUMMARY_OUTPUT_PATH is set to: ${SUPER_LINTER_SUMMARY_OUTPUT_PATH}" if [[ ! -e "${SUPER_LINTER_SUMMARY_OUTPUT_PATH}" ]]; then error "SUPER_LINTER_SUMMARY_OUTPUT_PATH (${SUPER_LINTER_SUMMARY_OUTPUT_PATH}) doesn't exist." return 1 fi if [[ ! -f "${SUPER_LINTER_SUMMARY_OUTPUT_PATH}" ]]; then error "SUPER_LINTER_SUMMARY_OUTPUT_PATH (${SUPER_LINTER_SUMMARY_OUTPUT_PATH}) is not a file." return 1 fi debug "Super-linter summary ouput path passed validation" } function WarnIfVariableIsSet() { local INPUT_VARIABLE="${1}" shift local INPUT_VARIABLE_NAME="${1}" if [ -n "${INPUT_VARIABLE:-}" ]; then warn "${INPUT_VARIABLE_NAME} environment variable is set, it's deprecated, and super-linter will ignore it. Remove it from your configuration. This warning may turn in a fatal error in the future. For more information, see the upgrade guide: https://github.com/super-linter/super-linter/blob/main/docs/upgrade-guide.md" fi } function WarnIfDeprecatedValueForConfigurationVariableIsSet() { local INPUT_VARIABLE_VALUE INPUT_VARIABLE_VALUE="${1}" shift local DEPRECATED_VARIABLE_VALUE DEPRECATED_VARIABLE_VALUE="${1}" shift local INPUT_VARIABLE_NAME INPUT_VARIABLE_NAME="${1}" shift local VALUE_TO_UPDATE_TO VALUE_TO_UPDATE_TO="${1}" if [[ "${INPUT_VARIABLE_VALUE}" == "${DEPRECATED_VARIABLE_VALUE}" ]]; then warn "${INPUT_VARIABLE_NAME} is set to a deprecated value: ${DEPRECATED_VARIABLE_VALUE}. Set it to ${VALUE_TO_UPDATE_TO} instead. Falling back to ${VALUE_TO_UPDATE_TO}. This warning may turn in a fatal error in the future." fi } function ValidateDeprecatedVariables() { # The following variables have been deprecated in v6.0.0 WarnIfVariableIsSet "${ERROR_ON_MISSING_EXEC_BIT:-}" "ERROR_ON_MISSING_EXEC_BIT" WarnIfVariableIsSet "${EXPERIMENTAL_BATCH_WORKER:-}" "EXPERIMENTAL_BATCH_WORKER" WarnIfVariableIsSet "${VALIDATE_JSCPD_ALL_CODEBASE:-}" "VALIDATE_JSCPD_ALL_CODEBASE" WarnIfVariableIsSet "${VALIDATE_KOTLIN_ANDROID:-}" "VALIDATE_KOTLIN_ANDROID" # The following values have been deprecated in v6.1.0 WarnIfDeprecatedValueForConfigurationVariableIsSet "${LOG_LEVEL}" "TRACE" "LOG_LEVEL" "DEBUG" WarnIfDeprecatedValueForConfigurationVariableIsSet "${LOG_LEVEL}" "VERBOSE" "LOG_LEVEL" "INFO" # The following variables have been deprecated in v6.8.0 WarnIfVariableIsSet "${JAVASCRIPT_DEFAULT_STYLE:-}" "JAVASCRIPT_DEFAULT_STYLE" WarnIfVariableIsSet "${TYPESCRIPT_DEFAULT_STYLE:-}" "TYPESCRIPT_DEFAULT_STYLE" }