Skip to content

Commit

Permalink
feat: Add support for version constraints in tfupdate (#437)
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxymVlasov committed Oct 6, 2022
1 parent f5aa7c8 commit a446642
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 112 deletions.
39 changes: 32 additions & 7 deletions hooks/_common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,22 @@ function common::parse_cmdline {
case $argv in
-a | --args)
shift
ARGS+=("$1")
# `argv` is an string from array with content like:
# ('provider aws' '--version "> 0.14"' '--ignore-path "some/path"')
# where each element is the value of each `--args` from hook config.
# `echo` prints contents of `argv` as an expanded string
# `xargs` passes expanded string to `printf`
# `printf` which splits it into NUL-separated elements,
# NUL-separated elements read by `read` using empty separator
# (`-d ''` or `-d $'\0'`)
# into an `ARGS` array

# This allows to "rebuild" initial `args` array of sort of grouped elements
# into a proper array, where each element is a standalone array slice
# with quoted elements being treated as a standalone slice of array as well.
while read -r -d '' ARG; do
ARGS+=("$ARG")
done < <(echo "$1" | xargs printf '%s\0')
shift
;;
-h | --hook-config)
Expand Down Expand Up @@ -129,7 +144,7 @@ function common::parse_and_export_env_vars {
#######################################################################
function common::is_hook_run_on_whole_repo {
local -r hook_id="$1"
shift 1
shift
local -a -r files=("$@")
# get directory containing `.pre-commit-hooks.yaml` file
local -r root_config_dir="$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)")"
Expand Down Expand Up @@ -163,21 +178,31 @@ function common::is_hook_run_on_whole_repo {
# 2.1. If at least 1 check failed - change exit code to non-zero
# 3. Complete hook execution and return exit code
# Arguments:
# args (string with array) arguments that configure wrapped tool behavior
# hook_id (string) hook ID, see `- id` for details in .pre-commit-hooks.yaml file
# args_array_length (integer) Count of arguments in args array.
# args (array) arguments that configure wrapped tool behavior
# files (array) filenames to check
#######################################################################
function common::per_dir_hook {
local -r args="$1"
local -r hook_id="$2"
local -r hook_id="$1"
local -i args_array_length=$2
shift 2
local -a args=()
# Expand args to a true array.
# Based on https://stackoverflow.com/a/10953834
while ((args_array_length-- > 0)); do
args+=("$1")
shift
done
# assign rest of function's positional ARGS into `files` array,
# despite there's only one positional ARG left
local -a -r files=("$@")

# check is (optional) function defined
if [ "$(type -t run_hook_on_whole_repo)" == function ] &&
# check is hook run via `pre-commit run --all`
common::is_hook_run_on_whole_repo "$hook_id" "${files[@]}"; then
run_hook_on_whole_repo "$args"
run_hook_on_whole_repo "${args[@]}"
exit 0
fi

Expand All @@ -203,7 +228,7 @@ function common::per_dir_hook {
dir_path="${dir_path//__REPLACED__SPACE__/ }"
pushd "$dir_path" > /dev/null || continue

per_dir_hook_unique_part "$args" "$dir_path"
per_dir_hook_unique_part "$dir_path" "${args[@]}"

local exit_code=$?
if [ $exit_code -ne 0 ]; then
Expand Down
28 changes: 14 additions & 14 deletions hooks/terraform_checkov.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,35 @@ function main {
common::export_provided_env_vars "${ENV_VARS[@]}"
common::parse_and_export_env_vars
# Support for setting PATH to repo root.
# shellcheck disable=SC2178 # It's the simplest syntax for that case
ARGS=${ARGS[*]/__GIT_WORKING_DIR__/$(pwd)\/}
for i in "${!ARGS[@]}"; do
ARGS[i]=${ARGS[i]/__GIT_WORKING_DIR__/$(pwd)\/}
done

# Suppress checkov color
if [ "$PRE_COMMIT_COLOR" = "never" ]; then
export ANSI_COLORS_DISABLED=true
fi
# shellcheck disable=SC2128 # It's the simplest syntax for that case
common::per_dir_hook "$ARGS" "$HOOK_ID" "${FILES[@]}"

common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}"
}

#######################################################################
# Unique part of `common::per_dir_hook`. The function is executed in loop
# on each provided dir path. Run wrapped tool with specified arguments
# Arguments:
# args (string with array) arguments that configure wrapped tool behavior
# dir_path (string) PATH to dir relative to git repo root.
# Can be used in error logging
# args (array) arguments that configure wrapped tool behavior
# Outputs:
# If failed - print out hook checks status
#######################################################################
function per_dir_hook_unique_part {
# common logic located in common::per_dir_hook
local -r args="$1"
# shellcheck disable=SC2034 # Unused var.
local -r dir_path="$2"
local -r dir_path="$1"
shift
local -a -r args=("$@")

# shellcheck disable=SC2068 # hook fails when quoting is used ("$arg[@]")
checkov -d . ${args[@]}
checkov -d . "${args[@]}"

# return exit code to common::per_dir_hook
local exit_code=$?
Expand All @@ -51,14 +52,13 @@ function per_dir_hook_unique_part {
# Unique part of `common::per_dir_hook`. The function is executed one time
# in the root git repo
# Arguments:
# args (string with array) arguments that configure wrapped tool behavior
# args (array) arguments that configure wrapped tool behavior
#######################################################################
function run_hook_on_whole_repo {
local -r args="$1"
local -a -r args=("$@")

# pass the arguments to hook
# shellcheck disable=SC2068 # hook fails when quoting is used ("$arg[@]")
checkov -d "$(pwd)" ${args[@]}
checkov -d "$(pwd)" "${args[@]}"

# return exit code to common::per_dir_hook
local exit_code=$?
Expand Down
10 changes: 5 additions & 5 deletions hooks/terraform_docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ function main {
common::export_provided_env_vars "${ENV_VARS[@]}"
common::parse_and_export_env_vars
# Support for setting relative PATH to .terraform-docs.yml config.
# shellcheck disable=SC2178 # It's the simplest syntax for that case
ARGS=${ARGS[*]/--config=/--config=$(pwd)\/}
# shellcheck disable=SC2128 # It's the simplest syntax for that case
for i in "${!ARGS[@]}"; do
ARGS[i]=${ARGS[i]/--config=/--config=$(pwd)\/}
done
# shellcheck disable=SC2153 # False positive
terraform_docs_ "${HOOK_CONFIG[*]}" "$ARGS" "${FILES[@]}"
terraform_docs_ "${HOOK_CONFIG[*]}" "${ARGS[*]}" "${FILES[@]}"
}

#######################################################################
Expand Down Expand Up @@ -91,7 +91,7 @@ function terraform_docs {
shift 3
local -a -r files=("$@")

declare -a paths
local -a paths

local index=0
local file_with_path
Expand Down
12 changes: 6 additions & 6 deletions hooks/terraform_fmt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,27 @@ function main {
fi

# shellcheck disable=SC2153 # False positive
common::per_dir_hook "${ARGS[*]}" "$HOOK_ID" "${FILES[@]}"
common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}"
}

#######################################################################
# Unique part of `common::per_dir_hook`. The function is executed in loop
# on each provided dir path. Run wrapped tool with specified arguments
# Arguments:
# args (string with array) arguments that configure wrapped tool behavior
# dir_path (string) PATH to dir relative to git repo root.
# Can be used in error logging
# args (array) arguments that configure wrapped tool behavior
# Outputs:
# If failed - print out hook checks status
#######################################################################
function per_dir_hook_unique_part {
local -r args="$1"
# shellcheck disable=SC2034 # Unused var.
local -r dir_path="$2"
local -r dir_path="$1"
shift
local -a -r args=("$@")

# pass the arguments to hook
# shellcheck disable=SC2068 # hook fails when quoting is used ("$arg[@]")
terraform fmt ${args[@]}
terraform fmt "${args[@]}"

# return exit code to common::per_dir_hook
local exit_code=$?
Expand Down
12 changes: 6 additions & 6 deletions hooks/terraform_providers_lock.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,23 @@ function main {
# JFYI: suppress color for `terraform providers lock` is N/A`

# shellcheck disable=SC2153 # False positive
common::per_dir_hook "${ARGS[*]}" "$HOOK_ID" "${FILES[@]}"
common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}"
}

#######################################################################
# Unique part of `common::per_dir_hook`. The function is executed in loop
# on each provided dir path. Run wrapped tool with specified arguments
# Arguments:
# args (string with array) arguments that configure wrapped tool behavior
# dir_path (string) PATH to dir relative to git repo root.
# Can be used in error logging
# args (array) arguments that configure wrapped tool behavior
# Outputs:
# If failed - print out hook checks status
#######################################################################
function per_dir_hook_unique_part {
local -r args="$1"
local -r dir_path="$2"
local -r dir_path="$1"
shift
local -a -r args=("$@")

local exit_code

Expand All @@ -41,8 +42,7 @@ function per_dir_hook_unique_part {
}

# pass the arguments to hook
# shellcheck disable=SC2068 # hook fails when quoting is used ("$arg[@]")
terraform providers lock ${args[@]}
terraform providers lock "${args[@]}"

# return exit code to common::per_dir_hook
exit_code=$?
Expand Down
19 changes: 10 additions & 9 deletions hooks/terraform_tflint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ function main {
common::export_provided_env_vars "${ENV_VARS[@]}"
common::parse_and_export_env_vars
# Support for setting PATH to repo root.
# shellcheck disable=SC2178 # It's the simplest syntax for that case
ARGS=${ARGS[*]/__GIT_WORKING_DIR__/$(pwd)\/}
for i in "${!ARGS[@]}"; do
ARGS[i]=${ARGS[i]/__GIT_WORKING_DIR__/$(pwd)\/}
done
# JFYI: tflint color already suppressed via PRE_COMMIT_COLOR=never

# Run `tflint --init` for check that plugins installed.
Expand All @@ -30,31 +31,31 @@ function main {
echo "${TFLINT_INIT}"
return ${exit_code}
}
# shellcheck disable=SC2128 # It's the simplest syntax for that case
common::per_dir_hook "$ARGS" "$HOOK_ID" "${FILES[@]}"

common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}"
}

#######################################################################
# Unique part of `common::per_dir_hook`. The function is executed in loop
# on each provided dir path. Run wrapped tool with specified arguments
# Arguments:
# args (string with array) arguments that configure wrapped tool behavior
# dir_path (string) PATH to dir relative to git repo root.
# Can be used in error logging
# args (array) arguments that configure wrapped tool behavior
# Outputs:
# If failed - print out hook checks status
#######################################################################
function per_dir_hook_unique_part {
local -r args="$1"
local -r dir_path="$2"
local -r dir_path="$1"
shift
local -a -r args=("$@")

# Print checked PATH **only** if TFLint have any messages
# shellcheck disable=SC2091,SC2068 # Suppress error output
$(tflint ${args[@]} 2>&1) 2> /dev/null || {
common::colorify "yellow" "TFLint in $dir_path/:"

# shellcheck disable=SC2068 # hook fails when quoting is used ("$arg[@]")
tflint ${args[@]}
tflint "${args[@]}"
}

# return exit code to common::per_dir_hook
Expand Down
28 changes: 13 additions & 15 deletions hooks/terraform_tfsec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,36 @@ function main {
common::export_provided_env_vars "${ENV_VARS[@]}"
common::parse_and_export_env_vars
# Support for setting PATH to repo root.
# shellcheck disable=SC2178 # It's the simplest syntax for that case
ARGS=${ARGS[*]/__GIT_WORKING_DIR__/$(pwd)\/}
for i in "${!ARGS[@]}"; do
ARGS[i]=${ARGS[i]/__GIT_WORKING_DIR__/$(pwd)\/}
done

# Suppress tfsec color
if [ "$PRE_COMMIT_COLOR" = "never" ]; then
# shellcheck disable=SC2178,SC2128 # It's the simplest syntax for that case
ARGS+=" --no-color"
ARGS+=("--no-color")
fi

# shellcheck disable=SC2128 # It's the simplest syntax for that case
common::per_dir_hook "$ARGS" "$HOOK_ID" "${FILES[@]}"
common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}"
}

#######################################################################
# Unique part of `common::per_dir_hook`. The function is executed in loop
# on each provided dir path. Run wrapped tool with specified arguments
# Arguments:
# args (string with array) arguments that configure wrapped tool behavior
# dir_path (string) PATH to dir relative to git repo root.
# Can be used in error logging
# args (array) arguments that configure wrapped tool behavior
# Outputs:
# If failed - print out hook checks status
#######################################################################
function per_dir_hook_unique_part {
local -r args="$1"
# shellcheck disable=SC2034 # Unused var.
local -r dir_path="$2"
local -r dir_path="$1"
shift
local -a -r args=("$@")

# pass the arguments to hook
# shellcheck disable=SC2068 # hook fails when quoting is used ("$arg[@]")
tfsec ${args[@]}
tfsec "${args[@]}"

# return exit code to common::per_dir_hook
local exit_code=$?
Expand All @@ -54,14 +53,13 @@ function per_dir_hook_unique_part {
# Unique part of `common::per_dir_hook`. The function is executed one time
# in the root git repo
# Arguments:
# args (string with array) arguments that configure wrapped tool behavior
# args (array) arguments that configure wrapped tool behavior
#######################################################################
function run_hook_on_whole_repo {
local -r args="$1"
local -a -r args=("$@")

# pass the arguments to hook
# shellcheck disable=SC2068 # hook fails when quoting is used ("$arg[@]")
tfsec "$(pwd)" ${args[@]}
tfsec "$(pwd)" "${args[@]}"

# return exit code to common::per_dir_hook
local exit_code=$?
Expand Down
14 changes: 6 additions & 8 deletions hooks/terraform_validate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function main {
ARGS+=("-no-color")
fi
# shellcheck disable=SC2153 # False positive
common::per_dir_hook "${ARGS[*]}" "$HOOK_ID" "${FILES[@]}"
common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}"
}

#######################################################################
Expand All @@ -31,17 +31,16 @@ function main {
# 2. Run `terraform validate`
# 3. If at least 1 check failed - change the exit code to non-zero
# Arguments:
# args (string with array) arguments that configure wrapped tool behavior
# dir_path (string) PATH to dir relative to git repo root.
# Can be used in error logging
# ENV_VARS (array) environment variables that will be used with
# `terraform` commands
# args (array) arguments that configure wrapped tool behavior
# Outputs:
# If failed - print out hook checks status
#######################################################################
function per_dir_hook_unique_part {
local -r args="$1"
local -r dir_path="$2"
local -r dir_path="$1"
shift
local -a -r args=("$@")

local exit_code
local validate_output
Expand All @@ -52,8 +51,7 @@ function per_dir_hook_unique_part {
}

# pass the arguments to hook
# shellcheck disable=SC2068 # hook fails when quoting is used ("$arg[@]")
validate_output=$(terraform validate ${args[@]} 2>&1)
validate_output=$(terraform validate "${args[@]}" 2>&1)
exit_code=$?

if [ $exit_code -ne 0 ]; then
Expand Down

0 comments on commit a446642

Please sign in to comment.