From e4eee9fb0da6e77300495a01c51fc7f38b2bd7fc Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Tue, 17 Feb 2026 16:33:07 +0100 Subject: [PATCH] fix: per-variant API to avoid Azure 240s timeout Co-authored-by: Cursor --- .github/workflows/build-deploy.yml | 4 --- src/bot/authTestProcedure.ts | 41 +++++++++++++++++++++++++++--- src/server/httpServer.ts | 31 ++++++++++++++++++---- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-deploy.yml b/.github/workflows/build-deploy.yml index 7d86a02..ad3924b 100644 --- a/.github/workflows/build-deploy.yml +++ b/.github/workflows/build-deploy.yml @@ -49,10 +49,6 @@ jobs: --name ${{ env.CONTAINER_APP_NAME }} \ --resource-group ${{ env.RESOURCE_GROUP }} \ --image ${{ secrets.ACR_LOGIN_SERVER }}/${{ env.IMAGE_NAME }}:${{ github.sha }} - az containerapp ingress update \ - --name ${{ env.CONTAINER_APP_NAME }} \ - --resource-group ${{ env.RESOURCE_GROUP }} \ - --request-timeout 900 - name: Summary run: | diff --git a/src/bot/authTestProcedure.ts b/src/bot/authTestProcedure.ts index 3555e99..c3a76f3 100644 --- a/src/bot/authTestProcedure.ts +++ b/src/bot/authTestProcedure.ts @@ -112,15 +112,50 @@ const _BROWSER_ARGS_MINIMAL = [ // ============================================================================ /** - * Run auth tests: 5 browser configs, all running the "Join a meeting" flow. - * Each variant: MS login → Teams landing page → "Join a meeting" → enter meeting ID + passcode → Join → screenshot. + * Return the list of available variant IDs for the frontend to iterate over. + */ +export function getVariantIds(): { id: string; name: string; description: string }[] { + return _VARIANTS.map(v => ({ id: v.id, name: v.name, description: v.description })); +} + +/** + * Run a SINGLE variant by ID. Called once per variant to stay within Azure's 240s timeout. + */ +export async function runSingleVariant( + variantId: string, + meetingUrl: string, + botAccountEmail?: string, + botAccountPassword?: string, +): Promise { + const variant = _VARIANTS.find(v => v.id === variantId); + if (!variant) { + throw new Error(`Unknown variant ID: ${variantId}`); + } + + if (!botAccountEmail || !botAccountPassword) { + return _createSkippedResult(variant, 'Keine Credentials angegeben'); + } + + logger.info(`[AuthTest] Running single variant: ${variant.name}`); + try { + const result = await _runVariant(variant, meetingUrl, botAccountEmail, botAccountPassword); + logger.info(`[AuthTest] Variant ${variant.name}: finalUrl=${result.finalUrl.substring(0, 80)}`); + return result; + } catch (err) { + logger.error(`[AuthTest] Variant ${variant.name} failed:`, err); + return _createErrorResult(variant, String(err)); + } +} + +/** + * Run ALL variants sequentially (legacy — may timeout on Azure). */ export async function runAuthTests( meetingUrl: string, botAccountEmail?: string, botAccountPassword?: string, ): Promise { - logger.info(`[AuthTest] Starting auth tests for: ${meetingUrl} (email=${!!botAccountEmail})`); + logger.info(`[AuthTest] Starting all auth tests for: ${meetingUrl} (email=${!!botAccountEmail})`); const results: AuthTestResult[] = []; diff --git a/src/server/httpServer.ts b/src/server/httpServer.ts index 1eafb73..818e36d 100644 --- a/src/server/httpServer.ts +++ b/src/server/httpServer.ts @@ -2,7 +2,7 @@ import express, { Express, Request, Response } from 'express'; import { Server } from 'http'; import { logger } from '../utils/logger'; import { config } from '../config'; -import { runAuthTests } from '../bot/authTestProcedure'; +import { runAuthTests, runSingleVariant, getVariantIds } from '../bot/authTestProcedure'; export interface HttpServerCallbacks { onJoinRequest: (sessionId: string, meetingUrl: string, botName?: string, instanceId?: string, gatewayWsUrl?: string, language?: string, botAccountEmail?: string, botAccountPassword?: string, backgroundImageUrl?: string) => Promise; @@ -138,7 +138,31 @@ export class HttpServer { res.json({ message: 'Not implemented' }); }); - // Run auth detection tests against a Teams meeting URL + // Get list of available test variants + this._app.get('/api/bot/test-auth/variants', (_req: Request, res: Response) => { + res.json(getVariantIds()); + }); + + // Run a SINGLE test variant (stays within Azure 240s timeout) + this._app.post('/api/bot/test-auth/variant', async (req: Request, res: Response) => { + try { + const { variantId, meetingUrl, botAccountEmail, botAccountPassword } = req.body; + + if (!meetingUrl || !variantId) { + res.status(400).json({ error: 'Missing required fields: variantId, meetingUrl' }); + return; + } + + logger.info(`Running single auth test variant: ${variantId} for ${meetingUrl}`); + const result = await runSingleVariant(variantId, meetingUrl, botAccountEmail, botAccountPassword); + res.json(result); + } catch (error) { + logger.error('Error running single variant:', error); + res.status(500).json({ error: (error as Error).message }); + } + }); + + // Run ALL auth detection tests (legacy — may timeout on Azure with many variants) this._app.post('/api/bot/test-auth', async (req: Request, res: Response) => { try { const { meetingUrl, botAccountEmail, botAccountPassword } = req.body; @@ -153,10 +177,7 @@ export class HttpServer { logger.info(`Starting auth detection tests for: ${meetingUrl} (credentials: email=${hasEmail}, password=${hasPassword})`); const results = await runAuthTests(meetingUrl, botAccountEmail, botAccountPassword); - - // Attach credential debug info so UI can show it (results as any).credentialsReceived = { hasEmail, hasPassword }; - res.json(results); } catch (error) { logger.error('Error running auth tests:', error);