refactor helm chart publishing workflow: replace script with inline logic for packaging and pushing charts, add error handling and validation
All checks were successful
Publish Helm Charts / helm-publish (push) Successful in 8s

This commit is contained in:
mangomqy
2025-11-19 09:45:08 +00:00
parent 9b58f9ad31
commit 30dd26120a
3 changed files with 75 additions and 135 deletions

View File

@ -20,12 +20,80 @@ jobs:
with:
version: v3.14.0
- name: Publish charts
- name: Package and push charts
env:
HELM_OCI_NAMESPACE: ${{ secrets.HELM_OCI_NAMESPACE }}
HELM_USERNAME: ${{ secrets.HELM_USERNAME }}
HELM_PASSWORD: ${{ secrets.HELM_PASSWORD }}
CHART_DIRS: vllm-serve
run: |
chmod +x scripts/helm_publish.sh
scripts/helm_publish.sh
set -euo pipefail
CHART_LIST_FILE="charts.list"
if [[ ! -f "$CHART_LIST_FILE" ]]; then
echo "[helm_publish] Missing chart list file ${CHART_LIST_FILE}" >&2
exit 1
fi
mapfile -t CHART_DIRS < <(grep -v '^\s*#' "$CHART_LIST_FILE" | sed '/^\s*$/d')
if [[ ${#CHART_DIRS[@]} -eq 0 ]]; then
echo "[helm_publish] No chart directories listed in ${CHART_LIST_FILE}"
exit 0
fi
if [[ -z "${HELM_OCI_NAMESPACE:-}" ]]; then
echo "[helm_publish] HELM_OCI_NAMESPACE is required" >&2
exit 1
fi
HELM_REGISTRY_HOST="${HELM_OCI_NAMESPACE%%/*}"
HELM_REGISTRY_PROJECT="${HELM_OCI_NAMESPACE#*/}"
if [[ -z "$HELM_REGISTRY_PROJECT" || "$HELM_REGISTRY_PROJECT" == "$HELM_OCI_NAMESPACE" ]]; then
echo "[helm_publish] HELM_OCI_NAMESPACE must be host/project (got ${HELM_OCI_NAMESPACE})" >&2
exit 1
fi
if [[ -n "${HELM_USERNAME:-}" && -n "${HELM_PASSWORD:-}" ]]; then
echo "[helm_publish] Logging into ${HELM_REGISTRY_HOST} as ${HELM_USERNAME}"
helm registry login "$HELM_REGISTRY_HOST" -u "$HELM_USERNAME" -p "$HELM_PASSWORD"
else
echo "[helm_publish] HELM_USERNAME/HELM_PASSWORD not set; assuming credentials already configured"
fi
status=0
for chart_dir in "${CHART_DIRS[@]}"; do
if [[ ! -f "$chart_dir/Chart.yaml" ]]; then
echo "[helm_publish] Skip ${chart_dir} (no Chart.yaml)"
continue
fi
echo "[helm_publish] Processing chart: ${chart_dir}"
helm dependency build "$chart_dir" || true
if ! helm lint "$chart_dir"; then
echo "[helm_publish] Warning: helm lint failed for ${chart_dir}"
fi
pkg_out_dir="$chart_dir/.packages"
mkdir -p "$pkg_out_dir"
pkg_path=$(helm package "$chart_dir" --destination "$pkg_out_dir" | awk '{print $NF}')
if [[ ! -f "$pkg_path" ]]; then
echo "[helm_publish] Failed to package ${chart_dir}" >&2
status=1
continue
fi
echo "[helm_publish] Packaged: ${pkg_path}"
if [[ "${DRY_RUN:-}" == "1" ]]; then
echo "[helm_publish] DRY_RUN enabled; skip push for ${pkg_path}"
continue
fi
echo "[helm_publish] Pushing ${pkg_path} to oci://${HELM_OCI_NAMESPACE}"
if ! helm push "$pkg_path" "oci://${HELM_OCI_NAMESPACE}"; then
echo "[helm_publish] Push failed for ${pkg_path}" >&2
status=1
fi
done
exit $status

3
charts.list Normal file
View File

@ -0,0 +1,3 @@
# List each Helm chart directory to package and push (one per line)
vllm-serve
code-server-chart

View File

@ -1,131 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Package and push all Helm charts found under the repo
# Required env:
# HELM_OCI_NAMESPACE e.g. ghcr.io/OWNER or gitea.example.com/OWNER
# Optional env:
# HELM_USERNAME / HELM_PASSWORD for registry login
# HELM_LOGIN_EXTRA_ARGS: extra flags for `helm registry login` (e.g., --insecure --plain-http)
# CHART_DIRS: space-separated list of chart directories; if empty, auto-discover
# DRY_RUN=1: only package, do not push
# HELM_PUSH_EXTRA_ARGS: extra flags for `helm push` (e.g., --insecure-skip-tls-verify --plain-http)
# ALLOW_OVERWRITE=1: delete existing chart version in Harbor/OCI before push (OCI tags are immutable)
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT_DIR"
if [[ -z "${HELM_OCI_NAMESPACE:-}" ]]; then
echo "[helm_publish] HELM_OCI_NAMESPACE not set (e.g., ghcr.io/owner or gitea.example.com/owner)." >&2
exit 1
fi
# Derive registry host and project from HELM_OCI_NAMESPACE
HELM_REGISTRY_HOST="${HELM_OCI_NAMESPACE%%/*}"
HELM_REGISTRY_PROJECT="${HELM_OCI_NAMESPACE#*/}"
if [[ -z "$HELM_REGISTRY_PROJECT" || "$HELM_REGISTRY_PROJECT" == "$HELM_OCI_NAMESPACE" ]]; then
echo "[helm_publish] Invalid HELM_OCI_NAMESPACE: expected host/project, got '$HELM_OCI_NAMESPACE'" >&2
exit 1
fi
# Infer API scheme/insecure flags for Harbor API calls
API_SCHEME="https"
if [[ "${HELM_LOGIN_EXTRA_ARGS:-}${HELM_PUSH_EXTRA_ARGS:-}" == *"--plain-http"* ]]; then
API_SCHEME="http"
fi
INSECURE_CURL_FLAG=""
if [[ "${HELM_LOGIN_EXTRA_ARGS:-}${HELM_PUSH_EXTRA_ARGS:-}" == *"--insecure"* || "${HELM_PUSH_EXTRA_ARGS:-}" == *"--insecure-skip-tls-verify"* ]]; then
INSECURE_CURL_FLAG="-k"
fi
# Auto-discover charts when CHART_DIRS not provided
if [[ -z "${CHART_DIRS:-}" ]]; then
mapfile -t chart_paths < <(find . -maxdepth 2 -type f -name Chart.yaml -not -path "*/charts/*" | sort)
if [[ ${#chart_paths[@]} -eq 0 ]]; then
echo "[helm_publish] No charts found (no Chart.yaml)." >&2
exit 1
fi
CHART_DIRS=""
for p in "${chart_paths[@]}"; do
d="$(dirname "$p")"
CHART_DIRS+=" ${d#./}"
done
fi
# Login if credentials present
if [[ -n "${HELM_USERNAME:-}" && -n "${HELM_PASSWORD:-}" ]]; then
echo "[helm_publish] Logging into registry ${HELM_REGISTRY_HOST} as ${HELM_USERNAME}"
# shellcheck disable=SC2086
helm registry login ${HELM_LOGIN_EXTRA_ARGS:-} "$HELM_REGISTRY_HOST" -u "$HELM_USERNAME" -p "$HELM_PASSWORD"
else
echo "[helm_publish] HELM_USERNAME/HELM_PASSWORD not set; assuming registry creds already configured"
fi
status=0
for chart_dir in ${CHART_DIRS}; do
if [[ ! -f "$chart_dir/Chart.yaml" ]]; then
echo "[helm_publish] Skip $chart_dir (no Chart.yaml)"
continue
fi
echo "[helm_publish] Processing chart: $chart_dir"
# Ensure dependencies are built
if [[ -f "$chart_dir/Chart.yaml" ]]; then
helm dependency build "$chart_dir" || true
fi
pkg_out_dir="$chart_dir/.packages"
mkdir -p "$pkg_out_dir"
# Lint chart (non-fatal)
if ! helm lint "$chart_dir"; then
echo "[helm_publish] Warning: helm lint failed for $chart_dir"
fi
# Package chart
pkg_path=$(helm package "$chart_dir" --destination "$pkg_out_dir" | awk '{print $NF}')
if [[ ! -f "$pkg_path" ]]; then
echo "[helm_publish] Failed to package $chart_dir" >&2
status=1
continue
fi
echo "[helm_publish] Packaged: $pkg_path"
if [[ "${DRY_RUN:-}" == "1" ]]; then
echo "[helm_publish] DRY_RUN enabled; skip push for $pkg_path"
continue
fi
# Resolve chart name/version from Chart.yaml
chart_name=$(sed -n 's/^name:[[:space:]]*\(.*\)$/\1/p' "$chart_dir/Chart.yaml" | head -n1 | tr -d '"' | xargs || true)
chart_version=$(sed -n 's/^version:[[:space:]]*\(.*\)$/\1/p' "$chart_dir/Chart.yaml" | head -n1 | tr -d '"' | xargs || true)
# Optional pre-delete to allow overwrite of existing tag in Harbor
if [[ "${ALLOW_OVERWRITE:-}" == "1" && -n "${chart_name}" && -n "${chart_version}" ]]; then
if [[ -n "${HELM_USERNAME:-}" && -n "${HELM_PASSWORD:-}" ]]; then
del_url="${API_SCHEME}://${HELM_REGISTRY_HOST}/api/v2.0/projects/${HELM_REGISTRY_PROJECT}/repositories/${chart_name}/artifacts/${chart_version}"
echo "[helm_publish] Attempting delete (if exists): $del_url"
http_code=$(curl -sS ${INSECURE_CURL_FLAG} -u "${HELM_USERNAME}:${HELM_PASSWORD}" -o /dev/null -w "%{http_code}" -X DELETE "$del_url" || true)
case "$http_code" in
200|202|404)
echo "[helm_publish] Delete HTTP $http_code (ok)";;
"")
echo "[helm_publish] Warning: curl returned no status; continuing";;
*)
echo "[helm_publish] Warning: delete returned HTTP $http_code; continuing to push";;
esac
else
echo "[helm_publish] ALLOW_OVERWRITE=1 but HELM_USERNAME/HELM_PASSWORD not set; skip delete"
fi
fi
# Push to OCI registry; Helm will use chart name from the package
echo "[helm_publish] Pushing $pkg_path to oci://$HELM_OCI_NAMESPACE"
if ! helm push ${HELM_PUSH_EXTRA_ARGS:-} "$pkg_path" "oci://$HELM_OCI_NAMESPACE"; then
echo "[helm_publish] Push failed for $pkg_path" >&2
status=1
fi
done
exit $status