blob: d0c0c1d069786fb3fe320d82717f82b02c764f4e [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]}"
117 ref[$key]="$val"
118
119 return
120}
121
122## -----------------------------------------------------------------------
Joey Armstronge9b327e2023-06-22 17:09:52 -0400123## Intent: Update helm package dependencies
124## -----------------------------------------------------------------------
125function helm_deps_update()
126{
127 local dest="$1"; shift # helm --destination
128
129 if [[ -v dry_run ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500130 func_echo "helm package --dependency-update --destination $dest $chartdir"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400131 else
Joey Armstrong0476e912024-02-09 16:00:26 -0500132 helm package --dependency-update --destination "$dest" "$chartdir"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400133 fi
134 return
135}
136
137## -----------------------------------------------------------------------
138## Intent: Update helm package index
139## -----------------------------------------------------------------------
140function helm_index_publish()
141{
142 local repo_dir="$1"; shift # helm --destination
143
144 if [[ -v dry_run ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500145 func_echo "helm repo index $repo_dir --url https://${PUBLISH_URL}"
Joey Armstrong2a079642023-07-31 15:12:37 -0400146
147 elif [[ -v no_publish ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500148 func_echo "[SKIP] helm publishing due to --no-publish"
149
Joey Armstronge9b327e2023-06-22 17:09:52 -0400150 else
Joey Armstrong0476e912024-02-09 16:00:26 -0500151 ## ------------------------------------------------
152 ## Helm updates are guarded by jenkins
153 ## Revision control should reinforce that assertion
154 ## ------------------------------------------------
155 case "$USER" in
156 jenkins)
157 helm repo index "$repo_dir" --url https://"${PUBLISH_URL}"
158 ;;
159 *)
160 func_echo "[SKIP] helm publishing due to ($USER != jenkins)"
161 ;;
162 esac
Joey Armstronge9b327e2023-06-22 17:09:52 -0400163 fi
Joey Armstrong2a079642023-07-31 15:12:37 -0400164
Joey Armstronge9b327e2023-06-22 17:09:52 -0400165 return
166}
167
168## -----------------------------------------------------------------------
169## Intent: Update helm package index
170## -----------------------------------------------------------------------
171function helm_index_merge()
172{
173 local old_repo="$1" ; shift
174 local new_repo="$1" ; shift
175
176 declare -a cmd=()
177 cmd+=('helm' 'repo' 'index')
178 cmd+=('--url' "https://${PUBLISH_URL}")
179 cmd+=('--merge' "${old_repo}/index.yaml" "$new_repo")
180
181 if [[ -v dry_run ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500182 func_echo "${cmd[@]}"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400183 else
Joey Armstrong0476e912024-02-09 16:00:26 -0500184 "${cmd[@]}"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400185 fi
186 return
187}
188
189## -----------------------------------------------------------------------
190## Intent: Given a Chart.yaml file path return test directory where stored
191## -----------------------------------------------------------------------
192function chart_path_to_test_dir()
193{
194 local val="$1" ; shift
195
Joey Armstrong0476e912024-02-09 16:00:26 -0500196 # shellcheck disable=SC2178
197 declare -n ref=$1 ; shift # indirect var
Joey Armstronge9b327e2023-06-22 17:09:52 -0400198
199 val="${val%/Chart.yaml}" # dirname: prune /Chart.yaml
200 val="${val##*/}" # basename: test directory
201
Joey Armstrong0476e912024-02-09 16:00:26 -0500202 # shellcheck disable=SC2034,SC2178
Joey Armstronge9b327e2023-06-22 17:09:52 -0400203 ref="$val" # Return value to caller
204 return
205}
206
207## -----------------------------------------------------------------------
Joey Armstrong2a079642023-07-31 15:12:37 -0400208## Intent: Given Chart.yaml files create a new indexed chart repository
Joey Armstronge9b327e2023-06-22 17:09:52 -0400209## -----------------------------------------------------------------------
210function create_helm_repo_new()
211{
212 local repo_dir="$1"; shift # NEW_REPO_DIR
213 local work_dir="$1"; shift # WORKSPACE
214
215 echo "Creating new helm repo: ${repo_dir}"
216
217 declare -a charts=()
218 get_chart_yaml "$work_dir" charts
219
220 local chart
221 for chart in "${charts[@]}";
222 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500223 echo
224 func_echo "Chart.yaml: $chart"
Joey Armstrong2a079642023-07-31 15:12:37 -0400225
Joey Armstrong0476e912024-02-09 16:00:26 -0500226 chartdir=''
227 chart_path_to_test_dir "$chart" chartdir
228 func_echo " Chart.dir: $chartdir"
Joey Armstrong2a079642023-07-31 15:12:37 -0400229
Joey Armstrong0476e912024-02-09 16:00:26 -0500230 helm_deps_update "${repo_dir}"
Joey Armstronge9b327e2023-06-22 17:09:52 -0400231 done
Joey Armstrong2a079642023-07-31 15:12:37 -0400232
Joey Armstronge9b327e2023-06-22 17:09:52 -0400233 helm_index_publish "${repo_dir}"
Joey Armstrong2a079642023-07-31 15:12:37 -0400234
235 return
236}
237
238## -----------------------------------------------------------------------
239## Intent: Compare version stings extracted from Chart.yaml delta.
240## o attribute version:x.y.z must be changed to enable change
241## detection and chart loading.
242## -----------------------------------------------------------------------
243function validate_changes()
244{
Joey Armstrong0476e912024-02-09 16:00:26 -0500245 local chart="$1"; shift
Joey Armstrong2a079642023-07-31 15:12:37 -0400246 # shellcheck disable=SC2178
247 local -n ref=$1; shift
248
249 local msg
250 ## -------------------------------------------
251 ## Validation logic: all keys collected exist
252 ## Chart version must change to enable loading
253 ## -------------------------------------------
254 local key0
255 for key0 in "${!ref[@]}";
256 do
Joey Armstrong0476e912024-02-09 16:00:26 -0500257 local key="${key0:1}"
258 # shellcheck disable=SC2034
259 local old="-${key}"
260 local new="+${key}"
Joey Armstrong2a079642023-07-31 15:12:37 -0400261
Joey Armstrong0476e912024-02-09 16:00:26 -0500262 ## Key/val paris are diff deltas:
263 ## -version : 1.2.3
264 ## +version : 4.5.6
265 if [[ ! -v ref['-version'] ]]; then
266 msg='Modify version= to publish chart changes'
267 elif [[ ! -v ref["$new"] ]]; then
268 msg="Failed to detect +${key}= change in attributes"
269 else
270 continue
271 fi
Joey Armstrong2a079642023-07-31 15:12:37 -0400272
Joey Armstrong0476e912024-02-09 16:00:26 -0500273 local -i failed=1
274 cat <<ERR
Joey Armstrong2a079642023-07-31 15:12:37 -0400275
276** -----------------------------------------------------------------------
277** Chart dir: $chartdir
278** Chart.yml: $chart
279** Error: $msg
280** -----------------------------------------------------------------------
281ERR
Joey Armstrong0476e912024-02-09 16:00:26 -0500282 func_echo "$(declare -p versions | sed -e 's/\[/\n\[/g')"
Joey Armstrong2a079642023-07-31 15:12:37 -0400283 done
284
285 if [[ -v failed ]]; then
Joey Armstrong0476e912024-02-09 16:00:26 -0500286 false
Joey Armstrong2a079642023-07-31 15:12:37 -0400287 else
Joey Armstrong0476e912024-02-09 16:00:26 -0500288 true
Joey Armstrong2a079642023-07-31 15:12:37 -0400289 fi
290
Joey Armstronge9b327e2023-06-22 17:09:52 -0400291 return
292}
293
294##----------------##
295##---] MAIN [---##
296##----------------##
297
298while [ $# -gt 0 ]; do
299 arg="$1"; shift
300
301 case "$arg" in
Joey Armstrong0476e912024-02-09 16:00:26 -0500302 -*debug) declare -g -i debug=1 ;;
303 -*dry*) declare -g -i dry_run=1 ;;
304 -*no-publish) declare -g -i no_publish=1 ;;
305 -*help)
306 cat <<EOH
Joey Armstronge9b327e2023-06-22 17:09:52 -0400307Usage: $0
308 --debug Enable debug mode
309 --dry-run Simulate helm calls
310EOH
Joey Armstrong0476e912024-02-09 16:00:26 -0500311 ;;
Joey Armstrong2a079642023-07-31 15:12:37 -0400312
Joey Armstrong0476e912024-02-09 16:00:26 -0500313 -*) echo "[SKIP] unknown switch [$arg]" ;;
314 *) echo "[SKIP] unknown argument [$arg]" ;;
Joey Armstronge9b327e2023-06-22 17:09:52 -0400315 esac
316done
317
318
319echo "# helmrepo.sh, using helm: $(helm version -c) #"
320
Zack Williams48542de2018-12-19 17:26:41 -0700321# create and clean NEW_REPO_DIR
322mkdir -p "${NEW_REPO_DIR}"
323rm -f "${NEW_REPO_DIR}"/*
Luca Prete94d95192018-12-14 09:56:00 -0800324
Zack Williams48542de2018-12-19 17:26:41 -0700325# if OLD_REPO_DIR doesn't exist, generate packages and index in NEW_REPO_DIR
326if [ ! -d "${OLD_REPO_DIR}" ]
327then
Joey Armstronge9b327e2023-06-22 17:09:52 -0400328 create_helm_repo_new "$NEW_REPO_DIR" "$WORKSPACE"
329 echo
330 echo "# helmrepo.sh Success! Generated new repo index in ${NEW_REPO_DIR}"
Luca Prete1b823d62018-12-13 17:33:47 -0800331
Zack Williams48542de2018-12-19 17:26:41 -0700332else
Joey Armstrong0476e912024-02-09 16:00:26 -0500333 # OLD_REPO_DIR exists, check for new charts and update only with changes
334 echo "Found existing helm repo: ${OLD_REPO_DIR}, attempting update"
Luca Prete1b823d62018-12-13 17:33:47 -0800335
Joey Armstrong0476e912024-02-09 16:00:26 -0500336 # Loop and create chart packages, only if changed
337 declare -a charts=()
338 get_chart_yaml "$WORKSPACE" charts
Joey Armstronge9b327e2023-06-22 17:09:52 -0400339
Joey Armstrong0476e912024-02-09 16:00:26 -0500340 for chart in "${charts[@]}";
341 do
342 echo
343 func_echo "Chart.yaml: $chart"
Luca Prete1b823d62018-12-13 17:33:47 -0800344
Joey Armstrong0476e912024-02-09 16:00:26 -0500345 chartdir=''
346 chart_path_to_test_dir "$chart" chartdir
347 func_echo " Chart.dir: $chartdir"
Luca Prete05ba35b2018-12-14 11:08:12 -0800348
Joey Armstrong0476e912024-02-09 16:00:26 -0500349 # See if chart version changed from previous HEAD commit
350 readarray -t chart_yaml_diff < <(git diff -p HEAD^ -- "$chart")
Joey Armstrong2a079642023-07-31 15:12:37 -0400351
Joey Armstrong0476e912024-02-09 16:00:26 -0500352 if [[ ! -v chart_yaml_diff ]]; then
353 echo "Chart unchanged, not packaging: '${chartdir}'"
Luca Prete1b823d62018-12-13 17:33:47 -0800354
Joey Armstrong0476e912024-02-09 16:00:26 -0500355 # -------------------------------------------------------------------
356 # Assumes that helmlint.sh and chart_version_check.sh have been run
357 # pre-merge, which ensures that all charts are valid and have their
358 # version updated in Chart.yaml
359 # -------------------------------------------------------------------
360 elif [ ${#chart_yaml_diff} -gt 0 ]; then
361 declare -A versions=()
362 for line in "${chart_yaml_diff[@]}";
363 do
364 [[ -v debug ]] && func_echo "$line"
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
369 [-+]*[vV]ersion:*) getVersion versions "$line" ;;
370 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]