blob: e332ec3097e758d756dc64f05d1ee052fbbcb00c [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# -----------------------------------------------------------------------
49# COMPARISON_BRANCH: ${COMPARISON_BRANCH}
50# WORKSPACE: ${WORKSPACE}
51# -----------------------------------------------------------------------
52BANNER
Zack Williams48542de2018-12-19 17:26:41 -070053
Joey Armstrongaebf1852022-12-09 08:34:13 -050054 return
55}
Zack Williams48542de2018-12-19 17:26:41 -070056
Joey Armstrongaebf1852022-12-09 08:34:13 -050057## -----------------------------------------------------------------------
Joey Armstrongf91c4372024-02-09 16:28:02 -050058## Intent: Augment a version string for display. If the given string
59## is empty rewrite to make that detail painfully obvious.
60## -----------------------------------------------------------------------
61function version_for_display()
62{
63 local -n ref=$1; shift
64
65 if [[ ${#ref} -eq 0 ]]; then
66 ref='?????????????????' # higlight the problem for reporting
67 fi
68 return
69}
70
71## -----------------------------------------------------------------------
72## Intent: Use git commands to retrieve chart version embedded within a file
73## -----------------------------------------------------------------------
74## Given:
75## ref Indirect var for version string return.
76## path Repository path to a Chart.yaml file
77## branch git branch to retrieve
78##
79## Return:
80## ref Extracted version string
81## -----------------------------------------------------------------------
82function get_version_by_git()
83{
84 local -n ref=$1 ; shift
85 local path="$1" ; shift
86 local branch="$1" ; shift
87 ref=''
88
89 # -----------------------------------------------------------------------
90 # cat "{branch}:{chart}" to stdout: (wanted => 'version : x.y.z')
91 # -----------------------------------------------------------------------
92 readarray -t buffer < <(\
93 git show "${branch}:${path}" \
94 | grep '^[[:blank:]]*version[[:blank:]]*:'\
95 )
96
97 # Extract version string
98 if [[ ${#buffer[@]} -ne 1 ]]; then
99 ref='' # Highly forgiving (display only)
100 else
101 local raw="${buffer[0]}"
102
103 # Extract value, split on whitespace, colon, comment or quote
104 readarray -t fields < <(awk -F '[[:blank:]:#"]+' '{print $2}' <<<"$raw")
105 ref="${fields[0]}"
106 fi
107
108 return
109}
110
111## -----------------------------------------------------------------------
Joey Armstrongaebf1852022-12-09 08:34:13 -0500112## Intent: Display a log summary entry then exit with status.
113## -----------------------------------------------------------------------
114function summary_status_with_exit()
115{
116 local exit_code=$1; shift
117 local program="${0##*/}"
118 local summary=''
119 [[ $# -gt 0 ]] && { summary=" - $1"; shift; }
Zack Williams48542de2018-12-19 17:26:41 -0700120
Joey Armstrongaebf1852022-12-09 08:34:13 -0500121 ## -----------------------------------
122 ## status override courtesy of error()
123 ## -----------------------------------
124 declare -i -g force_fail
125 if [ $force_fail -eq 1 ]; then exit_code=$force_fail; fi
Zack Williams48542de2018-12-19 17:26:41 -0700126
Joey Armstrongaebf1852022-12-09 08:34:13 -0500127 ## --------------------------
128 ## Set summary display string
129 ## --------------------------
130 case "$exit_code" in
Joey Armstrong0476e912024-02-09 16:00:26 -0500131 0) status='PASS' ;;
132 *) status='FAIL' ;;
Joey Armstrongaebf1852022-12-09 08:34:13 -0500133 esac
134
135 [[ $# -gt 0 ]] && formatStream "$@"
136
137 echo
138 echo "[$status] ${program} ${summary}"
139
Joey Armstrongf91c4372024-02-09 16:28:02 -0500140 exit "$exit_code"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500141}
142
143## -----------------------------------------------------------------------
144## Intent: Display an error and configure report summary_status as FAIL
145## -----------------------------------------------------------------------
146function error()
147{
148 declare -i -g force_fail=1
149 declare -a -g error_stream
150
151 # shellcheck disable=SC2124
152 local error="[ERROR] $@"
153 error_stream+=("$error")
154 echo "$error"
155 return
156}
157
158## -----------------------------------------------------------------------
159## Intent: Given a list (header and data) format contents as a log entry
160## -----------------------------------------------------------------------
161## Usage: displayList --banner "List of something" "${data_stream[@]}"
162## -----------------------------------------------------------------------
163function displayList()
164{
165 local indent=''
166 while [ $# -gt 0 ]; do
Joey Armstrong0476e912024-02-09 16:00:26 -0500167 local arg="$1"
168 case "$arg" in
169 -*banner) shift; echo "$1" ;;
170 -*indent) shift; indent="$1" ;;
171 -*tab-2) echo -n ' ' ;;
172 -*tab-4) echo -n ' ' ;;
173 -*tab-6) echo -n ' ' ;;
174 -*tab-8) echo -n ' ' ;;
175 -*newline) echo; ;;
176 -*tab) echo -n ' ' ;;
177 *) break ;;
178 esac
179 shift
Joey Armstrongaebf1852022-12-09 08:34:13 -0500180 done
181
182 for line in "$@";
183 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500184 echo -e " ${indent}$line"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500185 done
186 return
187}
188
189## -----------------------------------------------------------------------
190## Intent: Program init, provide defaults for globals, etc.
191## -----------------------------------------------------------------------
192function init()
193{
194 # when not running under Jenkins, use current dir as workspace
195 # o [TODO] - Perform a secondary username check to guard against a
196 # jenkins/bash env hiccup leaving WORKSPACE= temporarily undefined.
197 WORKSPACE=${WORKSPACE:-.}
198 COMPARISON_BRANCH="${COMPARISON_BRANCH:-opencord/master}"
199 return
200}
201
202## -----------------------------------------------------------------------
203## Intent: Remove quotes, whitespace & garbage from a string
204## -----------------------------------------------------------------------
205## ..seealso: https://www.regular-expressions.info/posixbrackets.html
206## -----------------------------------------------------------------------
207function filter_codes()
208{
209 declare -n val="$1"; shift # indirect
210 val="${val//[\"\'[:blank:][:cntrl:]]}" # [:punct:] contains hyphen
211 return
212}
213
214## -----------------------------------------------------------------------
215## Intent: Detect and report VERSION file changes
216## -----------------------------------------------------------------------
217## :param path: Path to a Chart.yaml file.
218## :type path: str
219##
220## :param branch: Comparsion baranch (?-remote-?)
221## :type branch: str
222##
223## :return: true if embedded version string was modified.
224## :rtype: int
225## -----------------------------------------------------------------------
226## ..note: What about change detection for: apiVersion, appVersion (?)
227## -----------------------------------------------------------------------
228function version_diff()
229{
230 local path="$1"; shift
231 local branch="$1"; shift
232
233 declare -n old_var="$1"; shift # indirect
234 declare -n new_var="$1"; shift # indirect
235
236 old_var=''
237 new_var=''
238 readarray -t delta < <(git diff -p "$branch" -- "$path")
239
240 local modified=0
241 if [ ${#delta[@]} -gt 0 ]; then # modified
242
Joey Armstrong0476e912024-02-09 16:00:26 -0500243 #----------------------------------------
244 # diff --git a/voltha-adapter-openolt/Chart.yaml [...]
245 # --- a/voltha-adapter-openolt/Chart.yaml
246 # +++ b/voltha-adapter-openolt/Chart.yaml
247 # @@ -14,7 +14,7 @@
248 # ---
249 # -version: "2.11.3" (====> 2.11.3)
250 # +version: "2.11.8" (====> 2.11.8)
251 #----------------------------------------
252 local line
253 for line in "${delta[@]}";
254 do
255 # [TODO] Replace awk with string builtins to reduce shell overhead.
256 case "$line" in
257 -version:*)
258 modified=1
259 readarray -t tmp < <(awk '/^\-version:/ { print $2 }' <<<"$line")
260 # shellcheck disable=SC2034
261 old_var="${tmp[0]}"
262 filter_codes 'old_var'
263 ;;
264 +version:*)
265 readarray -t tmp < <(awk '/^\+version:/ { print $2 }' <<<"$line")
266 # shellcheck disable=SC2034
267 new_var="${tmp[0]}"
268 filter_codes 'new_var'
269 ;;
270 esac
271 done
Joey Armstrongaebf1852022-12-09 08:34:13 -0500272 fi
273
274 [ $modified -ne 0 ] # set $? for if/then/elif use: "if version_diff; then"
275 return
276}
277
278## -----------------------------------------------------------------------
279## Intent: Gather a list of Chart.yaml files from the workspace.
280## -----------------------------------------------------------------------
281function gather_charts()
282{
283 declare -n varname="$1"; shift
284 readarray -t varname < <(find . -name 'Chart.yaml' -print)
285
286 local idx
287 for (( idx=0; idx<${#varname[@]}; idx++ ));
288 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500289 local val="${varname[idx]}"
290 if [ ${#val} -lt 2 ]; then continue; fi
Joey Armstrongaebf1852022-12-09 08:34:13 -0500291
Joey Armstrong0476e912024-02-09 16:00:26 -0500292 # Normalize: remove './' to support path comparison
293 if [[ "${val:0:2}" == './' ]]; then
294 varname[idx]="${val:2:${#val}}"
295 [[ -v debug ]] && echo "[$idx] ${varname[$idx]}"
296 fi
Joey Armstrongaebf1852022-12-09 08:34:13 -0500297 done
298
299 [[ -v debug ]] && declare -p varname
300 return
301}
302
303## -----------------------------------------------------------------------
304## Intent: Given a chart file and complete list of modified files
305## display a list of files modified in the chart directory.
306## -----------------------------------------------------------------------
307## :param chart: path to a Chart.yaml file
308## :type chart: str
309##
310## :param varname: A list files modified in a git sandbox.
311## :type varname: list, indirect
312## -----------------------------------------------------------------------
313function report_modified()
314{
315 local chart="$1"; shift
316 local dir="${chart%/*}"
317 # shellcheck disable=SC2178
318 declare -n varname="$1"; shift
319
320 ## ---------------------------------------------
321 ## Gather files contained in the chart directory
322 ## ---------------------------------------------
323 declare -a found=()
324 for val in "${varname[@]}";
325 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500326 case "$val" in
327 */Chart.yaml) ;; # special case
328 "${dir}"*) found+=("$val") ;;
329 esac
Joey Armstrongaebf1852022-12-09 08:34:13 -0500330 done
331
332 ## --------------------------------------------
333 ## Display results when modified files detected
334 ## --------------------------------------------
335 if [ ${#found[@]} -gt 0 ]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500336 declare -a stream=()
337 stream+=('--tab-4')
338 stream+=('--banner' "Files Changed: $dir")
339 stream+=('--tab-6') # really --tab-8
340 stream+=("${found[@]}")
341 displayList "${stream[@]}"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500342 fi
343
344 [ ${#found[@]} -gt 0 ] # set $? for if/else
345 return
346}
347
348## -----------------------------------------------------------------------
349## Intent: Gather a list of Chart.yaml files from the workspace.
350## -----------------------------------------------------------------------
351declare -a -g charts=()
352declare -a -g changes_remote=()
353declare -a -g untracked_files=()
354function gather_state()
355{
356 local branch="$1"; shift
357
358 gather_charts 'charts'
359 [[ -v debug ]] && declare -p charts
360
361 readarray -t changes_remote < <(git diff --name-only "$branch")
362 [[ -v debug ]] && declare -p changes_remote
363
364 readarray -t untracked_files < <(git ls-files -o --exclude-standard)
365 [[ -v debug ]] && declare -p untracked_files
366
367 return
368}
369
370# shellcheck disable=SC1073
371##----------------##
372##---] MAIN [---##
373##----------------##
374init
375# shellcheck disable=SC2119
376banner
377gather_state "$COMPARISON_BRANCH"
378
379chart=''
380for chart in "${charts[@]}";
Zack Williams48542de2018-12-19 17:26:41 -0700381do
Joey Armstrongaebf1852022-12-09 08:34:13 -0500382 [[ -v debug ]] && echo -e "\nCHART: $chart"
Zack Williams48542de2018-12-19 17:26:41 -0700383
Joey Armstrongaebf1852022-12-09 08:34:13 -0500384 ## ---------------------------
385 ## Detect VERSION file changes
386 ## ---------------------------
387 declare -i chart_modified=0
388 old=''
389 new=''
390 if version_diff "$chart" "$COMPARISON_BRANCH" 'old' 'new'; then
Joey Armstrongf91c4372024-02-09 16:28:02 -0500391 version_for_display new
Joey Armstrong0476e912024-02-09 16:00:26 -0500392 suffix="($old => $new)" # display verion deltas in the right margin
393 printf '[CHART] %-60s %s\n' "$chart" "$suffix"
394 chart_modified=1
Zack Williams48542de2018-12-19 17:26:41 -0700395 else
Joey Armstrongf91c4372024-02-09 16:28:02 -0500396 if [[ ${#old} -eq 0 ]]; then
397 get_version_by_git old "$chart" "$COMPARISON_BRANCH"
398 fi
399 version_for_display old
Joey Armstrong0476e912024-02-09 16:00:26 -0500400 suffix="($old)"
401 printf '[CHART] %s\n' "$chart"
Joey Armstrongf91c4372024-02-09 16:28:02 -0500402 new="$old"
Zack Williams48542de2018-12-19 17:26:41 -0700403 fi
Zack Williams48542de2018-12-19 17:26:41 -0700404
Joey Armstrongaebf1852022-12-09 08:34:13 -0500405 ## -----------------------------------
406 ## Report modified files for the chart
407 ## -----------------------------------
408 declare -a combo_list=()
409 combo_list+=("${changes_remote[@]}")
410 combo_list+=("${untracked_files[@]}")
411 if report_modified "$chart" 'combo_list';
412 then
Joey Armstrong0476e912024-02-09 16:00:26 -0500413 if [ $chart_modified -eq 0 ]; then
Joey Armstrongf91c4372024-02-09 16:28:02 -0500414 version_for_display new
415 suffix="($old)"
416 error "Chart modified but version unchanged: ${chart} ${suffix}"
Joey Armstrong0476e912024-02-09 16:00:26 -0500417 fi
Joey Armstrongaebf1852022-12-09 08:34:13 -0500418 fi
Zack Williams48542de2018-12-19 17:26:41 -0700419
Joey Armstrongaebf1852022-12-09 08:34:13 -0500420done
421
422## ---------------------------
423## Report summary: local edits
424## ---------------------------
Joey Armstrong0f8656b2022-12-21 11:29:36 -0500425if [[ -x changes_remote ]] && [ ${#changes_remote} -gt 0 ]; then # local_edits
Joey Armstrongaebf1852022-12-09 08:34:13 -0500426 displayList \
Joey Armstrong0476e912024-02-09 16:00:26 -0500427 '--newline' \
428 '--banner' 'Changed Files:' \
429 "${changes_remote[@]}"
Zack Williams48542de2018-12-19 17:26:41 -0700430fi
431
Joey Armstrongaebf1852022-12-09 08:34:13 -0500432## -------------------------------
433## Report summary: untracked files
434## -------------------------------
Joey Armstrongb41d8cc2023-01-03 10:49:10 -0500435if [ ${#untracked_files[@]} -gt 0 ]; then
Joey Armstrongaebf1852022-12-09 08:34:13 -0500436 displayList \
Joey Armstrong0476e912024-02-09 16:00:26 -0500437 '--newline' \
438 '--banner' 'Untracked Files:' \
439 "${untracked_files[@]}"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500440fi
Zack Williams48542de2018-12-19 17:26:41 -0700441
Joey Armstrongaebf1852022-12-09 08:34:13 -0500442## ---------------------------------
443## Report summary: problems detected
444## ---------------------------------
445declare -a -g error_stream
446if [ ${#error_stream[@]} -gt 0 ]; then
447 displayList \
Joey Armstrong0476e912024-02-09 16:00:26 -0500448 '--newline' \
449 '--banner' 'Error Sumamry:' \
450 "${error_stream[@]}"
Joey Armstrongaebf1852022-12-09 08:34:13 -0500451fi
Zack Williams48542de2018-12-19 17:26:41 -0700452
Joey Armstrongaebf1852022-12-09 08:34:13 -0500453summary_status_with_exit $?
454
455# -----------------------------------------------------------------------
456# Running: chart_version_check.sh
457# -----------------------------------------------------------------------
458# Now: 2022-12-09 03:10:52
459# Git: git version 2.34.1
460# -----------------------------------------------------------------------
461# COMPARISON_BRANCH: origin/master
462# WORKSPACE: .
463# -----------------------------------------------------------------------
464# [CHART] voltha-adapter-openolt/Chart.yaml (2.11.3 => 2.11.8)
465# [CHART] voltha-tracing/Chart.yaml
466# [CHART] voltha/Chart.yaml
467# Files Changed: voltha-tracing
468# voltha-tracing/values.yaml
469# [ERROR] Chart modified but version unchanged: voltha-tracing
470# [CHART] voltha/Chart.yaml
471# -----------------------------------------------------------------------
472
473# [SEE ALSO
474# ---------------------------------------------------------------------------
475# https://www.regular-expressions.info/posixbrackets.html (character classes)
476# ---------------------------------------------------------------------------