github.com/MetalBlockchain/metalgo@v1.11.9/scripts/lint.sh (about) 1 #!/usr/bin/env bash 2 3 set -euo pipefail 4 5 if ! [[ "$0" =~ scripts/lint.sh ]]; then 6 echo "must be run from repository root" 7 exit 255 8 fi 9 10 # The -P option is not supported by the grep version installed by 11 # default on macos. Since `-o errexit` is ignored in an if 12 # conditional, triggering the problem here ensures script failure when 13 # using an unsupported version of grep. 14 grep -P 'lint.sh' scripts/lint.sh &> /dev/null || (\ 15 >&2 echo "error: This script requires a recent version of gnu grep.";\ 16 >&2 echo " On macos, gnu grep can be installed with 'brew install grep'.";\ 17 >&2 echo " It will also be necessary to ensure that gnu grep is available in the path.";\ 18 exit 255 ) 19 20 if [ "$#" -eq 0 ]; then 21 # by default, check all source code 22 # to test only "snow" package 23 # ./scripts/lint.sh ./snow/... 24 TARGET="./..." 25 else 26 TARGET="${1}" 27 fi 28 29 # by default, "./scripts/lint.sh" runs all lint tests 30 # to run only "license_header" test 31 # TESTS='license_header' ./scripts/lint.sh 32 TESTS=${TESTS:-"golangci_lint license_header require_error_is_no_funcs_as_params single_import interface_compliance_nil require_no_error_inline_func"} 33 34 function test_golangci_lint { 35 go install -v github.com/golangci/golangci-lint/cmd/golangci-lint@v1.58.1 36 golangci-lint run --config .golangci.yml 37 } 38 39 # automatically checks license headers 40 # to modify the file headers (if missing), remove "--verify" flag 41 # TESTS='license_header' ADDLICENSE_FLAGS="--debug" ./scripts/lint.sh 42 _addlicense_flags=${ADDLICENSE_FLAGS:-"--verify --debug"} 43 function test_license_header { 44 go install -v github.com/palantir/go-license@v1.25.0 45 local files=() 46 while IFS= read -r line; do files+=("$line"); done < <(find . -type f -name '*.go' ! -name '*.pb.go' ! -name 'mock_*.go') 47 48 # shellcheck disable=SC2086 49 go-license \ 50 --config=./header.yml \ 51 ${_addlicense_flags} \ 52 "${files[@]}" 53 } 54 55 function test_single_import { 56 if grep -R -zo -P 'import \(\n\t".*"\n\)' .; then 57 echo "" 58 return 1 59 fi 60 } 61 62 function test_require_error_is_no_funcs_as_params { 63 if grep -R -zo -P 'require.ErrorIs\(.+?\)[^\n]*\)\n' .; then 64 echo "" 65 return 1 66 fi 67 } 68 69 function test_require_no_error_inline_func { 70 if grep -R -zo -P '\t+err :?= ((?!require|if).|\n)*require\.NoError\((t, )?err\)' .; then 71 echo "" 72 echo "Checking that a function with a single error return doesn't error should be done in-line." 73 echo "" 74 return 1 75 fi 76 } 77 78 # Ref: https://go.dev/doc/effective_go#blank_implements 79 function test_interface_compliance_nil { 80 if grep -R -o -P '_ .+? = &.+?\{\}' .; then 81 echo "" 82 echo "Interface compliance checks need to be of the form:" 83 echo " var _ json.Marshaler = (*RawMessage)(nil)" 84 echo "" 85 return 1 86 fi 87 } 88 89 function run { 90 local test="${1}" 91 shift 1 92 echo "START: '${test}' at $(date)" 93 if "test_${test}" "$@" ; then 94 echo "SUCCESS: '${test}' completed at $(date)" 95 else 96 echo "FAIL: '${test}' failed at $(date)" 97 exit 255 98 fi 99 } 100 101 echo "Running '$TESTS' at: $(date)" 102 for test in $TESTS; do 103 run "${test}" "${TARGET}" 104 done 105 106 echo "ALL SUCCESS!"