Misc cleanups, shellcheck warnings.
helmrepo.sh
-----------
o Use readarray -t to slurp command output.
o Replace while read -r with for loop iteration over named vars.
o Replace awk/string parsing with bash builtin string functions
(added insulation against external shell command failures).
o Added several functions to shorten all-code-in-main-program.
o Added functions func_echo() and error() for formatted output.
o Arguments --debug, --dry-run and --help added.
o 'helm package' command functions added to support --dry-run use.
o Detect and error on Chart.yaml files that lack 'version:'.
o chart_yaml_diff - differentiate no_diff case from error induced.
Change-Id: I54d4f1e71291899540ec0f339ee9e033ca62a443
diff --git a/helmrepo.sh b/helmrepo.sh
index 56808c0..230ae1f 100755
--- a/helmrepo.sh
+++ b/helmrepo.sh
@@ -20,7 +20,9 @@
set -eu -o pipefail
-echo "# helmrepo.sh, using helm: $(helm version -c) #"
+##-------------------##
+##---] GLOBALS [---##
+##-------------------##
# when not running under Jenkins, use current dir as workspace
WORKSPACE=${WORKSPACE:-.}
@@ -31,6 +33,162 @@
PUBLISH_URL="${PUBLISH_URL:-charts.opencord.org}"
+## -----------------------------------------------------------------------
+## Intent: Dispay called function with given output
+## -----------------------------------------------------------------------
+function func_echo()
+{
+ echo "** ${FUNCNAME[1]}: $*"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Display given text and exit with shell error status.
+## -----------------------------------------------------------------------
+function error()
+{
+ echo "** ${BASH_SOURCE[0]}::${FUNCNAME[1]} ERROR: $*"
+ exit 1
+}
+
+## -----------------------------------------------------------------------
+## Intent: Gather a list of Chart.yaml files from the filesystem.
+## -----------------------------------------------------------------------
+function get_chart_yaml()
+{
+ local dir="$1" ; shift
+ declare -n ref=$1 ; shift
+
+ readarray -t _charts < <(find "$dir" -name Chart.yaml -print | sort)
+ ref=("${_charts[@]}")
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Update helm package dependencies
+## -----------------------------------------------------------------------
+function helm_deps_update()
+{
+ local dest="$1"; shift # helm --destination
+
+ if [[ -v dry_run ]]; then
+ func_echo "helm package --dependency-update --destination $dest $chartdir"
+ else
+ helm package --dependency-update --destination "$dest" "$chartdir"
+ fi
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Update helm package index
+## -----------------------------------------------------------------------
+function helm_index_publish()
+{
+ local repo_dir="$1"; shift # helm --destination
+
+ if [[ -v dry_run ]]; then
+ func_echo "helm repo index $repo_dir --url https://${PUBLISH_URL}"
+ else
+ helm repo index "$repo_dir" --url https://"${PUBLISH_URL}"
+ fi
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Update helm package index
+## -----------------------------------------------------------------------
+function helm_index_merge()
+{
+ local old_repo="$1" ; shift
+ local new_repo="$1" ; shift
+
+ declare -a cmd=()
+ cmd+=('helm' 'repo' 'index')
+ cmd+=('--url' "https://${PUBLISH_URL}")
+ cmd+=('--merge' "${old_repo}/index.yaml" "$new_repo")
+
+ if [[ -v dry_run ]]; then
+ func_echo "${cmd[@]}"
+ else
+ "${cmd[@]}"
+ fi
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Given a Chart.yaml file path return test directory where stored
+## -----------------------------------------------------------------------
+function chart_path_to_test_dir()
+{
+ local val="$1" ; shift
+
+# shellcheck disable=SC2178
+ declare -n ref=$1 ; shift # indirect var
+
+ val="${val%/Chart.yaml}" # dirname: prune /Chart.yaml
+ val="${val##*/}" # basename: test directory
+
+# shellcheck disable=SC2034,SC2178
+ ref="$val" # Return value to caller
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Given a Chart.yaml file path return test directory where stored
+## -----------------------------------------------------------------------
+function create_helm_repo_new()
+{
+ local repo_dir="$1"; shift # NEW_REPO_DIR
+ local work_dir="$1"; shift # WORKSPACE
+
+ echo "Creating new helm repo: ${repo_dir}"
+
+ declare -a charts=()
+ get_chart_yaml "$work_dir" charts
+
+ local chart
+ for chart in "${charts[@]}";
+ do
+ echo
+ func_echo "Chart.yaml: $chart"
+
+ chartdir=''
+ chart_path_to_test_dir "$chart" chartdir
+ func_echo " Chart.dir: $chartdir"
+
+ helm_deps_update "${repo_dir}"
+ done
+
+ helm_index_publish "${repo_dir}"
+ return
+}
+
+##----------------##
+##---] MAIN [---##
+##----------------##
+
+while [ $# -gt 0 ]; do
+ arg="$1"; shift
+
+ case "$arg" in
+ -*debug) declare -g -i debug=1 ;;
+ -*dry*) declare -g -i dry_run=1 ;;
+ -*help)
+ cat <<EOH
+Usage: $0
+ --debug Enable debug mode
+ --dry-run Simulate helm calls
+EOH
+ ;;
+
+ -*) echo "[SKIP] unknown switch [$arg]" ;;
+ *) echo "[SKIP] unknown argument [$arg]" ;;
+ esac
+done
+
+
+echo "# helmrepo.sh, using helm: $(helm version -c) #"
+
# create and clean NEW_REPO_DIR
mkdir -p "${NEW_REPO_DIR}"
rm -f "${NEW_REPO_DIR}"/*
@@ -38,67 +196,104 @@
# if OLD_REPO_DIR doesn't exist, generate packages and index in NEW_REPO_DIR
if [ ! -d "${OLD_REPO_DIR}" ]
then
- echo "Creating new helm repo: ${NEW_REPO_DIR}"
-
- while IFS= read -r -d '' chart
- do
- chartdir=$(dirname "${chart#${WORKSPACE}/}")
- helm package --dependency-update --destination "${NEW_REPO_DIR}" "${chartdir}"
-
- done < <(find "${WORKSPACE}" -name Chart.yaml -print0)
-
- helm repo index "${NEW_REPO_DIR}" --url https://"${PUBLISH_URL}"
- echo "# helmrepo.sh Success! Generated new repo index in ${NEW_REPO_DIR}"
+ create_helm_repo_new "$NEW_REPO_DIR" "$WORKSPACE"
+ echo
+ echo "# helmrepo.sh Success! Generated new repo index in ${NEW_REPO_DIR}"
else
# OLD_REPO_DIR exists, check for new charts and update only with changes
echo "Found existing helm repo: ${OLD_REPO_DIR}, attempting update"
# Loop and create chart packages, only if changed
- while IFS= read -r -d '' chart
+ declare -a charts=()
+ get_chart_yaml "$WORKSPACE" charts
+
+ for chart in "${charts[@]}";
do
- chartdir=$(dirname "${chart#${WORKSPACE}/}")
+ echo
+ func_echo "Chart.yaml: $chart"
- # See if chart version changed from previous HEAD commit
- chart_yaml_diff=$(git diff -p HEAD^ -- "${chartdir}/Chart.yaml")
+ chartdir=''
+ chart_path_to_test_dir "$chart" chartdir
+ func_echo " Chart.dir: $chartdir"
- if [ -n "$chart_yaml_diff" ]
- then
- # assumes that helmlint.sh and chart_version_check.sh have been run
- # pre-merge, which ensures that all charts are valid and have their
- # version updated in Chart.yaml
- new_version_string=$(echo "$chart_yaml_diff" | awk '/^\+version:/ { print $2 }')
- echo "New version of chart ${chartdir}, creating package: ${new_version_string//+version:/}"
- helm package --dependency-update --destination "${NEW_REPO_DIR}" "${chartdir}"
- else
- echo "Chart unchanged, not packaging: '${chartdir}'"
- fi
+ # See if chart version changed from previous HEAD commit
+ readarray -t chart_yaml_diff < <(git diff -p HEAD^ -- "$chart")
+
+ if [[ ! -v chart_yaml_diff ]]; then
+ echo "Chart unchanged, not packaging: '${chartdir}'"
- done < <(find "${WORKSPACE}" -name Chart.yaml -print0)
+ elif [ ${#chart_yaml_diff} -gt 0 ]; then
+ # assumes that helmlint.sh and chart_version_check.sh have been run
+ # pre-merge, which ensures that all charts are valid and have their
+ # version updated in Chart.yaml
+ [[ -v new_version_string ]] && unset new_version_string
+
+ for line in "${chart_yaml_diff[@]}";
+ do
+ [[ -v debug ]] && func_echo "$line"
+
+ case "$line" in
+ # "-version: \"1.0.3\""
+ -version:*)
+ [[ ! -v debug ]] && func_echo "$line"
+ ;;
+
+ # "+version: \"1.0.4\""
+ +version:*)
+ [[ ! -v debug ]] && func_echo "$line"
+
+ readarray -d':' -t _fields <<<"$line" # split on delimiter
+ val="${_fields[1]}"
+ val="${val//[[:blank:]]}"
+
+ # error detection: only assign when we have a value.
+ [ ${#val} -gt 0 ] && new_version_string="$val"
+ break
+ ;;
+ esac
+ done
+
+ [[ ! -v new_version_string ]] && error "Failed to detect version: in $chart"
+
+ echo "New version of chart ${chartdir}, creating package: ${new_version_string}"
+
+ helm_deps_update "1${NEW_REPO_DIR}"
+
+ else
+ echo "Chart unchanged, not packaging: '${chartdir}'"
+ fi
+ done
+
+ ## -----------------------------------------------------------------------
+ ## -----------------------------------------------------------------------
+ readarray -t package_paths < <(find "${NEW_REPO_DIR}" -name '*.tgz' -print)
+ declare -p package_paths
+
# Check for collisions between old/new packages
- while IFS= read -r -d '' package_path
+ # while IFS= read -r -d '' package_path
+ for package_path in "${package_paths[@]}";
do
- package=$(basename "${package_path}")
+ package="${package_path##*/}" # basename
- if [ -f "${OLD_REPO_DIR}/${package}" ]
- then
- echo "# helmrepo.sh Failure! Package: ${package} with same version already exists in ${OLD_REPO_DIR}"
- exit 1
- fi
- done < <(find "${NEW_REPO_DIR}" -name '*.tgz' -print0)
+ [ -f "${OLD_REPO_DIR}/${package}" ] \
+ && error "Package: ${package} with same version already exists in ${OLD_REPO_DIR}"
+ done
+
+ ## -----------------------------------------------------------------------
+ ## -----------------------------------------------------------------------
+ # only update index when new charts are added
+ if [ ${#package_paths[@]} -gt 0 ]; then
- # only update index if new charts are added
- if ls "${NEW_REPO_DIR}"/*.tgz > /dev/null 2>&1;
- then
- # Create updated index.yaml (new version created in NEW_REPO_DIR)
- helm repo index --url "https://${PUBLISH_URL}" --merge "${OLD_REPO_DIR}/index.yaml" "${NEW_REPO_DIR}"
+ # Create updated index.yaml (new version created in NEW_REPO_DIR)
+ helm_index_merge "${OLD_REPO_DIR}" "${NEW_REPO_DIR}"
- # move over packages and index.yaml
- mv "${NEW_REPO_DIR}"/*.tgz "${OLD_REPO_DIR}/"
- mv "${NEW_REPO_DIR}/index.yaml" "${OLD_REPO_DIR}/index.yaml"
+ # move over packages and index.yaml
+ mv "${NEW_REPO_DIR}"/*.tgz "${OLD_REPO_DIR}/"
+ mv "${NEW_REPO_DIR}/index.yaml" "${OLD_REPO_DIR}/index.yaml"
- echo "# helmrepo.sh Success! Updated existing repo index in ${OLD_REPO_DIR}"
+ echo "# helmrepo.sh Success! Updated existing repo index in ${OLD_REPO_DIR}"
else
echo "# helmrepo.sh Success! No new charts added."