Skip to content
17 changes: 7 additions & 10 deletions .github/workflows/01-ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: 01 - CI

on:
pull_request:
branches:
- main

# Trigger the workflow on push to main branch
push:
branches:
Expand Down Expand Up @@ -150,17 +154,10 @@ jobs:
creds: ${{ secrets.AZURE_CREDENTIALS }}

- name: Login to Azure Container Registry
run: |
az acr login --name ${{ vars.ACR_NAME }}
run: az acr login --name ${{ vars.ACR_NAME }}

- name: Build Docker image
run: |
docker build \
--platform linux/amd64 \
-t ${{ vars.ACR_LOGIN_SERVER }}/${{ matrix.image }}:${{ github.sha }} \
./${{ matrix.service }}
run: docker build --platform=linux/amd64 --tag="${{ vars.ACR_LOGIN_SERVER }}/${{ matrix.image }}:${{ github.sha }}" "./${{ matrix.service }}"

- name: Push Docker image with commit SHA
run: |
docker push \
${{ vars.ACR_LOGIN_SERVER }}/${{ matrix.image }}:${{ github.sha }}
run: docker push "${{ vars.ACR_LOGIN_SERVER }}/${{ matrix.image }}:${{ github.sha }}"
70 changes: 53 additions & 17 deletions .github/workflows/02-deploy-staging.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

name: 02 - Deploy to Staging

on:
Expand All @@ -9,41 +10,62 @@ on:
branches:
- main

workflow_dispatch:
inputs:
image_tag:
description: "Full commit SHA from a successful CI build"
required: true
type: string

permissions:
contents: read

jobs:
deploy-staging:
name: Deploy to Staging
runs-on: ubuntu-latest

if: >
${{ github.event.workflow_run.conclusion == 'success' }}
if: >-
${{
github.event_name == 'workflow_dispatch' ||
(
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push'
)
}}

environment:
name: staging
env:
IMAGE_TAG: ${{ inputs.image_tag || github.event.workflow_run.head_sha }}

steps:
# 1. Checkout the tested commit
- name: Checkout tested commit
uses: actions/checkout@v4
with:
ref: ${{ github.event.workflow_run.head_sha }}
ref: ${{ env.IMAGE_TAG }}

# 2. Login to Azure
- name: Login to Azure
uses: azure/login@v3
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}

# 3. Connect to AKS
- name: Get AKS credentials
run: |
az aks get-credentials \
--resource-group ${{ vars.AKS_RESOURCE_GROUP }} \
--name ${{ vars.AKS_CLUSTER_NAME }} \
--resource-group "${{ vars.AKS_RESOURCE_GROUP }}" \
--name "${{ vars.AKS_CLUSTER_NAME }}" \
--overwrite-existing

# 4. Create staging namespace
- name: Create staging namespace
run: |
kubectl create namespace staging \
--dry-run=client \
-o yaml | kubectl apply -f -

# 5. Create PostgreSQL secret
- name: Create PostgreSQL secret
run: |
kubectl create secret generic postgres-secret \
Expand All @@ -53,6 +75,7 @@ jobs:
--dry-run=client \
-o yaml | kubectl apply -f -

# 6. Create application secret
- name: Create application secret
run: |
kubectl create secret generic application-secret \
Expand All @@ -67,85 +90,98 @@ jobs:
--dry-run=client \
-o yaml | kubectl apply -f -

# 7. Apply Kubernetes manifests
- name: Apply Kubernetes manifests
run: |
kubectl apply \
-f kubernetes/staging/
kubectl apply -f kubernetes/staging/

# 8. Update frontend image
- name: Update frontend image
run: |
kubectl set image deployment/frontend \
frontend=${{ vars.ACR_LOGIN_SERVER }}/koalatech-frontend:${{ github.event.workflow_run.head_sha }} \
frontend="${{ vars.ACR_LOGIN_SERVER }}/koalatech-frontend:${IMAGE_TAG}" \
-n staging

# 9. Update user-service image
- name: Update user-service image
run: |
kubectl set image deployment/user-service \
user-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-user-service:${{ github.event.workflow_run.head_sha }} \
user-service="${{ vars.ACR_LOGIN_SERVER }}/koalatech-user-service:${IMAGE_TAG}" \
-n staging

# 10. Update student-service image
- name: Update student-service image
run: |
kubectl set image deployment/student-service \
student-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-student-service:${{ github.event.workflow_run.head_sha }} \
student-service="${{ vars.ACR_LOGIN_SERVER }}/koalatech-student-service:${IMAGE_TAG}" \
-n staging

# 11. Update lecturer-service image
- name: Update lecturer-service image
run: |
kubectl set image deployment/lecturer-service \
lecturer-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-lecturer-service:${{ github.event.workflow_run.head_sha }} \
lecturer-service="${{ vars.ACR_LOGIN_SERVER }}/koalatech-lecturer-service:${IMAGE_TAG}" \
-n staging

# 12. Update course-service image
- name: Update course-service image
run: |
kubectl set image deployment/course-service \
course-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-course-service:${{ github.event.workflow_run.head_sha }} \
course-service="${{ vars.ACR_LOGIN_SERVER }}/koalatech-course-service:${IMAGE_TAG}" \
-n staging

# 13. Update enrollment-service image
- name: Update enrollment-service image
run: |
kubectl set image deployment/enrollment-service \
enrollment-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-enrollment-service:${{ github.event.workflow_run.head_sha }} \
enrollment-service="${{ vars.ACR_LOGIN_SERVER }}/koalatech-enrollment-service:${IMAGE_TAG}" \
-n staging

# 14. Verify frontend rollout
- name: Wait for frontend rollout
run: |
kubectl rollout status deployment/frontend \
-n staging \
--timeout=300s

# 15. Verify user-service rollout
- name: Wait for user-service rollout
run: |
kubectl rollout status deployment/user-service \
-n staging \
--timeout=300s

# 16. Verify student-service rollout
- name: Wait for student-service rollout
run: |
kubectl rollout status deployment/student-service \
-n staging \
--timeout=300s

# 17. Verify lecturer-service rollout
- name: Wait for lecturer-service rollout
run: |
kubectl rollout status deployment/lecturer-service \
-n staging \
--timeout=300s

# 18. Verify course-service rollout
- name: Wait for course-service rollout
run: |
kubectl rollout status deployment/course-service \
-n staging \
--timeout=300s

# 19. Verify enrollment-service rollout
- name: Wait for enrollment-service rollout
run: |
kubectl rollout status deployment/enrollment-service \
-n staging \
--timeout=300s

# 20. Display staging resources
- name: Show staging resources
run: |
kubectl get pods -n staging
kubectl get services -n staging
kubectl get pvc -n staging
kubectl get pvc -n staging
5 changes: 2 additions & 3 deletions .github/workflows/03-staging-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ jobs:
name: Staging Smoke Test
runs-on: ubuntu-latest

if: >
${{ github.event.workflow_run.conclusion == 'success' }}

if: github.event.workflow_run.conclusion == 'success'

environment:
name: staging

Expand Down
34 changes: 27 additions & 7 deletions .github/workflows/04-deploy-production.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
name: 04 - Deploy to Production

on:
# Continuous Deployment: promote to production automatically
# once the staging smoke test has passed for a commit on main
workflow_run:
workflows:
- "03 - Test Staging"
types:
- completed
branches:
- main

# Kept for manual deployments / rollbacks to a specific image
workflow_dispatch:
inputs:
image_tag:
Expand All @@ -13,12 +24,21 @@ jobs:
name: Deploy to Production
runs-on: ubuntu-latest

# Only deploy if the staging tests succeeded (or when run manually)
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'

environment:
name: production

env:
# Automatic runs use the tested commit SHA; manual runs use the input
IMAGE_TAG: ${{ inputs.image_tag || github.event.workflow_run.head_sha }}

steps:
- name: Checkout repository
- name: Checkout tested commit
uses: actions/checkout@v4
with:
ref: ${{ env.IMAGE_TAG }}

- name: Login to Azure
uses: azure/login@v3
Expand Down Expand Up @@ -69,37 +89,37 @@ jobs:
- name: Update frontend image
run: |
kubectl set image deployment/frontend \
frontend=${{ vars.ACR_LOGIN_SERVER }}/koalatech-frontend:${{ inputs.image_tag }} \
frontend=${{ vars.ACR_LOGIN_SERVER }}/koalatech-frontend:${{ env.IMAGE_TAG }} \
-n production

- name: Update user-service image
run: |
kubectl set image deployment/user-service \
user-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-user-service:${{ inputs.image_tag }} \
user-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-user-service:${{ env.IMAGE_TAG }} \
-n production

- name: Update student-service image
run: |
kubectl set image deployment/student-service \
student-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-student-service:${{ inputs.image_tag }} \
student-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-student-service:${{ env.IMAGE_TAG }} \
-n production

- name: Update lecturer-service image
run: |
kubectl set image deployment/lecturer-service \
lecturer-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-lecturer-service:${{ inputs.image_tag }} \
lecturer-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-lecturer-service:${{ env.IMAGE_TAG }} \
-n production

- name: Update course-service image
run: |
kubectl set image deployment/course-service \
course-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-course-service:${{ inputs.image_tag }} \
course-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-course-service:${{ env.IMAGE_TAG }} \
-n production

- name: Update enrollment-service image
run: |
kubectl set image deployment/enrollment-service \
enrollment-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-enrollment-service:${{ inputs.image_tag }} \
enrollment-service=${{ vars.ACR_LOGIN_SERVER }}/koalatech-enrollment-service:${{ env.IMAGE_TAG }} \
-n production

- name: Wait for frontend rollout
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const Header = () => {
fontWeight: 600,
}}
>
KoalaTech University
KoalaTech University - Deployed by CD
</Typography>

<Box
Expand Down