Skip to content

CD - Deploy Backend (then Frontend) #12

CD - Deploy Backend (then Frontend)

CD - Deploy Backend (then Frontend) #12

Workflow file for this run

name: CD - Deploy Backend (then Frontend)
on:
workflow_dispatch:
inputs:
aks_cluster_name: { description: 'AKS name', required: false, default: '' }
aks_resource_group: { description: 'RG name', required: false, default: '' }
image_tag: { description: 'Image tag to deploy (optional)', required: false, default: '' }
workflow_run:
workflows: ["CI - Test, Build & Push (Backend + Frontend)"]
types: [completed]
branches: [main]
permissions:
id-token: write
contents: read
concurrency:
group: deploy-backend-prod
cancel-in-progress: false
jobs:
deploy_backend:
# Run if manual OR CI completed successfully
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
environment: Production
outputs:
PRODUCT_API_IP: ${{ steps.capture.outputs.product_ip }}
ORDER_API_IP: ${{ steps.capture.outputs.order_ip }}
IMAGE_TAG: ${{ steps.compute_tag.outputs.val }}
AKS_NAME: ${{ steps.compute_aks.outputs.name }}
AKS_RG: ${{ steps.compute_aks.outputs.rg }}
steps:
- uses: actions/checkout@v4
# Decide which image tag to deploy
- name: Compute IMAGE_TAG
id: compute_tag
run: |
if [ "${{ github.event_name }}" = "workflow_run" ]; then
echo "val=${{ github.event.workflow_run.head_sha }}" >> $GITHUB_OUTPUT
elif [ -n "${{ github.event.inputs.image_tag }}" ]; then
echo "val=${{ github.event.inputs.image_tag }}" >> $GITHUB_OUTPUT
else
echo "val=${{ github.sha }}" >> $GITHUB_OUTPUT
fi
# Compute AKS name/RG (inputs override secrets)
- name: Compute AKS values
id: compute_aks
run: |
NAME="${{ github.event.inputs.aks_cluster_name }}"
RG="${{ github.event.inputs.aks_resource_group }}"
if [ -z "$NAME" ]; then NAME="${{ secrets.AKS_NAME }}"; fi
if [ -z "$RG" ]; then RG="${{ secrets.AKS_RG }}"; fi
echo "name=$NAME" >> $GITHUB_OUTPUT
echo "rg=$RG" >> $GITHUB_OUTPUT
echo "AKS_NAME=$NAME" >> $GITHUB_ENV
echo "AKS_RG=$RG" >> $GITHUB_ENV
# Azure login
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
enable-AzPSSession: true
- name: Set AKS context
run: |
az aks get-credentials \
--resource-group "$AKS_RG" \
--name "$AKS_NAME" \
--overwrite-existing
- name: Attach ACR
run: |
az aks update \
--resource-group "$AKS_RG" \
--name "$AKS_NAME" \
--attach-acr "${{ secrets.AZURE_ACR_NAME }}"
- name: Deploy Config & Databases
working-directory: k8s
run: |
kubectl apply -f configmaps.yaml
kubectl apply -f secrets.yaml
kubectl apply -f product-db.yaml
kubectl apply -f order-db.yaml
- name: Deploy Services (apply manifests and pin images)
env:
REGISTRY_LOGIN_SERVER: ${{ secrets.AZURE_ACR_LOGIN_SERVER }}
IMAGE_TAG: ${{ steps.compute_tag.outputs.val }}
run: |
kubectl apply -f k8s/product-service.yaml
kubectl apply -f k8s/order-service.yaml
kubectl set image deploy/product-service-w08e1 product-service-container="${REGISTRY_LOGIN_SERVER}/product_service:${IMAGE_TAG}" --record=true || true
kubectl set image deploy/order-service-w08e1 order-service-container="${REGISTRY_LOGIN_SERVER}/order_service:${IMAGE_TAG}" --record=true || true
echo "Waiting for product-service rollout..."
kubectl rollout status deploy/product-service-w08e1 --timeout=180s || exit 1
echo "Waiting for order-service rollout..."
kubectl rollout status deploy/order-service-w08e1 --timeout=180s || exit 1
- name: Capture LoadBalancer IPs
id: capture
run: |
for i in {1..60}; do
PRODUCT_IP=$(kubectl get svc product-service-w08e1 -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
ORDER_IP=$(kubectl get svc order-service-w08e1 -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
if [[ -n "$PRODUCT_IP" && -n "$ORDER_IP" ]]; then
echo "product_ip=$PRODUCT_IP" >> $GITHUB_OUTPUT
echo "order_ip=$ORDER_IP" >> $GITHUB_OUTPUT
exit 0
fi
sleep 5
done
echo "Timed out waiting for IPs"; exit 1
deploy_frontend:
needs: deploy_backend
uses: ./.github/workflows/frontend-cd.yml
with:
product_api_ip: "http://${{ needs.deploy_backend.outputs.PRODUCT_API_IP }}:8000"
order_api_ip: "http://${{ needs.deploy_backend.outputs.ORDER_API_IP }}:8001"
aks_cluster_name: ${{ needs.deploy_backend.outputs.AKS_NAME }}
aks_resource_group: ${{ needs.deploy_backend.outputs.AKS_RG }}
image_tag: ${{ needs.deploy_backend.outputs.IMAGE_TAG }}
secrets: inherit
# update