lint.sh 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #!/usr/bin/env bash
  2. # fail if any command fails
  3. set -eo pipefail -o nounset
  4. ROOT="$(dirname "$(dirname "$(realpath "$0")")")"
  5. DOCKERFILE="$ROOT/scripts/Dockerfile.lint"
  6. VALID_COMMANDS=("lint" "format")
  7. SELF_ARGS_WITHOUT_DOCKER=""
  8. GOIMPORTS_ARGS=""
  9. GOLANGCI_LINT_ARGS=""
  10. print_help() {
  11. cat <<-EOF >&2
  12. Usage: $(basename "$0") [-h] [-c] [-w] [-d] [-l] COMMAND
  13. COMMAND can be one of: "${VALID_COMMANDS[*]}"
  14. -h Print this help.
  15. -c Run in docker and don't worry about dependencies
  16. -w Automatically fix all formatting issues
  17. -d Print diff for all formatting issues
  18. -l List files that have formatting issues
  19. -g Format output to be parsed by github actions
  20. EOF
  21. }
  22. format(){
  23. if [ "$GOIMPORTS_ARGS" == "" ]; then
  24. GOIMPORTS_ARGS="-l"
  25. fi
  26. # only -l supports output as github action
  27. if [ "$GITHUB_ACTION" == "true" ]; then
  28. GOIMPORTS_ARGS="-l"
  29. fi
  30. # Check for dependencies
  31. if ! command -v goimports >/dev/null 2>&1; then
  32. 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
  33. exit 1
  34. fi
  35. # Use -exec because of pitfall #1 in http://mywiki.wooledge.org/BashPitfalls
  36. GOFMT_OUTPUT="$(find "./sdk" "./node" "./wormchain" -type f -name '*.go' -not -path '*.pb.go' -print0 | xargs -r -0 goimports $GOIMPORTS_ARGS 2>&1)"
  37. if [ -n "$GOFMT_OUTPUT" ]; then
  38. if [ "$GITHUB_ACTION" == "true" ]; then
  39. GOFMT_OUTPUT="$(echo "$GOFMT_OUTPUT" | awk '{print "::error file="$0"::Formatting error. Please format using ./scripts/lint.sh -d format."}')"
  40. fi
  41. echo "$GOFMT_OUTPUT" >&2
  42. exit 1
  43. fi
  44. }
  45. lint(){
  46. # Check for dependencies
  47. if ! command -v golangci-lint >/dev/null 2>&1; then
  48. 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/"
  49. fi
  50. # Do the actual linting!
  51. cd "$ROOT"/node
  52. golangci-lint run --skip-dirs pkg/supervisor --timeout=10m --path-prefix=node $GOLANGCI_LINT_ARGS ./...
  53. cd "${ROOT}/sdk"
  54. golangci-lint run --timeout=10m $GOLANGCI_LINT_ARGS ./...
  55. }
  56. DOCKER="false"
  57. GITHUB_ACTION="false"
  58. while getopts 'cwdlgh' opt; do
  59. case "$opt" in
  60. c)
  61. DOCKER="true"
  62. ;;
  63. w)
  64. GOIMPORTS_ARGS+="-w "
  65. SELF_ARGS_WITHOUT_DOCKER+="-w "
  66. ;;
  67. d)
  68. GOIMPORTS_ARGS+="-d "
  69. SELF_ARGS_WITHOUT_DOCKER+="-d "
  70. ;;
  71. l)
  72. GOIMPORTS_ARGS+="-l "
  73. SELF_ARGS_WITHOUT_DOCKER+="-l "
  74. ;;
  75. g)
  76. GOLANGCI_LINT_ARGS+="--out-format=github-actions "
  77. GITHUB_ACTION="true"
  78. SELF_ARGS_WITHOUT_DOCKER+="-g "
  79. ;;
  80. h)
  81. print_help
  82. exit 0
  83. ;;
  84. ?)
  85. echo "Invalid command option." >&2
  86. print_help
  87. exit 1
  88. ;;
  89. esac
  90. done
  91. shift $((OPTIND - 1))
  92. if [ "$#" -ne "1" ]; then
  93. echo "Need to specify COMMAND." >&2
  94. print_help
  95. exit 1
  96. fi
  97. COMMAND="$1"
  98. if [[ ! " ${VALID_COMMANDS[*]} " == *" $COMMAND "* ]]; then
  99. echo "Invalid command $COMMAND." >&2
  100. print_help
  101. exit 1
  102. fi
  103. # run this script recursively inside docker, if requested
  104. if [ "$DOCKER" == "true" ]; then
  105. # The easy thing to do here would be to use a bind mount to share the code with the container.
  106. # But this doesn't work in scenarios where we are in a container already.
  107. # But it's easy so we just won't support that case for now.
  108. # If we wanted to support it, my idea would be to `docker run`, `docker cp`, `docker exec`, `docker rm`.
  109. if grep -Esq 'docker|lxc|kubepods' /proc/1/cgroup; then
  110. echo "Already running inside a container. This situation isn't supported (yet)." >&2
  111. exit 1
  112. fi
  113. DOCKER_IMAGE="$(docker build -q -f "$DOCKERFILE" .)"
  114. DOCKER_EXEC="./scripts/$(basename "$0")"
  115. MOUNT="--mount=type=bind,target=/app,source=$PWD"
  116. # for safety, mount as readonly unless -w flag was given
  117. if ! [[ "$GOIMPORTS_ARGS" =~ "w" ]]; then
  118. MOUNT+=",readonly"
  119. fi
  120. docker run --workdir /app "$MOUNT" "$DOCKER_IMAGE" "$DOCKER_EXEC" $SELF_ARGS_WITHOUT_DOCKER "$COMMAND"
  121. exit "$?"
  122. fi
  123. case $COMMAND in
  124. "lint")
  125. lint
  126. ;;
  127. "format")
  128. format
  129. ;;
  130. esac