wordpress 1.0.0 — WordPress on a shared volumeset with bundled MariaDB #428
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
| name: Validate Helm Charts | |
| on: | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| workflow_call: | |
| inputs: | |
| version_dirs: | |
| description: 'Space-separated version dirs to validate (e.g. "redis/versions/3.0.0 nginx/versions/1.1.1")' | |
| type: string | |
| required: false | |
| default: '' | |
| charts: | |
| description: 'Space-separated template names to validate all versions of' | |
| type: string | |
| required: false | |
| default: '' | |
| concurrency: | |
| group: validate-${{ github.event_name == 'pull_request' && github.event.pull_request.number || github.run_id }} | |
| cancel-in-progress: true | |
| jobs: | |
| validate: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Helm | |
| uses: azure/setup-helm@v3 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Determine changed version directories | |
| id: versions | |
| run: | | |
| # When called as a reusable workflow, use the provided inputs directly | |
| if [ -n "${{ inputs.version_dirs }}" ] || [ -n "${{ inputs.charts }}" ]; then | |
| echo "version_dirs=${{ inputs.version_dirs }}" >> $GITHUB_OUTPUT | |
| echo "charts=${{ inputs.charts }}" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| # Otherwise detect from git diff (pull_request / workflow_dispatch) | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| base_sha="${{ github.event.pull_request.base.sha }}" | |
| else | |
| base_sha="$(git rev-parse HEAD^)" | |
| fi | |
| version_dirs=$(git diff --name-only "$base_sha" HEAD \ | |
| | grep -E '^[^/]+/versions/[^/]+/' \ | |
| | sed -E 's|^([^/]+/versions/[^/]+)/.*|\1|' \ | |
| | sort -u | tr '\n' ' ') | |
| echo "base_sha=$base_sha" >> $GITHUB_OUTPUT | |
| echo "version_dirs=$version_dirs" >> $GITHUB_OUTPUT | |
| - name: Validate charts | |
| if: steps.versions.outputs.version_dirs != '' || steps.versions.outputs.charts != '' | |
| run: | | |
| base_sha="${{ steps.versions.outputs.base_sha }}" | |
| failed=0 | |
| # The OCI registry throttles when several runs pull cpln-common at once. | |
| # Bound each attempt and retry with backoff; a real failure must be visible, | |
| # not swallowed into a step that appears to hang. | |
| helm_dep_update() { | |
| local dir="$1" n=1 | |
| while [ "$n" -le 3 ]; do | |
| if timeout 300 helm dependency update "$dir"; then return 0; fi | |
| echo "helm dependency update failed for $dir (attempt $n/3)" | |
| [ "$n" -lt 3 ] && sleep $((n * 15)) | |
| n=$((n + 1)) | |
| done | |
| return 1 | |
| } | |
| validate_version_dir() { | |
| local version_dir="${1%/}" | |
| [ ! -f "$version_dir/Chart.yaml" ] && return | |
| local template=$(echo "$version_dir" | cut -d/ -f1) | |
| local folder_version=$(echo "$version_dir" | cut -d/ -f3) | |
| local version=$(grep '^version:' "$version_dir/Chart.yaml" | awk '{print $2}') | |
| if [ "$version" != "$folder_version" ]; then | |
| echo "FAIL [$template]: Chart.yaml version '$version' does not match folder name '$folder_version'" | |
| failed=1 | |
| return | |
| fi | |
| # Library charts cannot be rendered standalone — skip helm template validation | |
| if grep -qE '^\s*type:\s*library' "$version_dir/Chart.yaml"; then | |
| echo "Skipping $template @ $version (library chart)" | |
| return | |
| fi | |
| echo "" | |
| echo "=== Validating $template @ $version ===" | |
| # 1. helm template with default values | |
| # charts with createsGvc:false expect global.cpln.gvc at runtime — pass a dummy value | |
| local creates_gvc=$(grep -E '^\s+createsGvc:' "$version_dir/Chart.yaml" | awk '{print $2}') | |
| local helm_flags="" | |
| if [ "$creates_gvc" = "false" ]; then | |
| helm_flags="--set global.cpln.gvc=validation-gvc" | |
| fi | |
| if ! helm_dep_update "$version_dir"; then | |
| echo "FAIL [$template @ $version]: helm dependency update failed (registry unreachable or throttled)" | |
| failed=1 | |
| return | |
| fi | |
| if ! rendered=$(helm template "validation" "$version_dir" $helm_flags 2>&1); then | |
| echo "FAIL [$template @ $version]: helm template failed with default values" | |
| echo "$rendered" | |
| failed=1 | |
| return | |
| fi | |
| # 2. Required marketplace tags in rendered output | |
| for tag in 'cpln/marketplace:' 'cpln/marketplace-template:' 'cpln/marketplace-template-version:'; do | |
| if ! echo "$rendered" | grep -q "$tag"; then | |
| echo "FAIL [$template @ $version]: Missing required tag '$tag' in rendered templates" | |
| failed=1 | |
| fi | |
| done | |
| if ! echo "$rendered" | grep -q 'cpln/marketplace: "true"'; then | |
| echo "FAIL [$template @ $version]: Tag 'cpln/marketplace' must equal \"true\"" | |
| failed=1 | |
| fi | |
| # cpln/marketplace-gvc is required when createsGvc is false | |
| if [ "$creates_gvc" = "false" ]; then | |
| if ! echo "$rendered" | grep -q 'cpln/marketplace-gvc:'; then | |
| echo "FAIL [$template @ $version]: Missing required tag 'cpln/marketplace-gvc' (required when createsGvc is false)" | |
| failed=1 | |
| fi | |
| fi | |
| # 3. Required Chart.yaml annotations | |
| for annotation in category created lastModified createsGvc; do | |
| if ! grep -qE "^\s+${annotation}:" "$version_dir/Chart.yaml"; then | |
| echo "FAIL [$template @ $version]: Missing annotation '$annotation' in Chart.yaml" | |
| failed=1 | |
| fi | |
| done | |
| # 3b. Chart.yaml description. The marketplace card has a fixed height and | |
| # CLIPS a long description mid-sentence (duckdb shipped 39 words and was | |
| # visibly cut off in the UI). Em dashes are punctuation, not words. | |
| local desc=$(sed -n 's/^description:[[:space:]]*//p' "$version_dir/Chart.yaml" | head -1) | |
| if [ -z "$desc" ]; then | |
| echo "FAIL [$template @ $version]: Chart.yaml description is empty - it is the marketplace card's one line" | |
| failed=1 | |
| else | |
| local words=$(echo "$desc" | tr ' ' '\n' | grep -vE '^$' | grep -vE '^(\xe2\x80\x94|\xe2\x80\x93|-)$' | wc -l | tr -d ' ') | |
| if [ "$words" -gt 15 ]; then | |
| echo "FAIL [$template @ $version]: description is $words words - the card clips past 15. Say what it IS, not everything it does" | |
| failed=1 | |
| fi | |
| if echo "$desc" | grep -qi 'for Control Plane'; then | |
| echo "FAIL [$template @ $version]: description says 'for Control Plane' - every template here is" | |
| failed=1 | |
| fi | |
| if echo "$desc" | grep -qiE '^(a |an |the )?helm chart'; then | |
| echo "FAIL [$template @ $version]: description starts 'a Helm chart for...' - say what the software is instead" | |
| failed=1 | |
| fi | |
| fi | |
| # 4. New template: require README.md and icon.png at the template root | |
| # (only checked when base_sha is available, i.e. PR / workflow_dispatch) | |
| if [ -n "$base_sha" ]; then | |
| if ! git ls-tree -r "$base_sha" --name-only 2>/dev/null | grep -q "^${template}/versions/"; then | |
| echo "New template detected: $template — checking required files..." | |
| if [ ! -f "$version_dir/README.md" ]; then | |
| echo "FAIL [$template]: Missing README.md (required for new templates)" | |
| failed=1 | |
| fi | |
| if [ ! -f "$template/icon.png" ]; then | |
| echo "FAIL [$template]: Missing icon.png (required for new templates)" | |
| failed=1 | |
| fi | |
| fi | |
| fi | |
| if [ "$failed" -eq 0 ]; then | |
| echo "OK: $template @ $version" | |
| fi | |
| } | |
| for version_dir in ${{ steps.versions.outputs.version_dirs }}; do | |
| validate_version_dir "$version_dir" | |
| done | |
| for template in ${{ steps.versions.outputs.charts }}; do | |
| for version_dir in "$template"/versions/*/; do | |
| validate_version_dir "$version_dir" | |
| done | |
| done | |
| exit $failed |