Skip to content

Commit 95d9640

Browse files
committed
Set up deployment to dev server on pushes to main
1 parent 1382cd8 commit 95d9640

File tree

3 files changed

+291
-0
lines changed

3 files changed

+291
-0
lines changed

.github/workflows/deploy-dev.yml

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
name: Deploy to Dev Environment
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- "recorder-backend/**"
9+
- ".github/workflows/deploy-dev.yml"
10+
11+
# Allow manual trigger
12+
workflow_dispatch:
13+
14+
permissions:
15+
id-token: write # Required for OIDC authentication
16+
contents: read
17+
18+
env:
19+
WORKING_DIRECTORY: recorder-backend
20+
21+
jobs:
22+
test:
23+
name: Run Tests
24+
runs-on: ubuntu-latest
25+
defaults:
26+
run:
27+
working-directory: ${{ env.WORKING_DIRECTORY }}
28+
29+
steps:
30+
- name: Checkout code
31+
uses: actions/checkout@v4
32+
33+
- name: Set up Python
34+
uses: actions/setup-python@v5
35+
with:
36+
python-version: "3.11"
37+
cache: "pip"
38+
39+
- name: Install uv
40+
run: pip install uv
41+
42+
- name: Install dependencies
43+
run: uv pip install --system -r pyproject.toml
44+
45+
- name: Run tests
46+
run: pytest tests/ -v
47+
48+
deploy:
49+
name: Deploy to Dev Container App
50+
runs-on: ubuntu-latest
51+
needs: test
52+
environment:
53+
name: development
54+
url: ${{ steps.deploy.outputs.url }}
55+
56+
defaults:
57+
run:
58+
working-directory: ${{ env.WORKING_DIRECTORY }}
59+
60+
steps:
61+
- name: Checkout code
62+
uses: actions/checkout@v4
63+
64+
- name: Get short SHA
65+
id: vars
66+
run: echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
67+
68+
- name: Azure Login via OIDC
69+
uses: azure/login@v2
70+
with:
71+
client-id: ${{ secrets.AZURE_CLIENT_ID }}
72+
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
73+
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
74+
75+
- name: Login to Azure Container Registry
76+
run: |
77+
az acr login --name ${{ secrets.DEV_ACR_NAME }}
78+
79+
- name: Build and push Docker image
80+
env:
81+
ACR_NAME: ${{ secrets.DEV_ACR_NAME }}
82+
SHORT_SHA: ${{ steps.vars.outputs.short_sha }}
83+
run: |
84+
IMAGE_NAME="${ACR_NAME}.azurecr.io/recorder-backend"
85+
86+
docker build -t ${IMAGE_NAME}:dev-${SHORT_SHA} \
87+
-t ${IMAGE_NAME}:dev-latest \
88+
.
89+
90+
docker push ${IMAGE_NAME}:dev-${SHORT_SHA}
91+
docker push ${IMAGE_NAME}:dev-latest
92+
93+
echo "Pushed images:"
94+
echo " - ${IMAGE_NAME}:dev-${SHORT_SHA}"
95+
echo " - ${IMAGE_NAME}:dev-latest"
96+
97+
- name: Deploy to Container App
98+
id: deploy
99+
env:
100+
ACR_NAME: ${{ secrets.DEV_ACR_NAME }}
101+
SHORT_SHA: ${{ steps.vars.outputs.short_sha }}
102+
RESOURCE_GROUP: ${{ secrets.DEV_RESOURCE_GROUP }}
103+
CONTAINER_APP: ${{ secrets.DEV_CONTAINER_APP }}
104+
run: |
105+
IMAGE_NAME="${ACR_NAME}.azurecr.io/recorder-backend:dev-${SHORT_SHA}"
106+
107+
az containerapp update \
108+
--name ${CONTAINER_APP} \
109+
--resource-group ${RESOURCE_GROUP} \
110+
--image ${IMAGE_NAME} \
111+
--revision-suffix ${SHORT_SHA}
112+
113+
# Get the app URL
114+
APP_URL=$(az containerapp show \
115+
--name ${CONTAINER_APP} \
116+
--resource-group ${RESOURCE_GROUP} \
117+
--query properties.configuration.ingress.fqdn \
118+
--output tsv)
119+
120+
echo "url=https://${APP_URL}" >> $GITHUB_OUTPUT
121+
echo "Deployed to: https://${APP_URL}"
122+
123+
- name: Deployment Summary
124+
env:
125+
APP_URL: ${{ steps.deploy.outputs.url }}
126+
SHORT_SHA: ${{ steps.vars.outputs.short_sha }}
127+
run: |
128+
echo "## Deployment Successful! :rocket:" >> $GITHUB_STEP_SUMMARY
129+
echo "" >> $GITHUB_STEP_SUMMARY
130+
echo "**Environment:** Development" >> $GITHUB_STEP_SUMMARY
131+
echo "**Commit:** \`${SHORT_SHA}\`" >> $GITHUB_STEP_SUMMARY
132+
echo "**Image:** \`${{ secrets.DEV_ACR_NAME }}.azurecr.io/recorder-backend:dev-${SHORT_SHA}\`" >> $GITHUB_STEP_SUMMARY
133+
echo "" >> $GITHUB_STEP_SUMMARY
134+
echo "### :link: Links" >> $GITHUB_STEP_SUMMARY
135+
echo "- **App URL:** ${APP_URL}" >> $GITHUB_STEP_SUMMARY
136+
echo "- **API Docs:** ${APP_URL}/docs" >> $GITHUB_STEP_SUMMARY
137+
echo "- **Health Check:** ${APP_URL}/" >> $GITHUB_STEP_SUMMARY

.github/workflows/test.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Run Tests
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
paths:
8+
- "recorder-backend/**"
9+
- ".github/workflows/test.yml"
10+
11+
# Also run on main branch to catch issues early
12+
push:
13+
branches:
14+
- main
15+
paths:
16+
- "recorder-backend/**"
17+
- ".github/workflows/test.yml"
18+
19+
# Allow manual trigger
20+
workflow_dispatch:
21+
22+
env:
23+
WORKING_DIRECTORY: recorder-backend
24+
25+
jobs:
26+
test:
27+
name: Test Python ${{ matrix.python-version }}
28+
runs-on: ubuntu-latest
29+
30+
strategy:
31+
matrix:
32+
python-version: ["3.11"]
33+
34+
defaults:
35+
run:
36+
working-directory: ${{ env.WORKING_DIRECTORY }}
37+
38+
steps:
39+
- name: Checkout code
40+
uses: actions/checkout@v4
41+
42+
- name: Set up Python ${{ matrix.python-version }}
43+
uses: actions/setup-python@v5
44+
with:
45+
python-version: ${{ matrix.python-version }}
46+
cache: "pip"
47+
48+
- name: Install uv
49+
run: pip install uv
50+
51+
- name: Install dependencies
52+
run: uv pip install --system -r pyproject.toml
53+
54+
- name: Run linter (ruff)
55+
run: ruff check . --output-format=github
56+
continue-on-error: true
57+
58+
- name: Run tests with pytest
59+
run: |
60+
pytest tests/ \
61+
-v \
62+
--tb=short \
63+
--color=yes
64+
65+
- name: Test Summary
66+
if: always()
67+
run: |
68+
echo "## Test Results :test_tube:" >> $GITHUB_STEP_SUMMARY
69+
echo "" >> $GITHUB_STEP_SUMMARY
70+
echo "**Python Version:** ${{ matrix.python-version }}" >> $GITHUB_STEP_SUMMARY
71+
echo "**Status:** ${{ job.status }}" >> $GITHUB_STEP_SUMMARY

recorder-backend/README.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,96 @@
22

33
**Note:** This is the modernized FastAPI version running on Azure.
44

5+
![Deploy Dev](https://github.com/divvun/Kielipankki-donatespeech-backend/actions/workflows/deploy-dev.yml/badge.svg)
6+
![Tests](https://github.com/divvun/Kielipankki-donatespeech-backend/actions/workflows/test.yml/badge.svg)
7+
58
## Architecture
69

710
- **Framework**: FastAPI (Python 3.11)
811
- **Storage**: Azure Blob Storage
912
- **Local Development**: Azurite (Azure Storage Emulator)
1013
- **Deployment**: Azure Container Apps or Azure App Service
1114

15+
## Deployment
16+
17+
### Continuous Deployment
18+
19+
The backend automatically deploys to environments based on branch activity:
20+
21+
- **Development Environment**: Auto-deploys on every push to `main` branch
22+
- **Production Environment**: *(Planned)* Will deploy from tagged releases
23+
(e.g., `v1.0.0`)
24+
25+
### Current Setup (Dev Only)
26+
27+
Push to `main` branch triggers automatic deployment:
28+
1. Tests run automatically
29+
2. Docker image builds from [Dockerfile](Dockerfile)
30+
3. Image pushes to Azure Container Registry with tags:
31+
- `dev-<commit-sha>` (specific version)
32+
- `dev-latest` (rolling latest)
33+
4. Azure Container App updates with new image
34+
5. Deployment completes with zero downtime
35+
36+
**View Deployment Status:**
37+
- GitHub Actions: [Deployment Workflows](../../actions)
38+
- Development URL: Provided by Container App ingress
39+
40+
### GitHub Secrets Required
41+
42+
Configure these in repository Settings → Secrets and variables → Actions:
43+
44+
| Secret | Description | Example |
45+
|--------|-------------|---------|
46+
| `AZURE_CLIENT_ID` | Service principal client ID | `12345678-1234-1234-1234-123456789abc` |
47+
| `AZURE_TENANT_ID` | Azure AD tenant ID | `87654321-4321-4321-4321-cba987654321` |
48+
| `AZURE_SUBSCRIPTION_ID` | Target subscription ID | `abcdef12-3456-7890-abcd-ef1234567890` |
49+
| `DEV_ACR_NAME` | Container registry name | `acrkielipankkirec` |
50+
| `DEV_RESOURCE_GROUP` | Resource group name | `rg-kielipankki-recorder-dev` |
51+
| `DEV_CONTAINER_APP` | Container app name | `ca-recorder-backend-dev` |
52+
53+
### Azure Resources Required
54+
55+
**Development Environment:**
56+
- Resource Group: `rg-kielipankki-recorder-dev`
57+
- Storage Account: With container `recorder-content`
58+
- Container Registry: For Docker images
59+
- Key Vault: For YLE API credentials
60+
- Container Apps Environment: Runtime environment
61+
- Container App: The application instance
62+
63+
**Setup Steps:**
64+
1. Create Azure resources (see deployment guide)
65+
2. Configure service principal with federated credential for `main` branch
66+
3. Add GitHub secrets listed above
67+
4. Push to `main` to trigger first deployment
68+
69+
### Manual Deployment
70+
71+
To deploy manually:
72+
```bash
73+
# Build image
74+
docker build -t <acr-name>.azurecr.io/recorder-backend:dev-manual .
75+
76+
# Login and push
77+
az acr login --name <acr-name>
78+
docker push <acr-name>.azurecr.io/recorder-backend:dev-manual
79+
80+
# Update Container App
81+
az containerapp update \
82+
--name ca-recorder-backend-dev \
83+
--resource-group rg-kielipankki-recorder-dev \
84+
--image <acr-name>.azurecr.io/recorder-backend:dev-manual
85+
```
86+
87+
### Future: Production Deployment
88+
89+
When production is ready:
90+
1. Create production Azure resources (mirroring dev setup)
91+
2. Add production federated credential for tag pattern `v*`
92+
3. Configure production GitHub secrets
93+
4. Create tag to deploy: `git tag v1.0.0 && git push origin v1.0.0`
94+
1295
## Quick Start - Local Development
1396

1497
### Prerequisites

0 commit comments

Comments
 (0)