Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 18 additions & 21 deletions .github/actions/charts-as-json/action.yml
Original file line number Diff line number Diff line change
@@ -1,38 +1,35 @@
---
name: charts_json
description: |
Return as JSON representation of all the charts and their values files so it's
easy to build a dynamic workflow matrix
inputs:
charts-root:
required: true
description: root directory containing the charts
type: string
charts-filter:
required: false
description: filter to apply to charts, e.g. "acs-sso-example" or "alfresco-content-services"
values-filter:
required: false
description: filter to apply to values files, e.g. "community_values.yaml"
outputs:
all:
description: matrix object charts
value: ${{ steps.getcharts.outputs.all }}
app:
description: matrix object apps
value: ${{ steps.getcharts.outputs.app }}
lib:
description: matrix object libs
value: ${{ steps.getcharts.outputs.lib }}
description: Return as JSON string with charts details
runs:
using: composite
steps:
- id: getcharts
name: Get main Charts and parse manifest
env:
YQ_FILTER: >
{"name": .name,"type": .type, "version": .version} | to_json
run: |
for CHART_ROOT in ${{ inputs.charts-root }}/*/; do
CHART=$(basename $CHART_ROOT)
VALUES_FILES=$(find ${{ inputs.charts-root }}/"${CHART}" -type f -name "*values.yaml" ! -name "linter_values.yaml" -maxdepth 1)
VALUES=${VALUES_FILES//${CHART_ROOT}/}
yq e "$YQ_FILTER" "${{ inputs.charts-root }}/${CHART}/Chart.yaml" | \
jq -c --arg v "${VALUES}" '.values=($v | split("\n"))' > /tmp/outputs_${CHART}.json
done
echo "app=$(jq -sc '{charts:.} | del(.charts[] | select(.type=="library"))' /tmp/outputs_*.json)" >> $GITHUB_OUTPUT
echo "lib=$(jq -sc '{charts:.} | del(.charts[] | select(.type!="library"))' /tmp/outputs_*.json)" >> $GITHUB_OUTPUT
echo "all=$(jq -sc '{charts:.}' /tmp/outputs_*.json)" >> $GITHUB_OUTPUT
CHART_FILTER="${{ inputs.charts-filter }}"
VALUES_FILTER="${{ inputs.values-filter }}"

FILTER_ARGS=""
[[ -n "$CHART_FILTER" ]] && FILTER_ARGS="$FILTER_ARGS --chart-filter $CHART_FILTER"
[[ -n "$VALUES_FILTER" ]] && FILTER_ARGS="$FILTER_ARGS --values-filter $VALUES_FILTER"

OUTPUT=$(python3 ${{ github.action_path }}/charts_parser.py "${{ inputs.charts-root }}" $FILTER_ARGS)
echo "all=$OUTPUT" >> $GITHUB_OUTPUT
shell: bash
109 changes: 109 additions & 0 deletions .github/actions/charts-as-json/charts_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env python3
"""Parse Helm charts and their values files into JSON format."""

import argparse
import json
import os
import sys
from pathlib import Path

try:
import yaml
except ImportError:
print("Error: PyYAML is required. Install with: pip install PyYAML", file=sys.stderr)
sys.exit(1)


def find_chart_directories(charts_root: Path, chart_filter: str = None):
"""Find all chart directories, optionally filtered by name."""
chart_dirs = []

if not charts_root.exists():
print(f"Error: Charts root directory does not exist: {charts_root}", file=sys.stderr)
sys.exit(1)

for item in charts_root.iterdir():
if item.is_dir():
chart_yaml = item / "Chart.yaml"
if chart_yaml.exists():
# Apply chart filter if provided
if chart_filter and item.name != chart_filter:
continue
chart_dirs.append(item)

return sorted(chart_dirs)


def find_values_files(chart_dir: Path, values_filter: str = None):
"""Find all values.yaml files in a chart directory, excluding linter_values.yaml."""
values_files = []

for values_file in chart_dir.glob("*values.yaml"):
if values_file.name == "linter_values.yaml":
continue

# Apply values filter if provided
if values_filter and values_filter not in values_file.name:
continue

# Store relative filename only
values_files.append(values_file.name)

return sorted(values_files)


def parse_chart_yaml(chart_yaml_path: Path):
"""Parse Chart.yaml and extract name, type, and version."""
try:
with open(chart_yaml_path, 'r') as f:
chart_data = yaml.safe_load(f)

return {
"name": chart_data.get("name", ""),
"type": chart_data.get("type", ""),
"version": chart_data.get("version", "")
}
except Exception as e:
print(f"Error parsing {chart_yaml_path}: {e}", file=sys.stderr)
return None


def main():
parser = argparse.ArgumentParser(description="Parse Helm charts and values files to JSON")
parser.add_argument("charts_root", help="Root directory containing the charts")
parser.add_argument("--chart-filter", help="Filter to apply to chart names")
parser.add_argument("--values-filter", help="Filter to apply to values filenames")

args = parser.parse_args()

charts_root = Path(args.charts_root)
chart_directories = find_chart_directories(charts_root, args.chart_filter)

if not chart_directories:
print(f"Warning: No charts found in {charts_root}", file=sys.stderr)

all_charts = []

for chart_dir in chart_directories:
chart_yaml_path = chart_dir / "Chart.yaml"
chart_info = parse_chart_yaml(chart_yaml_path)

if chart_info is None:
continue

values_files = find_values_files(chart_dir, args.values_filter)

# Skip charts with no matching values files
if not values_files:
continue

chart_info["values"] = values_files
all_charts.append(chart_info)

# Output the final JSON structure
output = {"charts": all_charts}
print(json.dumps(output, separators=(',', ':')))


if __name__ == "__main__":
main()
Loading