blob: 455e225e82c9dbf7c9be961a4df8e9a80966ac95 [file] [log] [blame]
Zack Williams48542de2018-12-19 17:26:41 -07001#!/usr/bin/env bash
Joey Armstrongaebf1852022-12-09 08:34:13 -05002# ---------------------------------------------------------------------------
3# Copyright 2018-2022 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## -----------------------------------------------------------------------
58## Intent: Display a log summary entry then exit with status.
59## -----------------------------------------------------------------------
60function summary_status_with_exit()
61{
62 local exit_code=$1; shift
63 local program="${0##*/}"
64 local summary=''
65 [[ $# -gt 0 ]] && { summary=" - $1"; shift; }
Zack Williams48542de2018-12-19 17:26:41 -070066
Joey Armstrongaebf1852022-12-09 08:34:13 -050067 ## -----------------------------------
68 ## status override courtesy of error()
69 ## -----------------------------------
70 declare -i -g force_fail
71 if [ $force_fail -eq 1 ]; then exit_code=$force_fail; fi
Zack Williams48542de2018-12-19 17:26:41 -070072
Joey Armstrongaebf1852022-12-09 08:34:13 -050073 ## --------------------------
74 ## Set summary display string
75 ## --------------------------
76 case "$exit_code" in
77 0) status='PASS' ;;
78 *) status='FAIL' ;;
79 esac
80
81 [[ $# -gt 0 ]] && formatStream "$@"
82
83 echo
84 echo "[$status] ${program} ${summary}"
85
86 exit $exit_code
87}
88
89## -----------------------------------------------------------------------
90## Intent: Display an error and configure report summary_status as FAIL
91## -----------------------------------------------------------------------
92function error()
93{
94 declare -i -g force_fail=1
95 declare -a -g error_stream
96
97 # shellcheck disable=SC2124
98 local error="[ERROR] $@"
99 error_stream+=("$error")
100 echo "$error"
101 return
102}
103
104## -----------------------------------------------------------------------
105## Intent: Given a list (header and data) format contents as a log entry
106## -----------------------------------------------------------------------
107## Usage: displayList --banner "List of something" "${data_stream[@]}"
108## -----------------------------------------------------------------------
109function displayList()
110{
111 local indent=''
112 while [ $# -gt 0 ]; do
113 local arg="$1"
114 case "$arg" in
115 -*banner) shift; echo "$1" ;;
116 -*indent) shift; indent="$1" ;;
117 -*tab-2) echo -n ' ' ;;
118 -*tab-4) echo -n ' ' ;;
119 -*tab-6) echo -n ' ' ;;
120 -*tab-8) echo -n ' ' ;;
121 -*newline) echo; ;;
122 -*tab) echo -n ' ' ;;
123 *) break ;;
124 esac
125 shift
126 done
127
128 for line in "$@";
129 do
130 echo -e " ${indent}$line"
131 done
132 return
133}
134
135## -----------------------------------------------------------------------
136## Intent: Program init, provide defaults for globals, etc.
137## -----------------------------------------------------------------------
138function init()
139{
140 # when not running under Jenkins, use current dir as workspace
141 # o [TODO] - Perform a secondary username check to guard against a
142 # jenkins/bash env hiccup leaving WORKSPACE= temporarily undefined.
143 WORKSPACE=${WORKSPACE:-.}
144 COMPARISON_BRANCH="${COMPARISON_BRANCH:-opencord/master}"
145 return
146}
147
148## -----------------------------------------------------------------------
149## Intent: Remove quotes, whitespace & garbage from a string
150## -----------------------------------------------------------------------
151## ..seealso: https://www.regular-expressions.info/posixbrackets.html
152## -----------------------------------------------------------------------
153function filter_codes()
154{
155 declare -n val="$1"; shift # indirect
156 val="${val//[\"\'[:blank:][:cntrl:]]}" # [:punct:] contains hyphen
157 return
158}
159
160## -----------------------------------------------------------------------
161## Intent: Detect and report VERSION file changes
162## -----------------------------------------------------------------------
163## :param path: Path to a Chart.yaml file.
164## :type path: str
165##
166## :param branch: Comparsion baranch (?-remote-?)
167## :type branch: str
168##
169## :return: true if embedded version string was modified.
170## :rtype: int
171## -----------------------------------------------------------------------
172## ..note: What about change detection for: apiVersion, appVersion (?)
173## -----------------------------------------------------------------------
174function version_diff()
175{
176 local path="$1"; shift
177 local branch="$1"; shift
178
179 declare -n old_var="$1"; shift # indirect
180 declare -n new_var="$1"; shift # indirect
181
182 old_var=''
183 new_var=''
184 readarray -t delta < <(git diff -p "$branch" -- "$path")
185
186 local modified=0
187 if [ ${#delta[@]} -gt 0 ]; then # modified
188
189 #----------------------------------------
190 # diff --git a/voltha-adapter-openolt/Chart.yaml [...]
191 # --- a/voltha-adapter-openolt/Chart.yaml
192 # +++ b/voltha-adapter-openolt/Chart.yaml
193 # @@ -14,7 +14,7 @@
194 # ---
195 # -version: "2.11.3" (====> 2.11.3)
196 # +version: "2.11.8" (====> 2.11.8)
197 #----------------------------------------
198 local line
199 for line in "${delta[@]}";
200 do
201 # [TODO] Replace awk with string builtins to reduce shell overhead.
202 case "$line" in
203 -version:*)
204 modified=1
205 readarray -t tmp < <(awk '/^\-version:/ { print $2 }' <<<"$line")
206 # shellcheck disable=SC2034
207 old_var="${tmp[0]}"
208 filter_codes 'old_var'
209 ;;
210 +version:*)
211 readarray -t tmp < <(awk '/^\+version:/ { print $2 }' <<<"$line")
212 # shellcheck disable=SC2034
213 new_var="${tmp[0]}"
214 filter_codes 'new_var'
215 ;;
216 esac
217 done
218 fi
219
220 [ $modified -ne 0 ] # set $? for if/then/elif use: "if version_diff; then"
221 return
222}
223
224## -----------------------------------------------------------------------
225## Intent: Gather a list of Chart.yaml files from the workspace.
226## -----------------------------------------------------------------------
227function gather_charts()
228{
229 declare -n varname="$1"; shift
230 readarray -t varname < <(find . -name 'Chart.yaml' -print)
231
232 local idx
233 for (( idx=0; idx<${#varname[@]}; idx++ ));
234 do
235 local val="${varname[idx]}"
236 if [ ${#val} -lt 2 ]; then continue; fi
237
238 # Normalize: remove './' to support path comparison
239 if [[ "${val:0:2}" == './' ]]; then
240 varname[idx]="${val:2:${#val}}"
241 [[ -v debug ]] && echo "[$idx] ${varname[$idx]}"
242 fi
243 done
244
245 [[ -v debug ]] && declare -p varname
246 return
247}
248
249## -----------------------------------------------------------------------
250## Intent: Given a chart file and complete list of modified files
251## display a list of files modified in the chart directory.
252## -----------------------------------------------------------------------
253## :param chart: path to a Chart.yaml file
254## :type chart: str
255##
256## :param varname: A list files modified in a git sandbox.
257## :type varname: list, indirect
258## -----------------------------------------------------------------------
259function report_modified()
260{
261 local chart="$1"; shift
262 local dir="${chart%/*}"
263 # shellcheck disable=SC2178
264 declare -n varname="$1"; shift
265
266 ## ---------------------------------------------
267 ## Gather files contained in the chart directory
268 ## ---------------------------------------------
269 declare -a found=()
270 for val in "${varname[@]}";
271 do
272 case "$val" in
273 */Chart.yaml) ;; # special case
274 "${dir}"*) found+=("$val") ;;
275 esac
276 done
277
278 ## --------------------------------------------
279 ## Display results when modified files detected
280 ## --------------------------------------------
281 if [ ${#found[@]} -gt 0 ]; then
282 declare -a stream=()
283 stream+=('--tab-4')
284 stream+=('--banner' "Files Changed: $dir")
285 stream+=('--tab-6') # really --tab-8
286 stream+=("${found[@]}")
287 displayList "${stream[@]}"
288 fi
289
290 [ ${#found[@]} -gt 0 ] # set $? for if/else
291 return
292}
293
294## -----------------------------------------------------------------------
295## Intent: Gather a list of Chart.yaml files from the workspace.
296## -----------------------------------------------------------------------
297declare -a -g charts=()
298declare -a -g changes_remote=()
299declare -a -g untracked_files=()
300function gather_state()
301{
302 local branch="$1"; shift
303
304 gather_charts 'charts'
305 [[ -v debug ]] && declare -p charts
306
307 readarray -t changes_remote < <(git diff --name-only "$branch")
308 [[ -v debug ]] && declare -p changes_remote
309
310 readarray -t untracked_files < <(git ls-files -o --exclude-standard)
311 [[ -v debug ]] && declare -p untracked_files
312
313 return
314}
315
316# shellcheck disable=SC1073
317##----------------##
318##---] MAIN [---##
319##----------------##
320init
321# shellcheck disable=SC2119
322banner
323gather_state "$COMPARISON_BRANCH"
324
325chart=''
326for chart in "${charts[@]}";
Zack Williams48542de2018-12-19 17:26:41 -0700327do
Joey Armstrongaebf1852022-12-09 08:34:13 -0500328 [[ -v debug ]] && echo -e "\nCHART: $chart"
Zack Williams48542de2018-12-19 17:26:41 -0700329
Joey Armstrongaebf1852022-12-09 08:34:13 -0500330 chart_dir="${chart%/*}"
Zack Williams48542de2018-12-19 17:26:41 -0700331
Joey Armstrongaebf1852022-12-09 08:34:13 -0500332 ## ---------------------------
333 ## Detect VERSION file changes
334 ## ---------------------------
335 declare -i chart_modified=0
336 old=''
337 new=''
338 if version_diff "$chart" "$COMPARISON_BRANCH" 'old' 'new'; then
339 suffix="($old => $new)" # display verion deltas in the right margin
340 printf '[CHART] %-60s %s\n' "$chart" "$suffix"
341 chart_modified=1
Zack Williams48542de2018-12-19 17:26:41 -0700342 else
Joey Armstrongaebf1852022-12-09 08:34:13 -0500343 suffix="($old)"
344 printf '[CHART] %s\n' "$chart"
Zack Williams48542de2018-12-19 17:26:41 -0700345 fi
Zack Williams48542de2018-12-19 17:26:41 -0700346
Joey Armstrongaebf1852022-12-09 08:34:13 -0500347 ## -----------------------------------
348 ## Report modified files for the chart
349 ## -----------------------------------
350 declare -a combo_list=()
351 combo_list+=("${changes_remote[@]}")
352 combo_list+=("${untracked_files[@]}")
353 if report_modified "$chart" 'combo_list';
354 then
355 if [ $chart_modified -eq 0 ]; then
356 error "Chart modified but version unchanged: ${chart_dir}"
357 fi
358 fi
Zack Williams48542de2018-12-19 17:26:41 -0700359
Joey Armstrongaebf1852022-12-09 08:34:13 -0500360done
361
362## ---------------------------
363## Report summary: local edits
364## ---------------------------
365if [ ${#changes_remote} -gt 0 ]; then # local_edits
366 displayList \
367 '--newline' \
368 '--banner' 'Changed Files:' \
369 "${changes_remote[@]}"
Zack Williams48542de2018-12-19 17:26:41 -0700370fi
371
Joey Armstrongaebf1852022-12-09 08:34:13 -0500372## -------------------------------
373## Report summary: untracked files
374## -------------------------------
375if [ ${#untracked_files} -gt 0 ]; then
376 displayList \
377 '--newline' \
378 '--banner' 'Untracked Files:' \
379 "${untracked_files[@]}"
380fi
Zack Williams48542de2018-12-19 17:26:41 -0700381
Joey Armstrongaebf1852022-12-09 08:34:13 -0500382## ---------------------------------
383## Report summary: problems detected
384## ---------------------------------
385declare -a -g error_stream
386if [ ${#error_stream[@]} -gt 0 ]; then
387 displayList \
388 '--newline' \
389 '--banner' 'Error Sumamry:' \
390 "${error_stream[@]}"
391fi
Zack Williams48542de2018-12-19 17:26:41 -0700392
Joey Armstrongaebf1852022-12-09 08:34:13 -0500393summary_status_with_exit $?
394
395# -----------------------------------------------------------------------
396# Running: chart_version_check.sh
397# -----------------------------------------------------------------------
398# Now: 2022-12-09 03:10:52
399# Git: git version 2.34.1
400# -----------------------------------------------------------------------
401# COMPARISON_BRANCH: origin/master
402# WORKSPACE: .
403# -----------------------------------------------------------------------
404# [CHART] voltha-adapter-openolt/Chart.yaml (2.11.3 => 2.11.8)
405# [CHART] voltha-tracing/Chart.yaml
406# [CHART] voltha/Chart.yaml
407# Files Changed: voltha-tracing
408# voltha-tracing/values.yaml
409# [ERROR] Chart modified but version unchanged: voltha-tracing
410# [CHART] voltha/Chart.yaml
411# -----------------------------------------------------------------------
412
413# [SEE ALSO
414# ---------------------------------------------------------------------------
415# https://www.regular-expressions.info/posixbrackets.html (character classes)
416# ---------------------------------------------------------------------------