blob: 230ae1fbae6e39560bcdb79512d997e039f568b7 [file] [log] [blame]
#!/usr/bin/env bash
# Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# helmrepo.sh
# creates or updates a helm repo for publishing on the guide website
# Reference: https://github.com/helm/charts/blob/master/test/repo-sync.sh
set -eu -o pipefail
##-------------------##
##---] GLOBALS [---##
##-------------------##
# when not running under Jenkins, use current dir as workspace
WORKSPACE=${WORKSPACE:-.}
# directory to compare against, doesn't need to be present
OLD_REPO_DIR="${OLD_REPO_DIR:-cord-charts-repo}"
NEW_REPO_DIR="${NEW_REPO_DIR:-chart_repo}"
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}"/*
# if OLD_REPO_DIR doesn't exist, generate packages and index in NEW_REPO_DIR
if [ ! -d "${OLD_REPO_DIR}" ]
then
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
declare -a charts=()
get_chart_yaml "$WORKSPACE" charts
for chart in "${charts[@]}";
do
echo
func_echo "Chart.yaml: $chart"
chartdir=''
chart_path_to_test_dir "$chart" chartdir
func_echo " Chart.dir: $chartdir"
# 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}'"
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
for package_path in "${package_paths[@]}";
do
package="${package_path##*/}" # basename
[ -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
# 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"
echo "# helmrepo.sh Success! Updated existing repo index in ${OLD_REPO_DIR}"
else
echo "# helmrepo.sh Success! No new charts added."
fi
fi
exit 0