Skip to content

ci: add azure container apps auto-deploy workflow #1

ci: add azure container apps auto-deploy workflow

ci: add azure container apps auto-deploy workflow #1

Workflow file for this run

name: Deploy API to Azure
on:
push:
branches: [main]
workflow_dispatch:
concurrency:
group: deploy-azure
cancel-in-progress: false
env:
AZURE_CONTAINER_APP_NAME: openlinear-api
AZURE_RESOURCE_GROUP: rg-openlinear-prod
AZURE_REGISTRY: openlinearcr.azurecr.io
AZURE_REGISTRY_NAME: openlinearcr
IMAGE_NAME: openlinear-api
jobs:
checks:
name: Checks
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: openlinear
POSTGRES_PASSWORD: openlinear
POSTGRES_DB: openlinear_test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
DATABASE_URL: postgresql://openlinear:openlinear@localhost:5432/openlinear_test
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Generate Prisma client
run: pnpm --filter @openlinear/db db:generate
- name: Push schema to test database
run: pnpm --filter @openlinear/db db:push
- name: Typecheck
run: pnpm --filter @openlinear/api typecheck
- name: Build API
run: pnpm --filter @openlinear/api build
- name: Build Web
run: pnpm --filter @openlinear/desktop-ui build
env:
NEXT_PUBLIC_API_URL: https://openlinear.tech
- name: Build Landing
run: pnpm --filter @openlinear/landing build
- name: Test
run: pnpm --filter @openlinear/api test
build-and-push:
name: Build and Push Docker Image
needs: checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Azure Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.AZURE_REGISTRY }}
username: ${{ secrets.AZURE_REGISTRY_USERNAME }}
password: ${{ secrets.AZURE_REGISTRY_PASSWORD }}
- name: Build and push API image
uses: docker/build-push-action@v5
with:
context: .
file: ./apps/api/Dockerfile
push: true
tags: |
${{ env.AZURE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
${{ env.AZURE_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
deploy-to-azure:
name: Deploy to Azure Container Apps
needs: build-and-push
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to Azure
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Update Container App
run: |
az containerapp update \
--name ${{ env.AZURE_CONTAINER_APP_NAME }} \
--resource-group ${{ env.AZURE_RESOURCE_GROUP }} \
--image ${{ env.AZURE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
--min-replicas 1 \
--max-replicas 3
- name: Wait for revision to be ready
run: |
echo "Waiting for Container App revision to be ready..."
for i in $(seq 1 30); do
STATUS=$(az containerapp show \
--name ${{ env.AZURE_CONTAINER_APP_NAME }} \
--resource-group ${{ env.AZURE_RESOURCE_GROUP }} \
--query "properties.runningStatus" -o tsv)
echo "Attempt $i: status=$STATUS"
if [ "$STATUS" = "Running" ]; then
echo "Container App is running!"
break
fi
if [ "$i" -eq 30 ]; then
echo "Timeout waiting for Container App"
exit 1
fi
sleep 10
done
- name: Verify deployment
run: |
echo "Testing API health endpoint..."
for i in $(seq 1 20); do
HTTP_STATUS=$(curl -s -o /dev/null -w '%{http_code}' \
https://api.openlinear.tech/health || echo "000")
echo "Attempt $i: HTTP $HTTP_STATUS"
if [ "$HTTP_STATUS" = "200" ]; then
echo "✓ Deployment verified — API is healthy"
exit 0
fi
if [ "$i" -eq 20 ]; then
echo "✗ Health check failed after 20 attempts"
exit 1
fi
sleep 5
done
- name: Run diagnostics on failure
if: failure()
run: |
echo "=== Container App Status ==="
az containerapp show \
--name ${{ env.AZURE_CONTAINER_APP_NAME }} \
--resource-group ${{ env.AZURE_RESOURCE_GROUP }} \
--query "properties"
echo ""
echo "=== Container Logs ==="
az containerapp logs show \
--name ${{ env.AZURE_CONTAINER_APP_NAME }} \
--resource-group ${{ env.AZURE_RESOURCE_GROUP }} \
--tail 50