vp-patterns/publish-charts #195
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This workflow is expected to be run by the git workflow of the remote | |
| # chart whenever a new target is pushed: | |
| # gh workflow run publish-charts.yml --repo mbaldessari/charts-test --ref main \ | |
| # -f SOURCE_TAG="v0.0.1" -f SOURCE_REPO="mbaldessari/helm-chart-test" | |
| name: vp-patterns/publish-charts | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| SOURCE_TAG: | |
| required: true | |
| description: The tag of the helm chart repo to build | |
| SOURCE_REPO: | |
| required: true | |
| description: The helm chart repo | |
| SOURCE_BRANCH_OVERRIDE: | |
| required: false | |
| description: If specified, checks out the head of this branch rather than the commit tagged by SOURCE_TAG | |
| default: "" | |
| TEMPLATE_DIR: | |
| required: false | |
| description: Directory containing the helm chart (relative to repo root). If not specified, will auto-detect Chart.yaml location | |
| default: "" | |
| ADDITIONAL_HELM_REPOS: | |
| required: false | |
| description: Additional helm repositories to add (JSON format, e.g. '[{"name":"myrepo","url":"https://example.com/charts"}]') | |
| default: "" | |
| env: | |
| SOURCE_TAG: "${{ inputs.SOURCE_TAG }}" | |
| SOURCE_REPO: "${{ inputs.SOURCE_REPO }}" | |
| SOURCE_BRANCH_OVERRIDE: "${{ inputs.SOURCE_BRANCH_OVERRIDE }}" | |
| TEMPLATE_DIR: "${{ inputs.TEMPLATE_DIR }}" | |
| ADDITIONAL_HELM_REPOS: "${{ inputs.ADDITIONAL_HELM_REPOS }}" | |
| UMBRELLA_REPO: "validatedpatterns/helm-charts" | |
| ASSETS_BASE_URL: "https://github.com/validatedpatterns/helm-charts/releases/download/main/" | |
| LEGACY_QUAY_BASE_URL: "oci://quay.io/hybridcloudpatterns" | |
| QUAY_BASE_URL: "oci://quay.io/validatedpatterns" | |
| jobs: | |
| update-charts: | |
| if: ${{ inputs.SOURCE_TAG }} | |
| runs-on: ubuntu-latest | |
| permissions: write-all | |
| steps: | |
| - name: Install Helm | |
| uses: azure/setup-helm@v4 | |
| with: | |
| version: v3.12.1 | |
| - name: Clone remote helm repo | |
| env: | |
| SOURCE_BRANCH_OVERRIDE: ${{ inputs.SOURCE_BRANCH_OVERRIDE }} | |
| run: |- | |
| set -e | |
| if [ -n "${SOURCE_BRANCH_OVERRIDE}" ]; then | |
| git clone "https://github.com/${SOURCE_REPO}.git" \ | |
| --branch "${SOURCE_BRANCH_OVERRIDE}" --single-branch helm-repo | |
| else | |
| git clone "https://github.com/${SOURCE_REPO}.git" \ | |
| --branch "${SOURCE_TAG}" --single-branch helm-repo | |
| fi | |
| - name: Handle chart dependencies | |
| shell: bash | |
| env: | |
| TEMPLATE_DIR: ${{ env.TEMPLATE_DIR }} | |
| ADDITIONAL_HELM_REPOS: ${{ env.ADDITIONAL_HELM_REPOS }} | |
| run: |- | |
| set -euo pipefail | |
| cd helm-repo | |
| # Determine the chart directory - check if TEMPLATE_DIR is provided or use default | |
| if [ -n "${TEMPLATE_DIR}" ]; then | |
| CHART_DIR="${TEMPLATE_DIR}" | |
| else | |
| # If no TEMPLATE_DIR specified, look for Chart.yaml in common locations | |
| if [ -f "Chart.yaml" ]; then | |
| CHART_DIR="." | |
| elif [ -f "chart/Chart.yaml" ]; then | |
| CHART_DIR="chart" | |
| elif [ -f "helm/Chart.yaml" ]; then | |
| CHART_DIR="helm" | |
| else | |
| echo "Could not find Chart.yaml file. Please specify TEMPLATE_DIR input." | |
| exit 1 | |
| fi | |
| fi | |
| cd "${CHART_DIR}" | |
| # Check if Chart.yaml exists and has dependencies | |
| if [ -f "Chart.yaml" ]; then | |
| echo "Found Chart.yaml in ${CHART_DIR}" | |
| cat Chart.yaml | |
| # Check if dependencies section exists in Chart.yaml | |
| if yq -e '.dependencies' Chart.yaml > /dev/null 2>&1; then | |
| echo "Dependencies found in Chart.yaml. Processing dependencies..." | |
| # Create a temporary file to track if repositories were added | |
| repo_added_flag=$(mktemp) | |
| echo "false" > "$repo_added_flag" | |
| # Extract repository URLs from dependencies and add them as helm repositories | |
| echo "Discovering repositories from Chart.yaml dependencies..." | |
| yq -r '.dependencies[]? | select(.repository) | .repository' Chart.yaml | sort -u | while read -r repo_url; do | |
| if [ -n "$repo_url" ] && [[ "$repo_url" == http* ]]; then | |
| # Convert URL to repository name by removing protocol and common prefixes | |
| repo_name=$(echo "$repo_url" | sed 's|^https\?://||' | sed 's|^www\.||' | sed 's|/$||') | |
| echo "Adding repository: $repo_name -> $repo_url" | |
| if helm repo add "$repo_name" "$repo_url"; then | |
| echo "true" > "$repo_added_flag" | |
| else | |
| echo "Failed to add repository $repo_name, continuing..." | |
| fi | |
| fi | |
| done | |
| # Add additional helm repositories if specified | |
| if [ -n "${ADDITIONAL_HELM_REPOS}" ] && [ "${ADDITIONAL_HELM_REPOS}" != "[]" ] && [ "${ADDITIONAL_HELM_REPOS}" != "" ]; then | |
| echo "Adding additional helm repositories..." | |
| echo "${ADDITIONAL_HELM_REPOS}" | yq -r '.[] | "helm repo add " + .name + " " + .url' | while read -r cmd; do | |
| echo "Running: $cmd" | |
| if eval "$cmd"; then | |
| echo "true" > "$repo_added_flag" | |
| else | |
| echo "Failed to add repository, continuing..." | |
| fi | |
| done | |
| fi | |
| # Update repositories only if any were added | |
| repos_added=$(cat "$repo_added_flag") | |
| rm -f "$repo_added_flag" | |
| if [ "$repos_added" = "true" ]; then | |
| echo "Updating helm repositories..." | |
| helm repo update | |
| else | |
| echo "No repositories were added, skipping helm repo update" | |
| fi | |
| # Check if dependencies are already present | |
| update_needed=false | |
| if [ -d "charts" ]; then | |
| echo "Charts directory exists, checking for missing dependencies..." | |
| # Get list of required dependencies from Chart.yaml | |
| required_deps=$(yq -r '.dependencies[]? | .name + "-" + .version' Chart.yaml 2>/dev/null || true) | |
| if [ -n "$required_deps" ]; then | |
| echo "Required dependencies:" | |
| echo "$required_deps" | |
| # Check each required dependency | |
| for dep in $required_deps; do | |
| dep_name=$(echo "$dep" | cut -d'-' -f1) | |
| # Look for chart files that match the dependency name | |
| if ! ls charts/"${dep_name}"-*.tgz >/dev/null 2>&1; then | |
| echo "Missing dependency chart: $dep_name" | |
| update_needed=true | |
| break | |
| else | |
| echo "Found existing chart for: $dep_name" | |
| fi | |
| done | |
| else | |
| echo "No specific dependencies found, will update to be safe" | |
| update_needed=true | |
| fi | |
| else | |
| echo "Charts directory does not exist, dependencies update needed" | |
| update_needed=true | |
| fi | |
| # Update dependencies only if needed | |
| if [ "$update_needed" = true ]; then | |
| echo "Updating dependencies..." | |
| helm dependency update | |
| # Verify dependencies were downloaded | |
| if [ -d "charts" ]; then | |
| echo "Dependencies successfully downloaded:" | |
| ls -la charts/ | |
| else | |
| echo "Warning: charts directory not created. Dependencies might not be needed or failed to download." | |
| fi | |
| else | |
| echo "All dependencies are already present, skipping dependency update" | |
| echo "Existing charts:" | |
| ls -la charts/ | |
| fi | |
| else | |
| echo "No dependencies found in Chart.yaml" | |
| fi | |
| else | |
| echo "Chart.yaml not found in ${CHART_DIR}" | |
| exit 1 | |
| fi | |
| - name: Package the helm chart | |
| shell: bash | |
| env: | |
| TEMPLATE_DIR: ${{ env.TEMPLATE_DIR }} | |
| run: |- | |
| set -euo pipefail | |
| cd helm-repo | |
| # Determine the chart directory - same logic as dependency handling | |
| if [ -n "${TEMPLATE_DIR}" ]; then | |
| CHART_DIR="${TEMPLATE_DIR}" | |
| else | |
| # If no TEMPLATE_DIR specified, look for Chart.yaml in common locations | |
| if [ -f "Chart.yaml" ]; then | |
| CHART_DIR="." | |
| elif [ -f "chart/Chart.yaml" ]; then | |
| CHART_DIR="chart" | |
| elif [ -f "helm/Chart.yaml" ]; then | |
| CHART_DIR="helm" | |
| else | |
| echo "Could not find Chart.yaml file. Please specify TEMPLATE_DIR input." | |
| exit 1 | |
| fi | |
| fi | |
| # Package the chart | |
| helm package "${CHART_DIR}" | |
| # Read chart metadata from the determined chart directory | |
| CHART_NAME=$(yq -r '.name' "${CHART_DIR}/Chart.yaml") | |
| CHART_VERSION=$(yq -r '.version' "${CHART_DIR}/Chart.yaml") | |
| CHART_TGZ="${CHART_NAME}-${CHART_VERSION}.tgz" | |
| # Move chart to parent dir | |
| mv ${CHART_TGZ} .. | |
| echo "CHART_NAME=${CHART_NAME}" >> $GITHUB_ENV | |
| echo "CHART_VERSION=${CHART_VERSION}" >> $GITHUB_ENV | |
| echo "CHART_TGZ=${CHART_TGZ}" >> $GITHUB_ENV | |
| # - name: Sign the chart | |
| # shell: bash | |
| # env: | |
| # GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | |
| # run: |- | |
| # set -euo pipefail | |
| # echo ${{ secrets.GPG_SECRET_SUBKEY }} | base64 -d | gpg --batch --import | |
| # echo ${{ secrets.GPG_PUBLIC_KEY }} | base64 -d | gpg --batch --import | |
| # # Needed because helm verify only supports old format | |
| # gpg --export >~/.gnupg/pubring.gpg | |
| # pip install git+https://gitlab.com/mbaldessari/helm-sign.git@couple-of-fixes | |
| # helm-sign ${{ env.CHART_TGZ }} | |
| # helm verify ${{ env.CHART_TGZ }} | |
| - name: Upload helm package as a release asset | |
| uses: svenstaro/upload-release-action@v2 | |
| with: | |
| repo_token: ${{ secrets.GITHUB_TOKEN }} | |
| file: ${{ env.CHART_TGZ }} | |
| asset_name: ${{ env.CHART_TGZ }} | |
| tag: ${{ github.ref }} | |
| body: "${{ env.CHART_NAME }} Released ${{ env.CHART_VERSION }}" | |
| overwrite: true | |
| # - name: Upload helm package signature as a release asset | |
| # uses: svenstaro/upload-release-action@v2 | |
| # with: | |
| # repo_token: ${{ secrets.GITHUB_TOKEN }} | |
| # file: ${{ env.CHART_TGZ }}.prov | |
| # asset_name: ${{ env.CHART_TGZ }}.prov | |
| # tag: ${{ github.ref }} | |
| # body: "${{ env.CHART_NAME }} Released ${{ env.CHART_VERSION }}" | |
| # overwrite: true | |
| # Uploaded to https://github.com/validatedpatterns/helm-charts/releases/download/main/test-0.0.1.tgz | |
| # This step fetches all assets and places them in the current folder | |
| # The reason for doing this is that it makes things fully idempotent and we do not need | |
| # to rely on the --merge feature when generating the index | |
| # While this probably does not scale all too well it should be fine for our not too large | |
| # helm repo | |
| - name: Fetch all assets locally | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: |- | |
| set -e | |
| for i in $(gh api repos/${UMBRELLA_REPO}/releases/latest | jq -r ".assets[].browser_download_url"); do | |
| curl -O -L "${i}" | |
| done | |
| - name: Update the helm index.yaml file | |
| run: |- | |
| set -e | |
| helm repo index --url "${ASSETS_BASE_URL}" . | |
| # FIXME(bandini): this is for debugging only | |
| cat index.yaml | |
| - name: Checkout code to git-repo folder | |
| uses: actions/checkout@v6 | |
| with: | |
| # Full git history is needed to get a proper list of changed files within `super-linter` | |
| fetch-depth: 0 | |
| path: git-repo | |
| - name: Commit to gh-pages | |
| run: |- | |
| set -e | |
| cd git-repo | |
| git config user.name "${{ github.actor }}" | |
| git config user.email "${{ github.actor }}@users.noreply.github.com" | |
| git checkout gh-pages | |
| # This copies the newly generated index.yaml to the git repo | |
| cp -fv ../index.yaml . | |
| # Copy index.tpl from the main branch which is where it lives | |
| git checkout origin/main index.tpl | |
| # Install index.html generator | |
| helm plugin install https://github.com/halkeye/helm-repo-html | |
| helm repo-html | |
| ls -l index.html | |
| git add index.yaml index.html | |
| git commit -m "Updated ${{ env.CHART_NAME }}-${{ env.CHART_VERSION }}" | |
| git push origin gh-pages | |
| - name: Push the chart to legacy and new quay repos | |
| run: |- | |
| set -e | |
| helm registry login -u="${{ secrets.LEGACY_QUAY_USERNAME }}" -p="${{ secrets.LEGACY_QUAY_PASSWORD }}" quay.io | |
| helm push "${{ env.CHART_TGZ }}" "${LEGACY_QUAY_BASE_URL}" | |
| helm registry login -u="${{ secrets.QUAY_USERNAME }}" -p="${{ secrets.QUAY_PASSWORD }}" quay.io | |
| helm push "${{ env.CHART_TGZ }}" "${QUAY_BASE_URL}" |