VOL-4846 - copyrights vs linthelm.sh
NOP Copyright notice update job failed due to peripheral chart problems.
Problem: reactionary failure, no local helm linting.
Jenkins performs late checks unavailable to local devs.
chart_version_check.sh
----------------------
o String based detection converted to array operations
- Greatly simplified script logic.
o Use readarray to capture command out:
- Safer I/O and array manipulation supported.
o Construct and test @modified_files early to simplify logic:
- Sonarqube exclusions removed.
- External sed calls formatting lists of display strings.
o Version string check moved into a named function.
o Replace "echo val |" with <<< (here string) and builtins:
- Avoid external process overhead (dirname, sed).
- Avoid potential failure sources.
Replace global var use with "pushd ${WORKSPACE}":
o Simplify: String path ops are normalized on dot.
o Global var references and use reduced.
Format report output:
o Insert whitespace for readability.
o More context for errors reported.
o Display a summary of errors at the end.
o Library function added to format report lines.
o A sample of genreated log output appended at the end.
Bump copyright notice on all scripts.
Change-Id: Iec939fdd8f6e0fe4ff3af381aa5d31785cc6b912
diff --git a/chart_version_check.sh b/chart_version_check.sh
index 265a817..455e225 100755
--- a/chart_version_check.sh
+++ b/chart_version_check.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-
-# Copyright 2018-present Open Networking Foundation
+# ---------------------------------------------------------------------------
+# Copyright 2018-2022 Open Networking Foundation (ONF) and the ONF Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -10,126 +10,407 @@
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# WITHOUT WARRANTIESS OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-
+# ---------------------------------------------------------------------------
# chart_version_check.sh
# checks that changes to a chart include a change to the chart version
+# ---------------------------------------------------------------------------
set -u
+# set -euo pipefail
-echo "# chart_version_check.sh, using git: $(git --version) #"
+##-------------------##
+##---] GLOBALS [---##
+##-------------------##
+declare -i -g force_fail=0
+declare -a -g error_stream=()
-# Collect success/failure, and list/types of failures
-fail_version=0
-failed_charts=""
+# declare -A -g ARGV=() # ARGV['debug']=1
+# declare -i -g debug=1 # uncomment to enable
-# when not running under Jenkins, use current dir as workspace
-WORKSPACE=${WORKSPACE:-.}
+## -----------------------------------------------------------------------
+## Intent: Display a program banner for logging
+## -----------------------------------------------------------------------
+# shellcheck disable=SC2120
+function banner()
+{
+ local program="${0##*/}"
-# branch to compare against, defaults to master
-COMPARISON_BRANCH="${COMPARISON_BRANCH:-opencord/master}"
-echo "# Comparing with branch: $COMPARISON_BRANCH"
+ cat <<BANNER
-# Create list of changed files compared to branch
-changed_files=$(git diff --name-only "${COMPARISON_BRANCH}")
+# -----------------------------------------------------------------------
+# Running: ${program} $@
+# -----------------------------------------------------------------------
+# Now: $(date '+%Y-%m-%d %H:%M:%S')
+# Git: $(git --version)
+# -----------------------------------------------------------------------
+# COMPARISON_BRANCH: ${COMPARISON_BRANCH}
+# WORKSPACE: ${WORKSPACE}
+# -----------------------------------------------------------------------
+BANNER
-# Create list of untracked by git files
-untracked_files=$(git ls-files -o --exclude-standard)
+ return
+}
-# Print lists of files that are changed/untracked
-if [ -z "$changed_files" ] && [ -z "$untracked_files" ]
-then
- echo "# chart_version_check.sh - No changes, Success! #"
- exit 0
-else
- if [ -n "$changed_files" ]
- then
- echo "Changed files compared with $COMPARISON_BRANCH:"
- # Search and replace per SC2001 doesn't recognize ^ (beginning of line)
- # shellcheck disable=SC2001
- echo "${changed_files}" | sed 's/^/ /'
- fi
- if [ -n "$untracked_files" ]
- then
- echo "Untracked files:"
- # shellcheck disable=SC2001
- echo "${untracked_files}" | sed 's/^/ /'
- fi
-fi
+## -----------------------------------------------------------------------
+## Intent: Display a log summary entry then exit with status.
+## -----------------------------------------------------------------------
+function summary_status_with_exit()
+{
+ local exit_code=$1; shift
+ local program="${0##*/}"
+ local summary=''
+ [[ $# -gt 0 ]] && { summary=" - $1"; shift; }
-# combine lists
-if [ -n "$changed_files" ]
-then
- if [ -n "$untracked_files" ]
- then
- changed_files+=$'\n'
- changed_files+="${untracked_files}"
- fi
-else
- changed_files="${untracked_files}"
-fi
+ ## -----------------------------------
+ ## status override courtesy of error()
+ ## -----------------------------------
+ declare -i -g force_fail
+ if [ $force_fail -eq 1 ]; then exit_code=$force_fail; fi
-# For all the charts, fail on changes within a chart without a version change
-# loop on result of 'find -name Chart.yaml'
-while IFS= read -r -d '' chart
+ ## --------------------------
+ ## Set summary display string
+ ## --------------------------
+ case "$exit_code" in
+ 0) status='PASS' ;;
+ *) status='FAIL' ;;
+ esac
+
+ [[ $# -gt 0 ]] && formatStream "$@"
+
+ echo
+ echo "[$status] ${program} ${summary}"
+
+ exit $exit_code
+}
+
+## -----------------------------------------------------------------------
+## Intent: Display an error and configure report summary_status as FAIL
+## -----------------------------------------------------------------------
+function error()
+{
+ declare -i -g force_fail=1
+ declare -a -g error_stream
+
+ # shellcheck disable=SC2124
+ local error="[ERROR] $@"
+ error_stream+=("$error")
+ echo "$error"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Given a list (header and data) format contents as a log entry
+## -----------------------------------------------------------------------
+## Usage: displayList --banner "List of something" "${data_stream[@]}"
+## -----------------------------------------------------------------------
+function displayList()
+{
+ local indent=''
+ while [ $# -gt 0 ]; do
+ local arg="$1"
+ case "$arg" in
+ -*banner) shift; echo "$1" ;;
+ -*indent) shift; indent="$1" ;;
+ -*tab-2) echo -n ' ' ;;
+ -*tab-4) echo -n ' ' ;;
+ -*tab-6) echo -n ' ' ;;
+ -*tab-8) echo -n ' ' ;;
+ -*newline) echo; ;;
+ -*tab) echo -n ' ' ;;
+ *) break ;;
+ esac
+ shift
+ done
+
+ for line in "$@";
+ do
+ echo -e " ${indent}$line"
+ done
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Program init, provide defaults for globals, etc.
+## -----------------------------------------------------------------------
+function init()
+{
+ # when not running under Jenkins, use current dir as workspace
+ # o [TODO] - Perform a secondary username check to guard against a
+ # jenkins/bash env hiccup leaving WORKSPACE= temporarily undefined.
+ WORKSPACE=${WORKSPACE:-.}
+ COMPARISON_BRANCH="${COMPARISON_BRANCH:-opencord/master}"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Remove quotes, whitespace & garbage from a string
+## -----------------------------------------------------------------------
+## ..seealso: https://www.regular-expressions.info/posixbrackets.html
+## -----------------------------------------------------------------------
+function filter_codes()
+{
+ declare -n val="$1"; shift # indirect
+ val="${val//[\"\'[:blank:][:cntrl:]]}" # [:punct:] contains hyphen
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Detect and report VERSION file changes
+## -----------------------------------------------------------------------
+## :param path: Path to a Chart.yaml file.
+## :type path: str
+##
+## :param branch: Comparsion baranch (?-remote-?)
+## :type branch: str
+##
+## :return: true if embedded version string was modified.
+## :rtype: int
+## -----------------------------------------------------------------------
+## ..note: What about change detection for: apiVersion, appVersion (?)
+## -----------------------------------------------------------------------
+function version_diff()
+{
+ local path="$1"; shift
+ local branch="$1"; shift
+
+ declare -n old_var="$1"; shift # indirect
+ declare -n new_var="$1"; shift # indirect
+
+ old_var=''
+ new_var=''
+ readarray -t delta < <(git diff -p "$branch" -- "$path")
+
+ local modified=0
+ if [ ${#delta[@]} -gt 0 ]; then # modified
+
+ #----------------------------------------
+ # diff --git a/voltha-adapter-openolt/Chart.yaml [...]
+ # --- a/voltha-adapter-openolt/Chart.yaml
+ # +++ b/voltha-adapter-openolt/Chart.yaml
+ # @@ -14,7 +14,7 @@
+ # ---
+ # -version: "2.11.3" (====> 2.11.3)
+ # +version: "2.11.8" (====> 2.11.8)
+ #----------------------------------------
+ local line
+ for line in "${delta[@]}";
+ do
+ # [TODO] Replace awk with string builtins to reduce shell overhead.
+ case "$line" in
+ -version:*)
+ modified=1
+ readarray -t tmp < <(awk '/^\-version:/ { print $2 }' <<<"$line")
+ # shellcheck disable=SC2034
+ old_var="${tmp[0]}"
+ filter_codes 'old_var'
+ ;;
+ +version:*)
+ readarray -t tmp < <(awk '/^\+version:/ { print $2 }' <<<"$line")
+ # shellcheck disable=SC2034
+ new_var="${tmp[0]}"
+ filter_codes 'new_var'
+ ;;
+ esac
+ done
+ fi
+
+ [ $modified -ne 0 ] # set $? for if/then/elif use: "if version_diff; then"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Gather a list of Chart.yaml files from the workspace.
+## -----------------------------------------------------------------------
+function gather_charts()
+{
+ declare -n varname="$1"; shift
+ readarray -t varname < <(find . -name 'Chart.yaml' -print)
+
+ local idx
+ for (( idx=0; idx<${#varname[@]}; idx++ ));
+ do
+ local val="${varname[idx]}"
+ if [ ${#val} -lt 2 ]; then continue; fi
+
+ # Normalize: remove './' to support path comparison
+ if [[ "${val:0:2}" == './' ]]; then
+ varname[idx]="${val:2:${#val}}"
+ [[ -v debug ]] && echo "[$idx] ${varname[$idx]}"
+ fi
+ done
+
+ [[ -v debug ]] && declare -p varname
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Given a chart file and complete list of modified files
+## display a list of files modified in the chart directory.
+## -----------------------------------------------------------------------
+## :param chart: path to a Chart.yaml file
+## :type chart: str
+##
+## :param varname: A list files modified in a git sandbox.
+## :type varname: list, indirect
+## -----------------------------------------------------------------------
+function report_modified()
+{
+ local chart="$1"; shift
+ local dir="${chart%/*}"
+ # shellcheck disable=SC2178
+ declare -n varname="$1"; shift
+
+ ## ---------------------------------------------
+ ## Gather files contained in the chart directory
+ ## ---------------------------------------------
+ declare -a found=()
+ for val in "${varname[@]}";
+ do
+ case "$val" in
+ */Chart.yaml) ;; # special case
+ "${dir}"*) found+=("$val") ;;
+ esac
+ done
+
+ ## --------------------------------------------
+ ## Display results when modified files detected
+ ## --------------------------------------------
+ if [ ${#found[@]} -gt 0 ]; then
+ declare -a stream=()
+ stream+=('--tab-4')
+ stream+=('--banner' "Files Changed: $dir")
+ stream+=('--tab-6') # really --tab-8
+ stream+=("${found[@]}")
+ displayList "${stream[@]}"
+ fi
+
+ [ ${#found[@]} -gt 0 ] # set $? for if/else
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Gather a list of Chart.yaml files from the workspace.
+## -----------------------------------------------------------------------
+declare -a -g charts=()
+declare -a -g changes_remote=()
+declare -a -g untracked_files=()
+function gather_state()
+{
+ local branch="$1"; shift
+
+ gather_charts 'charts'
+ [[ -v debug ]] && declare -p charts
+
+ readarray -t changes_remote < <(git diff --name-only "$branch")
+ [[ -v debug ]] && declare -p changes_remote
+
+ readarray -t untracked_files < <(git ls-files -o --exclude-standard)
+ [[ -v debug ]] && declare -p untracked_files
+
+ return
+}
+
+# shellcheck disable=SC1073
+##----------------##
+##---] MAIN [---##
+##----------------##
+init
+# shellcheck disable=SC2119
+banner
+gather_state "$COMPARISON_BRANCH"
+
+chart=''
+for chart in "${charts[@]}";
do
- chartdir=$(dirname "${chart#${WORKSPACE}/}")
- chart_changed_files=""
- version_updated=0
+ [[ -v debug ]] && echo -e "\nCHART: $chart"
- # create a list of files that were changed in the chart
- for file in $changed_files; do
- if [[ $file =~ ^$chartdir/ ]]
- then
- chart_changed_files+=$'\n'
- chart_changed_files+=" ${file}"
- fi
- done
+ chart_dir="${chart%/*}"
- # See if chart version changed using 'git diff', and is SemVer
- chart_yaml_diff=$(git diff -p "$COMPARISON_BRANCH" -- "${chartdir}/Chart.yaml")
-
- if [ -n "$chart_yaml_diff" ]
- then
- echo "Changes to Chart.yaml in '$chartdir'"
- old_version_string=$(echo "$chart_yaml_diff" | awk '/^\-version:/ { print $2 }')
- new_version_string=$(echo "$chart_yaml_diff" | awk '/^\+version:/ { print $2 }')
-
- if [ -n "$new_version_string" ]
- then
- version_updated=1
- echo " Old version string:${old_version_string//-version:/}"
- echo " New version string:${new_version_string//+version:/}"
- fi
- fi
-
- # if there are any changed files
- if [ -n "$chart_changed_files" ]
- then
- # and version updated, print changed files
- if [ $version_updated -eq 1 ]
- then
- echo " Files changed:${chart_changed_files}"
+ ## ---------------------------
+ ## Detect VERSION file changes
+ ## ---------------------------
+ declare -i chart_modified=0
+ old=''
+ new=''
+ if version_diff "$chart" "$COMPARISON_BRANCH" 'old' 'new'; then
+ suffix="($old => $new)" # display verion deltas in the right margin
+ printf '[CHART] %-60s %s\n' "$chart" "$suffix"
+ chart_modified=1
else
- # otherwise fail this chart
- echo "Changes to chart but no version update in '$chartdir':${chart_changed_files}"
- fail_version=1
- failed_charts+=$'\n'
- failed_charts+=" $chartdir"
+ suffix="($old)"
+ printf '[CHART] %s\n' "$chart"
fi
- fi
-done < <(find "${WORKSPACE}" -name Chart.yaml -print0)
+ ## -----------------------------------
+ ## Report modified files for the chart
+ ## -----------------------------------
+ declare -a combo_list=()
+ combo_list+=("${changes_remote[@]}")
+ combo_list+=("${untracked_files[@]}")
+ if report_modified "$chart" 'combo_list';
+ then
+ if [ $chart_modified -eq 0 ]; then
+ error "Chart modified but version unchanged: ${chart_dir}"
+ fi
+ fi
-if [[ $fail_version != 0 ]]; then
- echo "# chart_version_check.sh Failure! #"
- echo "Charts that need to be fixed:$failed_charts"
- exit 1
+done
+
+## ---------------------------
+## Report summary: local edits
+## ---------------------------
+if [ ${#changes_remote} -gt 0 ]; then # local_edits
+ displayList \
+ '--newline' \
+ '--banner' 'Changed Files:' \
+ "${changes_remote[@]}"
fi
-echo "# chart_version_check.sh Success! - all charts have updated versions #"
+## -------------------------------
+## Report summary: untracked files
+## -------------------------------
+if [ ${#untracked_files} -gt 0 ]; then
+ displayList \
+ '--newline' \
+ '--banner' 'Untracked Files:' \
+ "${untracked_files[@]}"
+fi
-exit 0
+## ---------------------------------
+## Report summary: problems detected
+## ---------------------------------
+declare -a -g error_stream
+if [ ${#error_stream[@]} -gt 0 ]; then
+ displayList \
+ '--newline' \
+ '--banner' 'Error Sumamry:' \
+ "${error_stream[@]}"
+fi
+summary_status_with_exit $?
+
+# -----------------------------------------------------------------------
+# Running: chart_version_check.sh
+# -----------------------------------------------------------------------
+# Now: 2022-12-09 03:10:52
+# Git: git version 2.34.1
+# -----------------------------------------------------------------------
+# COMPARISON_BRANCH: origin/master
+# WORKSPACE: .
+# -----------------------------------------------------------------------
+# [CHART] voltha-adapter-openolt/Chart.yaml (2.11.3 => 2.11.8)
+# [CHART] voltha-tracing/Chart.yaml
+# [CHART] voltha/Chart.yaml
+# Files Changed: voltha-tracing
+# voltha-tracing/values.yaml
+# [ERROR] Chart modified but version unchanged: voltha-tracing
+# [CHART] voltha/Chart.yaml
+# -----------------------------------------------------------------------
+
+# [SEE ALSO
+# ---------------------------------------------------------------------------
+# https://www.regular-expressions.info/posixbrackets.html (character classes)
+# ---------------------------------------------------------------------------