Skip to content

Release 1.9.1

Release 1.9.1 #22

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*.*.*'
env:
DOCKERHUB_BACKEND_IMAGE: tess1o/geopulse-backend
DOCKERHUB_FRONTEND_IMAGE: tess1o/geopulse-ui
GHCR_BACKEND_IMAGE: ghcr.io/tess1o/geopulse-backend
GHCR_FRONTEND_IMAGE: ghcr.io/tess1o/geopulse-ui
permissions:
contents: write
packages: write
jobs:
# Extract version from tag (remove 'v' prefix)
prepare:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.version }}
steps:
- name: Get version from tag
id: get_version
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Version: $VERSION"
# Build Backend JVM AMD64
build-backend-jvm-amd64:
needs: prepare
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Backend JVM AMD64
uses: docker/build-push-action@v5
with:
context: .
file: backend/Dockerfile
platforms: linux/amd64
push: true
build-args: |
VERSION=${{ needs.prepare.outputs.version }}-jvm
tags: |
${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-jvm-amd64
${{ env.DOCKERHUB_BACKEND_IMAGE }}:jvm-latest-amd64
${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-jvm-amd64
${{ env.GHCR_BACKEND_IMAGE }}:jvm-latest-amd64
cache-from: type=gha,scope=jvm-amd64
cache-to: type=gha,mode=max,scope=jvm-amd64
# Build Backend JVM ARM64
build-backend-jvm-arm64:
needs: prepare
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Backend JVM ARM64
uses: docker/build-push-action@v5
with:
context: .
file: backend/Dockerfile
platforms: linux/arm64
push: true
build-args: |
VERSION=${{ needs.prepare.outputs.version }}-jvm
tags: |
${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-jvm-arm64
${{ env.DOCKERHUB_BACKEND_IMAGE }}:jvm-latest-arm64
${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-jvm-arm64
${{ env.GHCR_BACKEND_IMAGE }}:jvm-latest-arm64
cache-from: type=gha,scope=jvm-arm64
cache-to: type=gha,mode=max,scope=jvm-arm64
# Build Backend Native AMD64
build-backend-native-amd64:
needs: prepare
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Backend Native AMD64
uses: docker/build-push-action@v5
with:
context: .
file: backend/Dockerfile.native
platforms: linux/amd64
push: true
build-args: |
VERSION=${{ needs.prepare.outputs.version }}-native
QUARKUS_NATIVE_BUILD_ARGS=
tags: |
${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-amd64
${{ env.DOCKERHUB_BACKEND_IMAGE }}:native-latest-amd64
${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-amd64
${{ env.GHCR_BACKEND_IMAGE }}:native-latest-amd64
cache-from: type=gha,scope=native-amd64
cache-to: type=gha,mode=max,scope=native-amd64
# Build Backend Native ARM64
build-backend-native-arm64:
needs: prepare
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Backend Native ARM64
uses: docker/build-push-action@v5
with:
context: .
file: backend/Dockerfile.native
platforms: linux/arm64
push: true
build-args: |
VERSION=${{ needs.prepare.outputs.version }}-native
QUARKUS_NATIVE_BUILD_ARGS=
tags: |
${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-arm64
${{ env.DOCKERHUB_BACKEND_IMAGE }}:native-latest-arm64
${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-arm64
${{ env.GHCR_BACKEND_IMAGE }}:native-latest-arm64
cache-from: type=gha,scope=native-arm64
cache-to: type=gha,mode=max,scope=native-arm64
# Build Backend Native AMD64 Compatible (x86-64-v2 for old CPUs)
build-backend-native-amd64-compat:
needs: prepare
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Backend Native AMD64 Compatible
uses: docker/build-push-action@v5
with:
context: .
file: backend/Dockerfile.native
platforms: linux/amd64
push: true
build-args: |
VERSION=${{ needs.prepare.outputs.version }}-native
QUARKUS_NATIVE_BUILD_ARGS=,-march=x86-64-v2
tags: |
${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-amd64-compat
${{ env.DOCKERHUB_BACKEND_IMAGE }}:native-compat-amd64
${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-amd64-compat
${{ env.GHCR_BACKEND_IMAGE }}:native-compat-amd64
cache-from: type=gha,scope=native-compat-amd64
cache-to: type=gha,mode=max,scope=native-compat-amd64
# Build Backend Native ARM64 Compatible (armv8-a+nolse for Raspberry Pi)
build-backend-native-arm64-compat:
needs: prepare
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Backend Native ARM64 Compatible
uses: docker/build-push-action@v5
with:
context: .
file: backend/Dockerfile.native
platforms: linux/arm64
push: true
build-args: |
VERSION=${{ needs.prepare.outputs.version }}-native
QUARKUS_NATIVE_BUILD_ARGS=,-march=armv8-a+nolse
tags: |
${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-arm64-compat
${{ env.DOCKERHUB_BACKEND_IMAGE }}:native-compat-arm64
${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-arm64-compat
${{ env.GHCR_BACKEND_IMAGE }}:native-compat-arm64
cache-from: type=gha,scope=native-compat-arm64
cache-to: type=gha,mode=max,scope=native-compat-arm64
# Build Frontend (multi-arch)
build-frontend:
needs: prepare
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Frontend
uses: docker/build-push-action@v5
with:
context: .
file: frontend/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
build-args: |
VERSION=${{ needs.prepare.outputs.version }}
tags: |
${{ env.DOCKERHUB_FRONTEND_IMAGE }}:${{ needs.prepare.outputs.version }}
${{ env.DOCKERHUB_FRONTEND_IMAGE }}:latest
${{ env.GHCR_FRONTEND_IMAGE }}:${{ needs.prepare.outputs.version }}
${{ env.GHCR_FRONTEND_IMAGE }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
# Create multi-arch manifests for JVM backend
create-jvm-manifests:
needs: [prepare, build-backend-jvm-amd64, build-backend-jvm-arm64]
runs-on: ubuntu-latest
steps:
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push Docker Hub JVM manifests
run: |
# Create versioned manifest
docker buildx imagetools create \
-t ${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-jvm \
${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-jvm-amd64 \
${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-jvm-arm64
# Create latest manifest
docker buildx imagetools create \
-t ${{ env.DOCKERHUB_BACKEND_IMAGE }}:jvm-latest \
${{ env.DOCKERHUB_BACKEND_IMAGE }}:jvm-latest-amd64 \
${{ env.DOCKERHUB_BACKEND_IMAGE }}:jvm-latest-arm64
- name: Create and push GHCR JVM manifests
run: |
# Create versioned manifest
docker buildx imagetools create \
-t ${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-jvm \
${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-jvm-amd64 \
${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-jvm-arm64
# Create latest manifest
docker buildx imagetools create \
-t ${{ env.GHCR_BACKEND_IMAGE }}:jvm-latest \
${{ env.GHCR_BACKEND_IMAGE }}:jvm-latest-amd64 \
${{ env.GHCR_BACKEND_IMAGE }}:jvm-latest-arm64
# Create multi-arch manifests for native backend (optimized)
create-native-manifests:
needs: [prepare, build-backend-native-amd64, build-backend-native-arm64]
runs-on: ubuntu-latest
steps:
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push Docker Hub manifests
run: |
# Create versioned manifest
docker buildx imagetools create \
-t ${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native \
${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-amd64 \
${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-arm64
# Create latest manifests
docker buildx imagetools create \
-t ${{ env.DOCKERHUB_BACKEND_IMAGE }}:native-latest \
-t ${{ env.DOCKERHUB_BACKEND_IMAGE }}:latest \
${{ env.DOCKERHUB_BACKEND_IMAGE }}:native-latest-amd64 \
${{ env.DOCKERHUB_BACKEND_IMAGE }}:native-latest-arm64
- name: Create and push GHCR manifests
run: |
# Create versioned manifest
docker buildx imagetools create \
-t ${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native \
${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-amd64 \
${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-arm64
# Create latest manifests
docker buildx imagetools create \
-t ${{ env.GHCR_BACKEND_IMAGE }}:native-latest \
-t ${{ env.GHCR_BACKEND_IMAGE }}:latest \
${{ env.GHCR_BACKEND_IMAGE }}:native-latest-amd64 \
${{ env.GHCR_BACKEND_IMAGE }}:native-latest-arm64
# Create multi-arch manifests for native backend (compatible)
create-native-compat-manifests:
needs: [prepare, build-backend-native-amd64-compat, build-backend-native-arm64-compat]
runs-on: ubuntu-latest
steps:
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push Docker Hub compatible manifests
run: |
# Create versioned compat manifest
docker buildx imagetools create \
-t ${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-compat \
${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-amd64-compat \
${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-arm64-compat
# Create latest compat manifest
docker buildx imagetools create \
-t ${{ env.DOCKERHUB_BACKEND_IMAGE }}:native-compat-latest \
-t ${{ env.DOCKERHUB_BACKEND_IMAGE }}:compat-latest \
${{ env.DOCKERHUB_BACKEND_IMAGE }}:native-compat-amd64 \
${{ env.DOCKERHUB_BACKEND_IMAGE }}:native-compat-arm64
- name: Create and push GHCR compatible manifests
run: |
# Create versioned compat manifest
docker buildx imagetools create \
-t ${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-compat \
${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-amd64-compat \
${{ env.GHCR_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native-arm64-compat
# Create latest compat manifest
docker buildx imagetools create \
-t ${{ env.GHCR_BACKEND_IMAGE }}:native-compat-latest \
-t ${{ env.GHCR_BACKEND_IMAGE }}:compat-latest \
${{ env.GHCR_BACKEND_IMAGE }}:native-compat-amd64 \
${{ env.GHCR_BACKEND_IMAGE }}:native-compat-arm64
# Publish Helm charts and documentation to GitHub Pages
publish-helm-and-docs:
needs: [prepare, build-frontend, create-jvm-manifests, create-native-manifests, create-native-compat-manifests]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Helm
uses: azure/setup-helm@v4
with:
version: 'latest'
- name: Configure Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Install docs-website dependencies
run: |
cd docs-website
npm ci
- name: Fetch published Helm index from GitHub Pages
run: |
echo "Fetching current published index.yaml from GitHub Pages..."
PUBLISHED_INDEX="https://tess1o.github.io/geopulse/charts/index.yaml"
# Try to fetch with retries (exponential backoff: 2s, 4s, 8s)
for i in 1 2 3; do
if curl -sSf -o charts/published-index.yaml "$PUBLISHED_INDEX"; then
echo "✅ Successfully fetched published index"
echo "MERGE_INDEX=charts/published-index.yaml" >> $GITHUB_ENV
break
else
if [ $i -eq 3 ]; then
echo "⚠️ Could not fetch published index, will use local index as fallback"
echo "MERGE_INDEX=charts/index.yaml" >> $GITHUB_ENV
else
WAIT_TIME=$((2 ** i))
echo "Attempt $i failed, retrying in ${WAIT_TIME}s..."
sleep $WAIT_TIME
fi
fi
done
- name: Download existing Helm charts from GitHub Pages
run: |
echo "Downloading existing chart packages to preserve old versions..."
CHARTS_URL="https://tess1o.github.io/geopulse/charts"
# Only download if we successfully fetched the published index
if [ -f charts/published-index.yaml ]; then
# Extract all chart URLs from the published index
CHART_URLS=$(grep -E "^\s+- https://tess1o.github.io/geopulse/charts/geopulse-.*\.tgz" charts/published-index.yaml | sed 's/.*- //' | sort -u)
if [ -n "$CHART_URLS" ]; then
echo "Found existing charts to download:"
echo "$CHART_URLS"
# Download each chart
for URL in $CHART_URLS; do
FILENAME=$(basename "$URL")
echo "Downloading $FILENAME..."
if curl -sSfL -o "charts/$FILENAME" "$URL"; then
echo "✅ Downloaded $FILENAME"
else
echo "⚠️ Failed to download $FILENAME (may not exist yet)"
fi
done
echo ""
echo "Downloaded charts:"
ls -lh charts/*.tgz 2>/dev/null || echo "No charts downloaded"
else
echo "No existing charts found in published index"
fi
else
echo "⚠️ Skipping chart download - no published index available"
fi
- name: Package Helm chart
run: |
echo "Packaging Helm chart..."
helm package helm/geopulse -d charts
- name: Update Helm repo index
run: |
echo "Updating Helm repository index..."
if [ -f "$MERGE_INDEX" ]; then
echo "Merging with: $MERGE_INDEX"
helm repo index charts --url https://tess1o.github.io/geopulse/charts --merge "$MERGE_INDEX"
else
echo "Creating new index (no existing index found)"
helm repo index charts --url https://tess1o.github.io/geopulse/charts
fi
# Cleanup temporary file
rm -f charts/published-index.yaml
- name: Validate Helm index
run: |
echo "Validating Helm repository index..."
# Check if index.yaml is valid YAML
if ! grep -q "apiVersion: v1" charts/index.yaml; then
echo "❌ Invalid index.yaml - missing apiVersion"
exit 1
fi
# Verify the new version is included
NEW_VERSION="${{ needs.prepare.outputs.version }}"
if ! grep -q "version: $NEW_VERSION" charts/index.yaml; then
echo "❌ New version $NEW_VERSION not found in index"
exit 1
fi
# Verify that all chart files referenced in index.yaml exist
echo "Verifying chart files exist..."
MISSING_CHARTS=0
while IFS= read -r url; do
FILENAME=$(basename "$url")
if [ ! -f "charts/$FILENAME" ]; then
echo "❌ Missing chart file: $FILENAME"
MISSING_CHARTS=$((MISSING_CHARTS + 1))
fi
done < <(grep -E "^\s+- https://tess1o.github.io/geopulse/charts/geopulse-.*\.tgz" charts/index.yaml | sed 's/.*- //' | sed 's|https://tess1o.github.io/geopulse/charts/||')
if [ $MISSING_CHARTS -gt 0 ]; then
echo "❌ Found $MISSING_CHARTS missing chart files"
exit 1
fi
# Display all versions for verification
echo "✅ Index validated successfully"
echo "All versions in index:"
grep "^ version:" charts/index.yaml | awk '{print " - " $2}' | sort -V
echo ""
echo "All chart files present:"
ls -1 charts/*.tgz | xargs -n1 basename
- name: Copy charts to docs-website
run: |
mkdir -p docs-website/static/charts
cp -r charts/* docs-website/static/charts/
echo "Copied to docs-website/static/charts:"
ls -lh docs-website/static/charts/
- name: Deploy documentation with Helm charts
env:
GIT_USER: ${{ github.actor }}
GIT_PASS: ${{ secrets.GITHUB_TOKEN }}
run: |
cd docs-website
npm run deploy
- name: Summary
run: |
echo "✅ Release ${{ needs.prepare.outputs.version }} completed successfully!"
echo ""
echo "📦 Published Docker images:"
echo " - ${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-jvm"
echo " - ${{ env.DOCKERHUB_BACKEND_IMAGE }}:${{ needs.prepare.outputs.version }}-native (multi-arch: amd64, arm64)"
echo " - ${{ env.DOCKERHUB_FRONTEND_IMAGE }}:${{ needs.prepare.outputs.version }}"
echo ""
echo "🎯 Published to:"
echo " - Docker Hub"
echo " - GitHub Container Registry"
echo " - Helm repository (GitHub Pages)"
echo ""
echo "📝 Next: Create GitHub Release at https://github.com/${{ github.repository }}/releases/new?tag=v${{ needs.prepare.outputs.version }}"