blob: cccd1836819abda1c290b2ed209b68fbc585a660 [file] [log] [blame]
Zack Williams48542de2018-12-19 17:26:41 -07001#!/usr/bin/env bash
Joey Armstrongaebf1852022-12-09 08:34:13 -05002# ---------------------------------------------------------------------------
Joey Armstrong0476e912024-02-09 16:00:26 -05003# Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
Zack Williams48542de2018-12-19 17:26:41 -07004#
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,
Joey Armstrongaebf1852022-12-09 08:34:13 -050013# WITHOUT WARRANTIESS OR CONDITIONS OF ANY KIND, either express or implied.
Zack Williams48542de2018-12-19 17:26:41 -070014# See the License for the specific language governing permissions and
15# limitations under the License.
Joey Armstrongaebf1852022-12-09 08:34:13 -050016# ---------------------------------------------------------------------------
Zack Williams48542de2018-12-19 17:26:41 -070017# chart_version_check.sh
18# checks that changes to a chart include a change to the chart version
Joey Armstrongaebf1852022-12-09 08:34:13 -050019# ---------------------------------------------------------------------------
Zack Williams48542de2018-12-19 17:26:41 -070020
21set -u
Joey Armstrongaebf1852022-12-09 08:34:13 -050022# set -euo pipefail
Zack Williams48542de2018-12-19 17:26:41 -070023
Joey Armstrongaebf1852022-12-09 08:34:13 -050024##-------------------##
25##---] GLOBALS [---##
26##-------------------##
27declare -i -g force_fail=0
28declare -a -g error_stream=()
Zack Williams48542de2018-12-19 17:26:41 -070029
Joey Armstrongaebf1852022-12-09 08:34:13 -050030# declare -A -g ARGV=() # ARGV['debug']=1
31# declare -i -g debug=1 # uncomment to enable
Zack Williams48542de2018-12-19 17:26:41 -070032
Joey Armstrongaebf1852022-12-09 08:34:13 -050033## -----------------------------------------------------------------------
34## Intent: Display a program banner for logging
35## -----------------------------------------------------------------------
36# shellcheck disable=SC2120
37function banner()
38{
39 local program="${0##*/}"
Zack Williams48542de2018-12-19 17:26:41 -070040
Joey Armstrongaebf1852022-12-09 08:34:13 -050041 cat <<BANNER
Zack Williams48542de2018-12-19 17:26:41 -070042
Joey Armstrongaebf1852022-12-09 08:34:13 -050043# -----------------------------------------------------------------------
44# Running: ${program} $@
45# -----------------------------------------------------------------------
46# Now: $(date '+%Y-%m-%d %H:%M:%S')
47# Git: $(git --version)
48# -----------------------------------------------------------------------
Joey Armstrongb879cf82024-02-10 12:55:17 -050049# WORKSPACE: $(realpath "${WORKSPACE}")
50# WORKSPACE_BRANCH: $(git rev-parse --abbrev-ref HEAD)
Joey Armstrongaebf1852022-12-09 08:34:13 -050051# COMPARISON_BRANCH: ${COMPARISON_BRANCH}
Joey Armstrongaebf1852022-12-09 08:34:13 -050052# -----------------------------------------------------------------------
53BANNER
Zack Williams48542de2018-12-19 17:26:41 -070054
Joey Armstrongaebf1852022-12-09 08:34:13 -050055 return
56}
Zack Williams48542de2018-12-19 17:26:41 -070057
Joey Armstrongaebf1852022-12-09 08:34:13 -050058## -----------------------------------------------------------------------
Joey Armstrongf91c4372024-02-09 16:28:02 -050059## Intent: Augment a version string for display. If the given string
60## is empty rewrite to make that detail painfully obvious.
61## -----------------------------------------------------------------------
62function version_for_display()
63{
64 local -n ref=$1; shift
65
66 if [[ ${#ref} -eq 0 ]]; then
67 ref='?????????????????' # higlight the problem for reporting
68 fi
69 return
70}
71
72## -----------------------------------------------------------------------
73## Intent: Use git commands to retrieve chart version embedded within a file
74## -----------------------------------------------------------------------
75## Given:
76## ref Indirect var for version string return.
77## path Repository path to a Chart.yaml file
78## branch git branch to retrieve
79##
80## Return:
81## ref Extracted version string
82## -----------------------------------------------------------------------
83function get_version_by_git()
84{
85 local -n ref=$1 ; shift
86 local path="$1" ; shift
87 local branch="$1" ; shift
88 ref=''
89
90 # -----------------------------------------------------------------------
91 # cat "{branch}:{chart}" to stdout: (wanted => 'version : x.y.z')
92 # -----------------------------------------------------------------------
93 readarray -t buffer < <(\
94 git show "${branch}:${path}" \
95 | grep '^[[:blank:]]*version[[:blank:]]*:'\
96 )
97
98 # Extract version string
99 if [[ ${#buffer[@]} -ne 1 ]]; then
100 ref='' # Highly forgiving (display only)
101 else
102 local raw="${buffer[0]}"
103
104 # Extract value, split on whitespace, colon, comment or quote
105 readarray -t fields < <(awk -F '[[:blank:]:#"]+' '{print $2}' <<<"$raw")
106 ref="${fields[0]}"
107 fi
108
109 return
110}
111
112## -----------------------------------------------------------------------
Joey Armstrongaebf1852022-12-09 08:34:13 -0500113## Intent: Display a log summary entry then exit with status.
114## -----------------------------------------------------------------------
115function summary_status_with_exit()
116{
117 local exit_code=$1; shift
118 local program="${0##*/}"
119 local summary=''
120 [[ $# -gt 0 ]] && { summary=" - $1"; shift; }
Zack Williams48542de2018-12-19 17:26:41 -0700121
Joey Armstrongaebf1852022-12-09 08:34:13 -0500122 ## -----------------------------------
123 ## status override courtesy of error()
124 ## -----------------------------------
125 declare -i -g force_fail
126 if [ $force_fail -eq 1 ]; then exit_code=$force_fail; fi
Zack Williams48542de2018-12-19 17:26:41 -0700127
Joey Armstrongaebf1852022-12-09 08:34:13 -0500128 ## --------------------------
129 ## Set summary display string
130 ## --------------------------
131 case "$exit_code" in
Joey Armstrong0476e912024-02-09 16:00:26 -0500132 0) status='PASS' ;;
133 *) status='FAIL' ;;
Joey Armstrongaebf1852022-12-09 08:34:13 -0500134 esac
135
136 [[ $# -gt 0 ]] && formatStream "$@"
137
138 echo
139 echo "[$status] ${program} ${summary}"
140
Joey Armstrongf91c4372024-02-09 16:28:02 -0500141 exit "$exit_code"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500142}
143
144## -----------------------------------------------------------------------
145## Intent: Display an error and configure report summary_status as FAIL
146## -----------------------------------------------------------------------
147function error()
148{
149 declare -i -g force_fail=1
150 declare -a -g error_stream
151
152 # shellcheck disable=SC2124
153 local error="[ERROR] $@"
154 error_stream+=("$error")
155 echo "$error"
156 return
157}
158
159## -----------------------------------------------------------------------
160## Intent: Given a list (header and data) format contents as a log entry
161## -----------------------------------------------------------------------
162## Usage: displayList --banner "List of something" "${data_stream[@]}"
163## -----------------------------------------------------------------------
164function displayList()
165{
166 local indent=''
167 while [ $# -gt 0 ]; do
Joey Armstrong0476e912024-02-09 16:00:26 -0500168 local arg="$1"
169 case "$arg" in
170 -*banner) shift; echo "$1" ;;
171 -*indent) shift; indent="$1" ;;
172 -*tab-2) echo -n ' ' ;;
173 -*tab-4) echo -n ' ' ;;
174 -*tab-6) echo -n ' ' ;;
175 -*tab-8) echo -n ' ' ;;
176 -*newline) echo; ;;
177 -*tab) echo -n ' ' ;;
178 *) break ;;
179 esac
180 shift
Joey Armstrongaebf1852022-12-09 08:34:13 -0500181 done
182
183 for line in "$@";
184 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500185 echo -e " ${indent}$line"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500186 done
187 return
188}
189
190## -----------------------------------------------------------------------
191## Intent: Program init, provide defaults for globals, etc.
192## -----------------------------------------------------------------------
193function init()
194{
195 # when not running under Jenkins, use current dir as workspace
196 # o [TODO] - Perform a secondary username check to guard against a
197 # jenkins/bash env hiccup leaving WORKSPACE= temporarily undefined.
198 WORKSPACE=${WORKSPACE:-.}
199 COMPARISON_BRANCH="${COMPARISON_BRANCH:-opencord/master}"
200 return
201}
202
203## -----------------------------------------------------------------------
204## Intent: Remove quotes, whitespace & garbage from a string
205## -----------------------------------------------------------------------
206## ..seealso: https://www.regular-expressions.info/posixbrackets.html
207## -----------------------------------------------------------------------
208function filter_codes()
209{
210 declare -n val="$1"; shift # indirect
211 val="${val//[\"\'[:blank:][:cntrl:]]}" # [:punct:] contains hyphen
212 return
213}
214
215## -----------------------------------------------------------------------
216## Intent: Detect and report VERSION file changes
217## -----------------------------------------------------------------------
218## :param path: Path to a Chart.yaml file.
219## :type path: str
220##
221## :param branch: Comparsion baranch (?-remote-?)
222## :type branch: str
223##
224## :return: true if embedded version string was modified.
225## :rtype: int
226## -----------------------------------------------------------------------
227## ..note: What about change detection for: apiVersion, appVersion (?)
228## -----------------------------------------------------------------------
229function version_diff()
230{
231 local path="$1"; shift
232 local branch="$1"; shift
233
234 declare -n old_var="$1"; shift # indirect
235 declare -n new_var="$1"; shift # indirect
236
237 old_var=''
238 new_var=''
239 readarray -t delta < <(git diff -p "$branch" -- "$path")
240
241 local modified=0
242 if [ ${#delta[@]} -gt 0 ]; then # modified
243
Joey Armstrong0476e912024-02-09 16:00:26 -0500244 #----------------------------------------
245 # diff --git a/voltha-adapter-openolt/Chart.yaml [...]
246 # --- a/voltha-adapter-openolt/Chart.yaml
247 # +++ b/voltha-adapter-openolt/Chart.yaml
248 # @@ -14,7 +14,7 @@
249 # ---
250 # -version: "2.11.3" (====> 2.11.3)
251 # +version: "2.11.8" (====> 2.11.8)
252 #----------------------------------------
253 local line
254 for line in "${delta[@]}";
255 do
256 # [TODO] Replace awk with string builtins to reduce shell overhead.
257 case "$line" in
258 -version:*)
259 modified=1
260 readarray -t tmp < <(awk '/^\-version:/ { print $2 }' <<<"$line")
261 # shellcheck disable=SC2034
262 old_var="${tmp[0]}"
263 filter_codes 'old_var'
264 ;;
265 +version:*)
266 readarray -t tmp < <(awk '/^\+version:/ { print $2 }' <<<"$line")
267 # shellcheck disable=SC2034
268 new_var="${tmp[0]}"
269 filter_codes 'new_var'
270 ;;
271 esac
272 done
Joey Armstrongaebf1852022-12-09 08:34:13 -0500273 fi
274
275 [ $modified -ne 0 ] # set $? for if/then/elif use: "if version_diff; then"
276 return
277}
278
279## -----------------------------------------------------------------------
280## Intent: Gather a list of Chart.yaml files from the workspace.
281## -----------------------------------------------------------------------
282function gather_charts()
283{
284 declare -n varname="$1"; shift
285 readarray -t varname < <(find . -name 'Chart.yaml' -print)
286
287 local idx
288 for (( idx=0; idx<${#varname[@]}; idx++ ));
289 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500290 local val="${varname[idx]}"
291 if [ ${#val} -lt 2 ]; then continue; fi
Joey Armstrongaebf1852022-12-09 08:34:13 -0500292
Joey Armstrong0476e912024-02-09 16:00:26 -0500293 # Normalize: remove './' to support path comparison
294 if [[ "${val:0:2}" == './' ]]; then
295 varname[idx]="${val:2:${#val}}"
296 [[ -v debug ]] && echo "[$idx] ${varname[$idx]}"
297 fi
Joey Armstrongaebf1852022-12-09 08:34:13 -0500298 done
299
300 [[ -v debug ]] && declare -p varname
301 return
302}
303
304## -----------------------------------------------------------------------
305## Intent: Given a chart file and complete list of modified files
306## display a list of files modified in the chart directory.
307## -----------------------------------------------------------------------
308## :param chart: path to a Chart.yaml file
309## :type chart: str
310##
311## :param varname: A list files modified in a git sandbox.
312## :type varname: list, indirect
313## -----------------------------------------------------------------------
314function report_modified()
315{
316 local chart="$1"; shift
317 local dir="${chart%/*}"
318 # shellcheck disable=SC2178
319 declare -n varname="$1"; shift
320
321 ## ---------------------------------------------
322 ## Gather files contained in the chart directory
323 ## ---------------------------------------------
324 declare -a found=()
325 for val in "${varname[@]}";
326 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500327 case "$val" in
328 */Chart.yaml) ;; # special case
329 "${dir}"*) found+=("$val") ;;
330 esac
Joey Armstrongaebf1852022-12-09 08:34:13 -0500331 done
332
333 ## --------------------------------------------
334 ## Display results when modified files detected
335 ## --------------------------------------------
336 if [ ${#found[@]} -gt 0 ]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500337 declare -a stream=()
338 stream+=('--tab-4')
339 stream+=('--banner' "Files Changed: $dir")
340 stream+=('--tab-6') # really --tab-8
341 stream+=("${found[@]}")
342 displayList "${stream[@]}"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500343 fi
344
345 [ ${#found[@]} -gt 0 ] # set $? for if/else
346 return
347}
348
349## -----------------------------------------------------------------------
350## Intent: Gather a list of Chart.yaml files from the workspace.
351## -----------------------------------------------------------------------
352declare -a -g charts=()
353declare -a -g changes_remote=()
354declare -a -g untracked_files=()
355function gather_state()
356{
357 local branch="$1"; shift
358
359 gather_charts 'charts'
360 [[ -v debug ]] && declare -p charts
361
362 readarray -t changes_remote < <(git diff --name-only "$branch")
363 [[ -v debug ]] && declare -p changes_remote
364
365 readarray -t untracked_files < <(git ls-files -o --exclude-standard)
366 [[ -v debug ]] && declare -p untracked_files
367
368 return
369}
370
371# shellcheck disable=SC1073
372##----------------##
373##---] MAIN [---##
374##----------------##
375init
376# shellcheck disable=SC2119
377banner
378gather_state "$COMPARISON_BRANCH"
379
380chart=''
381for chart in "${charts[@]}";
Zack Williams48542de2018-12-19 17:26:41 -0700382do
Joey Armstrongaebf1852022-12-09 08:34:13 -0500383 [[ -v debug ]] && echo -e "\nCHART: $chart"
Zack Williams48542de2018-12-19 17:26:41 -0700384
Joey Armstrongaebf1852022-12-09 08:34:13 -0500385 ## ---------------------------
386 ## Detect VERSION file changes
387 ## ---------------------------
388 declare -i chart_modified=0
389 old=''
390 new=''
391 if version_diff "$chart" "$COMPARISON_BRANCH" 'old' 'new'; then
Joey Armstrongf91c4372024-02-09 16:28:02 -0500392 version_for_display new
Joey Armstrong0476e912024-02-09 16:00:26 -0500393 suffix="($old => $new)" # display verion deltas in the right margin
394 printf '[CHART] %-60s %s\n' "$chart" "$suffix"
395 chart_modified=1
Zack Williams48542de2018-12-19 17:26:41 -0700396 else
Joey Armstrongf91c4372024-02-09 16:28:02 -0500397 if [[ ${#old} -eq 0 ]]; then
398 get_version_by_git old "$chart" "$COMPARISON_BRANCH"
399 fi
400 version_for_display old
Joey Armstrong0476e912024-02-09 16:00:26 -0500401 suffix="($old)"
402 printf '[CHART] %s\n' "$chart"
Joey Armstrongf91c4372024-02-09 16:28:02 -0500403 new="$old"
Zack Williams48542de2018-12-19 17:26:41 -0700404 fi
Zack Williams48542de2018-12-19 17:26:41 -0700405
Joey Armstrongaebf1852022-12-09 08:34:13 -0500406 ## -----------------------------------
407 ## Report modified files for the chart
408 ## -----------------------------------
409 declare -a combo_list=()
410 combo_list+=("${changes_remote[@]}")
411 combo_list+=("${untracked_files[@]}")
412 if report_modified "$chart" 'combo_list';
413 then
Joey Armstrong0476e912024-02-09 16:00:26 -0500414 if [ $chart_modified -eq 0 ]; then
Joey Armstrongf91c4372024-02-09 16:28:02 -0500415 version_for_display new
416 suffix="($old)"
417 error "Chart modified but version unchanged: ${chart} ${suffix}"
Joey Armstrong0476e912024-02-09 16:00:26 -0500418 fi
Joey Armstrongaebf1852022-12-09 08:34:13 -0500419 fi
Zack Williams48542de2018-12-19 17:26:41 -0700420
Joey Armstrongaebf1852022-12-09 08:34:13 -0500421done
422
423## ---------------------------
424## Report summary: local edits
425## ---------------------------
Joey Armstrong0f8656b2022-12-21 11:29:36 -0500426if [[ -x changes_remote ]] && [ ${#changes_remote} -gt 0 ]; then # local_edits
Joey Armstrongaebf1852022-12-09 08:34:13 -0500427 displayList \
Joey Armstrong0476e912024-02-09 16:00:26 -0500428 '--newline' \
429 '--banner' 'Changed Files:' \
430 "${changes_remote[@]}"
Zack Williams48542de2018-12-19 17:26:41 -0700431fi
432
Joey Armstrongaebf1852022-12-09 08:34:13 -0500433## -------------------------------
434## Report summary: untracked files
435## -------------------------------
Joey Armstrongb41d8cc2023-01-03 10:49:10 -0500436if [ ${#untracked_files[@]} -gt 0 ]; then
Joey Armstrongaebf1852022-12-09 08:34:13 -0500437 displayList \
Joey Armstrong0476e912024-02-09 16:00:26 -0500438 '--newline' \
439 '--banner' 'Untracked Files:' \
440 "${untracked_files[@]}"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500441fi
Zack Williams48542de2018-12-19 17:26:41 -0700442
Joey Armstrongaebf1852022-12-09 08:34:13 -0500443## ---------------------------------
444## Report summary: problems detected
445## ---------------------------------
446declare -a -g error_stream
447if [ ${#error_stream[@]} -gt 0 ]; then
448 displayList \
Joey Armstrong0476e912024-02-09 16:00:26 -0500449 '--newline' \
450 '--banner' 'Error Sumamry:' \
451 "${error_stream[@]}"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500452fi
Zack Williams48542de2018-12-19 17:26:41 -0700453
Joey Armstrongaebf1852022-12-09 08:34:13 -0500454summary_status_with_exit $?
455
456# -----------------------------------------------------------------------
457# Running: chart_version_check.sh
458# -----------------------------------------------------------------------
459# Now: 2022-12-09 03:10:52
460# Git: git version 2.34.1
461# -----------------------------------------------------------------------
462# COMPARISON_BRANCH: origin/master
463# WORKSPACE: .
464# -----------------------------------------------------------------------
465# [CHART] voltha-adapter-openolt/Chart.yaml (2.11.3 => 2.11.8)
466# [CHART] voltha-tracing/Chart.yaml
467# [CHART] voltha/Chart.yaml
468# Files Changed: voltha-tracing
469# voltha-tracing/values.yaml
470# [ERROR] Chart modified but version unchanged: voltha-tracing
471# [CHART] voltha/Chart.yaml
472# -----------------------------------------------------------------------
473
474# [SEE ALSO
475# ---------------------------------------------------------------------------
476# https://www.regular-expressions.info/posixbrackets.html (character classes)
477# ---------------------------------------------------------------------------