blob: 1d1b33c826142c11adc914315da7f6599243efe4 [file] [log] [blame]
Zack Williams48542de2018-12-19 17:26:41 -07001#!/usr/bin/env bash
Joey Armstrongf32accb2024-03-07 17:05:09 -05002# -----------------------------------------------------------------------
3# Copyright 2018-2024 Open Networking Foundation 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#
Joey Armstrongf32accb2024-03-07 17:05:09 -05009# http:#www.apache.org/licenses/LICENSE-2.0
Zack Williams48542de2018-12-19 17:26:41 -070010#
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 Armstrongf32accb2024-03-07 17:05:09 -050013# WITHOUT WARRANTIES 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 Armstrongf32accb2024-03-07 17:05:09 -050016# -----------------------------------------------------------------------
17# SPDX-FileCopyrightText: 2018-2024 Open Networking Foundation Contributors
18# SPDX-License-Identifier: Apache-2.0
19# -----------------------------------------------------------------------
20# Intent:
Zack Williams48542de2018-12-19 17:26:41 -070021# chart_version_check.sh
22# checks that changes to a chart include a change to the chart version
Joey Armstrongaebf1852022-12-09 08:34:13 -050023# ---------------------------------------------------------------------------
Zack Williams48542de2018-12-19 17:26:41 -070024
25set -u
Joey Armstrongaebf1852022-12-09 08:34:13 -050026# set -euo pipefail
Zack Williams48542de2018-12-19 17:26:41 -070027
Joey Armstrongaebf1852022-12-09 08:34:13 -050028##-------------------##
29##---] GLOBALS [---##
30##-------------------##
31declare -i -g force_fail=0
32declare -a -g error_stream=()
Zack Williams48542de2018-12-19 17:26:41 -070033
Joey Armstrongaebf1852022-12-09 08:34:13 -050034# declare -A -g ARGV=() # ARGV['debug']=1
35# declare -i -g debug=1 # uncomment to enable
Zack Williams48542de2018-12-19 17:26:41 -070036
Joey Armstrongf32accb2024-03-07 17:05:09 -050037##--------------------##
38##---] INCLUDES [---##
39##--------------------##
40{
41 declare pgm
42 pgm="$(realpath "${BASH_SOURCE[0]}")"
43 declare libdir="${pgm%.sh}"
44
45 # shellcheck source=chart_version_check/filter_files.sh
46 # shellcheck disable=SC1091
47 source "$libdir/filter_files.sh"
48}
49
Joey Armstrongaebf1852022-12-09 08:34:13 -050050## -----------------------------------------------------------------------
51## Intent: Display a program banner for logging
52## -----------------------------------------------------------------------
53# shellcheck disable=SC2120
54function banner()
55{
56 local program="${0##*/}"
Zack Williams48542de2018-12-19 17:26:41 -070057
Joey Armstrongaebf1852022-12-09 08:34:13 -050058 cat <<BANNER
Zack Williams48542de2018-12-19 17:26:41 -070059
Joey Armstrongaebf1852022-12-09 08:34:13 -050060# -----------------------------------------------------------------------
61# Running: ${program} $@
62# -----------------------------------------------------------------------
63# Now: $(date '+%Y-%m-%d %H:%M:%S')
64# Git: $(git --version)
65# -----------------------------------------------------------------------
Joey Armstrongb879cf82024-02-10 12:55:17 -050066# WORKSPACE: $(realpath "${WORKSPACE}")
67# WORKSPACE_BRANCH: $(git rev-parse --abbrev-ref HEAD)
Joey Armstrongaebf1852022-12-09 08:34:13 -050068# COMPARISON_BRANCH: ${COMPARISON_BRANCH}
Joey Armstrongaebf1852022-12-09 08:34:13 -050069# -----------------------------------------------------------------------
70BANNER
Zack Williams48542de2018-12-19 17:26:41 -070071
Joey Armstrongaebf1852022-12-09 08:34:13 -050072 return
73}
Zack Williams48542de2018-12-19 17:26:41 -070074
Joey Armstrongaebf1852022-12-09 08:34:13 -050075## -----------------------------------------------------------------------
Joey Armstrongf91c4372024-02-09 16:28:02 -050076## Intent: Augment a version string for display. If the given string
77## is empty rewrite to make that detail painfully obvious.
78## -----------------------------------------------------------------------
79function version_for_display()
80{
81 local -n ref=$1; shift
82
83 if [[ ${#ref} -eq 0 ]]; then
84 ref='?????????????????' # higlight the problem for reporting
85 fi
86 return
87}
88
89## -----------------------------------------------------------------------
90## Intent: Use git commands to retrieve chart version embedded within a file
91## -----------------------------------------------------------------------
92## Given:
93## ref Indirect var for version string return.
94## path Repository path to a Chart.yaml file
95## branch git branch to retrieve
96##
97## Return:
98## ref Extracted version string
99## -----------------------------------------------------------------------
100function get_version_by_git()
101{
102 local -n ref=$1 ; shift
103 local path="$1" ; shift
104 local branch="$1" ; shift
Joey Armstrongf32accb2024-03-07 17:05:09 -0500105
Joey Armstrongf91c4372024-02-09 16:28:02 -0500106 ref=''
107
108 # -----------------------------------------------------------------------
109 # cat "{branch}:{chart}" to stdout: (wanted => 'version : x.y.z')
110 # -----------------------------------------------------------------------
111 readarray -t buffer < <(\
112 git show "${branch}:${path}" \
113 | grep '^[[:blank:]]*version[[:blank:]]*:'\
114 )
115
Joey Armstrongf32accb2024-03-07 17:05:09 -0500116 # -----------------------------------------------------------------------
Joey Armstrongf91c4372024-02-09 16:28:02 -0500117 # Extract version string
Joey Armstrongf32accb2024-03-07 17:05:09 -0500118 # -----------------------------------------------------------------------
119 if [[ ${#buffer[@]} -gt 1 ]]; then
120 cat <<EOM
121
122** -----------------------------------------------------------------------
123** IAM: ${BASH_SOURCE[0]} (LINENO: ${LINENO})
124** CHART: $path
125** WARNING: Unable to identify chart version, multiple strings detected.
126** : Consider updating the lint tool to be aware of Chart.yaml
127** : record syntax so versions can be extracted for comparison.
128** -----------------------------------------------------------------------
129EOM
130 ## c_v_c.sh needs to be aware of Chart.yaml record syntax
131 ## so a version can be targeted.
132
133 # shellcheck disable=SC1003
134 declare -p buffer \
135 | tr '"' '\n' \
136 | grep '\.' \
137 | sed -e 's/^[[:blank:]]*//' \
138 | awk -F'\\' '{print " "$1}' \
139 | sort -nr
140 echo
141
142 ref='' # Highly forgiving (display only)
143 elif [[ ${#buffer[@]} -ne 1 ]]; then
Joey Armstrongf91c4372024-02-09 16:28:02 -0500144 ref='' # Highly forgiving (display only)
145 else
146 local raw="${buffer[0]}"
Joey Armstrongf91c4372024-02-09 16:28:02 -0500147 # Extract value, split on whitespace, colon, comment or quote
148 readarray -t fields < <(awk -F '[[:blank:]:#"]+' '{print $2}' <<<"$raw")
149 ref="${fields[0]}"
150 fi
151
152 return
153}
154
155## -----------------------------------------------------------------------
Joey Armstrongaebf1852022-12-09 08:34:13 -0500156## Intent: Display a log summary entry then exit with status.
157## -----------------------------------------------------------------------
158function summary_status_with_exit()
159{
160 local exit_code=$1; shift
161 local program="${0##*/}"
162 local summary=''
163 [[ $# -gt 0 ]] && { summary=" - $1"; shift; }
Zack Williams48542de2018-12-19 17:26:41 -0700164
Joey Armstrongaebf1852022-12-09 08:34:13 -0500165 ## -----------------------------------
166 ## status override courtesy of error()
167 ## -----------------------------------
168 declare -i -g force_fail
169 if [ $force_fail -eq 1 ]; then exit_code=$force_fail; fi
Zack Williams48542de2018-12-19 17:26:41 -0700170
Joey Armstrongaebf1852022-12-09 08:34:13 -0500171 ## --------------------------
172 ## Set summary display string
173 ## --------------------------
174 case "$exit_code" in
Joey Armstrong0476e912024-02-09 16:00:26 -0500175 0) status='PASS' ;;
176 *) status='FAIL' ;;
Joey Armstrongaebf1852022-12-09 08:34:13 -0500177 esac
178
179 [[ $# -gt 0 ]] && formatStream "$@"
180
181 echo
182 echo "[$status] ${program} ${summary}"
183
Joey Armstrongf91c4372024-02-09 16:28:02 -0500184 exit "$exit_code"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500185}
186
187## -----------------------------------------------------------------------
188## Intent: Display an error and configure report summary_status as FAIL
189## -----------------------------------------------------------------------
190function error()
191{
192 declare -i -g force_fail=1
193 declare -a -g error_stream
194
195 # shellcheck disable=SC2124
196 local error="[ERROR] $@"
197 error_stream+=("$error")
198 echo "$error"
199 return
200}
201
202## -----------------------------------------------------------------------
203## Intent: Given a list (header and data) format contents as a log entry
204## -----------------------------------------------------------------------
205## Usage: displayList --banner "List of something" "${data_stream[@]}"
206## -----------------------------------------------------------------------
207function displayList()
208{
209 local indent=''
210 while [ $# -gt 0 ]; do
Joey Armstrong0476e912024-02-09 16:00:26 -0500211 local arg="$1"
212 case "$arg" in
213 -*banner) shift; echo "$1" ;;
214 -*indent) shift; indent="$1" ;;
215 -*tab-2) echo -n ' ' ;;
216 -*tab-4) echo -n ' ' ;;
217 -*tab-6) echo -n ' ' ;;
218 -*tab-8) echo -n ' ' ;;
219 -*newline) echo; ;;
220 -*tab) echo -n ' ' ;;
221 *) break ;;
222 esac
223 shift
Joey Armstrongaebf1852022-12-09 08:34:13 -0500224 done
225
226 for line in "$@";
227 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500228 echo -e " ${indent}$line"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500229 done
230 return
231}
232
233## -----------------------------------------------------------------------
234## Intent: Program init, provide defaults for globals, etc.
235## -----------------------------------------------------------------------
236function init()
237{
238 # when not running under Jenkins, use current dir as workspace
239 # o [TODO] - Perform a secondary username check to guard against a
240 # jenkins/bash env hiccup leaving WORKSPACE= temporarily undefined.
241 WORKSPACE=${WORKSPACE:-.}
242 COMPARISON_BRANCH="${COMPARISON_BRANCH:-opencord/master}"
243 return
244}
245
246## -----------------------------------------------------------------------
247## Intent: Remove quotes, whitespace & garbage from a string
248## -----------------------------------------------------------------------
249## ..seealso: https://www.regular-expressions.info/posixbrackets.html
250## -----------------------------------------------------------------------
251function filter_codes()
252{
253 declare -n val="$1"; shift # indirect
254 val="${val//[\"\'[:blank:][:cntrl:]]}" # [:punct:] contains hyphen
255 return
256}
257
258## -----------------------------------------------------------------------
259## Intent: Detect and report VERSION file changes
260## -----------------------------------------------------------------------
261## :param path: Path to a Chart.yaml file.
262## :type path: str
263##
264## :param branch: Comparsion baranch (?-remote-?)
265## :type branch: str
266##
267## :return: true if embedded version string was modified.
268## :rtype: int
269## -----------------------------------------------------------------------
270## ..note: What about change detection for: apiVersion, appVersion (?)
271## -----------------------------------------------------------------------
272function version_diff()
273{
274 local path="$1"; shift
275 local branch="$1"; shift
276
277 declare -n old_var="$1"; shift # indirect
278 declare -n new_var="$1"; shift # indirect
279
280 old_var=''
281 new_var=''
282 readarray -t delta < <(git diff -p "$branch" -- "$path")
283
284 local modified=0
285 if [ ${#delta[@]} -gt 0 ]; then # modified
286
Joey Armstrong0476e912024-02-09 16:00:26 -0500287 #----------------------------------------
288 # diff --git a/voltha-adapter-openolt/Chart.yaml [...]
289 # --- a/voltha-adapter-openolt/Chart.yaml
290 # +++ b/voltha-adapter-openolt/Chart.yaml
291 # @@ -14,7 +14,7 @@
292 # ---
293 # -version: "2.11.3" (====> 2.11.3)
294 # +version: "2.11.8" (====> 2.11.8)
295 #----------------------------------------
296 local line
297 for line in "${delta[@]}";
298 do
299 # [TODO] Replace awk with string builtins to reduce shell overhead.
300 case "$line" in
301 -version:*)
302 modified=1
303 readarray -t tmp < <(awk '/^\-version:/ { print $2 }' <<<"$line")
304 # shellcheck disable=SC2034
305 old_var="${tmp[0]}"
306 filter_codes 'old_var'
307 ;;
308 +version:*)
309 readarray -t tmp < <(awk '/^\+version:/ { print $2 }' <<<"$line")
310 # shellcheck disable=SC2034
311 new_var="${tmp[0]}"
312 filter_codes 'new_var'
313 ;;
314 esac
315 done
Joey Armstrongaebf1852022-12-09 08:34:13 -0500316 fi
317
318 [ $modified -ne 0 ] # set $? for if/then/elif use: "if version_diff; then"
319 return
320}
321
322## -----------------------------------------------------------------------
323## Intent: Gather a list of Chart.yaml files from the workspace.
324## -----------------------------------------------------------------------
325function gather_charts()
326{
327 declare -n varname="$1"; shift
328 readarray -t varname < <(find . -name 'Chart.yaml' -print)
Joey Armstrongf32accb2024-03-07 17:05:09 -0500329 filter_files varname
Joey Armstrongaebf1852022-12-09 08:34:13 -0500330
331 local idx
332 for (( idx=0; idx<${#varname[@]}; idx++ ));
333 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500334 local val="${varname[idx]}"
335 if [ ${#val} -lt 2 ]; then continue; fi
Joey Armstrongaebf1852022-12-09 08:34:13 -0500336
Joey Armstrong0476e912024-02-09 16:00:26 -0500337 # Normalize: remove './' to support path comparison
338 if [[ "${val:0:2}" == './' ]]; then
339 varname[idx]="${val:2:${#val}}"
340 [[ -v debug ]] && echo "[$idx] ${varname[$idx]}"
341 fi
Joey Armstrongaebf1852022-12-09 08:34:13 -0500342 done
343
344 [[ -v debug ]] && declare -p varname
345 return
346}
347
348## -----------------------------------------------------------------------
349## Intent: Given a chart file and complete list of modified files
350## display a list of files modified in the chart directory.
351## -----------------------------------------------------------------------
352## :param chart: path to a Chart.yaml file
353## :type chart: str
354##
355## :param varname: A list files modified in a git sandbox.
356## :type varname: list, indirect
357## -----------------------------------------------------------------------
358function report_modified()
359{
360 local chart="$1"; shift
361 local dir="${chart%/*}"
362 # shellcheck disable=SC2178
363 declare -n varname="$1"; shift
364
365 ## ---------------------------------------------
366 ## Gather files contained in the chart directory
367 ## ---------------------------------------------
368 declare -a found=()
369 for val in "${varname[@]}";
370 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500371 case "$val" in
Joey Armstrongf32accb2024-03-07 17:05:09 -0500372 *'/Chart.yaml') ;; # special case
Joey Armstrong0476e912024-02-09 16:00:26 -0500373 "${dir}"*) found+=("$val") ;;
374 esac
Joey Armstrongaebf1852022-12-09 08:34:13 -0500375 done
376
377 ## --------------------------------------------
378 ## Display results when modified files detected
379 ## --------------------------------------------
380 if [ ${#found[@]} -gt 0 ]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500381 declare -a stream=()
382 stream+=('--tab-4')
383 stream+=('--banner' "Files Changed: $dir")
384 stream+=('--tab-6') # really --tab-8
385 stream+=("${found[@]}")
386 displayList "${stream[@]}"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500387 fi
388
389 [ ${#found[@]} -gt 0 ] # set $? for if/else
390 return
391}
392
393## -----------------------------------------------------------------------
394## Intent: Gather a list of Chart.yaml files from the workspace.
395## -----------------------------------------------------------------------
396declare -a -g charts=()
397declare -a -g changes_remote=()
398declare -a -g untracked_files=()
399function gather_state()
400{
401 local branch="$1"; shift
402
403 gather_charts 'charts'
404 [[ -v debug ]] && declare -p charts
405
406 readarray -t changes_remote < <(git diff --name-only "$branch")
Joey Armstrongf32accb2024-03-07 17:05:09 -0500407 filter_files changes_remote
Joey Armstrongaebf1852022-12-09 08:34:13 -0500408 [[ -v debug ]] && declare -p changes_remote
409
410 readarray -t untracked_files < <(git ls-files -o --exclude-standard)
Joey Armstrongf32accb2024-03-07 17:05:09 -0500411 filter_files untracked_files
Joey Armstrongaebf1852022-12-09 08:34:13 -0500412 [[ -v debug ]] && declare -p untracked_files
413
414 return
415}
416
417# shellcheck disable=SC1073
418##----------------##
419##---] MAIN [---##
420##----------------##
421init
422# shellcheck disable=SC2119
423banner
424gather_state "$COMPARISON_BRANCH"
425
426chart=''
427for chart in "${charts[@]}";
Zack Williams48542de2018-12-19 17:26:41 -0700428do
Joey Armstrongaebf1852022-12-09 08:34:13 -0500429 [[ -v debug ]] && echo -e "\nCHART: $chart"
Zack Williams48542de2018-12-19 17:26:41 -0700430
Joey Armstrongaebf1852022-12-09 08:34:13 -0500431 ## ---------------------------
432 ## Detect VERSION file changes
433 ## ---------------------------
434 declare -i chart_modified=0
435 old=''
436 new=''
437 if version_diff "$chart" "$COMPARISON_BRANCH" 'old' 'new'; then
Joey Armstrongf91c4372024-02-09 16:28:02 -0500438 version_for_display new
Joey Armstrong0476e912024-02-09 16:00:26 -0500439 suffix="($old => $new)" # display verion deltas in the right margin
440 printf '[CHART] %-60s %s\n' "$chart" "$suffix"
441 chart_modified=1
Zack Williams48542de2018-12-19 17:26:41 -0700442 else
Joey Armstrongf91c4372024-02-09 16:28:02 -0500443 if [[ ${#old} -eq 0 ]]; then
444 get_version_by_git old "$chart" "$COMPARISON_BRANCH"
445 fi
446 version_for_display old
Joey Armstrong0476e912024-02-09 16:00:26 -0500447 suffix="($old)"
448 printf '[CHART] %s\n' "$chart"
Joey Armstrongf91c4372024-02-09 16:28:02 -0500449 new="$old"
Zack Williams48542de2018-12-19 17:26:41 -0700450 fi
Zack Williams48542de2018-12-19 17:26:41 -0700451
Joey Armstrongaebf1852022-12-09 08:34:13 -0500452 ## -----------------------------------
453 ## Report modified files for the chart
454 ## -----------------------------------
455 declare -a combo_list=()
456 combo_list+=("${changes_remote[@]}")
457 combo_list+=("${untracked_files[@]}")
458 if report_modified "$chart" 'combo_list';
459 then
Joey Armstrong0476e912024-02-09 16:00:26 -0500460 if [ $chart_modified -eq 0 ]; then
Joey Armstrongf91c4372024-02-09 16:28:02 -0500461 version_for_display new
462 suffix="($old)"
463 error "Chart modified but version unchanged: ${chart} ${suffix}"
Joey Armstrong0476e912024-02-09 16:00:26 -0500464 fi
Joey Armstrongaebf1852022-12-09 08:34:13 -0500465 fi
Zack Williams48542de2018-12-19 17:26:41 -0700466
Joey Armstrongaebf1852022-12-09 08:34:13 -0500467done
468
469## ---------------------------
470## Report summary: local edits
471## ---------------------------
Joey Armstrong0f8656b2022-12-21 11:29:36 -0500472if [[ -x changes_remote ]] && [ ${#changes_remote} -gt 0 ]; then # local_edits
Joey Armstrongaebf1852022-12-09 08:34:13 -0500473 displayList \
Joey Armstrong0476e912024-02-09 16:00:26 -0500474 '--newline' \
475 '--banner' 'Changed Files:' \
476 "${changes_remote[@]}"
Zack Williams48542de2018-12-19 17:26:41 -0700477fi
478
Joey Armstrongaebf1852022-12-09 08:34:13 -0500479## -------------------------------
480## Report summary: untracked files
481## -------------------------------
Joey Armstrongb41d8cc2023-01-03 10:49:10 -0500482if [ ${#untracked_files[@]} -gt 0 ]; then
Joey Armstrongaebf1852022-12-09 08:34:13 -0500483 displayList \
Joey Armstrong0476e912024-02-09 16:00:26 -0500484 '--newline' \
485 '--banner' 'Untracked Files:' \
486 "${untracked_files[@]}"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500487fi
Zack Williams48542de2018-12-19 17:26:41 -0700488
Joey Armstrongaebf1852022-12-09 08:34:13 -0500489## ---------------------------------
490## Report summary: problems detected
491## ---------------------------------
492declare -a -g error_stream
493if [ ${#error_stream[@]} -gt 0 ]; then
494 displayList \
Joey Armstrong0476e912024-02-09 16:00:26 -0500495 '--newline' \
496 '--banner' 'Error Sumamry:' \
497 "${error_stream[@]}"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500498fi
Zack Williams48542de2018-12-19 17:26:41 -0700499
Joey Armstrongaebf1852022-12-09 08:34:13 -0500500summary_status_with_exit $?
501
502# -----------------------------------------------------------------------
503# Running: chart_version_check.sh
504# -----------------------------------------------------------------------
505# Now: 2022-12-09 03:10:52
506# Git: git version 2.34.1
507# -----------------------------------------------------------------------
508# COMPARISON_BRANCH: origin/master
509# WORKSPACE: .
510# -----------------------------------------------------------------------
511# [CHART] voltha-adapter-openolt/Chart.yaml (2.11.3 => 2.11.8)
512# [CHART] voltha-tracing/Chart.yaml
513# [CHART] voltha/Chart.yaml
514# Files Changed: voltha-tracing
515# voltha-tracing/values.yaml
516# [ERROR] Chart modified but version unchanged: voltha-tracing
517# [CHART] voltha/Chart.yaml
518# -----------------------------------------------------------------------
519
520# [SEE ALSO
521# ---------------------------------------------------------------------------
522# https://www.regular-expressions.info/posixbrackets.html (character classes)
523# ---------------------------------------------------------------------------