From 30dd26120a9790a2c7543f5cd99ce1edf9366d33 Mon Sep 17 00:00:00 2001 From: mangomqy Date: Wed, 19 Nov 2025 09:45:08 +0000 Subject: [PATCH] refactor helm chart publishing workflow: replace script with inline logic for packaging and pushing charts, add error handling and validation --- .gitea/workflows/publish-helm.yml | 76 ++++++++++++++++- charts.list | 3 + scripts/helm_publish.sh | 131 ------------------------------ 3 files changed, 75 insertions(+), 135 deletions(-) create mode 100644 charts.list delete mode 100755 scripts/helm_publish.sh diff --git a/.gitea/workflows/publish-helm.yml b/.gitea/workflows/publish-helm.yml index 0564f2d..d647b9b 100644 --- a/.gitea/workflows/publish-helm.yml +++ b/.gitea/workflows/publish-helm.yml @@ -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 diff --git a/charts.list b/charts.list new file mode 100644 index 0000000..7d216af --- /dev/null +++ b/charts.list @@ -0,0 +1,3 @@ +# List each Helm chart directory to package and push (one per line) +vllm-serve +code-server-chart diff --git a/scripts/helm_publish.sh b/scripts/helm_publish.sh deleted file mode 100755 index f4757ef..0000000 --- a/scripts/helm_publish.sh +++ /dev/null @@ -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