Build and Deploy to Synology NAS / test (push) Failing after 15m0s
Build and Deploy to Synology NAS / build (push) Has been cancelled
Build and Deploy to Synology NAS / deploy (push) Has been cancelled
Build and Deploy to Synology NAS / notify (push) Has been cancelled
- Add Terraform configuration for AKS cluster deployment - Add Kubernetes manifests for Laravel app (deployment, services, secrets) - Add PostgreSQL on Kubernetes with multi-schema support - Add Nginx Ingress Controller configuration - Add GitHub Actions workflow for Azure deployment - Add HTTP Basic Authentication for production - Add database restore functionality via Kubernetes jobs - Update Dockerfile and nginx config for production - Update database.php for multi-schema connections - Add deployment documentation and quickstart guides Deployed version: 1.0.7 at http://72.144.113.194/ Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
243 lines
8.2 KiB
YAML
243 lines
8.2 KiB
YAML
name: Deploy to Azure AKS
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
- production
|
|
workflow_dispatch:
|
|
inputs:
|
|
environment:
|
|
description: 'Environment to deploy to'
|
|
required: true
|
|
type: choice
|
|
options:
|
|
- staging
|
|
- production
|
|
default: staging
|
|
|
|
env:
|
|
REGISTRY: mylaravelregistry.azurecr.io
|
|
IMAGE_NAME: laravel-app
|
|
TERRAFORM_VERSION: 1.9.0
|
|
|
|
jobs:
|
|
build-and-push:
|
|
name: Build and Push Docker Image
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
image_tag: ${{ steps.meta.outputs.tags }}
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Log in to Azure Container Registry
|
|
uses: azure/docker-login@v1
|
|
with:
|
|
login-server: ${{ env.REGISTRY }}
|
|
username: ${{ secrets.ACR_USERNAME }}
|
|
password: ${{ secrets.ACR_PASSWORD }}
|
|
|
|
- name: Extract metadata (tags, labels) for Docker
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
tags: |
|
|
type=ref,event=branch
|
|
type=sha,prefix={{branch}}-
|
|
type=semver,pattern={{version}}
|
|
type=semver,pattern={{major}}.{{minor}}
|
|
|
|
- name: Build and push Docker image
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: .
|
|
file: ./Dockerfile
|
|
push: true
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
|
|
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
|
|
|
|
terraform-deploy:
|
|
name: Terraform Deploy
|
|
runs-on: ubuntu-latest
|
|
needs: build-and-push
|
|
environment: ${{ github.event.inputs.environment || 'staging' }}
|
|
|
|
defaults:
|
|
run:
|
|
working-directory: terraform
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Terraform
|
|
uses: hashicorp/setup-terraform@v3
|
|
with:
|
|
terraform_version: ${{ env.TERRAFORM_VERSION }}
|
|
|
|
- name: Azure Login
|
|
uses: azure/login@v1
|
|
with:
|
|
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
|
|
|
- name: Create terraform.tfvars
|
|
run: |
|
|
cat > terraform.tfvars <<EOF
|
|
subscription_id = "${{ secrets.AZURE_SUBSCRIPTION_ID }}"
|
|
resource_group_name = "trusted_ai_demo_rg"
|
|
location = "germanywestcentral"
|
|
aks_cluster_name = "trai_k8s_cluster"
|
|
|
|
app_name = "laravel-app"
|
|
app_namespace = "laravel-app"
|
|
app_env = "${{ github.event.inputs.environment || 'staging' }}"
|
|
app_debug = ${{ github.event.inputs.environment == 'production' && 'false' || 'true' }}
|
|
app_replicas = ${{ github.event.inputs.environment == 'production' && '3' || '2' }}
|
|
|
|
docker_image = "${{ needs.build-and-push.outputs.image_tag }}"
|
|
app_key = "${{ secrets.LARAVEL_APP_KEY }}"
|
|
|
|
postgresql_admin_username = "${{ secrets.POSTGRESQL_ADMIN_USERNAME }}"
|
|
postgresql_admin_password = "${{ secrets.POSTGRESQL_ADMIN_PASSWORD }}"
|
|
postgresql_sku_name = "${{ github.event.inputs.environment == 'production' && 'GP_Standard_D2s_v3' || 'B_Standard_B1ms' }}"
|
|
postgresql_storage_mb = ${{ github.event.inputs.environment == 'production' && '131072' || '32768' }}
|
|
|
|
ingress_enabled = true
|
|
ingress_host = "${{ secrets.INGRESS_HOST }}"
|
|
|
|
ssl_enabled = ${{ github.event.inputs.environment == 'production' && 'true' || 'false' }}
|
|
ssl_issuer_email = "${{ secrets.SSL_ISSUER_EMAIL }}"
|
|
|
|
db_restore_enabled = false
|
|
|
|
alert_email_address = "${{ secrets.ALERT_EMAIL }}"
|
|
EOF
|
|
|
|
- name: Terraform Init
|
|
run: terraform init
|
|
|
|
- name: Terraform Validate
|
|
run: terraform validate
|
|
|
|
- name: Terraform Plan
|
|
run: terraform plan -out=tfplan
|
|
|
|
- name: Terraform Apply
|
|
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/production'
|
|
run: terraform apply -auto-approve tfplan
|
|
|
|
- name: Get kubectl credentials
|
|
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/production'
|
|
run: |
|
|
az aks get-credentials \
|
|
--resource-group trusted_ai_demo_rg \
|
|
--name trai_k8s_cluster \
|
|
--overwrite-existing
|
|
|
|
- name: Wait for deployment
|
|
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/production'
|
|
run: |
|
|
kubectl wait --for=condition=ready pod \
|
|
-l app=laravel-app \
|
|
-n laravel-app \
|
|
--timeout=300s || true
|
|
|
|
- name: Get Application URL
|
|
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/production'
|
|
id: get-url
|
|
run: |
|
|
APP_URL=$(terraform output -raw app_url)
|
|
echo "url=$APP_URL" >> $GITHUB_OUTPUT
|
|
echo "### Deployment Complete! 🚀" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "Application URL: $APP_URL" >> $GITHUB_STEP_SUMMARY
|
|
|
|
- name: Upload Terraform Plan
|
|
if: github.ref != 'refs/heads/main' && github.ref != 'refs/heads/production'
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: terraform-plan
|
|
path: terraform/tfplan
|
|
|
|
smoke-tests:
|
|
name: Smoke Tests
|
|
runs-on: ubuntu-latest
|
|
needs: terraform-deploy
|
|
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/production'
|
|
|
|
steps:
|
|
- name: Azure Login
|
|
uses: azure/login@v1
|
|
with:
|
|
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
|
|
|
- name: Get kubectl credentials
|
|
run: |
|
|
az aks get-credentials \
|
|
--resource-group trusted_ai_demo_rg \
|
|
--name trai_k8s_cluster \
|
|
--overwrite-existing
|
|
|
|
- name: Check pod health
|
|
run: |
|
|
kubectl get pods -n laravel-app
|
|
READY_PODS=$(kubectl get pods -n laravel-app -l app=laravel-app -o jsonpath='{.items[*].status.conditions[?(@.type=="Ready")].status}' | grep -o "True" | wc -l)
|
|
if [ "$READY_PODS" -lt 1 ]; then
|
|
echo "Error: No ready pods found"
|
|
exit 1
|
|
fi
|
|
echo "✓ $READY_PODS pod(s) are ready"
|
|
|
|
- name: Check service endpoint
|
|
run: |
|
|
LOADBALANCER_IP=$(kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
|
if [ -z "$LOADBALANCER_IP" ]; then
|
|
echo "Warning: LoadBalancer IP not yet assigned"
|
|
else
|
|
echo "✓ LoadBalancer IP: $LOADBALANCER_IP"
|
|
|
|
# Try to reach the application
|
|
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://$LOADBALANCER_IP --max-time 10)
|
|
if [ "$HTTP_CODE" -eq 200 ] || [ "$HTTP_CODE" -eq 302 ]; then
|
|
echo "✓ Application is responding (HTTP $HTTP_CODE)"
|
|
else
|
|
echo "Warning: Application returned HTTP $HTTP_CODE"
|
|
fi
|
|
fi
|
|
|
|
- name: Check database connectivity
|
|
run: |
|
|
DB_SECRET=$(kubectl get secret laravel-app-db-credentials -n laravel-app -o jsonpath='{.data.DB_HOST}' | base64 -d)
|
|
echo "✓ Database host configured: $DB_SECRET"
|
|
|
|
notify:
|
|
name: Notify Deployment Status
|
|
runs-on: ubuntu-latest
|
|
needs: [build-and-push, terraform-deploy, smoke-tests]
|
|
if: always()
|
|
|
|
steps:
|
|
- name: Deployment Success
|
|
if: ${{ needs.terraform-deploy.result == 'success' && needs.smoke-tests.result == 'success' }}
|
|
run: |
|
|
echo "### ✅ Deployment Successful!" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "Environment: ${{ github.event.inputs.environment || 'staging' }}" >> $GITHUB_STEP_SUMMARY
|
|
echo "Commit: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
|
|
|
|
- name: Deployment Failed
|
|
if: ${{ needs.terraform-deploy.result == 'failure' || needs.smoke-tests.result == 'failure' }}
|
|
run: |
|
|
echo "### ❌ Deployment Failed!" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "Please check the logs for details." >> $GITHUB_STEP_SUMMARY
|
|
exit 1
|