wormhole/scripts/lint.sh

156 lines
4.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# fail if any command fails
set -eo pipefail -o nounset
ROOT="$(dirname "$(dirname "$(realpath "$0")")")"
DOCKERFILE="$ROOT/scripts/Dockerfile.lint"
VALID_COMMANDS=("lint" "format")
SELF_ARGS_WITHOUT_DOCKER=""
GOIMPORTS_ARGS=""
GOLANGCI_LINT_ARGS=""
print_help() {
cat <<-EOF >&2
Usage: $(basename "$0") [-h] [-c] [-w] [-d] [-l] COMMAND
COMMAND can be one of: "${VALID_COMMANDS[*]}"
-h Print this help.
-c Run in docker and don't worry about dependencies
-w Automatically fix all formatting issues
-d Print diff for all formatting issues
-l List files that have formatting issues
-g Format output to be parsed by github actions
EOF
}
format(){
if [ "$GOIMPORTS_ARGS" == "" ]; then
GOIMPORTS_ARGS="-l"
fi
# only -l supports output as github action
if [ "$GITHUB_ACTION" == "true" ]; then
GOIMPORTS_ARGS="-l"
fi
# Check for dependencies
if ! command -v goimports >/dev/null 2>&1; then
printf "%s\n" "Require goimports. You can run this command in a docker container instead with '-c' and not worry about it or install it: \n\tgo install golang.org/x/tools/cmd/goimports@latest" >&2
exit 1
fi
# Use -exec because of pitfall #1 in http://mywiki.wooledge.org/BashPitfalls
GOFMT_OUTPUT="$(find "./sdk" "./node" "./wormchain" -type f -name '*.go' -not -path '*.pb.go' -print0 | xargs -r -0 goimports $GOIMPORTS_ARGS 2>&1)"
if [ -n "$GOFMT_OUTPUT" ]; then
if [ "$GITHUB_ACTION" == "true" ]; then
GOFMT_OUTPUT="$(echo "$GOFMT_OUTPUT" | awk '{print "::error file="$0"::Formatting error. Please format using ./scripts/lint.sh -d format."}')"
fi
echo "$GOFMT_OUTPUT" >&2
exit 1
fi
}
lint(){
# Check for dependencies
if ! command -v golangci-lint >/dev/null 2>&1; then
printf "%s\n" "Require golangci-lint. You can run this command in a docker container instead with '-c' and not worry about it or install it: https://golangci-lint.run/usage/install/"
fi
# Do the actual linting!
cd "$ROOT"/node
golangci-lint run --skip-dirs pkg/supervisor --timeout=10m --path-prefix=node $GOLANGCI_LINT_ARGS ./...
cd "${ROOT}/sdk"
golangci-lint run --timeout=10m $GOLANGCI_LINT_ARGS ./...
}
DOCKER="false"
GITHUB_ACTION="false"
while getopts 'cwdlgh' opt; do
case "$opt" in
c)
DOCKER="true"
;;
w)
GOIMPORTS_ARGS+="-w "
SELF_ARGS_WITHOUT_DOCKER+="-w "
;;
d)
GOIMPORTS_ARGS+="-d "
SELF_ARGS_WITHOUT_DOCKER+="-d "
;;
l)
GOIMPORTS_ARGS+="-l "
SELF_ARGS_WITHOUT_DOCKER+="-l "
;;
g)
GOLANGCI_LINT_ARGS+="--out-format=github-actions "
GITHUB_ACTION="true"
SELF_ARGS_WITHOUT_DOCKER+="-g "
;;
h)
print_help
exit 0
;;
?)
echo "Invalid command option." >&2
print_help
exit 1
;;
esac
done
shift $((OPTIND - 1))
if [ "$#" -ne "1" ]; then
echo "Need to specify COMMAND." >&2
print_help
exit 1
fi
COMMAND="$1"
if [[ ! " ${VALID_COMMANDS[*]} " == *" $COMMAND "* ]]; then
echo "Invalid command $COMMAND." >&2
print_help
exit 1
fi
# run this script recursively inside docker, if requested
if [ "$DOCKER" == "true" ]; then
# The easy thing to do here would be to use a bind mount to share the code with the container.
# But this doesn't work in scenarios where we are in a container already.
# But it's easy so we just won't support that case for now.
# If we wanted to support it, my idea would be to `docker run`, `docker cp`, `docker exec`, `docker rm`.
if grep -Esq 'docker|lxc|kubepods' /proc/1/cgroup; then
echo "Already running inside a container. This situation isn't supported (yet)." >&2
exit 1
fi
DOCKER_IMAGE="$(docker build -q -f "$DOCKERFILE" .)"
DOCKER_EXEC="./scripts/$(basename "$0")"
MOUNT="--mount=type=bind,target=/app,source=$PWD"
# for safety, mount as readonly unless -w flag was given
if ! [[ "$GOIMPORTS_ARGS" =~ "w" ]]; then
MOUNT+=",readonly"
fi
docker run --workdir /app "$MOUNT" "$DOCKER_IMAGE" "$DOCKER_EXEC" $SELF_ARGS_WITHOUT_DOCKER "$COMMAND"
exit "$?"
fi
case $COMMAND in
"lint")
lint
;;
"format")
format
;;
esac