From e5999c731667ffc1cdf1013557eb5cbc83ea5b39 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 25 Jul 2026 08:33:05 -0700 Subject: [PATCH] fix(microsoft-foundry): honor Azure device-code lifetime (#113741) * fix(microsoft-foundry): honor device-code lifetime Co-authored-by: wangmiao0668000666 * fix(microsoft-foundry): allow login completion grace --------- Co-authored-by: wangmiao0668000666 --- extensions/microsoft-foundry/cli.ts | 5 +++-- extensions/microsoft-foundry/index.test.ts | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/extensions/microsoft-foundry/cli.ts b/extensions/microsoft-foundry/cli.ts index 638247d28d8e..89859b4deb9d 100644 --- a/extensions/microsoft-foundry/cli.ts +++ b/extensions/microsoft-foundry/cli.ts @@ -144,7 +144,8 @@ export async function getAccessTokenResultAsync( ) as AzAccessToken; } -const AZ_LOGIN_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes +// Entra device codes default to 15 minutes; keep five minutes for az to finish. +const AZ_LOGIN_TIMEOUT_MS = 20 * 60 * 1000; export async function azLoginDeviceCode(): Promise { return azLoginDeviceCodeWithOptions({}); @@ -188,7 +189,7 @@ export async function azLoginDeviceCodeWithOptions(params: { appendOutput("stdout", decoders.stdout.end()); appendOutput("stderr", decoders.stderr.end()); if (result.termination === "timeout") { - throw new Error("az login timed out after 5 minutes"); + throw new Error("az login timed out after 20 minutes"); } if (result.code === 0) { return; diff --git a/extensions/microsoft-foundry/index.test.ts b/extensions/microsoft-foundry/index.test.ts index 0b6da87d0edf..636cc7f71ac8 100644 --- a/extensions/microsoft-foundry/index.test.ts +++ b/extensions/microsoft-foundry/index.test.ts @@ -2107,7 +2107,7 @@ describe("azLoginDeviceCodeWithOptions utf-8 chunk boundary", () => { expect(stderrWriteSpy).toHaveBeenCalledWith("😊"); }); - it("requests process-tree termination and rejects when az login exceeds 5 minutes", async () => { + it("allows post-auth work after the 15-minute device-code lifetime", async () => { runCommandWithTimeoutMock.mockResolvedValueOnce({ stdout: "", stderr: "", @@ -2120,13 +2120,13 @@ describe("azLoginDeviceCodeWithOptions utf-8 chunk boundary", () => { const err = await azLoginDeviceCodeWithOptions({}).catch((e: unknown) => e); expect(err).toBeInstanceOf(Error); - expect((err as Error).message).toBe("az login timed out after 5 minutes"); + expect((err as Error).message).toBe("az login timed out after 20 minutes"); expect(runCommandWithTimeoutMock).toHaveBeenCalledWith( ["az", "login", "--use-device-code"], expect.objectContaining({ killProcessTree: true, outputCapture: "discard", - timeoutMs: 5 * 60 * 1000, + timeoutMs: 20 * 60 * 1000, }), ); });