ci: add azure container apps auto-deploy workflow #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | |