vet.sh 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #!/bin/bash
  2. set -ex # Exit on error; debugging enabled.
  3. set -o pipefail # Fail a pipe if any sub-command fails.
  4. # not makes sure the command passed to it does not exit with a return code of 0.
  5. not() {
  6. # This is required instead of the earlier (! $COMMAND) because subshells and
  7. # pipefail don't work the same on Darwin as in Linux.
  8. ! "$@"
  9. }
  10. die() {
  11. echo "$@" >&2
  12. exit 1
  13. }
  14. fail_on_output() {
  15. tee /dev/stderr | not read
  16. }
  17. # Check to make sure it's safe to modify the user's git repo.
  18. git status --porcelain | fail_on_output
  19. # Undo any edits made by this script.
  20. cleanup() {
  21. git reset --hard HEAD
  22. }
  23. trap cleanup EXIT
  24. PATH="${HOME}/go/bin:${GOROOT}/bin:${PATH}"
  25. go version
  26. if [[ "$1" = "-install" ]]; then
  27. # Install the pinned versions as defined in module tools.
  28. pushd ./test/tools
  29. go install \
  30. golang.org/x/lint/golint \
  31. golang.org/x/tools/cmd/goimports \
  32. honnef.co/go/tools/cmd/staticcheck \
  33. github.com/client9/misspell/cmd/misspell
  34. popd
  35. if [[ -z "${VET_SKIP_PROTO}" ]]; then
  36. if [[ "${GITHUB_ACTIONS}" = "true" ]]; then
  37. PROTOBUF_VERSION=22.0 # a.k.a v4.22.0 in pb.go files.
  38. PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
  39. pushd /home/runner/go
  40. wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME}
  41. unzip ${PROTOC_FILENAME}
  42. bin/protoc --version
  43. popd
  44. elif not which protoc > /dev/null; then
  45. die "Please install protoc into your path"
  46. fi
  47. fi
  48. exit 0
  49. elif [[ "$#" -ne 0 ]]; then
  50. die "Unknown argument(s): $*"
  51. fi
  52. # - Check that generated proto files are up to date.
  53. if [[ -z "${VET_SKIP_PROTO}" ]]; then
  54. make proto && git status --porcelain 2>&1 | fail_on_output || \
  55. (git status; git --no-pager diff; exit 1)
  56. fi
  57. if [[ -n "${VET_ONLY_PROTO}" ]]; then
  58. exit 0
  59. fi
  60. # - Ensure all source files contain a copyright message.
  61. # (Done in two parts because Darwin "git grep" has broken support for compound
  62. # exclusion matches.)
  63. (grep -L "DO NOT EDIT" $(git grep -L "\(Copyright [0-9]\{4,\} gRPC authors\)" -- '*.go') || true) | fail_on_output
  64. # - Make sure all tests in grpc and grpc/test use leakcheck via Teardown.
  65. not grep 'func Test[^(]' *_test.go
  66. not grep 'func Test[^(]' test/*.go
  67. # - Do not import x/net/context.
  68. not git grep -l 'x/net/context' -- "*.go"
  69. # - Do not import math/rand for real library code. Use internal/grpcrand for
  70. # thread safety.
  71. git grep -l '"math/rand"' -- "*.go" 2>&1 | not grep -v '^examples\|^stress\|grpcrand\|^benchmark\|wrr_test'
  72. # - Do not call grpclog directly. Use grpclog.Component instead.
  73. git grep -l -e 'grpclog.I' --or -e 'grpclog.W' --or -e 'grpclog.E' --or -e 'grpclog.F' --or -e 'grpclog.V' -- "*.go" | not grep -v '^grpclog/component.go\|^internal/grpctest/tlogger_test.go'
  74. # - Ensure all ptypes proto packages are renamed when importing.
  75. not git grep "\(import \|^\s*\)\"github.com/golang/protobuf/ptypes/" -- "*.go"
  76. # - Ensure all xds proto imports are renamed to *pb or *grpc.
  77. git grep '"github.com/envoyproxy/go-control-plane/envoy' -- '*.go' ':(exclude)*.pb.go' | not grep -v 'pb "\|grpc "'
  78. misspell -error .
  79. # - gofmt, goimports, golint (with exceptions for generated code), go vet,
  80. # go mod tidy.
  81. # Perform these checks on each module inside gRPC.
  82. for MOD_FILE in $(find . -name 'go.mod'); do
  83. MOD_DIR=$(dirname ${MOD_FILE})
  84. pushd ${MOD_DIR}
  85. go vet -all ./... | fail_on_output
  86. gofmt -s -d -l . 2>&1 | fail_on_output
  87. goimports -l . 2>&1 | not grep -vE "\.pb\.go"
  88. golint ./... 2>&1 | not grep -vE "/grpc_testing_not_regenerate/.*\.pb\.go:"
  89. go mod tidy -compat=1.17
  90. git status --porcelain 2>&1 | fail_on_output || \
  91. (git status; git --no-pager diff; exit 1)
  92. popd
  93. done
  94. # - Collection of static analysis checks
  95. #
  96. # TODO(dfawley): don't use deprecated functions in examples or first-party
  97. # plugins.
  98. # TODO(dfawley): enable ST1019 (duplicate imports) but allow for protobufs.
  99. SC_OUT="$(mktemp)"
  100. staticcheck -go 1.19 -checks 'inherit,-ST1015,-ST1019,-SA1019' ./... > "${SC_OUT}" || true
  101. # Error if anything other than deprecation warnings are printed.
  102. not grep -v "is deprecated:.*SA1019" "${SC_OUT}"
  103. # Only ignore the following deprecated types/fields/functions.
  104. not grep -Fv '.CredsBundle
  105. .HeaderMap
  106. .Metadata is deprecated: use Attributes
  107. .NewAddress
  108. .NewServiceConfig
  109. .Type is deprecated: use Attributes
  110. BuildVersion is deprecated
  111. balancer.ErrTransientFailure
  112. balancer.Picker
  113. extDesc.Filename is deprecated
  114. github.com/golang/protobuf/jsonpb is deprecated
  115. grpc.CallCustomCodec
  116. grpc.Code
  117. grpc.Compressor
  118. grpc.CustomCodec
  119. grpc.Decompressor
  120. grpc.MaxMsgSize
  121. grpc.MethodConfig
  122. grpc.NewGZIPCompressor
  123. grpc.NewGZIPDecompressor
  124. grpc.RPCCompressor
  125. grpc.RPCDecompressor
  126. grpc.ServiceConfig
  127. grpc.WithCompressor
  128. grpc.WithDecompressor
  129. grpc.WithDialer
  130. grpc.WithMaxMsgSize
  131. grpc.WithServiceConfig
  132. grpc.WithTimeout
  133. http.CloseNotifier
  134. info.SecurityVersion
  135. proto is deprecated
  136. proto.InternalMessageInfo is deprecated
  137. proto.EnumName is deprecated
  138. proto.ErrInternalBadWireType is deprecated
  139. proto.FileDescriptor is deprecated
  140. proto.Marshaler is deprecated
  141. proto.MessageType is deprecated
  142. proto.RegisterEnum is deprecated
  143. proto.RegisterFile is deprecated
  144. proto.RegisterType is deprecated
  145. proto.RegisterExtension is deprecated
  146. proto.RegisteredExtension is deprecated
  147. proto.RegisteredExtensions is deprecated
  148. proto.RegisterMapType is deprecated
  149. proto.Unmarshaler is deprecated
  150. resolver.Backend
  151. resolver.GRPCLB
  152. Target is deprecated: Use the Target field in the BuildOptions instead.
  153. xxx_messageInfo_
  154. ' "${SC_OUT}"
  155. # - special golint on package comments.
  156. lint_package_comment_per_package() {
  157. # Number of files in this go package.
  158. fileCount=$(go list -f '{{len .GoFiles}}' $1)
  159. if [ ${fileCount} -eq 0 ]; then
  160. return 0
  161. fi
  162. # Number of package errors generated by golint.
  163. lintPackageCommentErrorsCount=$(golint --min_confidence 0 $1 | grep -c "should have a package comment")
  164. # golint complains about every file that's missing the package comment. If the
  165. # number of files for this package is greater than the number of errors, there's
  166. # at least one file with package comment, good. Otherwise, fail.
  167. if [ ${fileCount} -le ${lintPackageCommentErrorsCount} ]; then
  168. echo "Package $1 (with ${fileCount} files) is missing package comment"
  169. return 1
  170. fi
  171. }
  172. lint_package_comment() {
  173. set +ex
  174. count=0
  175. for i in $(go list ./...); do
  176. lint_package_comment_per_package "$i"
  177. ((count += $?))
  178. done
  179. set -ex
  180. return $count
  181. }
  182. lint_package_comment
  183. echo SUCCESS