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);