diff --git a/.github/workflows/build-deploy.yml b/.github/workflows/build-deploy.yml index 28540e6..1b0704f 100644 --- a/.github/workflows/build-deploy.yml +++ b/.github/workflows/build-deploy.yml @@ -1,4 +1,4 @@ -name: Build and Deploy +name: Build and Push Image on: push: @@ -9,8 +9,6 @@ on: env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} - AZURE_CONTAINER_APP_NAME: teams-browser-bot - AZURE_RESOURCE_GROUP: rg-poweron-int jobs: build: @@ -19,9 +17,6 @@ jobs: contents: read packages: write - outputs: - image_tag: ${{ steps.meta.outputs.tags }} - steps: - name: Checkout repository uses: actions/checkout@v4 @@ -50,20 +45,10 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - deploy: - needs: build - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/main' - - steps: - - name: Azure Login - uses: azure/login@v1 - with: - creds: ${{ secrets.AZURE_CREDENTIALS }} - - - name: Deploy to Azure Container Apps - uses: azure/container-apps-deploy-action@v1 - with: - resourceGroup: ${{ env.AZURE_RESOURCE_GROUP }} - containerAppName: ${{ env.AZURE_CONTAINER_APP_NAME }} - imageToDeploy: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + - name: Summary + run: | + echo "### Image pushed successfully! :rocket:" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Image: \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "To deploy: Go to Azure Portal → Container Apps → teams-browser-bot → Create new revision" >> $GITHUB_STEP_SUMMARY diff --git a/AZURE_SETUP.md b/AZURE_SETUP.md index aff51ab..18e4f36 100644 --- a/AZURE_SETUP.md +++ b/AZURE_SETUP.md @@ -1,219 +1,203 @@ # Azure Setup für Teams Browser Bot -## Voraussetzungen +## Architektur -1. Azure CLI installiert und eingeloggt -2. GitHub Repository erstellt unter `valueonag/service-teams-browser-bot` +Der Browser Bot ist ein **zentraler Service** der von allen Gateway-Instanzen (dev, int, prod) genutzt wird. +Jede Gateway-Instanz sendet ihre eigene WebSocket-URL mit dem Join-Request, sodass der Bot +sich immer zur richtigen Gateway-Instanz zurückverbindet. ---- - -## 1. Azure Container App erstellen - -### 1.1 Resource Group (falls nicht vorhanden) - -```bash -az group create \ - --name rg-poweron-int \ - --location westeurope ``` - -### 1.2 Container Apps Environment - -```bash -az containerapp env create \ - --name cae-poweron-int \ - --resource-group rg-poweron-int \ - --location westeurope -``` - -### 1.3 Container App erstellen - -```bash -az containerapp create \ - --name teams-browser-bot \ - --resource-group rg-poweron-int \ - --environment cae-poweron-int \ - --image ghcr.io/valueonag/service-teams-browser-bot:latest \ - --target-port 4100 \ - --ingress external \ - --cpu 2 \ - --memory 4Gi \ - --min-replicas 0 \ - --max-replicas 3 \ - --env-vars \ - NODE_ENV=production \ - PORT=4100 \ - GATEWAY_WS_URL=wss://gateway-int.poweron-center.net/api/teamsbot/bot/ws \ - BOT_NAME="PowerOn AI" \ - BOT_HEADLESS=true \ - LOG_LEVEL=info \ - SCREENSHOT_ON_ERROR=true -``` - -### 1.4 Container App URL notieren - -```bash -az containerapp show \ - --name teams-browser-bot \ - --resource-group rg-poweron-int \ - --query properties.configuration.ingress.fqdn \ - --output tsv -``` - -Ergebnis z.B.: `teams-browser-bot.happysky-12345.westeurope.azurecontainerapps.io` - ---- - -## 2. GitHub Actions Setup - -### 2.1 Azure Service Principal erstellen - -```bash -az ad sp create-for-rbac \ - --name "github-teams-browser-bot" \ - --role contributor \ - --scopes /subscriptions//resourceGroups/rg-poweron-int \ - --sdk-auth -``` - -### 2.2 GitHub Secret hinzufügen - -1. GitHub Repo → Settings → Secrets and variables → Actions -2. New repository secret: `AZURE_CREDENTIALS` -3. Wert: JSON Output vom vorherigen Befehl - -### 2.3 GitHub Container Registry Zugriff - -Der Workflow verwendet `GITHUB_TOKEN` automatisch für ghcr.io. - -Falls Azure die Images nicht pullen kann: - -```bash -# PAT mit read:packages Scope erstellen auf GitHub -# Dann in Azure: -az containerapp registry set \ - --name teams-browser-bot \ - --resource-group rg-poweron-int \ - --server ghcr.io \ - --username \ - --password +┌─────────────────┐ ┌──────────────────────────┐ +│ Gateway PROD │────►│ │ +│ (gateway.xyz) │◄────│ Teams Browser Bot │ +├─────────────────┤ │ (zentraler Service) │ +│ Gateway INT │────►│ │ +│ (gateway-int..) │◄────│ resource-core │ +├─────────────────┤ │ │ +│ Gateway DEV │────►│ │ +│ (localhost) │◄────│ │ +└─────────────────┘ └──────────────────────────┘ ``` --- -## 3. Gateway Konfiguration +## 1. Container App erstellen (Azure Portal) -### 3.1 Environment Variable im Gateway +1. **Azure Portal öffnen**: https://portal.azure.com +2. **Suche**: "Container Apps" in der Suchleiste +3. **+ Create** klicken -Der Bot Service ist **multi-instance-fähig**: Ein Bot kann mit allen Gateway-Instanzen (main, int, dev) arbeiten. +### Basics Tab +| Feld | Wert | +|------|------| +| Subscription | Subscription Product | +| Resource group | resource-core | +| Container app name | `teams-browser-bot` | +| Region | Switzerland North | +| Container Apps Environment | **Create new** → Name: `cae-poweron-shared`, Zone redundancy: Disabled → **Create** | -In **jeder** Gateway-Instanz die gleiche Bot URL konfigurieren: +### Container Tab -**env_main.env:** +**Zuerst GitHub PAT erstellen** (brauchst du gleich): +1. https://github.com/settings/tokens/new +2. Note: "Azure Container App - teams-browser-bot" +3. Expiration: 90 days (oder länger) +4. Scope: ✅ `read:packages` +5. **Generate token** → Kopieren und sicher aufbewahren + +**Dann im Azure Portal:** + +| Feld | Wert | +|------|------| +| Registry | Other registry | +| Authentication type | Basic | +| Registry login server | `ghcr.io` | +| Username | `valueonag` | +| Password | Dein GitHub PAT von oben | +| Image | `valueonag/service-teams-browser-bot` | +| Image tag | `latest` | + +### Container Resources (weiter unten) +| Feld | Wert | +|------|------| +| CPU cores | 2 | +| Memory (Gi) | 4 | + +### Environment Variables +| Name | Value | +|------|-------| +| NODE_ENV | production | +| PORT | 4100 | +| BOT_NAME | PowerOn AI | +| BOT_HEADLESS | true | +| LOG_LEVEL | info | +| SCREENSHOT_ON_ERROR | true | + +> ⚠️ **Wichtig:** KEINE `GATEWAY_WS_URL` Variable setzen! Die URL kommt dynamisch vom Gateway. + +### Ingress Tab +| Feld | Wert | +|------|------| +| Ingress | ✅ Enabled | +| Ingress traffic | Accepting traffic from anywhere | +| Ingress type | HTTP | +| Target port | 4100 | + +### Scale Tab +| Feld | Wert | +|------|------| +| Min replicas | 0 | +| Max replicas | 3 | + +4. **Review + create** → **Create** + +--- + +## 2. Container App URL kopieren + +Nach dem Deployment: + +1. Gehe zu **Container Apps** → `teams-browser-bot` +2. Im **Overview** Tab findest du die **Application Url** +3. Kopiere die URL, z.B.: `https://teams-browser-bot.niceocean-12345678.switzerlandnorth.azurecontainerapps.io` + +--- + +## 3. GitHub Actions für Auto-Deployment (Optional) + +### 3.1 Service Principal erstellen (Azure Portal) + +1. **Azure Portal** → **Microsoft Entra ID** (früher Azure AD) +2. **App registrations** → **+ New registration** + - Name: `github-teams-browser-bot` + - Supported account types: Single tenant + - **Register** +3. Notiere die **Application (client) ID** und **Directory (tenant) ID** +4. **Certificates & secrets** → **+ New client secret** + - Description: "GitHub Actions" + - Expires: 24 months + - **Add** → Kopiere den **Value** (nur jetzt sichtbar!) + +### 3.2 Service Principal Berechtigung geben + +1. Gehe zu **Resource groups** → `resource-core` +2. **Access control (IAM)** → **+ Add** → **Add role assignment** +3. Role: **Contributor** +4. Members: Select members → Suche `github-teams-browser-bot` → **Select** +5. **Review + assign** + +### 3.3 GitHub Secrets konfigurieren + +1. GitHub Repo → **Settings** → **Secrets and variables** → **Actions** +2. **New repository secret** für jedes: + +| Secret Name | Wert | +|-------------|------| +| AZURE_CLIENT_ID | Application (client) ID | +| AZURE_TENANT_ID | Directory (tenant) ID | +| AZURE_CLIENT_SECRET | Client secret value | +| AZURE_SUBSCRIPTION_ID | Subscription ID* | +| AZURE_RESOURCE_GROUP | resource-core | +| AZURE_CONTAINER_APP_NAME | teams-browser-bot | + +*Subscription ID findest du unter: Subscriptions → Subscription Product → Subscription ID + +--- + +## 4. Gateway Konfiguration + +In **jeder** Gateway-Instanz die **gleiche** Bot URL konfigurieren: + +**env_prod.env:** ``` -TEAMSBOT_BROWSER_BOT_URL=https://teams-browser-bot..azurecontainerapps.io +TEAMSBOT_BROWSER_BOT_URL=https://teams-browser-bot..switzerlandnorth.azurecontainerapps.io ``` **env_int.env:** ``` -TEAMSBOT_BROWSER_BOT_URL=https://teams-browser-bot..azurecontainerapps.io +TEAMSBOT_BROWSER_BOT_URL=https://teams-browser-bot..switzerlandnorth.azurecontainerapps.io ``` -**env_dev.env:** +**env_dev.env (lokal):** ``` -TEAMSBOT_BROWSER_BOT_URL=https://teams-browser-bot..azurecontainerapps.io +TEAMSBOT_BROWSER_BOT_URL=http://localhost:4100 ``` -**Wie es funktioniert:** -1. Gateway sendet Join-Request an Bot mit `gatewayWsUrl` Parameter -2. `gatewayWsUrl` enthält die volle WebSocket-URL zurück zum aufrufenden Gateway -3. Bot verbindet sich zur richtigen Gateway-Instanz (main/int/dev) - -### 3.2 Gateway neu deployen - -```bash -# Push to respective branch triggers deployment -git push origin main # für main -git push origin int # für int -``` +Ersetze `` mit dem tatsächlichen Wert aus Schritt 3. --- -## 4. DNS (Optional) - -Falls du eine eigene Domain verwenden möchtest: - -```bash -az containerapp hostname add \ - --name teams-browser-bot \ - --resource-group rg-poweron-int \ - --hostname bot.poweron.swiss - -# Dann DNS A-Record oder CNAME auf die Container App zeigen -``` - ---- - -## 5. Monitoring - -### Logs anzeigen - -```bash -az containerapp logs show \ - --name teams-browser-bot \ - --resource-group rg-poweron-int \ - --follow -``` - -### Metriken - -```bash -az containerapp show \ - --name teams-browser-bot \ - --resource-group rg-poweron-int \ - --query properties.latestRevisionFqdn -``` - ---- - -## 6. Kosten +## 5. Kosten Azure Container Apps (Consumption Plan): - **vCPU**: ~$0.000024/vCPU-second - **Memory**: ~$0.000003/GiB-second - **Requests**: Erste 2M/Monat kostenlos +- **Scale to zero**: Keine Kosten wenn idle Geschätzte Kosten bei 10h Bot-Nutzung/Tag: -- ~$15-25/Monat (deutlich günstiger als die alte VM!) +- ~$15-25/Monat --- -## 7. Troubleshooting +## 6. Troubleshooting (Azure Portal) + +### Logs anzeigen +1. Container Apps → teams-browser-bot +2. **Monitoring** → **Log stream** (Live-Logs) +3. Oder: **Monitoring** → **Logs** (historisch) ### Container startet nicht +1. **Revisions and replicas** → Klicke auf aktive Revision +2. **Console logs** prüfen +3. Häufige Probleme: + - Image nicht gefunden → Registry credentials prüfen + - Port falsch → Target port = 4100 -```bash -# Logs prüfen -az containerapp logs show \ - --name teams-browser-bot \ - --resource-group rg-poweron-int \ - --type system +### Revision neu starten +1. **Revisions and replicas** +2. Aktive Revision → **...** → **Restart** -# Revision Status -az containerapp revision list \ - --name teams-browser-bot \ - --resource-group rg-poweron-int \ - --output table -``` - -### Playwright/Chrome Probleme - -Container Apps unterstützen keine GPU. Falls Chrome-Probleme: -1. Sicherstellen dass `BOT_HEADLESS=true` -2. Shared memory erhöhen (im Dockerfile bereits konfiguriert) - -### WebSocket Verbindung fehlschlägt - -1. Prüfen ob Gateway CORS erlaubt -2. Prüfen ob Container App WebSockets unterstützt (Standard: ja) -3. Gateway Logs prüfen +### WebSocket Probleme +- Container Apps unterstützen WebSockets standardmässig +- Gateway CORS-Einstellungen prüfen