diff --git a/.github/workflows/backend-cd.yml b/.github/workflows/backend-cd.yml index 6035ed15..7a11ec2b 100644 --- a/.github/workflows/backend-cd.yml +++ b/.github/workflows/backend-cd.yml @@ -1,101 +1,106 @@ -name: CD - Deploy Backend Services to AKS +name: CD - Deploy Backend Services to AKS on: workflow_dispatch: inputs: aks_cluster_name: - description: 'Name of the AKS Cluster to deploy to' + description: Name of the AKS Cluster required: true - default: '' aks_resource_group: - description: 'Resource Group of the AKS Cluster' + description: Resource Group of the AKS Cluster required: true - default: '' - aks_acr_name: - description: 'Name of ACR' - required: true - default: '' jobs: deploy_backend: - runs-on: ubuntu-latest - environment: Production - - outputs: - PRODUCT_API_IP: ${{ steps.get_product_ip.outputs.external_ip }} - ORDER_API_IP: ${{ steps.get_order_ip.outputs.external_ip }} - + runs-on: ubuntu-22.04 steps: - - name: Checkout repository - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Log in to Azure - uses: azure/login@v1 - with: - creds: ${{ secrets.AZURE_CREDENTIALS }} - enable-AzPSSession: true - - - name: Set Kubernetes context (get AKS credentials) + - name: Azure CLI login (service principal) + env: + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} run: | - az aks get-credentials --resource-group ${{ github.event.inputs.aks_resource_group }} --name ${{ github.event.inputs.aks_cluster_name }} --overwrite-existing + set -euxo pipefail + az cloud set -n azurecloud + az login --service-principal -u "$AZURE_CLIENT_ID" -p "$AZURE_CLIENT_SECRET" --tenant "$AZURE_TENANT_ID" + az account set --subscription "$AZURE_SUBSCRIPTION_ID" - - name: Attach ACR + - name: Set Kubernetes context (get AKS credentials) run: | - az aks update --name ${{ github.event.inputs.aks_cluster_name }} --resource-group ${{ github.event.inputs.aks_resource_group }} --attach-acr ${{ github.event.inputs.aks_acr_name }} + az aks get-credentials \ + --resource-group ${{ github.event.inputs.aks_resource_group }} \ + --name ${{ github.event.inputs.aks_cluster_name }} \ + --overwrite-existing - - name: Deploy Backend Infrastructure (Namespace, ConfigMaps, Secrets, Databases) + - name: Ensure namespace and image pull secret + env: + REGISTRY_LOGIN_SERVER: ${{ secrets.REGISTRY_LOGIN_SERVER }} + REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} + REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} run: | - echo "Deploying backend infrastructure..." - cd k8s/ - kubectl apply -f configmaps.yaml - kubectl apply -f secrets.yaml - kubectl apply -f product-db.yaml - kubectl apply -f order-db.yaml + set -euxo pipefail + kubectl create namespace sit722-w08 --dry-run=client -o yaml | kubectl apply -f - + kubectl create secret docker-registry acr-pull \ + --docker-server="$REGISTRY_LOGIN_SERVER" \ + --docker-username="$REGISTRY_USERNAME" \ + --docker-password="$REGISTRY_PASSWORD" \ + -n sit722-w08 --dry-run=client -o yaml | kubectl apply -f - + kubectl patch sa default -n sit722-w08 --type merge -p '{"imagePullSecrets":[{"name":"acr-pull"}]}' || true - - name: Deploy Backend Microservices (Product, Order) - run: | - echo "Deploying backend microservices..." - cd k8s/ - kubectl apply -f product-service.yaml - kubectl apply -f order-service.yaml - - - name: Wait for Backend LoadBalancer IPs + - name: Deploy backend services (product & order) + env: + REGISTRY_LOGIN_SERVER: ${{ secrets.REGISTRY_LOGIN_SERVER }} run: | - echo "Waiting for Product, Order LoadBalancer IPs to be assigned (up to 5 minutes)..." - PRODUCT_IP="" - ORDER_IP="" - - for i in $(seq 1 60); do - echo "Attempt $i/60 to get IPs..." - PRODUCT_IP=$(kubectl get service product-service-w08e1 -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - ORDER_IP=$(kubectl get service order-service-w08e1 -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - - if [[ -n "$PRODUCT_IP" && -n "$ORDER_IP" ]]; then - echo "All backend LoadBalancer IPs assigned!" - echo "Product Service IP: $PRODUCT_IP" - echo "Order Service IP: $ORDER_IP" - break - fi - sleep 5 # Wait 5 seconds before next attempt - done - - if [[ -z "$PRODUCT_IP" || -z "$ORDER_IP" ]]; then - echo "Error: One or more LoadBalancer IPs not assigned after timeout." - exit 1 # Fail the job if IPs are not obtained - fi - - # These are environment variables for subsequent steps in the *same job* - # And used to set the job outputs - echo "PRODUCT_IP=$PRODUCT_IP" >> $GITHUB_ENV - echo "ORDER_IP=$ORDER_IP" >> $GITHUB_ENV - - - name: Capture Product Service IP for Workflow Output - id: get_product_ip - run: echo "external_ip=${{ env.PRODUCT_IP }}" >> $GITHUB_OUTPUT - - - name: Capture Order Service IP for Workflow Output - id: get_order_ip - run: echo "external_ip=${{ env.ORDER_IP }}" >> $GITHUB_OUTPUT + cat <<'YAML' | kubectl apply -f - + apiVersion: apps/v1 + kind: Deployment + metadata: { name: product-service, namespace: sit722-w08 } + spec: + replicas: 1 + selector: { matchLabels: { app: product } } + template: + metadata: { labels: { app: product } } + spec: + containers: + - name: product + image: ${REGISTRY_LOGIN_SERVER}/product_service:latest + imagePullPolicy: Always + ports: [{ containerPort: 8000 }] + --- + apiVersion: v1 + kind: Service + metadata: { name: product-svc, namespace: sit722-w08 } + spec: + type: LoadBalancer + selector: { app: product } + ports: [{ port: 8000, targetPort: 8000 }] + --- + apiVersion: apps/v1 + kind: Deployment + metadata: { name: order-service, namespace: sit722-w08 } + spec: + replicas: 1 + selector: { matchLabels: { app: order } } + template: + metadata: { labels: { app: order } } + spec: + containers: + - name: order + image: ${REGISTRY_LOGIN_SERVER}/order_service:latest + imagePullPolicy: Always + ports: [{ containerPort: 8002 }] + --- + apiVersion: v1 + kind: Service + metadata: { name: order-svc, namespace: sit722-w08 } + spec: + type: LoadBalancer + selector: { app: order } + ports: [{ port: 8002, targetPort: 8002 }] + YAML - - name: Logout from Azure - run: az logout + - name: Verify rollout + run: kubectl get deploy,svc -n sit722-w08 -o wide diff --git a/.github/workflows/backend_ci.yml b/.github/workflows/backend_ci.yml index d69725aa..a9ef7f5f 100644 --- a/.github/workflows/backend_ci.yml +++ b/.github/workflows/backend_ci.yml @@ -1,4 +1,4 @@ -# week08/.github/workflows/backend_ci.yml +# week08/.github/workflows/backend_ci.yml name: Backend CI - Test, Build and Push Images to ACR @@ -20,7 +20,7 @@ on: env: # ACR Login Server (e.g., myregistry.azurecr.io) # This needs to be set as a GitHub Repository Secret - ACR_LOGIN_SERVER: ${{ secrets.AZURE_CONTAINER_REGISTRY }} + ACR_LOGIN_SERVER: ${{ secrets.REGISTRY_LOGIN_SERVER }} # Dynamically generate image tags based on Git SHA and GitHub Run ID # This provides unique, traceable tags for each image build IMAGE_TAG: ${{ github.sha }}-${{ github.run_id }} @@ -126,7 +126,7 @@ jobs: # Login to Azure Container Registry (ACR) - name: Login to Azure Container Registry - run: az acr login --name ${{ env.ACR_LOGIN_SERVER }} + run: az acr login --name ${{ secrets.AZURE_CONTAINER_REGISTRY }} # Build and Push Docker image for Product Service - name: Build and Push Product Service Image diff --git a/.github/workflows/frontend-cd.yml b/.github/workflows/frontend-cd.yml index 0a0879c8..5e448bc7 100644 --- a/.github/workflows/frontend-cd.yml +++ b/.github/workflows/frontend-cd.yml @@ -1,4 +1,4 @@ -# week08/.github/workflows/frontend-cd.yml +# week08/.github/workflows/frontend-cd.yml name: CD - Deploy Frontend to AKS @@ -73,8 +73,8 @@ jobs: # Build and Push Docker image for Frontend - name: Build and Push Frontend Image run: | - docker build -t ${{ secrets.AZURE_CONTAINER_REGISTRY }}/frontend:latest ./frontend/ - docker push ${{ secrets.AZURE_CONTAINER_REGISTRY }}/frontend:latest + docker build -t ${{ secrets.REGISTRY_LOGIN_SERVER }}/frontend:latest ./frontend/ + docker push ${{ secrets.REGISTRY_LOGIN_SERVER }}/frontend:latest - name: Set Kubernetes context (get AKS credentials) uses: azure/aks-set-context@v3 diff --git a/.github/workflows/frontend_ci.yml b/.github/workflows/frontend_ci.yml index 9f9e76d9..32dc9080 100644 --- a/.github/workflows/frontend_ci.yml +++ b/.github/workflows/frontend_ci.yml @@ -1,4 +1,4 @@ -# week08/.github/workflows/frontend_ci.yml +# week08/.github/workflows/frontend_ci.yml name: Frontend CI - Build & Push Image @@ -18,7 +18,7 @@ on: env: # ACR Login Server (e.g., myregistry.azurecr.io) # This needs to be set as a GitHub Repository Secret - ACR_LOGIN_SERVER: ${{ secrets.AZURE_CONTAINER_REGISTRY }} + ACR_LOGIN_SERVER: ${{ secrets.REGISTRY_LOGIN_SERVER }} # Dynamically generate image tags based on Git SHA and GitHub Run ID # This provides unique, traceable tags for each image build IMAGE_TAG: ${{ github.sha }}-${{ github.run_id }} @@ -39,7 +39,7 @@ jobs: # Login to Azure Container Registry (ACR) - name: Login to Azure Container Registry - run: az acr login --name ${{ env.ACR_LOGIN_SERVER }} + run: az acr login --name ${{ secrets.AZURE_CONTAINER_REGISTRY }} # Build and Push Docker image for Frontend - name: Build and Push Frontend Image diff --git a/README.md b/README.md index 23009398..c6a78578 100644 --- a/README.md +++ b/README.md @@ -36,3 +36,4 @@ image: .azurecr.io/: ### 2. Update Backend Pipeline (`.github/workflows/backend-cd.yml`) & Frontend Pipeline (`.github/workflows/frontend-cd.yml`) Ensure you replace all placeholders value to actual values. +trigger backend ci/cd diff --git a/frontend/main.js b/frontend/main.js index f321fd91..64035c81 100644 --- a/frontend/main.js +++ b/frontend/main.js @@ -1,11 +1,11 @@ -// week08/frontend/main.js +// week08/frontend/main.js document.addEventListener('DOMContentLoaded', () => { // API endpoints for the Product and Order services. // These ports (30000 for Product, 30001 for Order) are mapped // from the Docker containers to the host machine in docker-compose.yml for Example 2. - const PRODUCT_API_BASE_URL = '_PRODUCT_API_URL_'; - const ORDER_API_BASE_URL = '_ORDER_API_URL_'; + const PRODUCT_API_BASE_URL = 'http://4.198.148.230:8000'; + const ORDER_API_BASE_URL = 'http://20.11.234.69:8002'; // Product Service is named 'product-service-w04e2' and exposes port 8000 internally. //const PRODUCT_API_BASE_URL = 'http://product-service-w04e2:8000'; @@ -426,3 +426,7 @@ document.addEventListener('DOMContentLoaded', () => { fetchProducts(); fetchOrders(); }); + + + +