From 46b79d471651cb774ce1e51fad1a2bbbaf677ce2 Mon Sep 17 00:00:00 2001 From: Cosmin Truta Date: Thu, 8 Feb 2024 21:37:42 +0200 Subject: [PATCH] ci: Update and rename ci_lint_ci.sh to ci_lint.sh; update .shellcheckrc The ci_lint.sh program can now lint the entire libpng source tree. --- ci/.shellcheckrc | 4 ++ ci/ci_lint.sh | 135 +++++++++++++++++++++++++++++++++++++++++++++++ ci/ci_lint_ci.sh | 90 ------------------------------- 3 files changed, 139 insertions(+), 90 deletions(-) create mode 100755 ci/ci_lint.sh delete mode 100755 ci/ci_lint_ci.sh diff --git a/ci/.shellcheckrc b/ci/.shellcheckrc index 0260dcca3..051d55155 100644 --- a/ci/.shellcheckrc +++ b/ci/.shellcheckrc @@ -1,3 +1,7 @@ +# Disable the "expressions don't expand in single quotes, use double quotes" +# advice. We need the regular expressions to remain uninterpolated. +disable=SC2016 + # Disable the "variable appears unused" warning caused by the use of getopts # with an obligatory (but unused) variable name in the main function. disable=SC2034 diff --git a/ci/ci_lint.sh b/ci/ci_lint.sh new file mode 100755 index 000000000..9b9dc6bf2 --- /dev/null +++ b/ci/ci_lint.sh @@ -0,0 +1,135 @@ +#!/usr/bin/env bash +set -o errexit -o pipefail -o posix + +# Copyright (c) 2019-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +# shellcheck source="ci/lib/ci.lib.sh" +source "$(dirname "$0")/lib/ci.lib.sh" +cd "$CI_TOPLEVEL_DIR" + +# Initialize the global constants CI_{...}{CHECK,CHECKER,LINT}. +CI_SHELLCHECK="${CI_SHELLCHECK:-shellcheck}" +CI_EDITORCONFIG_CHECKER="${CI_EDITORCONFIG_CHECKER:-editorconfig-checker}" +CI_YAMLLINT="${CI_YAMLLINT:-yamllint}" + +# Initialize the global lint counter. +CI_LINT_COUNTER=0 + +function ci_init_lint { + ci_info "## START OF LINTING ##" + local my_program + # Complete the initialization of CI_SHELLCHECK. + # Set it to the empty string if the shellcheck program is unavailable. + my_program="$(command -v "$CI_SHELLCHECK")" || { + ci_warn "program not found: '$CI_SHELLCHECK'" + } + CI_SHELLCHECK="$my_program" + # Complete the initialization of CI_EDITORCONFIG_CHECKER. + # Set it to the empty string if the editorconfig-checker program is unavailable. + my_program="$(command -v "$CI_EDITORCONFIG_CHECKER")" || { + ci_warn "program not found: '$CI_EDITORCONFIG_CHECKER'" + } + CI_EDITORCONFIG_CHECKER="$my_program" + # Complete the initialization of CI_YAMLLINT. + # Set it to the empty string if the yamllint program is unavailable. + my_program="$(command -v "$CI_YAMLLINT")" || { + ci_warn "program not found: '$CI_YAMLLINT'" + } + CI_YAMLLINT="$my_program" +} + +function ci_finish_lint { + ci_info "## END OF LINTING ##" + if [[ $CI_LINT_COUNTER -eq 0 ]] + then + ci_info "success!" + return 0 + else + ci_warn "$CI_LINT_COUNTER failure(s)" + return 1 + fi +} + +function ci_lint_ci_scripts { + [[ -x $CI_SHELLCHECK ]] || { + ci_warn "## NOT LINTING: CI scripts ##" + return 0 + } + ci_info "## LINTING: CI scripts ##" + local my_file + ci_spawn "$CI_SHELLCHECK" --version + for my_file in ci/*.sh + do + ci_spawn "$CI_SHELLCHECK" -x "$my_file" || { + CI_LINT_COUNTER=$((CI_LINT_COUNTER + 1)) + } + done +} + +function ci_lint_text_files { + [[ -x $CI_EDITORCONFIG_CHECKER ]] || { + ci_warn "## NOT LINTING: text files ##" + return 0 + } + ci_info "## LINTING: text files ##" + local my_file + ci_spawn "$CI_EDITORCONFIG_CHECKER" --version + ci_spawn "$CI_EDITORCONFIG_CHECKER" || { + CI_LINT_COUNTER=$((CI_LINT_COUNTER + 1)) + } +} + +function ci_lint_yaml_files { + [[ -x $CI_YAMLLINT ]] || { + ci_warn "## NOT LINTING: YAML files ##" + return 0 + } + ci_info "## LINTING: YAML files ##" + local my_file + ci_spawn "$CI_YAMLLINT" --version + for my_file in .*.yml + do + ci_spawn "$CI_YAMLLINT" --strict "$my_file" || { + CI_LINT_COUNTER=$((CI_LINT_COUNTER + 1)) + } + done +} + +function ci_lint { + ci_init_lint + ci_lint_ci_scripts + ci_lint_text_files + ci_lint_yaml_files + # TODO: ci_lint_png_files, etc. + ci_finish_lint +} + +function usage { + echo "usage: $CI_SCRIPT_NAME []" + echo "options: -?|-h|--help" + exit "${@:-0}" +} + +function main { + local opt + while getopts ":" opt + do + # This ain't a while-loop. It only pretends to be. + [[ $1 == -[?h]* || $1 == --help || $1 == --help=* ]] && usage 0 + ci_err "unknown option: '$1'" + done + shift $((OPTIND - 1)) + [[ $# -eq 0 ]] || { + echo >&2 "error: unexpected argument: '$1'" + usage 2 + } + # And... go! + ci_lint +} + +main "$@" diff --git a/ci/ci_lint_ci.sh b/ci/ci_lint_ci.sh deleted file mode 100755 index 60b7faf30..000000000 --- a/ci/ci_lint_ci.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env bash -set -e - -# Copyright (c) 2019-2024 Cosmin Truta. -# -# Use, modification and distribution are subject to the MIT License. -# Please see the accompanying file LICENSE_MIT.txt -# -# SPDX-License-Identifier: MIT - -# shellcheck source="ci/lib/ci.lib.sh" -source "$(dirname "$0")/lib/ci.lib.sh" -cd "$CI_TOPLEVEL_DIR" - -CI_SHELLCHECK="$(command -v shellcheck || true)" -CI_YAMLLINT="$(command -v yamllint || true)" -CI_LINT_COUNTER=0 - -function ci_lint_ci_config_files { - ci_info "linting: CI config files" - local MY_FILE - if [[ -x $CI_YAMLLINT ]] - then - ci_spawn "$CI_YAMLLINT" --version - for MY_FILE in "$CI_TOPLEVEL_DIR"/.*.yml - do - ci_spawn "$CI_YAMLLINT" --strict "$MY_FILE" || { - CI_LINT_COUNTER=$((CI_LINT_COUNTER + 1)) - } - done - else - ci_warn "program not found: 'yamllint'; skipping checks" - fi -} - -function ci_lint_ci_scripts { - ci_info "linting: CI scripts" - local MY_FILE - if [[ -x $CI_SHELLCHECK ]] - then - ci_spawn "$CI_SHELLCHECK" --version - for MY_FILE in "$CI_SCRIPT_DIR"/*.sh - do - ci_spawn "$CI_SHELLCHECK" -x "$MY_FILE" || { - CI_LINT_COUNTER=$((CI_LINT_COUNTER + 1)) - } - done - else - ci_warn "program not found: 'shellcheck'; skipping checks" - fi -} - -function ci_lint_ci_scripts_license { - ci_info "linting: CI scripts license" - ci_spawn grep -F "MIT License" ci/LICENSE_MIT.txt || { - ci_warn "bad or missing CI license file: '$CI_SCRIPT_DIR/LICENSE_MIT.txt'" - CI_LINT_COUNTER=$((CI_LINT_COUNTER + 1)) - } -} - -function usage { - echo "usage: $CI_SCRIPT_NAME" - exit 0 -} - -function main { - local opt - while getopts ":" opt - do - # This ain't a while-loop. It only pretends to be. - [[ $1 == -[?h]* || $1 == --help ]] && usage - ci_err "unknown option: '$1'" - done - shift $((OPTIND - 1)) - # And... go! - [[ $# -eq 0 ]] || ci_err "unexpected argument: '$1'" - ci_lint_ci_config_files - ci_lint_ci_scripts - ci_lint_ci_scripts_license - if [[ $CI_LINT_COUNTER -eq 0 ]] - then - ci_info "success!" - exit 0 - else - ci_info "failed on $CI_LINT_COUNTER file(s)" - exit 1 - fi -} - -main "$@"