[visualizer] increase max speed from 20 to 50 #58 #48
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: visualizer build, push, deploy | |
| on: | |
| push: | |
| branches: [main, dev] | |
| paths: | |
| - "visualizer/**" | |
| - ".github/workflows/visualizer.yml" | |
| pull_request: | |
| branches: [main, dev] | |
| paths: | |
| - "visualizer/**" | |
| - ".github/workflows/visualizer.yml" | |
| create: | |
| tags: | |
| - "v*" | |
| permissions: | |
| contents: read | |
| packages: write | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: 42core-team/visualizer | |
| jobs: | |
| build: | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - architecture: amd64 | |
| runner: ubuntu-24.04 | |
| platform: linux/amd64 | |
| - architecture: arm64 | |
| runner: ubuntu-24.04-arm | |
| platform: linux/arm64 | |
| outputs: | |
| images: ${{ steps.meta.outputs.tags }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to container registry | |
| if: github.event_name != 'pull_request' | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Generate Docker metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=ref,event=branch | |
| type=ref,event=pr | |
| type=ref,event=tag | |
| type=sha,format=short,prefix={{branch}}- | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| labels: | | |
| org.opencontainers.image.title=Debug Visualizer | |
| org.opencontainers.image.description=Debug visualizer web application | |
| org.opencontainers.image.vendor=${{ github.repository_owner }} | |
| - name: Create architecture-specific tags | |
| id: arch-tags | |
| run: | | |
| # Get the base tags and add architecture suffix to each | |
| BASE_TAGS="${{ steps.meta.outputs.tags }}" | |
| ARCH_TAGS="" | |
| while IFS= read -r tag; do | |
| if [[ -n "$tag" ]]; then | |
| if [[ -z "$ARCH_TAGS" ]]; then | |
| ARCH_TAGS="${tag}-${{ matrix.architecture }}" | |
| else | |
| ARCH_TAGS="${ARCH_TAGS}\n${tag}-${{ matrix.architecture }}" | |
| fi | |
| fi | |
| done <<< "$BASE_TAGS" | |
| echo "arch-tags<<EOF" >> $GITHUB_OUTPUT | |
| echo -e "$ARCH_TAGS" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| - name: Build and push multi-arch image | |
| if: github.event_name != 'pull_request' | |
| id: build | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: ./visualizer | |
| file: ./visualizer/Dockerfile | |
| platforms: ${{ matrix.platform }} | |
| push: true | |
| tags: ${{ steps.arch-tags.outputs.arch-tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: | | |
| type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ github.ref_name }}-${{ matrix.architecture }} | |
| type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-main-${{ matrix.architecture }} | |
| cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ github.ref_name }}-${{ matrix.architecture }},mode=max | |
| - name: Build Docker image (PR test) | |
| if: github.event_name == 'pull_request' | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: ./visualizer | |
| file: ./visualizer/Dockerfile | |
| platforms: ${{ matrix.platform }} | |
| push: false | |
| tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test-${{ matrix.architecture }} | |
| cache-from: | | |
| type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ github.ref_name }}-${{ matrix.architecture }} | |
| type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-main-${{ matrix.architecture }} | |
| - name: Show build information | |
| run: | | |
| echo "Built for architecture: ${{ matrix.architecture }}" | |
| echo "Platform: ${{ matrix.platform }}" | |
| echo "Runner: ${{ matrix.runner }}" | |
| if [ "${{ github.event_name }}" == "push" ]; then | |
| echo "Image tags: ${{ steps.arch-tags.outputs.arch-tags }}" | |
| else | |
| echo "Test build completed for PR" | |
| fi | |
| merge: | |
| needs: build | |
| runs-on: ubuntu-24.04 | |
| if: github.event_name != 'pull_request' | |
| steps: | |
| - name: Setup Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to container registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Generate Docker metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=ref,event=branch | |
| type=ref,event=pr | |
| type=ref,event=tag | |
| type=sha,format=short,prefix={{branch}}- | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| labels: | | |
| org.opencontainers.image.title=Debug Visualizer | |
| org.opencontainers.image.description=Debug visualizer web application | |
| org.opencontainers.image.vendor=${{ github.repository_owner }} | |
| - name: Generate additional version tags | |
| id: version-tags | |
| if: startsWith(github.ref, 'refs/tags/') | |
| run: | | |
| # Extract version from tag (remove 'v' prefix if present) | |
| VERSION=${GITHUB_REF#refs/tags/} | |
| VERSION=${VERSION#v} | |
| # Split version into parts | |
| IFS='.' read -r -a parts <<< "$VERSION" | |
| # Generate hierarchical tags based on number of parts | |
| ADDITIONAL_TAGS="" | |
| if [ ${#parts[@]} -ge 1 ]; then | |
| ADDITIONAL_TAGS="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:v${parts[0]}" | |
| fi | |
| if [ ${#parts[@]} -ge 2 ]; then | |
| ADDITIONAL_TAGS="$ADDITIONAL_TAGS,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:v${parts[0]}.${parts[1]}" | |
| fi | |
| if [ ${#parts[@]} -ge 3 ]; then | |
| ADDITIONAL_TAGS="$ADDITIONAL_TAGS,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:v${parts[0]}.${parts[1]}.${parts[2]}" | |
| fi | |
| if [ ${#parts[@]} -ge 4 ]; then | |
| ADDITIONAL_TAGS="$ADDITIONAL_TAGS,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:v${parts[0]}.${parts[1]}.${parts[2]}.${parts[3]}" | |
| fi | |
| echo "additional-tags=$ADDITIONAL_TAGS" >> $GITHUB_OUTPUT | |
| echo "Generated additional tags: $ADDITIONAL_TAGS" | |
| - name: Create multi-architecture manifest | |
| run: | | |
| # Get the tags from metadata (convert newlines to spaces for proper iteration) | |
| TAGS=$(echo "${{ steps.meta.outputs.tags }}" | tr '\n' ' ') | |
| # Create manifest for each tag from metadata | |
| for tag in $TAGS; do | |
| # Skip empty tags | |
| if [[ -z "$tag" ]]; then | |
| continue | |
| fi | |
| echo "Creating manifest for tag: $tag" | |
| # Create manifest from existing architecture-specific images | |
| docker buildx imagetools create -t "$tag" \ | |
| "${tag}-amd64" \ | |
| "${tag}-arm64" | |
| echo "Manifest created for $tag" | |
| done | |
| # Create manifest for additional version tags if they exist | |
| if [ -n "${{ steps.version-tags.outputs.additional-tags }}" ]; then | |
| # Find the ref tag from the base tags to use as source | |
| REF_TAG="" | |
| for tag in $TAGS; do | |
| if [[ "$tag" == *"$GITHUB_REF_NAME" ]] && [[ "$tag" != *"-"* ]]; then | |
| REF_TAG="$tag" | |
| break | |
| fi | |
| done | |
| if [ -n "$REF_TAG" ]; then | |
| IFS=',' read -r -a additional_tags <<< "${{ steps.version-tags.outputs.additional-tags }}" | |
| for tag in "${additional_tags[@]}"; do | |
| if [ -n "$tag" ]; then | |
| echo "Creating additional tag: $tag from $REF_TAG" | |
| # Create additional tags from the ref tag that was already built | |
| docker buildx imagetools create -t "$tag" \ | |
| "${REF_TAG}-amd64" \ | |
| "${REF_TAG}-arm64" | |
| echo "Additional manifest created for $tag" | |
| fi | |
| done | |
| fi | |
| fi | |
| - name: Show manifest information | |
| run: | | |
| echo "Multi-architecture manifest created" | |
| echo "Image tags: ${{ steps.meta.outputs.tags }}" | |
| echo "Supported platforms: linux/amd64, linux/arm64" | |
| deploy: | |
| needs: merge | |
| runs-on: ubuntu-24.04 | |
| if: (github.event_name == 'push' && github.ref == 'refs/heads/dev') || (github.event_name == 'create' && startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, '-')) | |
| environment: ${{ ((github.ref_name == 'main') || (startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, '-'))) && 'prod' || 'dev' }} | |
| permissions: | |
| contents: read | |
| packages: read | |
| deployments: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Prepare deployment configuration | |
| id: cfg | |
| run: | | |
| BRANCH="${{ github.ref_name }}" | |
| if [[ "$GITHUB_REF" == refs/tags/* ]]; then | |
| NAMESPACE="production" | |
| ENVIRONMENT_URL="https://visualizer.coregame.de" | |
| DEPLOYMENT_NAME="debug-visualizer" | |
| elif [ "$BRANCH" = "main" ]; then | |
| NAMESPACE="production" | |
| ENVIRONMENT_URL="https://visualizer.coregame.de" | |
| DEPLOYMENT_NAME="debug-visualizer" | |
| else | |
| NAMESPACE="development" | |
| ENVIRONMENT_URL="https://dev.visualizer.coregame.de" | |
| DEPLOYMENT_NAME="debug-visualizer-dev" | |
| fi | |
| echo "namespace=${NAMESPACE}" >> $GITHUB_OUTPUT | |
| echo "environment_url=${ENVIRONMENT_URL}" >> $GITHUB_OUTPUT | |
| echo "deployment_name=${DEPLOYMENT_NAME}" >> $GITHUB_OUTPUT | |
| - name: Setup kubectl CLI | |
| uses: azure/setup-kubectl@v4 | |
| with: | |
| version: "v1.28.4" | |
| - name: Configure Kubernetes context | |
| run: | | |
| set -euo pipefail | |
| mkdir -p ~/.kube | |
| if [ -n "${KUBECONFIG_DATA:-}" ]; then | |
| echo "Using KUBECONFIG_DATA from environment variable" | |
| echo "$KUBECONFIG_DATA" | base64 -d > ~/.kube/config | |
| elif [ -n "${{ secrets.KUBECONFIG_DATA }}" ]; then | |
| echo "Using KUBECONFIG_DATA from GitHub secret" | |
| echo "${{ secrets.KUBECONFIG_DATA }}" | base64 -d > ~/.kube/config | |
| elif [ -f .kube/config ]; then | |
| echo "Using repository kubeconfig at .kube/config" | |
| cp .kube/config ~/.kube/config | |
| else | |
| echo "ERROR: No kubeconfig provided. Set KUBECONFIG_DATA (env or secret) or commit .kube/config for CI use." | |
| exit 1 | |
| fi | |
| chmod 600 ~/.kube/config | |
| echo "KUBECONFIG=$HOME/.kube/config" >> $GITHUB_ENV | |
| - name: Verify Kubernetes cluster | |
| run: | | |
| kubectl cluster-info | |
| kubectl get nodes | |
| - name: Setup Helm | |
| uses: azure/setup-helm@v4 | |
| with: | |
| version: "v3.13.3" | |
| - name: Determine image tag to deploy | |
| id: image | |
| run: | | |
| BRANCH="${{ github.ref_name }}" | |
| SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7) | |
| TAG="${BRANCH}-${SHORT_SHA}" | |
| echo "repo=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" >> $GITHUB_OUTPUT | |
| echo "tag=${TAG}" >> $GITHUB_OUTPUT | |
| echo "Deploying image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${TAG}" | |
| - name: Ensure Kubernetes namespace exists | |
| run: | | |
| kubectl create namespace ${{ steps.cfg.outputs.namespace }} --dry-run=client -o yaml | kubectl apply -f - | |
| - name: Validate Helm chart | |
| run: | | |
| helm lint ./visualizer/helm/debug-visualizer --values ./visualizer/helm/debug-visualizer/${{ ((github.ref_name == 'main') || (startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, '-'))) && 'values-prod.yaml' || 'values-dev.yaml' }} | |
| - name: Deploy application with Helm | |
| run: | | |
| VALUES_FILE=${{ ((github.ref_name == 'main') || (startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, '-'))) && 'values-prod.yaml' || 'values-dev.yaml' }} | |
| helm upgrade --install \ | |
| ${{ steps.cfg.outputs.deployment_name }} \ | |
| ./visualizer/helm/debug-visualizer \ | |
| --namespace ${{ steps.cfg.outputs.namespace }} \ | |
| --values ./visualizer/helm/debug-visualizer/${VALUES_FILE} \ | |
| --set image.repository=${{ steps.image.outputs.repo }} \ | |
| --set image.tag=${{ steps.image.outputs.tag }} \ | |
| --wait \ | |
| --timeout=3m \ | |
| --atomic \ | |
| --history-max=5 | |
| - name: Verify Kubernetes deployment | |
| run: | | |
| kubectl rollout status deployment/${{ steps.cfg.outputs.deployment_name }} -n ${{ steps.cfg.outputs.namespace }} --timeout=300s | |
| kubectl get deploy/${{ steps.cfg.outputs.deployment_name }} -n ${{ steps.cfg.outputs.namespace }} -o wide | cat | |
| kubectl get svc -n ${{ steps.cfg.outputs.namespace }} | cat | |
| kubectl get ingress -n ${{ steps.cfg.outputs.namespace }} | cat | |
| - name: Write deployment summary | |
| run: | | |
| echo "## Application Deployment" >> $GITHUB_STEP_SUMMARY | |
| echo "Environment: ${{ ((github.ref_name == 'main') || (startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, '-'))) && 'prod' || 'dev' }}" >> $GITHUB_STEP_SUMMARY | |
| echo "Namespace: ${{ steps.cfg.outputs.namespace }}" >> $GITHUB_STEP_SUMMARY | |
| echo "Deployment: ${{ steps.cfg.outputs.deployment_name }}" >> $GITHUB_STEP_SUMMARY | |
| echo "Image: ${{ steps.image.outputs.repo }}:${{ steps.image.outputs.tag }}" >> $GITHUB_STEP_SUMMARY | |
| echo "URL: ${{ steps.cfg.outputs.environment_url }}" >> $GITHUB_STEP_SUMMARY |