diff --git a/.automation/test/kubeval/README.md b/.automation/test/kubeval/README.md new file mode 100644 index 00000000..8ed5df62 --- /dev/null +++ b/.automation/test/kubeval/README.md @@ -0,0 +1,19 @@ +# Kubeval Test Cases + +This folder holds the test cases for **Kubeval**. + +## Additional Docs + +No Additional information is needed for this test case. + +## Good Test Cases + +The test cases denoted: `LANGUAGE_good_FILE.EXTENSION` are all valid, and should pass successfully when linted. + +- **Note:** They are linted utilizing the default linter rules. + +## Bad Test Cases + +The test cases denoted: `LANGUAGE_bad_FILE.EXTENSION` are **NOT** valid, and should trigger errors when linted. + +- **Note:** They are linted utilizing the default linter rules. diff --git a/.automation/test/kubeval/kubeval_bad_1.yaml b/.automation/test/kubeval/kubeval_bad_1.yaml new file mode 100755 index 00000000..2164579e --- /dev/null +++ b/.automation/test/kubeval/kubeval_bad_1.yaml @@ -0,0 +1,20 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + selector: + matchLabels: + app: nginx + replicas: 4 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image2: nginx:1.13.12 + ports: + - containerPort: 80 diff --git a/.automation/test/kubeval/kubeval_good_1.yaml b/.automation/test/kubeval/kubeval_good_1.yaml new file mode 100755 index 00000000..1494fa23 --- /dev/null +++ b/.automation/test/kubeval/kubeval_good_1.yaml @@ -0,0 +1,20 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + selector: + matchLabels: + app: nginx + replicas: 4 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.13.12 + ports: + - containerPort: 80 diff --git a/.github/workflows/deploy-DEV.yml b/.github/workflows/deploy-DEV.yml index 5e6e0de2..d6144545 100644 --- a/.github/workflows/deploy-DEV.yml +++ b/.github/workflows/deploy-DEV.yml @@ -71,7 +71,7 @@ jobs: run: docker run -e RUN_LOCAL=true -e TEST_CASE_RUN=true -e OUTPUT_FORMAT=tap -e OUTPUT_FOLDER=${GITHUB_SHA} -e OUTPUT_DETAILS=detailed -v ${GITHUB_WORKSPACE}:/tmp/lint github/super-linter:${GITHUB_SHA} ######################################### - # Clean code base to run agaisnt it all # + # Clean code base to run against it all # ######################################### - name: Clean Test code base for additional testing shell: bash diff --git a/Dockerfile b/Dockerfile index c4ee38d8..ff3a2d41 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,6 +18,7 @@ FROM accurics/terrascan:d182f1c as terrascan FROM hadolint/hadolint:latest-alpine as dockerfile-lint FROM ghcr.io/assignuser/lintr-lib:0.1.2 as lintr-lib FROM ghcr.io/assignuser/chktex-alpine:0.1.1 as chktex +FROM garethr/kubeval:0.15.0 as kubeval ################## # Get base image # @@ -305,6 +306,11 @@ RUN R -e "install.packages(list.dirs('/home/r-library',recursive = FALSE), repos COPY --from=chktex /usr/bin/chktex /usr/bin/ RUN cd ~ && touch .chktexrc +################### +# Install kubeval # +################### +COPY --from=kubeval /kubeval /usr/bin/ + ################# # Install shfmt # ################# @@ -331,6 +337,7 @@ ENV ACTIONS_RUNNER_DEBUG=${ACTIONS_RUNNER_DEBUG} \ GITHUB_TOKEN=${GITHUB_TOKEN} \ GITHUB_WORKSPACE=${GITHUB_WORKSPACE} \ JAVASCRIPT_ES_CONFIG_FILE=${JAVASCRIPT_ES_CONFIG_FILE} \ + KUBERNETES_DIRECTORY=${KUBERNETES_DIRECTORY} \ LINTER_RULES_PATH=${LINTER_RULES_PATH} \ LOG_FILE=${LOG_FILE} \ LOG_LEVEL=${LOG_LEVEL} \ @@ -362,6 +369,7 @@ ENV ACTIONS_RUNNER_DEBUG=${ACTIONS_RUNNER_DEBUG} \ VALIDATE_JAVASCRIPT_ES=${VALIDATE_JAVASCRIPT_ES} \ VALIDATE_JAVASCRIPT_STANDARD=${VALIDATE_JAVASCRIPT_STANDARD} \ VALIDATE_JSON=${VALIDATE_JSON} \ + VALIDATE_KUBERNETES_KUBEVAL=${VALIDATE_KUBERNETES_KUBEVAL} \ VALIDATE_KOTLIN=${VALIDATE_KOTLIN} \ VALIDATE_LATEX=${VALIDATE_LATEX} \ VALIDATE_LUA=${VALIDATE_LUA} \ diff --git a/README.md b/README.md index fe73ed65..03a4e9a4 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ Developers on **GitHub** can call the **GitHub Action** to lint their code base | **Java** | [checkstyle](https://checkstyle.org) | | **JavaScript** | [eslint](https://eslint.org/) / [standard js](https://standardjs.com/) | | **JSON** | [jsonlint](https://github.com/zaach/jsonlint) | +| **Kubeval** | [kubeval](https://github.com/instrumenta/kubeval) | | **Kotlin** | [ktlint](https://github.com/pinterest/ktlint) | | **LaTeX** | [ChkTex](https://www.nongnu.org/chktex/) | | **Lua** | [luacheck](https://github.com/luarocks/luacheck) | @@ -198,7 +199,7 @@ But if you wish to select or exclude specific linters, we give you full control | **ENV VAR** | **Default Value** | **Notes** | | --------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **ACTIONS_RUNNER_DEBUG** | `false` | Flag to enable additional information about the linter, versions, and additional output. | -| **ANSIBLE_DIRECTORY** | `/ansible` | Flag to set the root directory for Ansible file location(s). | +| **ANSIBLE_DIRECTORY** | `/ansible` | Flag to set the root directory for Ansible file location(s), relative to `DEFAULT_WORKSPACE`. | | **CSS_FILE_NAME** | `.stylelintrc.json` | Filename for [Stylelint configuration](https://github.com/stylelint/stylelint) (ex: `.stylelintrc.yml`, `.stylelintrc.yaml`) | | **DEFAULT_BRANCH** | `master` | The name of the repository default branch. | | **DEFAULT_WORKSPACE** | `/tmp/lint` | The location containing files to lint if you are running locally. | @@ -208,6 +209,7 @@ But if you wish to select or exclude specific linters, we give you full control | **FILTER_REGEX_EXCLUDE** | `none` | Regular expression defining which files will be excluded from linting (ex: `.*src/test.*`) | | **FILTER_REGEX_INCLUDE** | `all` | Regular expression defining which files will be processed by linters (ex: `.*src/.*`) | | **JAVASCRIPT_ES_CONFIG_FILE** | `.eslintrc.yml` | Filename for [eslint configuration](https://eslint.org/docs/user-guide/configuring#configuration-file-formats) (ex: `.eslintrc.yml`, `.eslintrc.json`) | +| **KUBERNETES_DIRECTORY** | `/kubernetes` | The path to the root directory for Kubernetes descriptors, relative to `DEFAULT_WORKSPACE`. | | **LINTER_RULES_PATH** | `.github/linters` | Directory for all linter configuration rules. | | **LOG_FILE** | `super-linter.log` | The file name for outputting logs. All output is sent to the log file regardless of `LOG_LEVEL`. | | **LOG_LEVEL** | `VERBOSE` | How much output the script will generate to the console. One of `VERBOSE`, `DEBUG` or `TRACE`. | @@ -246,6 +248,7 @@ But if you wish to select or exclude specific linters, we give you full control | **VALIDATE_JSON** | `true` | Flag to enable or disable the linting process of the JSON language. | | **VALIDATE_JSX** | `true` | Flag to enable or disable the linting process for jsx files (Utilizing: eslint) | | **VALIDATE_KOTLIN** | `true` | Flag to enable or disable the linting process of the Kotlin language. | +| **VALIDATE_KUBERNETES_KUBEVAL** | `true` | Flag to enable or disable the linting process of Kubernetes descriptors with Kubeval | | **VALIDATE_LATEX** | `true` | Flag to enable or disable the linting process of the LaTeX language. | | **VALIDATE_LUA** | `true` | Flag to enable or disable the linting process of the language. | | **VALIDATE_MD** | `true` | Flag to enable or disable the linting process of the Markdown language. | diff --git a/docs/disabling-linters.md b/docs/disabling-linters.md index 49f0702e..eafbf798 100644 --- a/docs/disabling-linters.md +++ b/docs/disabling-linters.md @@ -33,6 +33,7 @@ For some linters it is also possible to override rules on a case by case level w - [JavaScript eslint](#javascript-eslint) - [JavaScript standard](#javascript-standard) - [JSON](#json) + - [Kubeval](#kubeval) - [Kotlin](#kotlin) - [LaTeX](#latex) - [Lua](#lua) @@ -605,6 +606,16 @@ import package.b.* --- +## Kubernetes + +- [kubeval](https://github.com/instrumenta/kubeval) + +### Kubeval + +- There is no top level _configuration file_ available at this time + +--- + ## LaTeX - [ChkTex](https://www.nongnu.org/chktex/) diff --git a/lib/buildFileList.sh b/lib/buildFileList.sh index ff339727..889e9d2e 100755 --- a/lib/buildFileList.sh +++ b/lib/buildFileList.sh @@ -591,6 +591,16 @@ function BuildFileList() { READ_ONLY_CHANGE_FLAG=1 fi + ############################################ + # Check if the file is Kubernetes template # + ############################################ + if DetectKubernetesFile "${FILE}"; then + ################################ + # Append the file to the array # + ################################ + FILE_ARRAY_KUBERNETES+=("${FILE}") + fi + ######################################################################## # We have something that we need to try to check file type another way # ######################################################################## diff --git a/lib/linter.sh b/lib/linter.sh index 5ee4cca4..e2416454 100755 --- a/lib/linter.sh +++ b/lib/linter.sh @@ -142,7 +142,7 @@ YAML_LINTER_RULES="${DEFAULT_RULES_LOCATION}/${YAML_FILE_NAME}" # Path to the ya ############################# LANGUAGE_ARRAY=('ANSIBLE' 'ARM' 'BASH' 'BASH_EXEC' 'CLOUDFORMATION' 'CLOJURE' 'COFFEESCRIPT' 'CSHARP' 'CSS' 'DART' 'DOCKERFILE' 'DOCKERFILE_HADOLINT' 'EDITORCONFIG' 'ENV' 'GO' 'GROOVY' 'HTML' - 'JAVA' 'JAVASCRIPT_ES' 'JAVASCRIPT_STANDARD' 'JSON' 'JSX' 'KOTLIN' 'LATEX' 'LUA' 'MARKDOWN' + 'JAVA' 'JAVASCRIPT_ES' 'JAVASCRIPT_STANDARD' 'JSON' 'JSX' 'KUBERNETES_KUBEVAL' 'KOTLIN' 'LATEX' 'LUA' 'MARKDOWN' 'OPENAPI' 'PERL' 'PHP_BUILTIN' 'PHP_PHPCS' 'PHP_PHPSTAN' 'PHP_PSALM' 'POWERSHELL' 'PROTOBUF' 'PYTHON_BLACK' 'PYTHON_PYLINT' 'PYTHON_FLAKE8' 'R' 'RAKU' 'RUBY' 'SHELL_SHFMT' 'STATES' 'SQL' 'TERRAFORM' 'TERRAFORM_TERRASCAN' 'TSX' 'TYPESCRIPT_ES' 'TYPESCRIPT_STANDARD' 'XML' 'YAML') @@ -166,6 +166,7 @@ GITHUB_RUN_ID="${GITHUB_RUN_ID}" # GitHub RU GITHUB_SHA="${GITHUB_SHA}" # GitHub sha from the commit GITHUB_TOKEN="${GITHUB_TOKEN}" # GitHub Token passed from environment GITHUB_WORKSPACE="${GITHUB_WORKSPACE}" # Github Workspace +KUBERNETES_DIRECTORY="${KUBERNETES_DIRECTORY}" # Kubernetes directory LOG_FILE="${LOG_FILE:-super-linter.log}" # Default log file name (located in GITHUB_WORKSPACE folder) LOG_LEVEL="${LOG_LEVEL:-VERBOSE}" # Default log level (VERBOSE, DEBUG, TRACE) MULTI_STATUS="${MULTI_STATUS:-true}" # Multiple status are created for each check ran @@ -193,6 +194,7 @@ VALIDATE_JAVASCRIPT_ES="${VALIDATE_JAVASCRIPT_ES}" # Boolean t 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_KUBERNETES_KUBEVAL="${VALIDATE_KUBERNETES_KUBEVAL}" # Boolean to validate language VALIDATE_KOTLIN="${VALIDATE_KOTLIN}" # Boolean to validate language VALIDATE_LATEX="${VALIDATE_LATEX}" # Boolean to validate language VALIDATE_LUA="${VALIDATE_LUA}" # Boolean to validate language @@ -265,8 +267,6 @@ READ_ONLY_CHANGE_FLAG=0 # Flag set to 1 if files export READ_ONLY_CHANGE_FLAG # Workaround SC2034 TEST_CASE_FOLDER='.automation/test' # Folder for test cases we should always ignore export TEST_CASE_FOLDER # Workaround SC2034 -DEFAULT_ANSIBLE_DIRECTORY="${GITHUB_WORKSPACE}/ansible" # Default Ansible Directory -export DEFAULT_ANSIBLE_DIRECTORY # Workaround SC2034 WARNING_ARRAY_TEST=() # Array of warning linters that did not have an expected test result. export WARNING_ARRAY_TEST # Workaround SC2034 @@ -276,7 +276,6 @@ export WARNING_ARRAY_TEST # Workaround SC2034 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="${GITHUB_WORKSPACE}/${OUTPUT_FOLDER}" # Location for the report folder ########################## # Array of changed files # @@ -299,6 +298,7 @@ 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_KUBERNETES=() FILE_ARRAY_KOTLIN=() # Array of files to check FILE_ARRAY_LATEX=() # Array of files to check FILE_ARRAY_LUA=() # Array of files to check @@ -373,6 +373,8 @@ ERRORS_FOUND_JSON=0 # Count of errors found export ERRORS_FOUND_JSON # Workaround SC2034 ERRORS_FOUND_JSX=0 # Count of errors found export ERRORS_FOUND_JSX # Workaround SC2034 +ERRORS_FOUND_KUBERNETES_KUBEVAL=0 # Count of errors found +export ERRORS_FOUND_KUBERNETES_KUBEVAL ERRORS_FOUND_KOTLIN=0 # Count of errors found export ERRORS_FOUND_KOTLIN # Workaround SC2034 ERRORS_FOUND_LATEX=0 # Count of errors found @@ -740,6 +742,24 @@ DetectCloudFormationFile() { 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 -E '(apiVersion):' "${FILE}" >/dev/null; then + debug "${FILE} is a Kubernetes descriptor" + return 0 + fi + + debug "${FILE} is NOT a Kubernetes descriptor" + return 1 + +} +################################################################################ #### Function DetectAWSStatesFIle ############################################## DetectAWSStatesFIle() { ################ @@ -1222,6 +1242,15 @@ fi # needed to connect back and update checks GetGitHubVars +######################################################## +# Initialize variables that depend on GitHub variables # +######################################################## +DEFAULT_ANSIBLE_DIRECTORY="${GITHUB_WORKSPACE}/ansible" # Default Ansible Directory +export DEFAULT_ANSIBLE_DIRECTORY # Workaround SC2034 +DEFAULT_KUBERNETES_DIRECTORY="${GITHUB_WORKSPACE}/kubernetes" # Default Kubernetes Directory +export DEFAULT_KUBERNETES_DIRECTORY # Workaround SC2034 +REPORT_OUTPUT_FOLDER="${GITHUB_WORKSPACE}/${OUTPUT_FOLDER}" # Location for the report folder + ######################################### # Get the languages we need to validate # ######################################### @@ -1632,6 +1661,37 @@ if [ "${VALIDATE_KOTLIN}" == "true" ]; then LintCodebase "KOTLIN" "ktlint" "ktlint" ".*\.\(kt\|kts\)\$" "${FILTER_REGEX_INCLUDE}" "${FILTER_REGEX_EXCLUDE}" "${FILE_ARRAY_KOTLIN[@]}" fi +############################## +# KUBERNETES Kubeval LINTING # +############################## +if [ "${VALIDATE_KUBERNETES_KUBEVAL}" == "true" ]; then + if [ -d "${KUBERNETES_DIRECTORY}" ]; then + 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 "${KUBERNETES_DIRECTORY}" -path "*/node_modules" -prune -o -type f -regex ".*\.\(yml\|yaml\|json\)\$" 2>&1) + for FILE in "${LIST_FILES[@]}"; do + if DetectKubernetesFile "${FILE}"; then + FILE_ARRAY_KUBERNETES+=("${FILE}") + fi + done + + ########################### + # Set IFS back to default # + ########################### + IFS="${DEFAULT_IFS}" + fi + + LintCodebase "KUBERNETES_KUBEVAL" "kubeval" "kubeval --strict" ".*\.\(yml\|yaml\|json\)\$" "${FILTER_REGEX_INCLUDE}" "${FILTER_REGEX_EXCLUDE}" "${FILE_ARRAY_KUBERNETES[@]}" + else + warn "No Kubernetes directory found at:[${KUBERNETES_DIRECTORY}]" + debug "skipping Kubeval lint" + fi +fi + ################# # LATEX LINTING # ################# diff --git a/lib/linterVersions.sh b/lib/linterVersions.sh index 5c659cb9..8b2a92c2 100755 --- a/lib/linterVersions.sh +++ b/lib/linterVersions.sh @@ -23,7 +23,7 @@ ARM_TTK_PSD1='/usr/bin/arm-ttk' # Powershell var ####################################### LINTER_ARRAY=('ansible-lint' 'arm-ttk' 'asl-validator' 'bash-exec' 'black' 'cfn-lint' 'checkstyle' 'chktex' 'clj-kondo' 'coffeelint' 'dotnet-format' 'dart' 'dockerfilelint' 'dotenv-linter' 'editorconfig-checker' 'eslint' 'flake8' 'golangci-lint' - 'hadolint' 'htmlhint' 'jsonlint' 'ktlint' 'lintr' 'lua' 'markdownlint' 'npm-groovy-lint' 'perl' 'protolint' + 'hadolint' 'htmlhint' 'jsonlint' 'kubeval' 'ktlint' 'lintr' 'lua' 'markdownlint' 'npm-groovy-lint' 'perl' 'protolint' 'pwsh' 'pylint' 'raku' 'rubocop' 'shellcheck' 'shfmt' 'spectral' 'standard' 'stylelint' 'sql-lint' 'terrascan' 'tflint' 'xmllint' 'yamllint') diff --git a/lib/validation.sh b/lib/validation.sh index c63ea87e..9ac77ad5 100755 --- a/lib/validation.sh +++ b/lib/validation.sh @@ -123,6 +123,7 @@ function GetValidationInfo() { if [ -z "${ANSIBLE_DIRECTORY}" ]; then # No Value, need to default ANSIBLE_DIRECTORY="${DEFAULT_ANSIBLE_DIRECTORY}" + debug "Setting Ansible directory to the default: ${DEFAULT_ANSIBLE_DIRECTORY}" else # Check if first char is '/' if [[ ${ANSIBLE_DIRECTORY:0:1} == "/" ]]; then @@ -133,6 +134,27 @@ function GetValidationInfo() { TEMP_ANSIBLE_DIRECTORY="${GITHUB_WORKSPACE}/${ANSIBLE_DIRECTORY}" # Set the value ANSIBLE_DIRECTORY="${TEMP_ANSIBLE_DIRECTORY}" + debug "Setting Ansible directory to: ${ANSIBLE_DIRECTORY}" + fi + + ################################# + # Validate Kubernetes Directory # + ################################# + if [ -z "${KUBERNETES_DIRECTORY}" ]; then + # No Value, need to default + KUBERNETES_DIRECTORY="${DEFAULT_KUBERNETES_DIRECTORY}" + debug "Setting Kubernetes directory to the default: ${DEFAULT_KUBERNETES_DIRECTORY}" + else + # Check if first char is '/' + if [[ ${KUBERNETES_DIRECTORY:0:1} == "/" ]]; then + # Remove first char + KUBERNETES_DIRECTORY="${KUBERNETES_DIRECTORY:1}" + fi + # Need to give it full path + TEMP_KUBERNETES_DIRECTORY="${GITHUB_WORKSPACE}/${KUBERNETES_DIRECTORY}" + # Set the value + KUBERNETES_DIRECTORY="${TEMP_KUBERNETES_DIRECTORY}" + debug "Setting Kubernetes directory to: ${KUBERNETES_DIRECTORY}" fi ############################### diff --git a/lib/worker.sh b/lib/worker.sh index 5ac42607..6f03ff71 100755 --- a/lib/worker.sh +++ b/lib/worker.sh @@ -706,6 +706,7 @@ function RunTestCases() { TestCodebase "JAVASCRIPT_ES" "eslint" "eslint --no-eslintrc -c ${JAVASCRIPT_LINTER_RULES}" ".*\.\(js\)\$" "javascript" TestCodebase "JAVASCRIPT_STANDARD" "standard" "standard ${JAVASCRIPT_STANDARD_LINTER_RULES}" ".*\.\(js\)\$" "javascript" TestCodebase "JSON" "jsonlint" "jsonlint" ".*\.\(json\)\$" "json" + TestCodebase "KUBERNETES_KUBEVAL" "kubeval" "kubeval --strict" ".*\.\(yml\|yaml\)\$" "kubeval" TestCodebase "KOTLIN" "ktlint" "ktlint" ".*\.\(kt\|kts\)\$" "kotlin" TestCodebase "LATEX" "chktex" "chktex -q -l ${LATEX_LINTER_RULES}" ".*\.\(tex\)\$" "latex" TestCodebase "LUA" "lua" "luacheck" ".*\.\(lua\)\$" "lua" @@ -807,26 +808,7 @@ function LintAnsibleFiles() { ################################# # Get list of all files to lint # ################################# - mapfile -t LIST_FILES < <(ls "${ANSIBLE_DIRECTORY}"/*.{yaml,yml} 2>&1) - - ############################################################### - # Set the list to empty if only MD and TXT files were changed # - ############################################################### - # No need to run the full ansible checks on read only file changes - if [ "${READ_ONLY_CHANGE_FLAG}" -eq 0 ]; then - ########################## - # Set the array to empty # - ########################## - LIST_FILES=() - ################################### - # Send message that were skipping # - ################################### - debug "- Skipping Ansible lint run as file(s) that were modified were read only..." - ############################ - # Create flag to skip loop # - ############################ - SKIP_FLAG=1 - fi + mapfile -t LIST_FILES < <(find "${ANSIBLE_DIRECTORY}" -path "*/node_modules" -prune -o -type f -regex ".*\.\(yml\|yaml\|json\)\$" 2>&1) #################################### # Check if we have data to look at #