From 50bdf10fa85441c89c27d75bc6fd4f923ca11ed3 Mon Sep 17 00:00:00 2001 From: harshaboppi Date: Thu, 3 Sep 2026 21:30:03 +1000 Subject: [PATCH 01/10] Fix Node.js 20 deprecation warning --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3457426..4f585e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,7 +81,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.12" @@ -140,7 +140,7 @@ jobs: uses: actions/checkout@v4 - name: Login to Azure - uses: azure/login@v2 + uses: azure/login@v3 with: creds: ${{ secrets.AZURE_CREDENTIALS }} @@ -164,4 +164,4 @@ jobs: - name: Push Docker image with latest tag run: | docker push \ - ${{ vars.ACR_LOGIN_SERVER }}/${{ matrix.image }}:latest + ${{ vars.ACR_LOGIN_SERVER }}/${{ matrix.image }}:latest \ No newline at end of file From 46c14daeebb1b83c11489ebb3d19a8beadb47038 Mon Sep 17 00:00:00 2001 From: harshaboppi Date: Thu, 3 Sep 2026 21:45:27 +1000 Subject: [PATCH 02/10] Fix checkout Node.js deprecation warning --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f585e9..420717f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,7 +78,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v6 @@ -137,7 +137,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Login to Azure uses: azure/login@v3 From 826d93d4219af1d3d31c377473eb35fa7da53b25 Mon Sep 17 00:00:00 2001 From: harshaboppi Date: Thu, 3 Sep 2026 22:23:51 +1000 Subject: [PATCH 03/10] Add frontend testing to CI pipeline --- .github/workflows/ci.yml | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 420717f..5f57fdb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,6 @@ on: # Manual trigger for the workflow workflow_dispatch: - jobs: # ========================================================= @@ -97,6 +96,41 @@ jobs: pytest -v + # ========================================================= + # Frontend Tests + # ========================================================= + frontend-test: + name: Test frontend + runs-on: ubuntu-latest + + env: + VITE_USER_SERVICE_URL: /api/user-service + VITE_STUDENT_SERVICE_URL: /api/student-service + VITE_LECTURER_SERVICE_URL: /api/lecturer-service + VITE_COURSE_SERVICE_URL: /api/course-service + VITE_ENROLLMENT_SERVICE_URL: /api/enrollment-service + + steps: + + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install frontend dependencies + working-directory: frontend + run: | + npm ci + + - name: Run frontend tests + working-directory: frontend + run: | + npm run test:run + + # ========================================================= # Build and Push Docker Images # ========================================================= @@ -104,9 +138,10 @@ jobs: name: Build and Push ${{ matrix.image }} runs-on: ubuntu-latest - # All backend tests must pass before this job starts + # Backend and frontend tests must pass before this job starts needs: - backend-test + - frontend-test # Build and push when code is pushed to main or manually triggered if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' From f84e5e9555cf895ddaad60ef9e36b083afd8b20d Mon Sep 17 00:00:00 2001 From: harshaboppi Date: Thu, 3 Sep 2026 22:29:57 +1000 Subject: [PATCH 04/10] Update setup-node action to v6 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f57fdb..31dd3a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,7 +116,7 @@ jobs: uses: actions/checkout@v6 - name: Set up Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: "20" From 958c0eba78a59e28087885fba428d0876f90cc94 Mon Sep 17 00:00:00 2001 From: harshaboppi Date: Fri, 18 Sep 2026 15:27:16 +1000 Subject: [PATCH 05/10] Update CI pipeline for new Azure Container Registry --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 31dd3a8..a0ebcbc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,11 @@ name: CI Pipeline on: + # Trigger the pipeline when a Pull Request targets main + pull_request: + branches: + - main + # Manual trigger for the workflow workflow_dispatch: From c0e723274cb8e1fb5d648c8cea79ce4bf7a68db8 Mon Sep 17 00:00:00 2001 From: harshaboppi Date: Fri, 18 Sep 2026 15:45:12 +1000 Subject: [PATCH 06/10] Update Azure login to OIDC --- .github/workflows/ci.yml | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0ebcbc..10152b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,9 +6,19 @@ on: branches: - main + # Trigger the pipeline when code is pushed to main + push: + branches: + - main + # Manual trigger for the workflow workflow_dispatch: +# Required for Azure OIDC authentication +permissions: + id-token: write + contents: read + jobs: # ========================================================= @@ -143,12 +153,12 @@ jobs: name: Build and Push ${{ matrix.image }} runs-on: ubuntu-latest - # Backend and frontend tests must pass before this job starts + # Tests must pass before images are built needs: - backend-test - frontend-test - # Build and push when code is pushed to main or manually triggered + # Only build/push for main pushes or manual runs if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' strategy: @@ -179,15 +189,26 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 + # ===================================================== + # Azure OIDC Login + # ===================================================== - name: Login to Azure uses: azure/login@v3 with: - creds: ${{ secrets.AZURE_CREDENTIALS }} + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + # ===================================================== + # Azure Container Registry Login + # ===================================================== - name: Login to Azure Container Registry run: | az acr login --name ${{ vars.ACR_NAME }} + # ===================================================== + # Build Docker Image + # ===================================================== - name: Build Docker image run: | docker build \ @@ -196,11 +217,17 @@ jobs: -t ${{ vars.ACR_LOGIN_SERVER }}/${{ matrix.image }}:latest \ ./${{ matrix.service }} + # ===================================================== + # Push SHA Tagged Image + # ===================================================== - name: Push Docker image with commit SHA run: | docker push \ ${{ vars.ACR_LOGIN_SERVER }}/${{ matrix.image }}:${{ github.sha }} + # ===================================================== + # Push Latest Tagged Image + # ===================================================== - name: Push Docker image with latest tag run: | docker push \ From c5662399036ffb7785bfceda3648a61a02965edd Mon Sep 17 00:00:00 2001 From: harshaboppi Date: Fri, 18 Sep 2026 15:50:06 +1000 Subject: [PATCH 07/10] Debug GitHub OIDC context --- .github/workflows/ci.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10152b7..4f3342d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -189,6 +189,16 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 + # ===================================================== + # Debug GitHub Repository / OIDC Context + # ===================================================== + - name: Debug GitHub OIDC Context + run: | + echo "Repository: $GITHUB_REPOSITORY" + echo "Ref: $GITHUB_REF" + echo "Event: $GITHUB_EVENT_NAME" + echo "Commit: $GITHUB_SHA" + # ===================================================== # Azure OIDC Login # ===================================================== From 591b9e38dfef8c1ba480ec9aa5562a1dfc69db48 Mon Sep 17 00:00:00 2001 From: harshaboppi Date: Fri, 18 Sep 2026 22:13:45 +1000 Subject: [PATCH 08/10] Add Kubernetes deployment manifests --- k8s/apps.yaml | 308 ++++++++++++++++++++++++++++++++++++++++ k8s/databases.yaml | 343 +++++++++++++++++++++++++++++++++++++++++++++ k8s/frontend.yaml | 31 ++++ 3 files changed, 682 insertions(+) create mode 100644 k8s/apps.yaml create mode 100644 k8s/databases.yaml create mode 100644 k8s/frontend.yaml diff --git a/k8s/apps.yaml b/k8s/apps.yaml new file mode 100644 index 0000000..4c77844 --- /dev/null +++ b/k8s/apps.yaml @@ -0,0 +1,308 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: user-service +spec: + replicas: 1 + selector: + matchLabels: + app: user-service + template: + metadata: + labels: + app: user-service + spec: + containers: + - name: user-service + image: koalatechweek07acr2.azurecr.io/koalatech-user-service:latest + ports: + - containerPort: 8000 + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: users + - name: POSTGRES_HOST + value: user-db + - name: POSTGRES_PORT + value: "5432" + readinessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 10 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 20 + periodSeconds: 10 +--- +apiVersion: v1 +kind: Service +metadata: + name: user-service +spec: + selector: + app: user-service + ports: + - port: 8000 + targetPort: 8000 + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: student-service +spec: + replicas: 1 + selector: + matchLabels: + app: student-service + template: + metadata: + labels: + app: student-service + spec: + containers: + - name: student-service + image: koalatechweek07acr2.azurecr.io/koalatech-student-service:latest + ports: + - containerPort: 8000 + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: students + - name: POSTGRES_HOST + value: student-db + - name: POSTGRES_PORT + value: "5432" + readinessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 10 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 20 + periodSeconds: 10 +--- +apiVersion: v1 +kind: Service +metadata: + name: student-service +spec: + selector: + app: student-service + ports: + - port: 8000 + targetPort: 8000 + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lecturer-service +spec: + replicas: 1 + selector: + matchLabels: + app: lecturer-service + template: + metadata: + labels: + app: lecturer-service + spec: + containers: + - name: lecturer-service + image: koalatechweek07acr2.azurecr.io/koalatech-lecturer-service:latest + ports: + - containerPort: 8000 + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: lecturers + - name: POSTGRES_HOST + value: lecturer-db + - name: POSTGRES_PORT + value: "5432" + readinessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 10 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 20 + periodSeconds: 10 +--- +apiVersion: v1 +kind: Service +metadata: + name: lecturer-service +spec: + selector: + app: lecturer-service + ports: + - port: 8000 + targetPort: 8000 + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: course-service +spec: + replicas: 1 + selector: + matchLabels: + app: course-service + template: + metadata: + labels: + app: course-service + spec: + containers: + - name: course-service + image: koalatechweek07acr2.azurecr.io/koalatech-course-service:latest + ports: + - containerPort: 8000 + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: courses + - name: POSTGRES_HOST + value: course-db + - name: POSTGRES_PORT + value: "5432" + readinessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 10 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 20 + periodSeconds: 10 +--- +apiVersion: v1 +kind: Service +metadata: + name: course-service +spec: + selector: + app: course-service + ports: + - port: 8000 + targetPort: 8000 + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: enrollment-service +spec: + replicas: 1 + selector: + matchLabels: + app: enrollment-service + template: + metadata: + labels: + app: enrollment-service + spec: + containers: + - name: enrollment-service + image: koalatechweek07acr2.azurecr.io/koalatech-enrollment-service:latest + ports: + - containerPort: 8000 + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: enrollments + - name: POSTGRES_HOST + value: enrollment-db + - name: POSTGRES_PORT + value: "5432" + readinessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 10 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 20 + periodSeconds: 10 +--- +apiVersion: v1 +kind: Service +metadata: + name: enrollment-service +spec: + selector: + app: enrollment-service + ports: + - port: 8000 + targetPort: 8000 + type: ClusterIP \ No newline at end of file diff --git a/k8s/databases.yaml b/k8s/databases.yaml new file mode 100644 index 0000000..273bf5a --- /dev/null +++ b/k8s/databases.yaml @@ -0,0 +1,343 @@ +apiVersion: v1 +kind: Secret +metadata: + name: postgres-secret +type: Opaque +stringData: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: user-db-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: user-db +spec: + replicas: 1 + selector: + matchLabels: + app: user-db + template: + metadata: + labels: + app: user-db + spec: + containers: + - name: postgres + image: postgres:16-alpine + ports: + - containerPort: 5432 + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: users + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: user-db-pvc + +--- +apiVersion: v1 +kind: Service +metadata: + name: user-db +spec: + selector: + app: user-db + ports: + - port: 5432 + targetPort: 5432 + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: student-db-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: student-db +spec: + replicas: 1 + selector: + matchLabels: + app: student-db + template: + metadata: + labels: + app: student-db + spec: + containers: + - name: postgres + image: postgres:16-alpine + ports: + - containerPort: 5432 + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: students + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: student-db-pvc + +--- +apiVersion: v1 +kind: Service +metadata: + name: student-db +spec: + selector: + app: student-db + ports: + - port: 5432 + targetPort: 5432 + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: lecturer-db-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lecturer-db +spec: + replicas: 1 + selector: + matchLabels: + app: lecturer-db + template: + metadata: + labels: + app: lecturer-db + spec: + containers: + - name: postgres + image: postgres:16-alpine + ports: + - containerPort: 5432 + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: lecturers + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: lecturer-db-pvc + +--- +apiVersion: v1 +kind: Service +metadata: + name: lecturer-db +spec: + selector: + app: lecturer-db + ports: + - port: 5432 + targetPort: 5432 + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: course-db-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: course-db +spec: + replicas: 1 + selector: + matchLabels: + app: course-db + template: + metadata: + labels: + app: course-db + spec: + containers: + - name: postgres + image: postgres:16-alpine + ports: + - containerPort: 5432 + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: courses + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: course-db-pvc + +--- +apiVersion: v1 +kind: Service +metadata: + name: course-db +spec: + selector: + app: course-db + ports: + - port: 5432 + targetPort: 5432 + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: enrollment-db-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: enrollment-db +spec: + replicas: 1 + selector: + matchLabels: + app: enrollment-db + template: + metadata: + labels: + app: enrollment-db + spec: + containers: + - name: postgres + image: postgres:16-alpine + ports: + - containerPort: 5432 + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: enrollments + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: enrollment-db-pvc + +--- +apiVersion: v1 +kind: Service +metadata: + name: enrollment-db +spec: + selector: + app: enrollment-db + ports: + - port: 5432 + targetPort: 5432 \ No newline at end of file diff --git a/k8s/frontend.yaml b/k8s/frontend.yaml new file mode 100644 index 0000000..c3b3d3a --- /dev/null +++ b/k8s/frontend.yaml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend +spec: + replicas: 1 + selector: + matchLabels: + app: frontend + template: + metadata: + labels: + app: frontend + spec: + containers: + - name: frontend + image: koalatechweek07acr2.azurecr.io/koalatech-frontend:latest + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: frontend +spec: + type: LoadBalancer + selector: + app: frontend + ports: + - port: 80 + targetPort: 80 \ No newline at end of file From 79d674ac0159fbc4bf95d901a769f0920ddfb501 Mon Sep 17 00:00:00 2001 From: harshaboppi Date: Fri, 18 Sep 2026 22:22:52 +1000 Subject: [PATCH 09/10] Add continuous deployment to AKS --- .github/workflows/ci.yml | 109 +++++++++++++++++++++++++++++++++++---- 1 file changed, 98 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f3342d..5b95dea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -189,16 +189,6 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 - # ===================================================== - # Debug GitHub Repository / OIDC Context - # ===================================================== - - name: Debug GitHub OIDC Context - run: | - echo "Repository: $GITHUB_REPOSITORY" - echo "Ref: $GITHUB_REF" - echo "Event: $GITHUB_EVENT_NAME" - echo "Commit: $GITHUB_SHA" - # ===================================================== # Azure OIDC Login # ===================================================== @@ -241,4 +231,101 @@ jobs: - name: Push Docker image with latest tag run: | docker push \ - ${{ vars.ACR_LOGIN_SERVER }}/${{ matrix.image }}:latest \ No newline at end of file + ${{ vars.ACR_LOGIN_SERVER }}/${{ matrix.image }}:latest + + + # ========================================================= + # Continuous Deployment to Azure Kubernetes Service + # ========================================================= + deploy-to-aks: + name: Deploy to AKS + runs-on: ubuntu-latest + + # Deploy only after all Docker images are successfully pushed + needs: + - build-and-push + + # Only deploy for pushes to main or manual runs + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + + steps: + + # ===================================================== + # Checkout Repository + # ===================================================== + - name: Checkout repository + uses: actions/checkout@v6 + + # ===================================================== + # Azure OIDC Login + # ===================================================== + - name: Login to Azure + uses: azure/login@v3 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + # ===================================================== + # Configure kubectl for AKS + # ===================================================== + - name: Set AKS context + uses: azure/aks-set-context@v4 + with: + resource-group: koalatech-week07-rg + cluster-name: koalatech-week07-aks + + - name: Set up kubectl + uses: azure/setup-kubectl@v4 + + # ===================================================== + # Apply Kubernetes Manifests + # ===================================================== + - name: Deploy Kubernetes manifests + run: | + kubectl apply -f k8s/databases.yaml + kubectl apply -f k8s/apps.yaml + kubectl apply -f k8s/frontend.yaml + + # ===================================================== + # Update Deployments to Exact Git Commit Image + # ===================================================== + - name: Deploy images + run: | + kubectl set image deployment/user-service \ + user-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-user-service:${{ github.sha }} + + kubectl set image deployment/student-service \ + student-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-student-service:${{ github.sha }} + + kubectl set image deployment/lecturer-service \ + lecturer-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-lecturer-service:${{ github.sha }} + + kubectl set image deployment/course-service \ + course-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-course-service:${{ github.sha }} + + kubectl set image deployment/enrollment-service \ + enrollment-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-enrollment-service:${{ github.sha }} + + kubectl set image deployment/frontend \ + frontend=${{ vars.ACR_LOGIN_SERVER }}/koalatech-frontend:${{ github.sha }} + + # ===================================================== + # Wait for Successful Rollout + # ===================================================== + - name: Verify deployments + run: | + kubectl rollout status deployment/user-service --timeout=180s + kubectl rollout status deployment/student-service --timeout=180s + kubectl rollout status deployment/lecturer-service --timeout=180s + kubectl rollout status deployment/course-service --timeout=180s + kubectl rollout status deployment/enrollment-service --timeout=180s + kubectl rollout status deployment/frontend --timeout=180s + + # ===================================================== + # Verify Kubernetes Pods and Services + # ===================================================== + - name: Verify Kubernetes pods + run: | + kubectl get pods + kubectl get services \ No newline at end of file From 9c7f0d2825e32b3482e4d9c45c419747e3e0231f Mon Sep 17 00:00:00 2001 From: harshaboppi Date: Fri, 18 Sep 2026 22:38:26 +1000 Subject: [PATCH 10/10] Update frontend for CD demonstration --- frontend/src/pages/Login.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/Login.jsx b/frontend/src/pages/Login.jsx index 1132741..884b57d 100644 --- a/frontend/src/pages/Login.jsx +++ b/frontend/src/pages/Login.jsx @@ -93,7 +93,7 @@ const Login = () => { variant="h4" gutterBottom > - KoalaTech University + KoalaTech University - Continuous Deployment Demo { ); }; -export default Login; +export default Login; \ No newline at end of file