blob: 8f23a9abd32f2b7b5f874b518c3845309570e06f [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
Joey Armstrong2a079642023-07-31 15:12:37 -0400107 # version : x.y.z
108 readarray -d':' -t _fields < <(printf '%s' "$line")
109
110 local key="${_fields[0]}"
111 local val="${_fields[1]}"
Eric Ball0d7a0e62024-11-14 13:07:04 -0800112 # shellcheck disable=SC2004
Joey Armstrong2a079642023-07-31 15:12:37 -0400113 ref[$key]="$val"
114
115 return
116}
117
118## -----------------------------------------------------------------------
Joey Armstronge9b327e2023-06-22 17:09:52 -0400119## Intent: Update helm package dependencies
120## -----------------------------------------------------------------------
121function helm_deps_update()
122{
123 local dest="$1"; shift # helm --destination
124
125 if [[ -v dry_run ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500126 func_echo "helm package --dependency-update --destination $dest $chartdir"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400127 else
Joey Armstrong0476e912024-02-09 16:00:26 -0500128 helm package --dependency-update --destination "$dest" "$chartdir"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400129 fi
130 return
131}
132
133## -----------------------------------------------------------------------
134## Intent: Update helm package index
135## -----------------------------------------------------------------------
136function helm_index_publish()
137{
138 local repo_dir="$1"; shift # helm --destination
139
140 if [[ -v dry_run ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500141 func_echo "helm repo index $repo_dir --url https://${PUBLISH_URL}"
Joey Armstrong2a079642023-07-31 15:12:37 -0400142
143 elif [[ -v no_publish ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500144 func_echo "[SKIP] helm publishing due to --no-publish"
145
Joey Armstronge9b327e2023-06-22 17:09:52 -0400146 else
Joey Armstrong0476e912024-02-09 16:00:26 -0500147 ## ------------------------------------------------
148 ## Helm updates are guarded by jenkins
149 ## Revision control should reinforce that assertion
150 ## ------------------------------------------------
151 case "$USER" in
152 jenkins)
153 helm repo index "$repo_dir" --url https://"${PUBLISH_URL}"
154 ;;
155 *)
156 func_echo "[SKIP] helm publishing due to ($USER != jenkins)"
157 ;;
158 esac
Joey Armstronge9b327e2023-06-22 17:09:52 -0400159 fi
Joey Armstrong2a079642023-07-31 15:12:37 -0400160
Joey Armstronge9b327e2023-06-22 17:09:52 -0400161 return
162}
163
164## -----------------------------------------------------------------------
165## Intent: Update helm package index
166## -----------------------------------------------------------------------
167function helm_index_merge()
168{
169 local old_repo="$1" ; shift
170 local new_repo="$1" ; shift
171
172 declare -a cmd=()
173 cmd+=('helm' 'repo' 'index')
174 cmd+=('--url' "https://${PUBLISH_URL}")
175 cmd+=('--merge' "${old_repo}/index.yaml" "$new_repo")
176
177 if [[ -v dry_run ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500178 func_echo "${cmd[@]}"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400179 else
Joey Armstrong0476e912024-02-09 16:00:26 -0500180 "${cmd[@]}"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400181 fi
182 return
183}
184
185## -----------------------------------------------------------------------
186## Intent: Given a Chart.yaml file path return test directory where stored
187## -----------------------------------------------------------------------
188function chart_path_to_test_dir()
189{
190 local val="$1" ; shift
191
Joey Armstrong0476e912024-02-09 16:00:26 -0500192 # shellcheck disable=SC2178
193 declare -n ref=$1 ; shift # indirect var
Joey Armstronge9b327e2023-06-22 17:09:52 -0400194
195 val="${val%/Chart.yaml}" # dirname: prune /Chart.yaml
196 val="${val##*/}" # basename: test directory
197
Joey Armstrong0476e912024-02-09 16:00:26 -0500198 # shellcheck disable=SC2034,SC2178
Joey Armstronge9b327e2023-06-22 17:09:52 -0400199 ref="$val" # Return value to caller
200 return
201}
202
203## -----------------------------------------------------------------------
Joey Armstrong2a079642023-07-31 15:12:37 -0400204## Intent: Given Chart.yaml files create a new indexed chart repository
Joey Armstronge9b327e2023-06-22 17:09:52 -0400205## -----------------------------------------------------------------------
206function create_helm_repo_new()
207{
208 local repo_dir="$1"; shift # NEW_REPO_DIR
209 local work_dir="$1"; shift # WORKSPACE
210
211 echo "Creating new helm repo: ${repo_dir}"
212
213 declare -a charts=()
214 get_chart_yaml "$work_dir" charts
215
216 local chart
217 for chart in "${charts[@]}";
218 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500219 echo
220 func_echo "Chart.yaml: $chart"
Joey Armstrong2a079642023-07-31 15:12:37 -0400221
Joey Armstrong0476e912024-02-09 16:00:26 -0500222 chartdir=''
223 chart_path_to_test_dir "$chart" chartdir
224 func_echo " Chart.dir: $chartdir"
Joey Armstrong2a079642023-07-31 15:12:37 -0400225
Joey Armstrong0476e912024-02-09 16:00:26 -0500226 helm_deps_update "${repo_dir}"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400227 done
Joey Armstrong2a079642023-07-31 15:12:37 -0400228
Joey Armstronge9b327e2023-06-22 17:09:52 -0400229 helm_index_publish "${repo_dir}"
Joey Armstrong2a079642023-07-31 15:12:37 -0400230
231 return
232}
233
234## -----------------------------------------------------------------------
235## Intent: Compare version stings extracted from Chart.yaml delta.
236## o attribute version:x.y.z must be changed to enable change
237## detection and chart loading.
238## -----------------------------------------------------------------------
239function validate_changes()
240{
Joey Armstrong0476e912024-02-09 16:00:26 -0500241 local chart="$1"; shift
Joey Armstrong2a079642023-07-31 15:12:37 -0400242 # shellcheck disable=SC2178
243 local -n ref=$1; shift
244
245 local msg
246 ## -------------------------------------------
247 ## Validation logic: all keys collected exist
248 ## Chart version must change to enable loading
249 ## -------------------------------------------
250 local key0
251 for key0 in "${!ref[@]}";
252 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500253 local key="${key0:1}"
254 # shellcheck disable=SC2034
255 local old="-${key}"
256 local new="+${key}"
Joey Armstrong2a079642023-07-31 15:12:37 -0400257
Joey Armstrong0476e912024-02-09 16:00:26 -0500258 ## Key/val paris are diff deltas:
259 ## -version : 1.2.3
260 ## +version : 4.5.6
261 if [[ ! -v ref['-version'] ]]; then
Eric Balled4451c2024-11-13 14:57:55 -0800262 msg='Modify version to publish chart changes'
Joey Armstrong0476e912024-02-09 16:00:26 -0500263 elif [[ ! -v ref["$new"] ]]; then
Eric Balled4451c2024-11-13 14:57:55 -0800264 msg="Failed to detect +${key} change in attributes"
Joey Armstrong0476e912024-02-09 16:00:26 -0500265 else
266 continue
267 fi
Joey Armstrong2a079642023-07-31 15:12:37 -0400268
Joey Armstrong0476e912024-02-09 16:00:26 -0500269 local -i failed=1
270 cat <<ERR
Joey Armstrong2a079642023-07-31 15:12:37 -0400271
272** -----------------------------------------------------------------------
273** Chart dir: $chartdir
274** Chart.yml: $chart
275** Error: $msg
276** -----------------------------------------------------------------------
277ERR
Joey Armstrong0476e912024-02-09 16:00:26 -0500278 func_echo "$(declare -p versions | sed -e 's/\[/\n\[/g')"
Joey Armstrong2a079642023-07-31 15:12:37 -0400279 done
280
281 if [[ -v failed ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500282 false
Joey Armstrong2a079642023-07-31 15:12:37 -0400283 else
Joey Armstrong0476e912024-02-09 16:00:26 -0500284 true
Joey Armstrong2a079642023-07-31 15:12:37 -0400285 fi
286
Joey Armstronge9b327e2023-06-22 17:09:52 -0400287 return
288}
289
290##----------------##
291##---] MAIN [---##
292##----------------##
293
294while [ $# -gt 0 ]; do
295 arg="$1"; shift
296
297 case "$arg" in
Joey Armstrong0476e912024-02-09 16:00:26 -0500298 -*debug) declare -g -i debug=1 ;;
299 -*dry*) declare -g -i dry_run=1 ;;
300 -*no-publish) declare -g -i no_publish=1 ;;
301 -*help)
302 cat <<EOH
Joey Armstronge9b327e2023-06-22 17:09:52 -0400303Usage: $0
304 --debug Enable debug mode
305 --dry-run Simulate helm calls
306EOH
Joey Armstrong0476e912024-02-09 16:00:26 -0500307 ;;
Joey Armstrong2a079642023-07-31 15:12:37 -0400308
Joey Armstrong0476e912024-02-09 16:00:26 -0500309 -*) echo "[SKIP] unknown switch [$arg]" ;;
310 *) echo "[SKIP] unknown argument [$arg]" ;;
Joey Armstronge9b327e2023-06-22 17:09:52 -0400311 esac
312done
313
314
315echo "# helmrepo.sh, using helm: $(helm version -c) #"
316
Zack Williams48542de2018-12-19 17:26:41 -0700317# create and clean NEW_REPO_DIR
318mkdir -p "${NEW_REPO_DIR}"
319rm -f "${NEW_REPO_DIR}"/*
Luca Prete94d95192018-12-14 09:56:00 -0800320
Zack Williams48542de2018-12-19 17:26:41 -0700321# if OLD_REPO_DIR doesn't exist, generate packages and index in NEW_REPO_DIR
322if [ ! -d "${OLD_REPO_DIR}" ]
323then
Joey Armstronge9b327e2023-06-22 17:09:52 -0400324 create_helm_repo_new "$NEW_REPO_DIR" "$WORKSPACE"
325 echo
326 echo "# helmrepo.sh Success! Generated new repo index in ${NEW_REPO_DIR}"
Luca Prete1b823d62018-12-13 17:33:47 -0800327
Zack Williams48542de2018-12-19 17:26:41 -0700328else
Joey Armstrong0476e912024-02-09 16:00:26 -0500329 # OLD_REPO_DIR exists, check for new charts and update only with changes
330 echo "Found existing helm repo: ${OLD_REPO_DIR}, attempting update"
Luca Prete1b823d62018-12-13 17:33:47 -0800331
Joey Armstrong0476e912024-02-09 16:00:26 -0500332 # Loop and create chart packages, only if changed
333 declare -a charts=()
334 get_chart_yaml "$WORKSPACE" charts
Joey Armstronge9b327e2023-06-22 17:09:52 -0400335
Joey Armstrong0476e912024-02-09 16:00:26 -0500336 for chart in "${charts[@]}";
337 do
338 echo
339 func_echo "Chart.yaml: $chart"
Luca Prete1b823d62018-12-13 17:33:47 -0800340
Joey Armstrong0476e912024-02-09 16:00:26 -0500341 chartdir=''
342 chart_path_to_test_dir "$chart" chartdir
343 func_echo " Chart.dir: $chartdir"
Luca Prete05ba35b2018-12-14 11:08:12 -0800344
Joey Armstrong0476e912024-02-09 16:00:26 -0500345 # See if chart version changed from previous HEAD commit
346 readarray -t chart_yaml_diff < <(git diff -p HEAD^ -- "$chart")
Joey Armstrong2a079642023-07-31 15:12:37 -0400347
Joey Armstrong0476e912024-02-09 16:00:26 -0500348 if [[ ! -v chart_yaml_diff ]]; then
349 echo "Chart unchanged, not packaging: '${chartdir}'"
Luca Prete1b823d62018-12-13 17:33:47 -0800350
Joey Armstrong0476e912024-02-09 16:00:26 -0500351 # -------------------------------------------------------------------
352 # Assumes that helmlint.sh and chart_version_check.sh have been run
353 # pre-merge, which ensures that all charts are valid and have their
354 # version updated in Chart.yaml
355 # -------------------------------------------------------------------
356 elif [ ${#chart_yaml_diff} -gt 0 ]; then
357 declare -A versions=()
358 for line in "${chart_yaml_diff[@]}";
359 do
360 [[ -v debug ]] && func_echo "$line"
Eric Ball0c5800b2025-01-21 13:14:11 -0800361
362 # foo=${string#"$prefix"}
363 line="${line%\#*}" # Snip comments
364 line="${line//[[:blank:]]}" # Prune whitespace
Joey Armstronge9b327e2023-06-22 17:09:52 -0400365
Joey Armstrong0476e912024-02-09 16:00:26 -0500366 case "$line" in
367 # appVersion: "1.0.3"
368 # version: 1.2.3
Eric Ball0c5800b2025-01-21 13:14:11 -0800369 [-+]*[vV]ersion:*) getVersion versions "$line" ;;
Joey Armstrong0476e912024-02-09 16:00:26 -0500370 esac
371 done
Joey Armstronge9b327e2023-06-22 17:09:52 -0400372
Joey Armstrong0476e912024-02-09 16:00:26 -0500373 # ---------------------------------------------------------------
374 # [TODO] -- versions['-version']='version string change required'
375 # ---------------------------------------------------------------
376 # version: string change initiates a delta forcing helm to update.
377 # Should it be required by every checkin ? For ex: release may
378 # accumulate several version edits then publish all when finished.
379 #
380 # Danger would be chart changes are not published/tested when
381 # a dev forgets to update the chart version string.
382 # ---------------------------------------------------------------
Joey Armstronge9b327e2023-06-22 17:09:52 -0400383
Joey Armstrong0476e912024-02-09 16:00:26 -0500384 ## ---------------------------------------------------------------
385 ## Check for required version change and stray attribute deletions
386 ## We are comparing diff output [-+]verison : x.y
387 ## +{key} indicates a required attribute exists and was modified
388 ## ---------------------------------------------------------------
389 if ! validate_changes "$chart" versions; then
390 declare -g -i failed=1
391 continue
392 fi
Joey Armstronge9b327e2023-06-22 17:09:52 -0400393
Joey Armstrong0476e912024-02-09 16:00:26 -0500394 # Always query, version string may not have changed
395 readarray -t ver < <(grep -oP '(?<= version: )\S+' "$chart")
396 declare -p ver
Joey Armstrong2a079642023-07-31 15:12:37 -0400397
Joey Armstrong0476e912024-02-09 16:00:26 -0500398 echo "Detected new version of chart ${chartdir}, creating package: ${ver[*]}"
Joey Armstrong2a079642023-07-31 15:12:37 -0400399
Joey Armstrong0476e912024-02-09 16:00:26 -0500400 helm_deps_update "${NEW_REPO_DIR}"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400401
Joey Armstrong0476e912024-02-09 16:00:26 -0500402 else
403 echo "Chart unchanged, not packaging: '${chartdir}'"
404 fi
405 done
Joey Armstronge9b327e2023-06-22 17:09:52 -0400406
Joey Armstrong0476e912024-02-09 16:00:26 -0500407 check_packages "$NEW_REPO_DIR"
Zack Williams48542de2018-12-19 17:26:41 -0700408
Joey Armstrong0476e912024-02-09 16:00:26 -0500409 ## -----------------------------------------------------------------------
410 ## -----------------------------------------------------------------------
411 # only update index when new charts are added
412 if [ ${#package_paths[@]} -gt 0 ]; then
Zack Williams48542de2018-12-19 17:26:41 -0700413
Joey Armstrong0476e912024-02-09 16:00:26 -0500414 # Create updated index.yaml (new version created in NEW_REPO_DIR)
415 helm_index_merge "${OLD_REPO_DIR}" "${NEW_REPO_DIR}"
Zack Williams48542de2018-12-19 17:26:41 -0700416
Joey Armstrong0476e912024-02-09 16:00:26 -0500417 # move over packages and index.yaml
418 mv "${NEW_REPO_DIR}"/*.tgz "${OLD_REPO_DIR}/"
419 mv "${NEW_REPO_DIR}/index.yaml" "${OLD_REPO_DIR}/index.yaml"
Zack Williams48542de2018-12-19 17:26:41 -0700420
Joey Armstrong0476e912024-02-09 16:00:26 -0500421 echo "# helmrepo.sh Success! Updated existing repo index in ${OLD_REPO_DIR}"
Zack Williams2f075ea2019-01-03 14:20:29 -0700422
Joey Armstrong0476e912024-02-09 16:00:26 -0500423 else
424 echo "# helmrepo.sh Success! No new charts added."
425 fi
Zack Williams48542de2018-12-19 17:26:41 -0700426fi
427
428exit 0
Joey Armstrong2a079642023-07-31 15:12:37 -0400429
430# [EOF]