Skip to content

Commit b4b47ee

Browse files
authored
chore: azure deployment
2 parents e456cb8 + 005878f commit b4b47ee

6 files changed

Lines changed: 179 additions & 15 deletions

File tree

.github/workflows/ci.yml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,3 @@ jobs:
2323
run: uv run ruff check
2424
- name: Test
2525
run: uv run pytest
26-
27-
docker:
28-
name: Docker
29-
runs-on: ubuntu-latest
30-
needs: test
31-
steps:
32-
- name: Checkout code
33-
uses: actions/checkout@v5
34-
- name: Build
35-
uses: docker/build-push-action@v6
36-
with:
37-
push: false
38-
# To be changed
39-
tags: andig/evopt:latest

.github/workflows/deploy.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Deploy
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
image_tag:
7+
description: Image tag to deploy
8+
required: false
9+
default: latest
10+
11+
env:
12+
IMAGE: evcc/optimizer
13+
RESOURCE_GROUP: rg-optimizer-prod
14+
15+
jobs:
16+
deploy:
17+
name: Deploy
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- uses: actions/checkout@v6
22+
23+
- uses: azure/login@v2
24+
with:
25+
creds: ${{ secrets.AZURE_CREDENTIALS }}
26+
27+
- name: Deploy infrastructure
28+
uses: azure/cli@v2
29+
with:
30+
inlineScript: |
31+
az deployment group create \
32+
--resource-group ${{ env.RESOURCE_GROUP }} \
33+
--template-file infra/main.bicep \
34+
--parameters \
35+
containerImage=${{ env.IMAGE }}:${{ inputs.image_tag || 'latest' }}

.github/workflows/publish.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Publish Docker
2+
3+
on:
4+
workflow_dispatch:
5+
6+
env:
7+
IMAGE: evcc/optimizer
8+
9+
jobs:
10+
publish:
11+
name: Build & Push
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v6
15+
- name: Login to Docker Hub
16+
uses: docker/login-action@v3
17+
with:
18+
username: ${{ secrets.DOCKER_USER }}
19+
password: ${{ secrets.DOCKER_PASS }}
20+
- name: Setup Buildx
21+
uses: docker/setup-buildx-action@v3
22+
- name: Build and push
23+
uses: docker/build-push-action@v6
24+
with:
25+
context: .
26+
platforms: linux/amd64,linux/arm64
27+
push: true
28+
tags: |
29+
${{ env.IMAGE }}:${{ github.sha }}
30+
${{ env.IMAGE }}:latest

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ FROM python:3.13-slim
2424
COPY --from=builder --chown=app:app /app/.venv /app/.venv
2525

2626
# Run the application
27+
ENV PYTHONUNBUFFERED=1
2728
ENV OPTIMIZER_TIME_LIMIT=25
2829
ENV OPTIMIZER_NUM_THREADS=1
2930
ENV GUNICORN_CMD_ARGS="--workers 4 --max-requests 32"

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
DOCKER_IMAGE := evcc-io/optimizer
1+
DOCKER_IMAGE ?= evcc/optimizer
22

33
default: build docker-build
44

infra/main.bicep

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
@description('Container image to deploy')
2+
param containerImage string = 'evcc/optimizer:latest'
3+
4+
@description('Azure region for all resources')
5+
param location string = 'germanywestcentral'
6+
7+
resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = {
8+
name: 'kv-optimizer-prod'
9+
location: location
10+
properties: {
11+
sku: {
12+
family: 'A'
13+
name: 'standard'
14+
}
15+
tenantId: subscription().tenantId
16+
enableRbacAuthorization: true
17+
}
18+
}
19+
20+
resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2025-02-01' = {
21+
name: 'optimizer-logs'
22+
location: location
23+
properties: {
24+
sku: {
25+
name: 'PerGB2018'
26+
}
27+
retentionInDays: 30
28+
}
29+
}
30+
31+
resource containerAppEnv 'Microsoft.App/managedEnvironments@2025-01-01' = {
32+
name: 'optimizer-env'
33+
location: location
34+
properties: {
35+
appLogsConfiguration: {
36+
destination: 'log-analytics'
37+
logAnalyticsConfiguration: {
38+
customerId: logAnalytics.properties.customerId
39+
sharedKey: logAnalytics.listKeys().primarySharedKey
40+
}
41+
}
42+
}
43+
}
44+
45+
resource containerApp 'Microsoft.App/containerApps@2025-01-01' = {
46+
name: 'optimizer'
47+
location: location
48+
identity: {
49+
type: 'SystemAssigned'
50+
}
51+
properties: {
52+
managedEnvironmentId: containerAppEnv.id
53+
configuration: {
54+
ingress: {
55+
external: true
56+
targetPort: 7050
57+
}
58+
secrets: [
59+
{
60+
name: 'jwt-token-secret'
61+
keyVaultUrl: '${keyVault.properties.vaultUri}secrets/jwt-token-secret'
62+
identity: 'system'
63+
}
64+
]
65+
}
66+
template: {
67+
containers: [
68+
{
69+
name: 'optimizer'
70+
image: containerImage
71+
resources: {
72+
cpu: json('2')
73+
memory: '4Gi'
74+
}
75+
env: [
76+
{ name: 'OPTIMIZER_TIME_LIMIT', value: '25' }
77+
{ name: 'OPTIMIZER_NUM_THREADS', value: '1' }
78+
{ name: 'GUNICORN_CMD_ARGS', value: '--workers 4 --max-requests 32' }
79+
{ name: 'JWT_TOKEN_SECRET', secretRef: 'jwt-token-secret' }
80+
]
81+
probes: [
82+
{
83+
type: 'startup'
84+
tcpSocket: {
85+
port: 7050
86+
}
87+
periodSeconds: 5
88+
failureThreshold: 10
89+
}
90+
]
91+
}
92+
]
93+
scale: {
94+
minReplicas: 1
95+
maxReplicas: 5
96+
rules: [
97+
{
98+
name: 'http-scaling'
99+
http: {
100+
metadata: {
101+
concurrentRequests: '10'
102+
}
103+
}
104+
}
105+
]
106+
}
107+
}
108+
}
109+
}
110+
111+
112+
output fqdn string = containerApp.properties.configuration.ingress.fqdn

0 commit comments

Comments
 (0)