From fdd10a9fb2c822df30e40a6671057875fc286714 Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Wed, 1 Oct 2025 01:48:11 +1000 Subject: [PATCH 01/13] Remove Attach ACR step --- .github/workflows/backend-cd.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/backend-cd.yml b/.github/workflows/backend-cd.yml index 6035ed15..6472627b 100644 --- a/.github/workflows/backend-cd.yml +++ b/.github/workflows/backend-cd.yml @@ -38,10 +38,25 @@ jobs: - name: Set Kubernetes context (get AKS credentials) run: | az aks get-credentials --resource-group ${{ github.event.inputs.aks_resource_group }} --name ${{ github.event.inputs.aks_cluster_name }} --overwrite-existing + + - name: Ensure namespace exists + run: | + kubectl create namespace sit722 --dry-run=client -o yaml | kubectl apply -f - - - name: Attach ACR + - name: Create/refresh imagePullSecret (acr-auth) 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 }} + kubectl delete secret acr-auth -n sit722 --ignore-not-found + kubectl create secret docker-registry acr-auth \ + --namespace sit722 \ + --docker-server=${{ secrets.AZURE_CONTAINER_REGISTRY }} \ + --docker-username=${{ secrets.AZURE_CONTAINER_REGISTRY_NAME }} \ + --docker-password='${{ secrets.ACR_PASSWORD }}' \ + --docker-email="devnull@example.local" + kubectl get secret acr-auth -n sit722 + +# - name: Attach ACR +# 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 }} - name: Deploy Backend Infrastructure (Namespace, ConfigMaps, Secrets, Databases) run: | From d1b41dd7f9b2bc0667267a91a608d555d9c1160e Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Wed, 1 Oct 2025 04:27:45 +1000 Subject: [PATCH 02/13] Update frontend API endpoints for product/order services --- frontend/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/main.js b/frontend/main.js index f321fd91..2676fc6f 100644 --- a/frontend/main.js +++ b/frontend/main.js @@ -4,8 +4,8 @@ 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://172.188.196.47:8000'; + const ORDER_API_BASE_URL = 'http://4.144.233.236:8001'; // Product Service is named 'product-service-w04e2' and exposes port 8000 internally. //const PRODUCT_API_BASE_URL = 'http://product-service-w04e2:8000'; From 9dfefe4eff2a66210f819a8f0afdeec44f05c98e Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Wed, 1 Oct 2025 13:50:36 +1000 Subject: [PATCH 03/13] Update frontend with real product and order API IPs --- frontend/main.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/main.js b/frontend/main.js index 2676fc6f..5bca83c6 100644 --- a/frontend/main.js +++ b/frontend/main.js @@ -5,7 +5,8 @@ document.addEventListener('DOMContentLoaded', () => { // 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 = 'http://172.188.196.47:8000'; - const ORDER_API_BASE_URL = 'http://4.144.233.236:8001'; + const ORDER_API_BASE_URL = 'http://4.144.233.236:8001'; + // Product Service is named 'product-service-w04e2' and exposes port 8000 internally. //const PRODUCT_API_BASE_URL = 'http://product-service-w04e2:8000'; From eb3fd7ae521ef0a41c93043c9767eb1f8509cb6a Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Wed, 1 Oct 2025 13:51:12 +1000 Subject: [PATCH 04/13] CD fixes: namespace, imagePullSecret, LB IP wait, frontend update --- .github/workflows/backend-cd.yml | 29 +++++++++++++++++++---------- .github/workflows/frontend-cd.yml | 12 ++++++------ k8s/frontend.yaml | 2 +- k8s/order-service.yaml | 4 +++- k8s/product-service.yaml | 4 +++- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/.github/workflows/backend-cd.yml b/.github/workflows/backend-cd.yml index 6472627b..c3420791 100644 --- a/.github/workflows/backend-cd.yml +++ b/.github/workflows/backend-cd.yml @@ -6,15 +6,15 @@ on: aks_cluster_name: description: 'Name of the AKS Cluster to deploy to' required: true - default: '' + default: 'sit722-aks' aks_resource_group: description: 'Resource Group of the AKS Cluster' required: true - default: '' + default: 'SIT722-RG' aks_acr_name: - description: 'Name of ACR' + description: 'Azure Container Registry name (not FQDN)' required: true - default: '' + default: '223313284acr' jobs: deploy_backend: @@ -30,7 +30,7 @@ jobs: uses: actions/checkout@v4 - name: Log in to Azure - uses: azure/login@v1 + uses: azure/login@v2 with: creds: ${{ secrets.AZURE_CREDENTIALS }} enable-AzPSSession: true @@ -39,6 +39,9 @@ jobs: run: | az aks get-credentials --resource-group ${{ github.event.inputs.aks_resource_group }} --name ${{ github.event.inputs.aks_cluster_name }} --overwrite-existing + - name: Setup kubectl + uses: azure/setup-kubectl@v4 + - name: Ensure namespace exists run: | kubectl create namespace sit722 --dry-run=client -o yaml | kubectl apply -f - @@ -74,16 +77,19 @@ jobs: kubectl apply -f product-service.yaml kubectl apply -f order-service.yaml - - name: Wait for Backend LoadBalancer IPs + - name: Wait for Backend LoadBalancer IPs run: | + echo "Sanity check: services across namespaces" + kubectl get svc -A + 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}') + PRODUCT_IP=$(kubectl get service product-service-w08e1 -n sit722 -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + ORDER_IP=$(kubectl get service order-service-w08e1 -n sit722 -o jsonpath='{.status.loadBalancer.ingress[0].ip}') if [[ -n "$PRODUCT_IP" && -n "$ORDER_IP" ]]; then echo "All backend LoadBalancer IPs assigned!" @@ -95,10 +101,13 @@ jobs: done if [[ -z "$PRODUCT_IP" || -z "$ORDER_IP" ]]; then + echo "DEBUG: describe services in sit722" + kubectl describe svc product-service-w08e1 -n sit722 || true + kubectl describe svc order-service-w08e1 -n sit722 || true echo "Error: One or more LoadBalancer IPs not assigned after timeout." - exit 1 # Fail the job if IPs are not obtained + exit 1 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 diff --git a/.github/workflows/frontend-cd.yml b/.github/workflows/frontend-cd.yml index 0a0879c8..edbea9ca 100644 --- a/.github/workflows/frontend-cd.yml +++ b/.github/workflows/frontend-cd.yml @@ -10,19 +10,19 @@ on: product_api_ip: description: 'External IP of Product Service' required: true - default: 'http://:8000' + default: 'http://172.188.196.47:8000' order_api_ip: description: 'External IP of Order Service (e.g., http://Y.Y.Y.Y:8001)' required: true - default: 'http://:8001' + default: 'http://4.144.233.236:8001' aks_cluster_name: - description: 'Name of the AKS Cluster to deploy to' + description: 'AKS cluster name' required: true - default: '' + default: 'sit722-aks' aks_resource_group: - description: 'Resource Group of the AKS Cluster' + description: 'AKS resource group' required: true - default: '<' + default: 'SIT722-RG' workflow_call: inputs: diff --git a/k8s/frontend.yaml b/k8s/frontend.yaml index 1948536d..a66b1cfb 100644 --- a/k8s/frontend.yaml +++ b/k8s/frontend.yaml @@ -18,7 +18,7 @@ spec: spec: containers: - name: frontend-container - image: durgeshsamariya.azurecr.io/frontend:latest + image: 223313284acr.azurecr.io/frontend:latest imagePullPolicy: Always ports: - containerPort: 80 diff --git a/k8s/order-service.yaml b/k8s/order-service.yaml index c9d92e4d..58bd9423 100644 --- a/k8s/order-service.yaml +++ b/k8s/order-service.yaml @@ -16,9 +16,11 @@ spec: labels: app: order-service spec: + imagePullSecrets: + - name: acr-auth containers: - name: order-service-container - image: durgeshsamariya.azurecr.io/order_service:latest + image: 223313284acr.azurecr.io/order_service:latest imagePullPolicy: Always ports: - containerPort: 8000 diff --git a/k8s/product-service.yaml b/k8s/product-service.yaml index 0cbbd505..91c18d30 100644 --- a/k8s/product-service.yaml +++ b/k8s/product-service.yaml @@ -16,9 +16,11 @@ spec: labels: app: product-service spec: + imagePullSecrets: + - name: acr-auth containers: - name: product-service-container - image: durgeshsamariya.azurecr.io/product_service:latest + image: 223313284acr.azurecr.io/product_service:latest imagePullPolicy: Always ports: - containerPort: 8000 From 569909289c08afbc02be91d62d1436b7203473b1 Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Wed, 1 Oct 2025 13:51:45 +1000 Subject: [PATCH 05/13] chore: ignore sp_output.json --- .gitignore | Bin 4338 -> 4566 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index cfa76a7f9df7a7dce47fb09d3a358402e7cb4a04..8776beb499dbeaab1953caa4d60bb3e664a3d91c 100644 GIT binary patch delta 1963 zcmZ8i&u<(x6yAs=ZKs)}2mw_=Wl)NOBGx(ZLllHWnjbWWlvTD#D-apHGu~Y%v$nB4 zn~adi0jY2Vt@uNF=fI7>fO0{I3uh#5-1wenvJG5pzxTfP?DyVh`|nquEPuCh7Ds7n zs*Gntk)~^Lw8~8NX{Phfu)Jj|mKEH&IEtg?WFrx$UMMHEf@YODUF&yw_Hj3k*k(8F zdTm9m-IUH-*(*KZ$y#D~cFYG-4FK#^eyCL(^-9?*a%`H5u_&}@i^0H=2v?f)i7GVD zN!3_bGZ(T4CB}E&!fd$p1aghzm|I9ELm>*NzyIs`59zpYZA;bHFfpl|=S3lMmi2L> zV2q>P^?N(pTiyG00-b87LD_in!OZqdJo$R2gMzKH5m&M=oDWqnBC8#y@TAZKRLDrv z#)|n<07=M2A-rh&p>*wBT9KhzRc)sF?knjNkFY3LrpLnafk><{8rj9s(2oje&*=DG zpVFl2=^P8q`I4=YKuwJ!r5$#4-m%kB5l2% zw}$)!3I;m!ean?AI5jzNVx&VTjf}~>dBoK~C(f7s{(EFWJiroy{+lQiMGndPRM;+YF_9jj}G zQk^Eb&dQNcJ|sYl%iLNDS_W29j81ijBw<4xV0o4VZ0Wfj2x4hGdHl?CdoW8=sa}eb zXU9fMMLnYkJLhaSR`+Eg(p>a;S&%C{=pv+lW z&`nxn+PZgu5o^}t$BnvK#*-hT8#q04rUHvVh$FlKwLBFllRa%j(rA+Ndjgz={y)Ic zF;VvaG+uMKNOf|fif$L9sky-KL(EBLM~--OaZP)7Dk~CS;Q)ck4f8EsGjQhW&2{*r zHvo`^${vWBG85nG_~(ZVMf|5!MD0kN3O z1#i&nJ^UXW?1Pt(&k!a`~aRcF_!Iy=NwT+q^nXCe?J6v0T_JpCJ` zbsFEq?@JG`(c9N(`yZ~|-UciSCOJ^yXFL~GE>7|I)oRx=t+b_EWy@nlBWoSC95kvG Hx1!d+Jnc@C delta 1605 zcmZuxL2n#26jn+SQY+b{O@*o!%AgG@TCpAwsDf}xlMPL(gjKg~5U81WJ>FSoXKZ78 zH#-v5Uf{qDxA z^wraw6NKBP?Ms2WL!PHGO4*3zQZ-qY8JKZnVU%Ygmm~$Cf^qfBc{fHd+<7}jif9Xd zQ>_>g9iy{8W4XurM6+0hZJIN%;bS!Uo1!OUgt;)5DC-__bj3pc>_y+%SBW??IX$3>3L{eIG@=%oI?zf{upnc+}B zz!X)0^7ts*@v14lM_2Vr9%1`(t6jF_=XOT^5v0Ag43d1*tG=npJ(k?NCirIU{2erankV z^|=^Fsieb#2^;bSQBV^nQ`G>eUEcKyV%pamU|*yqI%6OqAnXr)A9QpmU2T4G9}ZoW zqMJZ-=|D*?Y!L3=RE|o^9?w~lvK|@c5CPa;rwNs!$1`6%#8f2{BiEaM-UyQsJqt@YLxb9+vyJS#dl?4fOR0-!C!4aJ@ zYNMGT5nMv=nBrkNvnR0ZfmG~&7HNQIG+-42udM%wEjFNWUwcu)!DBzpt`koE44)b} z?F%Mw+ofiaEn!pIUjdO-(uAi7xtEr2ZF-%0Z`IQvnXz z;VmoNr^_Ec2OGHeR`0qSE9(xgeB{1ZIlhYOn5T>c?pD`WP297Ucif%Yf%~j>dl_L8 zK<{@y)z;mQwG$Vw_F?_|?zh$J?(fxmuR&ZqGVr8Vi9LY(e|{x3OlEaEv3BFCuR(Dg kUcT+2Hd4E<*N)s@YbWmL%DXjqyaLEG0q?#0=E@8I0R6ra1ONa4 From e3148428d521e1e83148d39f3fe321179b6f5045 Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Wed, 1 Oct 2025 23:15:52 +1000 Subject: [PATCH 06/13] fix: correct ACR login in frontend CI --- .github/workflows/frontend_ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/frontend_ci.yml b/.github/workflows/frontend_ci.yml index 9f9e76d9..da4a14bb 100644 --- a/.github/workflows/frontend_ci.yml +++ b/.github/workflows/frontend_ci.yml @@ -39,13 +39,15 @@ 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_NAME }} # Build and Push Docker image for Frontend - name: Build and Push Frontend Image run: | docker build -t ${{ env.ACR_LOGIN_SERVER }}/frontend:latest ./frontend/ docker push ${{ env.ACR_LOGIN_SERVER }}/frontend:latest + docker tag ${{ env.ACR_LOGIN_SERVER }}/frontend:${{ env.IMAGE_TAG }} ${{ env.ACR_LOGIN_SERVER }}/frontend:latest + docker push ${{ env.ACR_LOGIN_SERVER }}/frontend:latest # Logout from Azure for security (runs even if image push fails) - name: Logout from Azure From ea55d07ba2d1f0f89056c93c10f3363b7aaedb7f Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Wed, 1 Oct 2025 23:53:08 +1000 Subject: [PATCH 07/13] fix: correct ACR login in frontend CI --- .github/workflows/frontend_ci.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/frontend_ci.yml b/.github/workflows/frontend_ci.yml index da4a14bb..63da12e6 100644 --- a/.github/workflows/frontend_ci.yml +++ b/.github/workflows/frontend_ci.yml @@ -44,10 +44,17 @@ jobs: # Build and Push Docker image for Frontend - name: Build and Push Frontend Image run: | + # Build as :latest docker build -t ${{ env.ACR_LOGIN_SERVER }}/frontend:latest ./frontend/ + + # Tag the same image with a unique IMAGE_TAG + docker tag ${{ env.ACR_LOGIN_SERVER }}/frontend:latest ${{ env.ACR_LOGIN_SERVER }}/frontend:${{ env.IMAGE_TAG }} + + # Push both tags docker push ${{ env.ACR_LOGIN_SERVER }}/frontend:latest - docker tag ${{ env.ACR_LOGIN_SERVER }}/frontend:${{ env.IMAGE_TAG }} ${{ env.ACR_LOGIN_SERVER }}/frontend:latest - docker push ${{ env.ACR_LOGIN_SERVER }}/frontend:latest + docker push ${{ env.ACR_LOGIN_SERVER }}/frontend:${{ env.IMAGE_TAG }} + + # Logout from Azure for security (runs even if image push fails) - name: Logout from Azure From cd2f59dabcca21058e3653be84263494f8db5752 Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Sat, 4 Oct 2025 15:47:48 +1000 Subject: [PATCH 08/13] =?UTF-8?q?feat:=20add=20linked=20CD=20workflow=20(b?= =?UTF-8?q?ackend=5Fcd=20=E2=86=92=20frontend=5Fcd)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/CD_linked.yml | 108 ++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 .github/workflows/CD_linked.yml diff --git a/.github/workflows/CD_linked.yml b/.github/workflows/CD_linked.yml new file mode 100644 index 00000000..500724e9 --- /dev/null +++ b/.github/workflows/CD_linked.yml @@ -0,0 +1,108 @@ +# .github/workflows/cd_linked.yml +name: CD - Deploy Backend then Frontend to AKS + +on: + push: + branches: [ main ] + +permissions: + id-token: write + contents: read + +env: + RG: SIT722-RG + AKS: sit722-aks + NS: sit722 + PRODUCT_PORT: "8000" + ORDER_PORT: "8001" + +jobs: + backend_cd: + name: Deploy Backend (product + order) + runs-on: ubuntu-latest + outputs: + product_ip: ${{ steps.capture.outputs.product_ip }} + order_ip: ${{ steps.capture.outputs.order_ip }} + steps: + - uses: actions/checkout@v4 + + - name: Azure Login + uses: azure/login@v2 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + + - name: Set AKS context + uses: azure/aks-set-context@v4 + with: + resource-group: ${{ env.RG }} # = SIT722-RG + cluster-name: ${{ env.AKS }} # = sit722-aks + + - name: Deploy product + order services + run: | + kubectl apply -n $NS -f k8s/product-service.yaml + kubectl apply -n $NS -f k8s/order-service.yaml + + - name: Wait for External IPs & capture + id: capture + shell: bash + run: | + for i in {1..60}; do + PIP=$(kubectl get svc product-service-w08e1 -n $NS -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + OIP=$(kubectl get svc order-service-w08e1 -n $NS -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + if [[ -n "$PIP" && -n "$OIP" ]]; then + echo "Product IP: $PIP" + echo "Order IP: $OIP" + break + fi + sleep 5 + done + [[ -n "$PIP" && -n "$OIP" ]] || { echo "IPs not assigned"; exit 1; } + echo "product_ip=$PIP" >> $GITHUB_OUTPUT + echo "order_ip=$OIP" >> $GITHUB_OUTPUT + + frontend_cd: + name: Deploy Frontend (uses backend IPs) + runs-on: ubuntu-latest + needs: backend_cd + steps: + - uses: actions/checkout@v4 + + - name: Azure Login + uses: azure/login@v2 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + + - name: Login to ACR + run: az acr login --name ${{ secrets.AZURE_CONTAINER_REGISTRY_NAME }} # einweek9acr + + - name: Inject Backend IPs into frontend/main.js + shell: bash + env: + PRODUCT_IP: ${{ needs.backend_cd.outputs.product_ip }} + ORDER_IP: ${{ needs.backend_cd.outputs.order_ip }} + PRODUCT_PORT: ${{ env.PRODUCT_PORT }} + ORDER_PORT: ${{ env.ORDER_PORT }} + run: | + FILE="frontend/main.js" + test -f "$FILE" || { echo "Missing $FILE"; exit 1; } + grep -q "_PRODUCT_API_URL_" "$FILE" || { echo "PRODUCT placeholder missing"; exit 1; } + grep -q "_ORDER_API_URL_" "$FILE" || { echo "ORDER placeholder missing"; exit 1; } + sed -i "s|_PRODUCT_API_URL_|http://${PRODUCT_IP}:${PRODUCT_PORT}|g" "$FILE" + sed -i "s|_ORDER_API_URL_|http://${ORDER_IP}:${ORDER_PORT}|g" "$FILE" + sed -n '1,25p' "$FILE" + + - name: Build & push frontend + run: | + docker build -t ${{ secrets.AZURE_CONTAINER_REGISTRY }}/frontend:latest ./frontend + docker push ${{ secrets.AZURE_CONTAINER_REGISTRY }}/frontend:latest + + - name: Set AKS context + uses: azure/aks-set-context@v4 + with: + resource-group: ${{ env.RG }} # = SIT722-RG + cluster-name: ${{ env.AKS }} # = sit722-aks + + - name: Deploy frontend & show service + run: | + kubectl apply -n $NS -f k8s/frontend.yaml + kubectl get svc -n $NS -o wide From 64ac9b5515d223a8dfb7fea8043fcbc9a91c2e93 Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Sat, 4 Oct 2025 23:03:47 +1000 Subject: [PATCH 09/13] chore(frontend): add placeholders for linked CD injection --- frontend/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/main.js b/frontend/main.js index 5bca83c6..4bd6d2da 100644 --- a/frontend/main.js +++ b/frontend/main.js @@ -4,8 +4,8 @@ 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 = 'http://172.188.196.47:8000'; - const ORDER_API_BASE_URL = 'http://4.144.233.236:8001'; + const PRODUCT_API_BASE_URL = "_PRODUCT_API_URL_"; + const ORDER_API_BASE_URL = "_ORDER_API_URL_"; // Product Service is named 'product-service-w04e2' and exposes port 8000 internally. From db4fd25264a95c7943182cc4086f9b8f0fe75b31 Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Sun, 5 Oct 2025 10:05:52 +1100 Subject: [PATCH 10/13] ci: Backend CI on PRs; linked CD on push to main (needs: backend_cd) --- .github/workflows/CD_linked.yml | 7 ++++++- .github/workflows/backend_ci.yml | 8 ++++++-- .github/workflows/frontend_ci.yml | 7 +++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/workflows/CD_linked.yml b/.github/workflows/CD_linked.yml index 500724e9..fedb66e1 100644 --- a/.github/workflows/CD_linked.yml +++ b/.github/workflows/CD_linked.yml @@ -4,7 +4,12 @@ name: CD - Deploy Backend then Frontend to AKS on: push: branches: [ main ] - + paths: + - 'k8s/**' + - 'backend/**' + - 'frontend/**' + - '.github/workflows/CD_linked.yml' + permissions: id-token: write contents: read diff --git a/.github/workflows/backend_ci.yml b/.github/workflows/backend_ci.yml index d69725aa..39be22cc 100644 --- a/.github/workflows/backend_ci.yml +++ b/.github/workflows/backend_ci.yml @@ -5,8 +5,11 @@ name: Backend CI - Test, Build and Push Images to ACR # Trigger the workflow on pushes to the 'main' branch # You can also add 'pull_request:' to run on PRs on: - # Manual trigger - workflow_dispatch: + pull_request: + branches: [ main ] # or: [ development ] + paths: + - 'backend/**' + - '.github/workflows/backend_ci.yml' # Automatically on pushes to main branch push: @@ -111,6 +114,7 @@ jobs: # Job 2: Build and Push Docker Images (runs only if tests pass) build_and_push_images: + if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/main') runs-on: ubuntu-latest needs: test_and_lint_backends diff --git a/.github/workflows/frontend_ci.yml b/.github/workflows/frontend_ci.yml index 63da12e6..7e442b38 100644 --- a/.github/workflows/frontend_ci.yml +++ b/.github/workflows/frontend_ci.yml @@ -3,8 +3,11 @@ name: Frontend CI - Build & Push Image on: - # Manual trigger - workflow_dispatch: + pull_request: + branches: [ main ] + paths: + - 'frontend/**' + - '.github/workflows/frontend_ci.yml' # Automatically on pushes to main branch push: From 6d83fc484767890a19a3e6a2782fd476d4656953 Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Sun, 5 Oct 2025 10:30:36 +1100 Subject: [PATCH 11/13] ci: Backend CI on PRs; linked CD on push to main (needs: backend_cd) --- .github/workflows/CD_linked.yml | 4 ++-- .github/workflows/backend_ci.yml | 2 +- .github/workflows/frontend_ci.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CD_linked.yml b/.github/workflows/CD_linked.yml index fedb66e1..c373e387 100644 --- a/.github/workflows/CD_linked.yml +++ b/.github/workflows/CD_linked.yml @@ -1,4 +1,4 @@ -# .github/workflows/cd_linked.yml +## .github/workflows/cd_linked.yml name: CD - Deploy Backend then Frontend to AKS on: @@ -9,7 +9,7 @@ on: - 'backend/**' - 'frontend/**' - '.github/workflows/CD_linked.yml' - + permissions: id-token: write contents: read diff --git a/.github/workflows/backend_ci.yml b/.github/workflows/backend_ci.yml index 39be22cc..f81b2e5f 100644 --- a/.github/workflows/backend_ci.yml +++ b/.github/workflows/backend_ci.yml @@ -112,7 +112,7 @@ jobs: run: | pytest tests --maxfail=1 --disable-warnings -q - # Job 2: Build and Push Docker Images (runs only if tests pass) + ## Job 2: Build and Push Docker Images (runs only if tests pass) build_and_push_images: if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/main') runs-on: ubuntu-latest diff --git a/.github/workflows/frontend_ci.yml b/.github/workflows/frontend_ci.yml index 7e442b38..dec267e0 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 From b62c7cd76fae0bfeb58da2f79895092b702802a3 Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Sun, 5 Oct 2025 11:22:50 +1100 Subject: [PATCH 12/13] ci: use az acr login --name (short name) and show in logs --- .github/workflows/backend_ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/backend_ci.yml b/.github/workflows/backend_ci.yml index f81b2e5f..5d59b5fd 100644 --- a/.github/workflows/backend_ci.yml +++ b/.github/workflows/backend_ci.yml @@ -27,6 +27,7 @@ env: # 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 }} + ACR_NAME: ${{ secrets.AZURE_CONTAINER_REGISTRY_NAME }} jobs: # Job 1: Run tests and linting for all backend services @@ -129,8 +130,10 @@ jobs: creds: ${{ secrets.AZURE_CREDENTIALS }} # Needs to be set as a GitHub Secret (Service Principal JSON) # Login to Azure Container Registry (ACR) - - name: Login to Azure Container Registry - run: az acr login --name ${{ env.ACR_LOGIN_SERVER }} + - name: ACR login (AAD, short name) + run: | + echo "az acr login --name $ACR_NAME" + az acr login --name "$ACR_NAME" # Build and Push Docker image for Product Service - name: Build and Push Product Service Image From 8a3af9a4f3beb4454e8f3b8fd52a50a9e1933928 Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Sun, 5 Oct 2025 11:57:38 +1100 Subject: [PATCH 13/13] ci(cd): linked CD with IP capture outputs + hardened sed --- .github/workflows/CD_linked.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CD_linked.yml b/.github/workflows/CD_linked.yml index c373e387..06af9fc2 100644 --- a/.github/workflows/CD_linked.yml +++ b/.github/workflows/CD_linked.yml @@ -92,9 +92,13 @@ jobs: test -f "$FILE" || { echo "Missing $FILE"; exit 1; } grep -q "_PRODUCT_API_URL_" "$FILE" || { echo "PRODUCT placeholder missing"; exit 1; } grep -q "_ORDER_API_URL_" "$FILE" || { echo "ORDER placeholder missing"; exit 1; } + cp "$FILE" "${FILE}.before" + sed -i "s|_PRODUCT_API_URL_|http://${PRODUCT_IP}:${PRODUCT_PORT}|g" "$FILE" sed -i "s|_ORDER_API_URL_|http://${ORDER_IP}:${ORDER_PORT}|g" "$FILE" - sed -n '1,25p' "$FILE" + + echo "Diff (context=0, only changed lines):" + diff -u --strip-trailing-cr --label before "${FILE}.before" --label after "$FILE" | sed -n '1,120p' || true - name: Build & push frontend run: |