Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7dbdcda
CI: use ACR admin creds & push images
TitikshaDeakin Sep 16, 2025
2126c51
Fix: proper ACR login server and debug step
TitikshaDeakin Sep 16, 2025
77d0bd7
Fix: YAML indentation for debug + docker login step
TitikshaDeakin Sep 16, 2025
4af3a7d
Fix indentation: make build_and_push_images a separate job
TitikshaDeakin Sep 16, 2025
adb2123
Fix indentation #2: make build_and_push_images a separate job
TitikshaDeakin Sep 16, 2025
16662ac
CD: decode kubeconfig + deploy backend services
TitikshaDeakin Sep 16, 2025
1a1f3cf
Fix: create .kube directory before writing config
TitikshaDeakin Sep 16, 2025
d4c39b0
Frontend: update API endpoints to deployed AKS backend services
TitikshaDeakin Sep 16, 2025
af88eb4
Frontend CI: final clean YAML + ACR creds
TitikshaDeakin Sep 16, 2025
d24ffd4
Frontend CI: final clean YAM#2L + ACR creds
TitikshaDeakin Sep 16, 2025
7970d37
Frontend CD: use kubeconfig secret; simple kubectl apply
TitikshaDeakin Sep 16, 2025
e3d6196
Point frontend to correct API URLs
TitikshaDeakin Sep 16, 2025
32b3165
Frontend CI: add manual inputs + inject API URLs before build
TitikshaDeakin Sep 16, 2025
b46815e
Frontend CI: add manual inputs#2 + inject API URLs before build
TitikshaDeakin Sep 16, 2025
e424165
Use placeholders for API URLs in main.js
TitikshaDeakin Sep 16, 2025
da75eee
#2Use placeholders for API URLs in main.js
TitikshaDeakin Sep 16, 2025
9fee7bc
chore(actions): add PR checks + concurrency; skip image push on PRs
TitikshaDeakin Sep 25, 2025
c30a0ea
chore(actions): add pip caching + ruff lint + mypy type-checks to Bac…
TitikshaDeakin Sep 25, 2025
ea5cddd
chore(actions): add pip caching + ruff lint + mypy type-checks to Bac…
TitikshaDeakin Sep 25, 2025
2f3a289
fix(actions): add ruff lint + mypy steps correctly
TitikshaDeakin Sep 25, 2025
b0e5e84
fix(actions): add ruff lint + mypy steps correctly2
TitikshaDeakin Sep 25, 2025
c608ca1
fix(actions): correct indentation; add ruff+mypy steps properly
TitikshaDeakin Sep 25, 2025
2aece4e
fix(actions): correct indentation; add ruff+mypy steps properly
TitikshaDeakin Sep 25, 2025
2b4ba25
chore(actions): frontend PR checks + concurrency; skip image push on PRs
TitikshaDeakin Sep 25, 2025
372a770
fix(actions): remove stray top-level push block in frontend CI
TitikshaDeakin Sep 25, 2025
5df9bab
feat(actions): add caching + eslint + tests to frontend CI
TitikshaDeakin Sep 25, 2025
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
39 changes: 8 additions & 31 deletions .github/workflows/backend-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,6 @@ name: CD - Deploy Backend Services to AKS

on:
workflow_dispatch:
inputs:
aks_cluster_name:
description: 'Name of the AKS Cluster to deploy to'
required: true
default: '<aks_cluster_name>'
aks_resource_group:
description: 'Resource Group of the AKS Cluster'
required: true
default: '<resource_group_name>'
aks_acr_name:
description: 'Name of ACR'
required: true
default: '<acr_name>'

jobs:
deploy_backend:
Expand All @@ -29,19 +16,14 @@ jobs:
- name: Checkout repository
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)
# 🗝️ Configure kubeconfig using GitHub Secret
- name: Configure kubeconfig
run: |
az aks get-credentials --resource-group ${{ github.event.inputs.aks_resource_group }} --name ${{ github.event.inputs.aks_cluster_name }} --overwrite-existing
mkdir -p ~/.kube
echo "${{ secrets.KUBECONFIG_B64 }}" | base64 --decode > ~/.kube/config

- 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: Verify cluster connection
run: kubectl get nodes

- name: Deploy Backend Infrastructure (Namespace, ConfigMaps, Secrets, Databases)
run: |
Expand Down Expand Up @@ -76,16 +58,14 @@ jobs:
echo "Order Service IP: $ORDER_IP"
break
fi
sleep 5 # Wait 5 seconds before next attempt
sleep 5
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
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
echo "ORDER_IP=$ORDER_IP" >> $GITHUB_ENV

Expand All @@ -96,6 +76,3 @@ jobs:
- name: Capture Order Service IP for Workflow Output
id: get_order_ip
run: echo "external_ip=${{ env.ORDER_IP }}" >> $GITHUB_OUTPUT

- name: Logout from Azure
run: az logout
162 changes: 83 additions & 79 deletions .github/workflows/backend_ci.yml
Original file line number Diff line number Diff line change
@@ -1,91 +1,89 @@
# week08/.github/workflows/backend_ci.yml

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:

# Automatically on pushes to main branch
pull_request:
branches: [ main ]
paths:
- 'backend/**'
- '.github/workflows/backend_ci.yml'
push:
branches:
- main
paths: # Only trigger if changes are in backend directories
branches: [ main ]
paths:
- 'backend/**'
- '.github/workflows/backend_ci.yml' # Trigger if this workflow file changes
- '.github/workflows/backend_ci.yml'
workflow_dispatch:

# minimal, explicit permissions (prep for later OIDC work)
permissions:
contents: read
id-token: write
packages: write

# cancel stale runs on same ref
concurrency:
group: backend-ci-${{ github.ref }}
cancel-in-progress: true

# Define global environment variables that can be used across jobs
env:
# ACR Login Server (e.g., myregistry.azurecr.io)
# This needs to be set as a GitHub Repository Secret
# e.g. myregistry.azurecr.io
ACR_LOGIN_SERVER: ${{ secrets.AZURE_CONTAINER_REGISTRY }}
# 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 }}

jobs:
# Job 1: Run tests and linting for all backend services
test_and_lint_backends:
runs-on: ubuntu-latest # Use a GitHub-hosted runner
runs-on: ubuntu-latest

services:
# Product DB container
product_db:
image: postgres:15
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: products
# Make pg_isready available so the service is healthy before tests run
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

# Order DB
order_db:
image: postgres:15
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: orders
ports:
- 5433:5432
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5433:5432

steps:
# 1. Checkout the repository code to the runner
- name: Checkout repository
uses: actions/checkout@v4 # Action to check out your repository code
uses: actions/checkout@v4

# 2. Set up Python environment
- name: Set up Python 3.10
uses: actions/setup-python@v5 # Action to set up Python environment
- uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'

- name: Install tooling & deps
run: |
python -m pip install --upgrade pip
pip install ruff mypy pytest httpx
# Single-service or multi-service deps:
if [ -f backend/requirements.txt ]; then pip install -r backend/requirements.txt; fi
for req in backend/*/requirements.txt; do [ -f "$req" ] && pip install -r "$req"; done

- name: Lint (ruff)
run: ruff check backend/ || true

- name: Type-check (mypy)
run: mypy backend/ || true

# 3. Install dependencies and run code quality checks
- name: Install dependencies
run: | # Use a multi-line script to install pip dependencies
pip install --upgrade pip
# Loop through each backend service folder
for req in backend/*/requirements.txt; do
echo "Installing $req"
pip install -r "$req"
done
# Install CI tools
pip install pytest httpx

# 5. Run tests for product service
- name: Run product_service tests
working-directory: backend/product_service
env:
Expand All @@ -94,10 +92,8 @@ jobs:
POSTGRES_DB: products
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
run: |
pytest tests --maxfail=1 --disable-warnings -q

# 6. Run tests for order service
run: pytest tests --maxfail=1 --disable-warnings -q

- name: Run order_service tests
working-directory: backend/order_service
env:
Expand All @@ -106,41 +102,49 @@ jobs:
POSTGRES_DB: orders
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
run: |
pytest tests --maxfail=1 --disable-warnings -q
run: pytest tests --maxfail=1 --disable-warnings -q

# Job 2: Build and Push Docker Images (runs only if tests pass)
build_and_push_images:
# do not build/push images on PR validation
if: ${{ github.event_name != 'pull_request' }}
runs-on: ubuntu-latest
needs: test_and_lint_backends

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

# Azure login using a Service Principal secret
- name: Azure Login
uses: azure/login@v1
with:
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 }}

# Build and Push Docker image for Product Service
- name: Build and Push Product Service Image
run: |
docker build -t ${{ env.ACR_LOGIN_SERVER }}/product_service:latest ./backend/product_service/
docker push ${{ env.ACR_LOGIN_SERVER }}/product_service:latest

# Build and Push Docker image for Order Service
- name: Build and Push Order Service Image
run: |
docker build -t ${{ env.ACR_LOGIN_SERVER }}/order_service:latest ./backend/order_service/
docker push ${{ env.ACR_LOGIN_SERVER }}/order_service:latest

# Logout from Azure for security (runs even if image push fails)
- name: Logout from Azure
run: az logout
if: always()
- name: Checkout repository
uses: actions/checkout@v4

- name: Debug ACR login server
run: echo "Using ACR login server:${{ env.ACR_LOGIN_SERVER }}"

- name: Docker login to ACR
shell: bash
run: |
if [ -z "${{ env.ACR_LOGIN_SERVER }}" ]; then
echo "ACR_LOGIN_SERVER is empty. Check secret AZURE_CONTAINER_REGISTRY."
exit 1
fi
echo "${{ secrets.ACR_PASSWORD }}" | docker login "${{ env.ACR_LOGIN_SERVER }}" \
-u "${{ secrets.ACR_USERNAME }}" --password-stdin

- name: Build and Push Product Service Image
shell: bash
run: |
docker build -t "${{ env.ACR_LOGIN_SERVER }}/product_service:latest" \
-t "${{ env.ACR_LOGIN_SERVER }}/product_service:${{ env.IMAGE_TAG }}" \
./backend/product_service/
docker push "${{ env.ACR_LOGIN_SERVER }}/product_service:latest"
docker push "${{ env.ACR_LOGIN_SERVER }}/product_service:${{ env.IMAGE_TAG }}"

- name: Build and Push Order Service Image
shell: bash
run: |
docker build -t "${{ env.ACR_LOGIN_SERVER }}/order_service:latest" \
-t "${{ env.ACR_LOGIN_SERVER }}/order_service:${{ env.IMAGE_TAG }}" \
./backend/order_service/
docker push "${{ env.ACR_LOGIN_SERVER }}/order_service:latest"
docker push "${{ env.ACR_LOGIN_SERVER }}/order_service:${{ env.IMAGE_TAG }}"

- name: Docker logout
if: always()
run: docker logout "${{ env.ACR_LOGIN_SERVER }}"
Loading