k8s.io/registry.k8s.io@v0.3.1/hack/make-rules/shellcheck.sh (about)

     1  #!/usr/bin/env bash
     2  
     3  # Copyright 2022 The Kubernetes Authors.
     4  #
     5  # Licensed under the Apache License, Version 2.0 (the "License");
     6  # you may not use this file except in compliance with the License.
     7  # You may obtain a copy of the License at
     8  #
     9  #     http://www.apache.org/licenses/LICENSE-2.0
    10  #
    11  # Unless required by applicable law or agreed to in writing, software
    12  # distributed under the License is distributed on an "AS IS" BASIS,
    13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  # See the License for the specific language governing permissions and
    15  # limitations under the License.
    16  
    17  # CI script to run shellcheck
    18  set -o errexit
    19  set -o nounset
    20  set -o pipefail
    21  
    22  # cd to the repo root
    23  REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." &> /dev/null && pwd -P)"
    24  cd "${REPO_ROOT}"
    25  
    26  # we will be installing under bin_dir if necessary, and re-using if possible
    27  bin_dir="${REPO_ROOT}/bin"
    28  export PATH="${bin_dir}:${PATH}"
    29  
    30  # required version for this script, if not installed on the host already we will
    31  # install it under bin/
    32  SHELLCHECK_VERSION="0.8.0"
    33  
    34  # Find all shell scripts excluding:
    35  # - Anything git-ignored - No need to lint untracked files.
    36  # - ./.git/* - Ignore anything in the git object store.
    37  # - ./hack/third_party/* - Ignore vendored scripts.
    38  # - ./bin/* - No need to lint output directories.
    39  all_shell_scripts=()
    40  while IFS=$'\n' read -r script;
    41    do git check-ignore -q "$script" || all_shell_scripts+=("$script");
    42  done < <(grep -irl '#!.*sh' . | grep -Ev '^(\./\.git/)|(\./hack/third_party/)|(\./bin/)')
    43  
    44  # common arguments we'll pass to shellcheck
    45  SHELLCHECK_OPTIONS=(
    46    # allow following sourced files that are not specified in the command,
    47    # we need this because we specify one file at a time in order to trivially
    48    # detect which files are failing
    49    '--external-sources'
    50    # disabled lint codes
    51    # 2330 - disabled due to https://github.com/koalaman/shellcheck/issues/1162
    52    '--exclude=2230'
    53    # 2126 - disabled because grep -c exits error when there are zero matches,
    54    # unlike grep | wc -l
    55    '--exclude=2126'
    56    # set colorized output
    57    '--color=auto'
    58  )
    59  
    60  # detect if the host machine has the required shellcheck version installed
    61  # if so, we will use that instead.
    62  HAVE_SHELLCHECK=false
    63  if command -v shellcheck &>/dev/null; then
    64    detected_version="$(shellcheck --version | grep 'version: .*')"
    65    if [[ "${detected_version}" = "version: ${SHELLCHECK_VERSION}" ]]; then
    66      HAVE_SHELLCHECK=true
    67    fi
    68  fi
    69  
    70  # install shellcheck to bin/ if missing or the wrong version
    71  if ! ${HAVE_SHELLCHECK}; then
    72    echo "Installing shellcheck v${SHELLCHECK_VERSION} under bin/ ..." >&2
    73    # in CI we can install xz so we can untar the upstream release
    74    # otherwise tell the user they must install xz or shellcheck
    75    if ! command -v xz &>/dev/null; then
    76      if [[ -n "${PROW_JOB_ID}" ]]; then
    77        export DEBIAN_FRONTEND=noninteractive
    78        apt-get -qq update
    79        DEBCONF_NOWARNINGS="yes" apt-get -qq install --no-install-recommends xz-utils >/dev/null
    80      else
    81        echo "xz is required to install shellcheck in bin/!" >&2
    82        echo "either install xz or install shellcheck v${SHELLCHECK_VERSION}" >&2
    83        exit 1
    84      fi
    85    fi
    86    os=$(uname | tr '[:upper:]' '[:lower:]')
    87    arch=$(uname -m)
    88    # TODO: shellcheck currently only has x86_64 binaries on macOS, but those will work on M1
    89    if [[ "${os}" == 'darwin' ]]; then
    90      arch='x86_64'
    91    fi
    92    mkdir -p "${bin_dir}"
    93    # download and untar shellcheck into bin_dir
    94    curl -sSL "https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION?}/shellcheck-v${SHELLCHECK_VERSION?}.${os}.${arch}.tar.xz" \
    95      | tar -C "${bin_dir}" --strip-components=1 -xJ -f - "shellcheck-v${SHELLCHECK_VERSION}/shellcheck"
    96    # debug newly setup version
    97    shellcheck --version >&2
    98  fi
    99  
   100  
   101  # lint all scripts
   102  res=0
   103  shellcheck "${SHELLCHECK_OPTIONS[@]}" "${all_shell_scripts[@]}" >&2 || res=$?
   104  # print a message based on the result
   105  if [ $res -eq 0 ]; then
   106    echo 'Congratulations! All shell files are passing lint :-)'
   107  else
   108    {
   109      echo
   110      echo 'Please review the above warnings. You can test via "./hack/verify/shellcheck.sh"'
   111      echo 'If the above warnings do not make sense, you can exempt this warning with a comment'
   112      echo ' (if your reviewer is okay with it).'
   113      echo 'In general please prefer to fix the error, we have already disabled specific lints'
   114      echo ' that the project chooses to ignore.'
   115      echo 'See: https://github.com/koalaman/shellcheck/wiki/Ignore#ignoring-one-specific-instance-in-a-file'
   116      echo
   117    } >&2
   118    exit 1
   119  fi
   120  
   121  # preserve the result
   122  exit $res