2022-03-06 16:37:49 +00:00
|
|
|
#! /bin/bash
|
2020-10-04 17:34:15 +00:00
|
|
|
|
2021-06-01 16:12:17 +00:00
|
|
|
# version v0.2.0 unstable
|
|
|
|
# executed by Make during CI or manually
|
|
|
|
# task checks files against linting targets
|
2020-10-04 17:34:15 +00:00
|
|
|
|
2020-12-10 09:30:39 +00:00
|
|
|
SCRIPT="lint.sh"
|
2020-10-04 17:34:15 +00:00
|
|
|
|
2021-06-15 12:03:41 +00:00
|
|
|
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
2022-05-05 08:28:38 +00:00
|
|
|
REPO_ROOT=$(realpath "${SCRIPT_DIR}"/../../)
|
2021-06-07 12:58:34 +00:00
|
|
|
|
2021-12-19 10:56:22 +00:00
|
|
|
HADOLINT_VERSION=2.8.0
|
2021-06-07 12:58:34 +00:00
|
|
|
ECLINT_VERSION=2.3.5
|
2021-12-19 10:56:22 +00:00
|
|
|
SHELLCHECK_VERSION=0.8.0
|
2021-06-07 12:58:34 +00:00
|
|
|
|
2020-10-04 17:34:15 +00:00
|
|
|
set -eEuo pipefail
|
2021-12-19 10:56:22 +00:00
|
|
|
shopt -s inherit_errexit
|
2021-06-01 16:12:17 +00:00
|
|
|
trap '__log_err "${FUNCNAME[0]:-?}" "${BASH_COMMAND:-?}" ${LINENO:-?} ${?:-?}' ERR
|
2020-10-04 17:34:15 +00:00
|
|
|
|
|
|
|
function __log_err
|
|
|
|
{
|
2021-06-08 01:20:20 +00:00
|
|
|
printf "\n--- \e[1m\e[31mUNCHECKED ERROR\e[0m\n%s\n%s\n%s\n%s\n\n" \
|
|
|
|
" - script = ${SCRIPT:-${0}}" \
|
|
|
|
" - function = ${1} / ${2}" \
|
|
|
|
" - line = ${3}" \
|
|
|
|
" - exit code = ${4}"
|
2020-10-04 17:34:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function __log_info
|
|
|
|
{
|
2021-06-08 01:20:20 +00:00
|
|
|
printf "\n--- \e[34m%s\e[0m\n%s\n%s\n\n" \
|
2020-12-22 19:07:08 +00:00
|
|
|
"${SCRIPT:-${0}}" \
|
2021-06-08 01:20:20 +00:00
|
|
|
" - type = INFO" \
|
|
|
|
" - version = ${*}"
|
2020-10-04 17:34:15 +00:00
|
|
|
}
|
|
|
|
|
2020-12-10 09:30:39 +00:00
|
|
|
function __log_failure
|
2020-10-04 17:34:15 +00:00
|
|
|
{
|
2021-06-08 01:20:20 +00:00
|
|
|
printf "\n--- \e[91m%s\e[0m\n%s\n%s\n\n" \
|
2020-12-22 19:07:08 +00:00
|
|
|
"${SCRIPT:-${0}}" \
|
2021-06-08 01:20:20 +00:00
|
|
|
" - type = FAILURE" \
|
|
|
|
" - message = ${*:-errors encountered}"
|
2020-10-04 17:34:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function __log_success
|
|
|
|
{
|
2021-06-08 01:20:20 +00:00
|
|
|
printf "\n--- \e[32m%s\e[0m\n%s\n%s\n\n" \
|
2020-10-04 17:34:15 +00:00
|
|
|
"${SCRIPT}" \
|
2021-06-08 01:20:20 +00:00
|
|
|
" - type = SUCCESS" \
|
|
|
|
" - message = no errors detected"
|
2020-10-04 17:34:15 +00:00
|
|
|
}
|
|
|
|
|
2021-06-01 16:12:17 +00:00
|
|
|
function __in_path
|
|
|
|
{
|
2022-03-08 23:30:29 +00:00
|
|
|
command -v "${@}" &>/dev/null && return 0 ; return 1 ;
|
2021-06-01 16:12:17 +00:00
|
|
|
}
|
2020-10-04 17:34:15 +00:00
|
|
|
|
|
|
|
function _eclint
|
|
|
|
{
|
2020-10-21 16:16:32 +00:00
|
|
|
local SCRIPT='EDITORCONFIG LINTER'
|
2021-06-01 16:12:17 +00:00
|
|
|
|
2021-06-07 12:58:34 +00:00
|
|
|
if docker run --rm --tty \
|
|
|
|
--volume "${REPO_ROOT}:/ci:ro" \
|
|
|
|
--workdir "/ci" \
|
|
|
|
--name eclint \
|
|
|
|
"mstruebing/editorconfig-checker:${ECLINT_VERSION}" ec -config "/ci/test/linting/.ecrc.json"
|
2020-10-04 17:34:15 +00:00
|
|
|
then
|
2020-12-22 19:07:08 +00:00
|
|
|
__log_success
|
2020-10-04 17:34:15 +00:00
|
|
|
else
|
2020-12-10 09:30:39 +00:00
|
|
|
__log_failure
|
|
|
|
return 1
|
2020-10-04 17:34:15 +00:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hadolint
|
|
|
|
{
|
2020-10-21 16:16:32 +00:00
|
|
|
local SCRIPT='HADOLINT'
|
2020-10-04 17:34:15 +00:00
|
|
|
|
2021-06-07 12:58:34 +00:00
|
|
|
if docker run --rm --tty \
|
|
|
|
--volume "${REPO_ROOT}:/ci:ro" \
|
|
|
|
--workdir "/ci" \
|
|
|
|
"hadolint/hadolint:v${HADOLINT_VERSION}-alpine" hadolint --config "/ci/test/linting/.hadolint.yaml" Dockerfile
|
2020-10-04 17:34:15 +00:00
|
|
|
then
|
2020-12-22 19:07:08 +00:00
|
|
|
__log_success
|
2020-10-04 17:34:15 +00:00
|
|
|
else
|
2020-12-10 09:30:39 +00:00
|
|
|
__log_failure
|
|
|
|
return 1
|
2020-10-04 17:34:15 +00:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function _shellcheck
|
|
|
|
{
|
2020-10-21 16:16:32 +00:00
|
|
|
local SCRIPT='SHELLCHECK'
|
2021-11-20 20:33:49 +00:00
|
|
|
|
2021-06-07 12:58:34 +00:00
|
|
|
# File paths for shellcheck:
|
2022-05-05 08:28:38 +00:00
|
|
|
F_SH=$(find . -type f -iname '*.sh' \
|
2021-06-07 12:58:34 +00:00
|
|
|
-not -path './test/bats/*' \
|
|
|
|
-not -path './test/test_helper/*' \
|
|
|
|
-not -path './target/docker-configomat/*'
|
2022-05-05 08:28:38 +00:00
|
|
|
)
|
2021-06-07 12:58:34 +00:00
|
|
|
# shellcheck disable=SC2248
|
2022-05-05 08:28:38 +00:00
|
|
|
F_BIN=$(find 'target/bin' -type f -not -name '*.py')
|
|
|
|
F_BATS=$(find 'test' -maxdepth 1 -type f -iname '*.bats')
|
2021-06-07 12:58:34 +00:00
|
|
|
|
2021-11-20 20:33:49 +00:00
|
|
|
# This command is a bit easier to grok as multi-line.
|
|
|
|
# There is a `.shellcheckrc` file, but it's only supports half of the options below, thus kept as CLI:
|
|
|
|
# `SCRIPTDIR` is a special value that represents the path of the script being linted,
|
|
|
|
# all sourced scripts share the same SCRIPTDIR source-path of the original script being linted.
|
|
|
|
CMD_SHELLCHECK=(shellcheck
|
|
|
|
--external-sources
|
2021-06-07 12:58:34 +00:00
|
|
|
--check-sourced
|
|
|
|
--severity=style
|
|
|
|
--color=auto
|
|
|
|
--wiki-link-count=50
|
|
|
|
--enable=all
|
|
|
|
--exclude=SC2154
|
2021-12-19 10:56:22 +00:00
|
|
|
--exclude=SC2310
|
|
|
|
--exclude=SC2311
|
|
|
|
--exclude=SC2312
|
2021-06-07 12:58:34 +00:00
|
|
|
--source-path=SCRIPTDIR
|
|
|
|
"${F_SH} ${F_BIN} ${F_BATS}"
|
|
|
|
)
|
2021-11-20 20:33:49 +00:00
|
|
|
|
|
|
|
# The linter can reference additional source-path values declared in scripts,
|
|
|
|
# which in our case rarely benefit from extending from `SCRIPTDIR` and instead
|
|
|
|
# should use a relative path from the project root (mounted at `/ci`), eg `target/scripts/`.
|
|
|
|
# Note that `SCRIPTDIR` will strip a prefix variable for a source path, which can be useful
|
|
|
|
# if `SCRIPTDIR` would always be the same value, and combined with relative path via another
|
|
|
|
# `source-path=SCRIPTDIR/relative/path/to/scripts` in the .sh file.
|
|
|
|
# These source-path values can apply to the entire file (and sourced files) if not wrapped in a function scope.
|
|
|
|
# Otherwise it only applies to the line below it. You can declare multiple source-paths, they don't override the previous.
|
|
|
|
# `source=relative/path/to/file.sh` will check the source value in each source-path as well.
|
2021-06-07 12:58:34 +00:00
|
|
|
# shellcheck disable=SC2068
|
|
|
|
if docker run --rm --tty \
|
|
|
|
--volume "${REPO_ROOT}:/ci:ro" \
|
|
|
|
--workdir "/ci" \
|
|
|
|
"koalaman/shellcheck-alpine:v${SHELLCHECK_VERSION}" ${CMD_SHELLCHECK[@]}
|
2020-10-04 17:34:15 +00:00
|
|
|
then
|
2020-12-22 19:07:08 +00:00
|
|
|
__log_success
|
2021-06-07 12:58:34 +00:00
|
|
|
else
|
|
|
|
__log_failure
|
|
|
|
return 1
|
2020-10-04 17:34:15 +00:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2021-06-01 16:12:17 +00:00
|
|
|
function __main
|
2020-10-04 17:34:15 +00:00
|
|
|
{
|
2021-06-01 16:12:17 +00:00
|
|
|
case "${1:-}" in
|
2020-10-04 17:34:15 +00:00
|
|
|
'eclint' ) _eclint ;;
|
|
|
|
'hadolint' ) _hadolint ;;
|
|
|
|
'shellcheck' ) _shellcheck ;;
|
|
|
|
*)
|
2021-06-01 16:12:17 +00:00
|
|
|
__log_failure "'${1:-}' is not a command nor an option."
|
|
|
|
return 3
|
2020-10-04 17:34:15 +00:00
|
|
|
;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
2022-03-08 23:30:29 +00:00
|
|
|
__main "${@}" || exit ${?}
|