Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/00-terraform.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: 00 - Terraform

on:
push:
branches:
- main
- feature/continuous-deployment
pull_request:
branches:
- main
workflow_dispatch:

jobs:
terraform:
name: Terraform Validate and Plan
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

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

- name: Verify Azure account
run: |
az account show

- name: Setup Terraform
uses: hashicorp/setup-terraform@v3

- name: Terraform Format Check
run: |
terraform fmt -check -recursive

- name: Terraform Init
run: |
terraform init -backend=false

- name: Terraform Validate
run: |
terraform validate

- name: Terraform Plan
run: |
terraform plan \
-refresh=false \
-input=false \
-var="location=Australia East" \
-var="resource_group_name=koalatech-week08-rg" \
-var="acr_name=koalatechweek09acr" \
-var="storage_account_name=koalatechweek09storage" \
-var="aks_cluster_name=koalatech-week08-aks" \
-var="aks_dns_prefix=koalatech" \
-var="aks_node_count=3" \
-var="aks_node_vm_size=Standard_D2s_v3" \
-var="environment=development"
46 changes: 46 additions & 0 deletions .github/workflows/01-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
push:
branches:
- main
- feature/continuous-deployment

# Manual trigger for the workflow
workflow_dispatch:
Expand Down Expand Up @@ -101,6 +102,38 @@ jobs:
run: |
pytest -v

# =========================================================
# Frontend Tests
# =========================================================
frontend-test:
name: Test frontend
runs-on: ubuntu-latest

env:
VITE_USER_SERVICE_URL: http://localhost:8001
VITE_STUDENT_SERVICE_URL: http://localhost:8002
VITE_LECTURER_SERVICE_URL: http://localhost:8003
VITE_COURSE_SERVICE_URL: http://localhost:8004
VITE_ENROLLMENT_SERVICE_URL: http://localhost:8005

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Install dependencies
working-directory: frontend
run: |
npm install

- name: Run frontend tests
working-directory: frontend
run: |
npm run test:run

# =========================================================
# Build and Push Docker Images
Expand All @@ -112,6 +145,7 @@ jobs:
# All backend 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'
Expand Down Expand Up @@ -160,6 +194,18 @@ jobs:
-t ${{ vars.ACR_LOGIN_SERVER }}/${{ matrix.image }}:${{ github.sha }} \
./${{ matrix.service }}

- name: Docker Scout vulnerability scan
uses: docker/scout-action@v1
with:
command: cves
image: ${{ vars.ACR_LOGIN_SERVER }}/${{ matrix.image }}:${{ github.sha }}
only-severities: critical,high
exit-code: false
summary: true
env:
DOCKER_SCOUT_HUB_USER: ${{ secrets.DOCKER_SCOUT_HUB_USER }}
DOCKER_SCOUT_HUB_PASSWORD: ${{ secrets.DOCKER_SCOUT_TOKEN }}

- name: Push Docker image with commit SHA
run: |
docker push \
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/02-deploy-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
- completed
branches:
- main
- feature/continuous-deployment

jobs:
deploy-staging:
Expand Down
30 changes: 17 additions & 13 deletions .github/workflows/04-deploy-production.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
name: 04 - Deploy to Production

on:
workflow_dispatch:
inputs:
image_tag:
description: "Tested image SHA to deploy"
required: true
type: string
workflow_run:
workflows:
- "03 - Test Staging"
types:
- completed
branches:
- main

jobs:
deploy-production:
name: Deploy to Production
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest

environment:
name: production

steps:
- name: Checkout repository
- name: Checkout tested commit
uses: actions/checkout@v4
with:
ref: ${{ github.event.workflow_run.head_sha }}

- name: Login to Azure
uses: azure/login@v3
Expand Down Expand Up @@ -69,37 +73,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:${{ github.event.workflow_run.head_sha }} \
-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:${{ github.event.workflow_run.head_sha }} \
-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:${{ github.event.workflow_run.head_sha }} \
-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:${{ github.event.workflow_run.head_sha }} \
-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:${{ github.event.workflow_run.head_sha }} \
-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:${{ github.event.workflow_run.head_sha }} \
-n production

- name: Wait for frontend rollout
Expand Down
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,10 @@ cython_debug/
.cursorignore
.cursorindexingignore

node_modules/
node_modules/
# Terraform
.terraform/
*.tfstate
*.tfstate.*
*.tfvars
*.tfvars.json
22 changes: 22 additions & 0 deletions .terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions container_registry.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
resource "azurerm_container_registry" "acr" {
name = var.acr_name
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location

sku = "Basic"
admin_enabled = true

tags = merge(
var.tags,
{
Environment = var.environment
}
)
}
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 — Continuous Deployment
</Typography>

<Box
Expand Down
34 changes: 34 additions & 0 deletions kubernetes_serivce.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
resource "azurerm_kubernetes_cluster" "aks" {
name = var.aks_cluster_name
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
dns_prefix = var.aks_dns_prefix
kubernetes_version = var.kubernetes_version

default_node_pool {
name = "default"
node_count = var.aks_node_count
vm_size = var.aks_node_vm_size
}

identity {
type = "SystemAssigned"
}

tags = merge(
var.tags,
{
Environment = var.environment
}
)
}

#
# Grant AKS permission to pull images from your ACR
#
resource "azurerm_role_assignment" "acr_pull" {
principal_id = azurerm_kubernetes_cluster.aks.kubelet_identity[0].object_id
role_definition_name = "AcrPull"
scope = azurerm_container_registry.acr.id
skip_service_principal_aad_check = true
}
57 changes: 57 additions & 0 deletions output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
output "resource_group_name" {
description = "Name of the resource group"
value = azurerm_resource_group.rg.name
}

output "acr_name" {
description = "Name of the Azure Container Registry"
value = azurerm_container_registry.acr.name
}

output "acr_login_server" {
description = "Login server of the Azure Container Registry"
value = azurerm_container_registry.acr.login_server
}

output "storage_account_name" {
description = "Name of the Azure Storage Account"
value = azurerm_storage_account.storage_account.name
}

output "storage_connection_string" {
description = "Connection string used by the application to access Blob Storage"
value = azurerm_storage_account.storage_account.primary_connection_string
sensitive = true
}

output "student_profile_container" {
description = "Student profile photo Blob container"
value = azurerm_storage_container.student_profile_photo.name
}

output "lecturer_profile_container" {
description = "Lecturer profile photo Blob container"
value = azurerm_storage_container.lecturer_profile_photo.name
}

output "aks_cluster_name" {
description = "Name of the AKS cluster"
value = azurerm_kubernetes_cluster.aks.name
}

output "aks_get_credentials_command" {
description = "Azure CLI command used to configure kubectl"
value = join(" ", [
"az aks get-credentials",
"--resource-group",
azurerm_resource_group.rg.name,
"--name",
azurerm_kubernetes_cluster.aks.name,
"--overwrite-existing"
])
}

output "acr_login_command" {
description = "Azure CLI command used to log in to ACR"
value = "az acr login --name ${azurerm_container_registry.acr.name}"
}
11 changes: 11 additions & 0 deletions resource_group.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
resource "azurerm_resource_group" "rg" {
name = var.resource_group_name
location = var.location

tags = merge(
var.tags,
{
Environment = var.environment
}
)
}
Loading