blob: 3d365957f5873bfd82dacdb874c83bf4bf1ddc4c [file] [log] [blame]
Luca Prete1b823d62018-12-13 17:33:47 -08001#!/usr/bin/env bash
2
Joey Armstrong0476e912024-02-09 16:00:26 -05003# Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
Luca Prete1b823d62018-12-13 17:33:47 -08004#
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,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# helmrepo.sh
Zack Williams48542de2018-12-19 17:26:41 -070018# creates or updates a helm repo for publishing on the guide website
19# Reference: https://github.com/helm/charts/blob/master/test/repo-sync.sh
Luca Prete1b823d62018-12-13 17:33:47 -080020
21set -eu -o pipefail
22
Joey Armstronge9b327e2023-06-22 17:09:52 -040023##-------------------##
24##---] GLOBALS [---##
25##-------------------##
Zack Williams48542de2018-12-19 17:26:41 -070026
Luca Prete1b823d62018-12-13 17:33:47 -080027# when not running under Jenkins, use current dir as workspace
28WORKSPACE=${WORKSPACE:-.}
29
Zack Williams48542de2018-12-19 17:26:41 -070030# directory to compare against, doesn't need to be present
31OLD_REPO_DIR="${OLD_REPO_DIR:-cord-charts-repo}"
32NEW_REPO_DIR="${NEW_REPO_DIR:-chart_repo}"
Luca Prete1b823d62018-12-13 17:33:47 -080033
Luca Prete138c7762018-12-14 14:16:14 -080034PUBLISH_URL="${PUBLISH_URL:-charts.opencord.org}"
Luca Prete1b823d62018-12-13 17:33:47 -080035
Joey Armstronge9b327e2023-06-22 17:09:52 -040036## -----------------------------------------------------------------------
37## Intent: Dispay called function with given output
38## -----------------------------------------------------------------------
39function func_echo()
40{
41 echo "** ${FUNCNAME[1]}: $*"
42 return
43}
44
45## -----------------------------------------------------------------------
46## Intent: Display given text and exit with shell error status.
47## -----------------------------------------------------------------------
48function error()
49{
Joey Armstrong2a079642023-07-31 15:12:37 -040050 echo -e "** ${BASH_SOURCE[0]##*/}::${FUNCNAME[1]} ERROR: $*"
Joey Armstronge9b327e2023-06-22 17:09:52 -040051 exit 1
52}
53
54## -----------------------------------------------------------------------
Joey Armstrong2a079642023-07-31 15:12:37 -040055## Intent: Detect pre-existing versioned packages.
56## -----------------------------------------------------------------------
57function check_packages()
58{
59 local dir="$1"; shift
60
61 readarray -t package_paths < <(find "${dir}" -name '*.tgz' -print)
62 declare -p package_paths
63
64 # ---------------------------------------------
65 # Check for versioned package collision.
66 # ---------------------------------------------
67 for package_path in "${package_paths[@]}";
68 do
Joey Armstrong0476e912024-02-09 16:00:26 -050069 package="${package_path##*/}" # basename
70
71 if [ -f "${OLD_REPO_DIR}/${package}" ]; then
72 echo
73 echo "PACKAGE: $package"
74 /bin/ls -l "$package_path"
75 /bin/ls -l "${OLD_REPO_DIR}/${package}"
76 error "Package: ${package} with same version already exists in ${OLD_REPO_DIR}"
77 fi
Joey Armstrong2a079642023-07-31 15:12:37 -040078 done
79
80 return
81}
82
83## -----------------------------------------------------------------------
Joey Armstronge9b327e2023-06-22 17:09:52 -040084## Intent: Gather a list of Chart.yaml files from the filesystem.
85## -----------------------------------------------------------------------
86function get_chart_yaml()
87{
88 local dir="$1" ; shift
89 declare -n ref=$1 ; shift
90
91 readarray -t _charts < <(find "$dir" -name Chart.yaml -print | sort)
92 ref=("${_charts[@]}")
93 return
94}
95
96## -----------------------------------------------------------------------
Joey Armstrong2a079642023-07-31 15:12:37 -040097## Intent: Given a helm chart line extract and return *version.
98## -----------------------------------------------------------------------
99function getVersion()
100{
101 # shellcheck disable=SC2178
102 local -n ref=$1; shift # declare -A
103 local line="$1"; shift
104
105 [[ -v debug ]] && func_echo "LINE: $line"
106
107 # foo=${string#"$prefix"}
108
109 line="${line%\#*}" # Snip comments
110 line="${line//[[:blank:]]}" # Prune whitespace
111
112 # version : x.y.z
113 readarray -d':' -t _fields < <(printf '%s' "$line")
114
115 local key="${_fields[0]}"
116 local val="${_fields[1]}"
Eric Ball0d7a0e62024-11-14 13:07:04 -0800117 # shellcheck disable=SC2004
Joey Armstrong2a079642023-07-31 15:12:37 -0400118 ref[$key]="$val"
119
120 return
121}
122
123## -----------------------------------------------------------------------
Joey Armstronge9b327e2023-06-22 17:09:52 -0400124## Intent: Update helm package dependencies
125## -----------------------------------------------------------------------
126function helm_deps_update()
127{
128 local dest="$1"; shift # helm --destination
129
130 if [[ -v dry_run ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500131 func_echo "helm package --dependency-update --destination $dest $chartdir"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400132 else
Joey Armstrong0476e912024-02-09 16:00:26 -0500133 helm package --dependency-update --destination "$dest" "$chartdir"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400134 fi
135 return
136}
137
138## -----------------------------------------------------------------------
139## Intent: Update helm package index
140## -----------------------------------------------------------------------
141function helm_index_publish()
142{
143 local repo_dir="$1"; shift # helm --destination
144
145 if [[ -v dry_run ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500146 func_echo "helm repo index $repo_dir --url https://${PUBLISH_URL}"
Joey Armstrong2a079642023-07-31 15:12:37 -0400147
148 elif [[ -v no_publish ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500149 func_echo "[SKIP] helm publishing due to --no-publish"
150
Joey Armstronge9b327e2023-06-22 17:09:52 -0400151 else
Joey Armstrong0476e912024-02-09 16:00:26 -0500152 ## ------------------------------------------------
153 ## Helm updates are guarded by jenkins
154 ## Revision control should reinforce that assertion
155 ## ------------------------------------------------
156 case "$USER" in
157 jenkins)
158 helm repo index "$repo_dir" --url https://"${PUBLISH_URL}"
159 ;;
160 *)
161 func_echo "[SKIP] helm publishing due to ($USER != jenkins)"
162 ;;
163 esac
Joey Armstronge9b327e2023-06-22 17:09:52 -0400164 fi
Joey Armstrong2a079642023-07-31 15:12:37 -0400165
Joey Armstronge9b327e2023-06-22 17:09:52 -0400166 return
167}
168
169## -----------------------------------------------------------------------
170## Intent: Update helm package index
171## -----------------------------------------------------------------------
172function helm_index_merge()
173{
174 local old_repo="$1" ; shift
175 local new_repo="$1" ; shift
176
177 declare -a cmd=()
178 cmd+=('helm' 'repo' 'index')
179 cmd+=('--url' "https://${PUBLISH_URL}")
180 cmd+=('--merge' "${old_repo}/index.yaml" "$new_repo")
181
182 if [[ -v dry_run ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500183 func_echo "${cmd[@]}"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400184 else
Joey Armstrong0476e912024-02-09 16:00:26 -0500185 "${cmd[@]}"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400186 fi
187 return
188}
189
190## -----------------------------------------------------------------------
191## Intent: Given a Chart.yaml file path return test directory where stored
192## -----------------------------------------------------------------------
193function chart_path_to_test_dir()
194{
195 local val="$1" ; shift
196
Joey Armstrong0476e912024-02-09 16:00:26 -0500197 # shellcheck disable=SC2178
198 declare -n ref=$1 ; shift # indirect var
Joey Armstronge9b327e2023-06-22 17:09:52 -0400199
200 val="${val%/Chart.yaml}" # dirname: prune /Chart.yaml
201 val="${val##*/}" # basename: test directory
202
Joey Armstrong0476e912024-02-09 16:00:26 -0500203 # shellcheck disable=SC2034,SC2178
Joey Armstronge9b327e2023-06-22 17:09:52 -0400204 ref="$val" # Return value to caller
205 return
206}
207
208## -----------------------------------------------------------------------
Joey Armstrong2a079642023-07-31 15:12:37 -0400209## Intent: Given Chart.yaml files create a new indexed chart repository
Joey Armstronge9b327e2023-06-22 17:09:52 -0400210## -----------------------------------------------------------------------
211function create_helm_repo_new()
212{
213 local repo_dir="$1"; shift # NEW_REPO_DIR
214 local work_dir="$1"; shift # WORKSPACE
215
216 echo "Creating new helm repo: ${repo_dir}"
217
218 declare -a charts=()
219 get_chart_yaml "$work_dir" charts
220
221 local chart
222 for chart in "${charts[@]}";
223 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500224 echo
225 func_echo "Chart.yaml: $chart"
Joey Armstrong2a079642023-07-31 15:12:37 -0400226
Joey Armstrong0476e912024-02-09 16:00:26 -0500227 chartdir=''
228 chart_path_to_test_dir "$chart" chartdir
229 func_echo " Chart.dir: $chartdir"
Joey Armstrong2a079642023-07-31 15:12:37 -0400230
Joey Armstrong0476e912024-02-09 16:00:26 -0500231 helm_deps_update "${repo_dir}"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400232 done
Joey Armstrong2a079642023-07-31 15:12:37 -0400233
Joey Armstronge9b327e2023-06-22 17:09:52 -0400234 helm_index_publish "${repo_dir}"
Joey Armstrong2a079642023-07-31 15:12:37 -0400235
236 return
237}
238
239## -----------------------------------------------------------------------
240## Intent: Compare version stings extracted from Chart.yaml delta.
241## o attribute version:x.y.z must be changed to enable change
242## detection and chart loading.
243## -----------------------------------------------------------------------
244function validate_changes()
245{
Joey Armstrong0476e912024-02-09 16:00:26 -0500246 local chart="$1"; shift
Joey Armstrong2a079642023-07-31 15:12:37 -0400247 # shellcheck disable=SC2178
248 local -n ref=$1; shift
249
250 local msg
251 ## -------------------------------------------
252 ## Validation logic: all keys collected exist
253 ## Chart version must change to enable loading
254 ## -------------------------------------------
255 local key0
256 for key0 in "${!ref[@]}";
257 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500258 local key="${key0:1}"
259 # shellcheck disable=SC2034
260 local old="-${key}"
261 local new="+${key}"
Joey Armstrong2a079642023-07-31 15:12:37 -0400262
Joey Armstrong0476e912024-02-09 16:00:26 -0500263 ## Key/val paris are diff deltas:
264 ## -version : 1.2.3
265 ## +version : 4.5.6
266 if [[ ! -v ref['-version'] ]]; then
Eric Balled4451c2024-11-13 14:57:55 -0800267 msg='Modify version to publish chart changes'
Joey Armstrong0476e912024-02-09 16:00:26 -0500268 elif [[ ! -v ref["$new"] ]]; then
Eric Balled4451c2024-11-13 14:57:55 -0800269 msg="Failed to detect +${key} change in attributes"
Joey Armstrong0476e912024-02-09 16:00:26 -0500270 else
271 continue
272 fi
Joey Armstrong2a079642023-07-31 15:12:37 -0400273
Joey Armstrong0476e912024-02-09 16:00:26 -0500274 local -i failed=1
275 cat <<ERR
Joey Armstrong2a079642023-07-31 15:12:37 -0400276
277** -----------------------------------------------------------------------
278** Chart dir: $chartdir
279** Chart.yml: $chart
280** Error: $msg
281** -----------------------------------------------------------------------
282ERR
Joey Armstrong0476e912024-02-09 16:00:26 -0500283 func_echo "$(declare -p versions | sed -e 's/\[/\n\[/g')"
Joey Armstrong2a079642023-07-31 15:12:37 -0400284 done
285
286 if [[ -v failed ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500287 false
Joey Armstrong2a079642023-07-31 15:12:37 -0400288 else
Joey Armstrong0476e912024-02-09 16:00:26 -0500289 true
Joey Armstrong2a079642023-07-31 15:12:37 -0400290 fi
291
Joey Armstronge9b327e2023-06-22 17:09:52 -0400292 return
293}
294
295##----------------##
296##---] MAIN [---##
297##----------------##
298
299while [ $# -gt 0 ]; do
300 arg="$1"; shift
301
302 case "$arg" in
Joey Armstrong0476e912024-02-09 16:00:26 -0500303 -*debug) declare -g -i debug=1 ;;
304 -*dry*) declare -g -i dry_run=1 ;;
305 -*no-publish) declare -g -i no_publish=1 ;;
306 -*help)
307 cat <<EOH
Joey Armstronge9b327e2023-06-22 17:09:52 -0400308Usage: $0
309 --debug Enable debug mode
310 --dry-run Simulate helm calls
311EOH
Joey Armstrong0476e912024-02-09 16:00:26 -0500312 ;;
Joey Armstrong2a079642023-07-31 15:12:37 -0400313
Joey Armstrong0476e912024-02-09 16:00:26 -0500314 -*) echo "[SKIP] unknown switch [$arg]" ;;
315 *) echo "[SKIP] unknown argument [$arg]" ;;
Joey Armstronge9b327e2023-06-22 17:09:52 -0400316 esac
317done
318
319
320echo "# helmrepo.sh, using helm: $(helm version -c) #"
321
Zack Williams48542de2018-12-19 17:26:41 -0700322# create and clean NEW_REPO_DIR
323mkdir -p "${NEW_REPO_DIR}"
324rm -f "${NEW_REPO_DIR}"/*
Luca Prete94d95192018-12-14 09:56:00 -0800325
Zack Williams48542de2018-12-19 17:26:41 -0700326# if OLD_REPO_DIR doesn't exist, generate packages and index in NEW_REPO_DIR
327if [ ! -d "${OLD_REPO_DIR}" ]
328then
Joey Armstronge9b327e2023-06-22 17:09:52 -0400329 create_helm_repo_new "$NEW_REPO_DIR" "$WORKSPACE"
330 echo
331 echo "# helmrepo.sh Success! Generated new repo index in ${NEW_REPO_DIR}"
Luca Prete1b823d62018-12-13 17:33:47 -0800332
Zack Williams48542de2018-12-19 17:26:41 -0700333else
Joey Armstrong0476e912024-02-09 16:00:26 -0500334 # OLD_REPO_DIR exists, check for new charts and update only with changes
335 echo "Found existing helm repo: ${OLD_REPO_DIR}, attempting update"
Luca Prete1b823d62018-12-13 17:33:47 -0800336
Joey Armstrong0476e912024-02-09 16:00:26 -0500337 # Loop and create chart packages, only if changed
338 declare -a charts=()
339 get_chart_yaml "$WORKSPACE" charts
Joey Armstronge9b327e2023-06-22 17:09:52 -0400340
Joey Armstrong0476e912024-02-09 16:00:26 -0500341 for chart in "${charts[@]}";
342 do
343 echo
344 func_echo "Chart.yaml: $chart"
Luca Prete1b823d62018-12-13 17:33:47 -0800345
Joey Armstrong0476e912024-02-09 16:00:26 -0500346 chartdir=''
347 chart_path_to_test_dir "$chart" chartdir
348 func_echo " Chart.dir: $chartdir"
Luca Prete05ba35b2018-12-14 11:08:12 -0800349
Joey Armstrong0476e912024-02-09 16:00:26 -0500350 # See if chart version changed from previous HEAD commit
351 readarray -t chart_yaml_diff < <(git diff -p HEAD^ -- "$chart")
Joey Armstrong2a079642023-07-31 15:12:37 -0400352
Joey Armstrong0476e912024-02-09 16:00:26 -0500353 if [[ ! -v chart_yaml_diff ]]; then
354 echo "Chart unchanged, not packaging: '${chartdir}'"
Luca Prete1b823d62018-12-13 17:33:47 -0800355
Joey Armstrong0476e912024-02-09 16:00:26 -0500356 # -------------------------------------------------------------------
357 # Assumes that helmlint.sh and chart_version_check.sh have been run
358 # pre-merge, which ensures that all charts are valid and have their
359 # version updated in Chart.yaml
360 # -------------------------------------------------------------------
361 elif [ ${#chart_yaml_diff} -gt 0 ]; then
362 declare -A versions=()
363 for line in "${chart_yaml_diff[@]}";
364 do
365 [[ -v debug ]] && func_echo "$line"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400366
Joey Armstrong0476e912024-02-09 16:00:26 -0500367 case "$line" in
368 # appVersion: "1.0.3"
369 # version: 1.2.3
Eric Balled4451c2024-11-13 14:57:55 -0800370 [-+]*[vV]ersion*:*) getVersion versions "$line" ;;
Joey Armstrong0476e912024-02-09 16:00:26 -0500371 esac
372 done
Joey Armstronge9b327e2023-06-22 17:09:52 -0400373
Joey Armstrong0476e912024-02-09 16:00:26 -0500374 # ---------------------------------------------------------------
375 # [TODO] -- versions['-version']='version string change required'
376 # ---------------------------------------------------------------
377 # version: string change initiates a delta forcing helm to update.
378 # Should it be required by every checkin ? For ex: release may
379 # accumulate several version edits then publish all when finished.
380 #
381 # Danger would be chart changes are not published/tested when
382 # a dev forgets to update the chart version string.
383 # ---------------------------------------------------------------
Joey Armstronge9b327e2023-06-22 17:09:52 -0400384
Joey Armstrong0476e912024-02-09 16:00:26 -0500385 ## ---------------------------------------------------------------
386 ## Check for required version change and stray attribute deletions
387 ## We are comparing diff output [-+]verison : x.y
388 ## +{key} indicates a required attribute exists and was modified
389 ## ---------------------------------------------------------------
390 if ! validate_changes "$chart" versions; then
391 declare -g -i failed=1
392 continue
393 fi
Joey Armstronge9b327e2023-06-22 17:09:52 -0400394
Joey Armstrong0476e912024-02-09 16:00:26 -0500395 # Always query, version string may not have changed
396 readarray -t ver < <(grep -oP '(?<= version: )\S+' "$chart")
397 declare -p ver
Joey Armstrong2a079642023-07-31 15:12:37 -0400398
Joey Armstrong0476e912024-02-09 16:00:26 -0500399 echo "Detected new version of chart ${chartdir}, creating package: ${ver[*]}"
Joey Armstrong2a079642023-07-31 15:12:37 -0400400
Joey Armstrong0476e912024-02-09 16:00:26 -0500401 helm_deps_update "${NEW_REPO_DIR}"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400402
Joey Armstrong0476e912024-02-09 16:00:26 -0500403 else
404 echo "Chart unchanged, not packaging: '${chartdir}'"
405 fi
406 done
Joey Armstronge9b327e2023-06-22 17:09:52 -0400407
Joey Armstrong0476e912024-02-09 16:00:26 -0500408 check_packages "$NEW_REPO_DIR"
Zack Williams48542de2018-12-19 17:26:41 -0700409
Joey Armstrong0476e912024-02-09 16:00:26 -0500410 ## -----------------------------------------------------------------------
411 ## -----------------------------------------------------------------------
412 # only update index when new charts are added
413 if [ ${#package_paths[@]} -gt 0 ]; then
Zack Williams48542de2018-12-19 17:26:41 -0700414
Joey Armstrong0476e912024-02-09 16:00:26 -0500415 # Create updated index.yaml (new version created in NEW_REPO_DIR)
416 helm_index_merge "${OLD_REPO_DIR}" "${NEW_REPO_DIR}"
Zack Williams48542de2018-12-19 17:26:41 -0700417
Joey Armstrong0476e912024-02-09 16:00:26 -0500418 # move over packages and index.yaml
419 mv "${NEW_REPO_DIR}"/*.tgz "${OLD_REPO_DIR}/"
420 mv "${NEW_REPO_DIR}/index.yaml" "${OLD_REPO_DIR}/index.yaml"
Zack Williams48542de2018-12-19 17:26:41 -0700421
Joey Armstrong0476e912024-02-09 16:00:26 -0500422 echo "# helmrepo.sh Success! Updated existing repo index in ${OLD_REPO_DIR}"
Zack Williams2f075ea2019-01-03 14:20:29 -0700423
Joey Armstrong0476e912024-02-09 16:00:26 -0500424 else
425 echo "# helmrepo.sh Success! No new charts added."
426 fi
Zack Williams48542de2018-12-19 17:26:41 -0700427fi
428
429exit 0
Joey Armstrong2a079642023-07-31 15:12:37 -0400430
431# [EOF]