diff --git a/.github/workflows/helm-ci.yaml b/.github/workflows/helm-ci.yaml index dc57399..6c89c8e 100644 --- a/.github/workflows/helm-ci.yaml +++ b/.github/workflows/helm-ci.yaml @@ -8,6 +8,7 @@ env: HELM_VERSION: v3.18.2 KUBECONFORM_VERSION: 0.7.0 PYTHON_VERSION: 3.13 + HELM_UNITTEST_VERSION: v1.0.3 jobs: helm-ci: @@ -25,7 +26,7 @@ jobs: - name: Install helm-unittest plugin run: | - helm plugin install https://github.com/helm-unittest/helm-unittest + helm plugin install https://github.com/helm-unittest/helm-unittest --version ${{ env.HELM_UNITTEST_VERSION }} - name: Install kubeconform run: | diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 2325f85..cb62d32 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -6,6 +6,10 @@ on: env: HELM_VERSION: v3.18.2 + HELM_S3_VERSION: v0.17.1 + HELM_S3_BUCKET: geosolutions-charts/charts + HELM_S3_REPO: charts + CHARTS_URL: https://charts.geosolutionsgroup.com/charts jobs: release-charts: @@ -13,6 +17,7 @@ jobs: permissions: contents: write packages: write + id-token: write steps: - name: Checkout uses: actions/checkout@v4 @@ -22,34 +27,64 @@ jobs: with: version: ${{ env.HELM_VERSION }} - - name: Login to GHCR + - name: Configure AWS credentials from OIDC + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::227022658256:role/charts-s3-bucket-role + aws-region: eu-west-2 + + - name: Install Helm S3 plugin run: | - echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io --username ${{ github.actor }} --password-stdin + helm plugin install https://github.com/hypnoglow/helm-s3.git --version ${{ env.HELM_S3_VERSION }} - - name: Package and Push charts to GHCR + - name: Package and push charts to S3 run: | + set -euo pipefail + + repo_name="${HELM_S3_REPO}" + repo_url="s3://${HELM_S3_BUCKET}" + http_url="${CHARTS_URL}" + + # Initialize Helm repo index in S3 if it does not exist yet + if ! aws s3api head-object --bucket "${HELM_S3_BUCKET}" --key "index.yaml" >/dev/null 2>&1; then + echo "Initializing Helm repo at ${repo_url}" + helm s3 init "$repo_url" + fi + + if ! helm repo list | awk '{print $1}' | grep -qx "$repo_name"; then + helm repo add "$repo_name" "$repo_url" + fi + + helm repo update + for chart_dir in */*/; do if [ -f "${chart_dir}Chart.yaml" ]; then chart_name=$(grep '^name:' "${chart_dir}Chart.yaml" | awk '{print $2}' | tr -d '"' | tr -d "'") chart_version=$(grep '^version:' "${chart_dir}Chart.yaml" | awk '{print $2}' | tr -d '"' | tr -d "'") echo "Processing $chart_name:$chart_version" - if helm pull "oci://ghcr.io/geosolutions-it/charts/$chart_name" --version "$chart_version" --destination /tmp >/dev/null 2>&1; then - echo "Chart is already exists, skipping..." - rm -f /tmp/${chart_name}-${chart_version}.tgz 2>/dev/null + if helm search repo "${repo_name}/${chart_name}" --version "$chart_version" 2>/dev/null | grep -q "${chart_name}"; then + echo "Chart already exists in $repo_url, skipping..." continue fi - - helm package "$chart_dir" - package_file="${chart_name}-${chart_version}.tgz" - if [ -f "$package_file" ]; then - helm push "$package_file" oci://ghcr.io/geosolutions-it/charts - echo "✅ Pushed $chart_name:$chart_version" - rm "$package_file" - fi + + helm package "$chart_dir" + package_file="${chart_name}-${chart_version}.tgz" + if [ -f "$package_file" ]; then + helm s3 push "$package_file" "$repo_name" + echo "✅ Pushed $chart_name:$chart_version to $repo_url" + rm "$package_file" + fi fi done + # Fix index.yaml URLs from s3:// to HTTP + echo "Converting index.yaml URLs from s3:// to HTTP..." + aws s3 cp "s3://${HELM_S3_BUCKET}/index.yaml" /tmp/index.yaml + sed -i "s|s3://${HELM_S3_BUCKET}/|${http_url}/|g" /tmp/index.yaml + aws s3 cp /tmp/index.yaml "s3://${HELM_S3_BUCKET}/index.yaml" + echo "✅ Updated index.yaml with HTTP URLs" + - name: Checkout GitOps Repository uses: actions/checkout@v4 with: @@ -62,7 +97,9 @@ jobs: cd gitops-dev git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - + + repo_url="${CHARTS_URL}" + changes_made=false for chart_dir in ../*/*/; do if [ -f "${chart_dir}Chart.yaml" ]; then @@ -70,13 +107,14 @@ jobs: chart_version=$(grep '^version:' "${chart_dir}Chart.yaml" | awk '{print $2}' | tr -d '"' | tr -d "'") if [ -d "apps/$chart_name" ]; then - current_version=$(grep -A 5 'repoURL: ghcr.io' "apps/$chart_name/application.yaml" | grep 'targetRevision:' | awk '{print $2}' | tr -d '"' | tr -d "'") + current_version=$(grep 'targetRevision:' "apps/$chart_name/application.yaml" | head -1 | awk '{print $2}' | tr -d '"' | tr -d "'") if [ "$current_version" = "$chart_version" ]; then echo "$chart_name version $chart_version is already deployed, skipping..." continue - fi - echo "Updating $chart_name from $current_version to $chart_version in GitOps repository" - sed -i "/repoURL: ghcr.io/,/targetRevision:/ s/targetRevision: .*/targetRevision: $chart_version/" "apps/$chart_name/application.yaml" + fi + echo "Updating $chart_name from $current_version to $chart_version in GitOps repository" + sed -i "0,/targetRevision: .*/s/targetRevision: .*/targetRevision: $chart_version/" "apps/$chart_name/application.yaml" + sed -i "0,/repoURL: .*/s|repoURL: .*|repoURL: $repo_url|" "apps/$chart_name/application.yaml" git add "apps/$chart_name/application.yaml" git commit -m "chore: update $chart_name chart version from $current_version to $chart_version" changes_made=true diff --git a/README.md b/README.md index 1624e33..e17333f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,120 @@ -# charts -HELM Charts by GeoSolutions +# GeoSolutions Helm Charts + +## Overview + +This repository contains Helm charts for: +- **[GeoServer](geoserver/latest/)** - Open-source geospatial server for sharing, processing, and editing geospatial data +- **[MapStore](mapstore/latest/)** - Web mapping framework for creating, managing, and sharing maps and mashups + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.0+ + +## Repository Structure + +``` +charts/ +├── .github/workflows/ # CI/CD pipelines +│ ├── helm-ci.yaml # Validation and testing +│ └── release.yaml # Automated releases to S3 +├── geoserver/latest/ # GeoServer Helm chart +└── mapstore/latest/ # MapStore Helm chart +``` + +## Chart Registry + +Charts are hosted on AWS S3: +- **Bucket**: `s3://geosolutions-charts` (eu-west-2) +- **Public URL**: https://charts.geosolutionsgroup.com +- **Authentication**: AWS [OIDC](https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-aws?utm_source=chatgpt.com) + +## Quick Start + +### Adding the Helm Repository + +```bash +# Add the GeoSolutions chart repository +helm repo add charts https://charts.geosolutionsgroup.com/charts + +# Update your local chart repository cache +helm repo update + +# Search for available charts +helm search repo charts +``` + +### Installing Charts + +#### GeoServer + +```bash +# Install with default values +helm install geoserver charts/geoserver + +# Install with custom values +helm install geoserver charts/geoserver \ + --set admin_password=MySecurePassword \ + --set persistence.datadir.size=10Gi +``` + +#### MapStore + +```bash +# Install with default values +helm install mapstore geosolutions/mapstore + +# Install with custom values +helm install mapstore geosolutions/mapstore \ + --set ingress.host=mapstore.example.com \ + --set persistence.size=10Gi +``` + +## Configuration + +Each chart has its own `values.yaml` file with configurable parameters. See individual chart documentation for details: + +- [GeoServer Configuration](geoserver/latest/README.md) +- [MapStore Configuration](mapstore/latest/README.md) + +## Upgrading + +```bash +# Update repository cache +helm repo update + +# Upgrade to latest version +helm upgrade geoserver geosolutions/geoserver + +# Upgrade with custom values +helm upgrade geoserver geosolutions/geoserver -f my-values.yaml + +# View upgrade history +helm history geoserver + +# Rollback to previous version +helm rollback geoserver +``` + +## Uninstalling + +```bash +# Uninstall a release +helm uninstall geoserver +``` + +## CI/CD Workflows + +### Pull Request Validation + +When you submit a PR, the [helm-ci.yaml](.github/workflows/helm-ci.yaml) workflow automatically: +1. Lints all charts with `helm lint` +2. Runs unit tests with `helm unittest` +3. Validates Kubernetes manifests with `kubeconform` + +### Automated Releases + +When changes are merged to main, the [release.yaml](.github/workflows/release.yaml) workflow: +1. Packages charts using `helm package` +2. Publishes to S3 bucket registry (geosolutions-charts) +3. Triggers GitOps deployment updates