diff --git a/packages/ado-npm-auth-lib/src/azureauth/ado.test.ts b/packages/ado-npm-auth-lib/src/azureauth/ado.test.ts index d5409d77..912f4ff8 100644 --- a/packages/ado-npm-auth-lib/src/azureauth/ado.test.ts +++ b/packages/ado-npm-auth-lib/src/azureauth/ado.test.ts @@ -4,6 +4,7 @@ import { exec } from "../utils/exec.js"; import * as utils from "../utils/is-wsl.js"; import type { AdoPatResponse } from "./ado.js"; import { adoPat } from "./ado.js"; +import { clearMemo as clearAuthCommandMemo } from "./azureauth-command.js"; vi.mock("child_process", async () => { return { @@ -28,7 +29,7 @@ vi.mock("../utils/exec.js", async () => { vi.mock("../utils/is-wsl.js", async () => { return { - isWsl: vi.fn(), + isLinux: vi.fn(), }; }); @@ -40,10 +41,11 @@ vi.mock("./is-supported-platform-and-architecture.js", async () => { beforeEach(() => { vi.clearAllMocks(); + clearAuthCommandMemo(); }); test("it should spawn azureauth", async () => { - vi.mocked(utils.isWsl).mockReturnValue(false); + vi.mocked(utils.isLinux).mockReturnValue(false); vi.mocked(exec).mockReturnValue( Promise.resolve({ stdout: '{ "token": "foobarabc123" }', @@ -68,12 +70,12 @@ test("it should spawn azureauth", async () => { expect(results.token).toBe("foobarabc123"); }); -test("it should spawnSync azureauth on wsl", async () => { +test("it should spawnSync azureauth on linux", async () => { vi.mocked(spawnSync).mockReturnValue({ status: 0, stdout: '{ "token": "foobarabc123" }', } as any); - vi.mocked(utils.isWsl).mockReturnValue(true); + vi.mocked(utils.isLinux).mockReturnValue(true); const results = (await adoPat({ promptHint: "hint", @@ -86,13 +88,8 @@ test("it should spawnSync azureauth on wsl", async () => { })) as AdoPatResponse; expect(spawnSync).toHaveBeenCalledWith( - "npm", + "azureauth", [ - "exec", - "--silent", - "--yes", - "azureauth", - "--", "ado", "pat", "--prompt-hint hint", @@ -108,8 +105,8 @@ test("it should spawnSync azureauth on wsl", async () => { expect(results.token).toBe("foobarabc123"); }); -test("it should handle errors on wsl if azureauth exit code is not 0", async () => { - vi.mocked(utils.isWsl).mockReturnValue(true); +test("it should handle errors on linux if azureauth exit code is not 0", async () => { + vi.mocked(utils.isLinux).mockReturnValue(true); vi.mocked(spawnSync).mockReturnValue({ status: 1, stdout: "", @@ -131,8 +128,8 @@ test("it should handle errors on wsl if azureauth exit code is not 0", async () ); }); -test("it should handle errors on wsl if azureauth has stderr output", async () => { - vi.mocked(utils.isWsl).mockReturnValue(true); +test("it should handle errors on linux if azureauth has stderr output", async () => { + vi.mocked(utils.isLinux).mockReturnValue(true); vi.mocked(spawnSync).mockReturnValue({ status: 0, stdout: "", @@ -155,7 +152,7 @@ test("it should handle errors on wsl if azureauth has stderr output", async () = }); test("it should handle json errors", async () => { - vi.mocked(utils.isWsl).mockReturnValue(false); + vi.mocked(utils.isLinux).mockReturnValue(false); vi.mocked(exec).mockReturnValue( Promise.resolve({ stdout: "an error", @@ -177,7 +174,7 @@ test("it should handle json errors", async () => { }); test("it should handle errors from azureauth-cli", async () => { - vi.mocked(utils.isWsl).mockReturnValue(false); + vi.mocked(utils.isLinux).mockReturnValue(false); vi.mocked(exec).mockReturnValue( Promise.resolve({ stdout: "", diff --git a/packages/ado-npm-auth-lib/src/azureauth/ado.ts b/packages/ado-npm-auth-lib/src/azureauth/ado.ts index c8120cd6..93e72a1e 100644 --- a/packages/ado-npm-auth-lib/src/azureauth/ado.ts +++ b/packages/ado-npm-auth-lib/src/azureauth/ado.ts @@ -3,7 +3,7 @@ import { spawnSync } from "node:child_process"; import { exec } from "../utils/exec.js"; import { isSupportedPlatformAndArchitecture } from "./is-supported-platform-and-architecture.js"; import { azureAuthCommand } from "./azureauth-command.js"; -import { isWsl } from "../utils/is-wsl.js"; +import { isLinux } from "../utils/is-wsl.js"; import { isAzureAuthInstalled } from "./is-azureauth-installed.js"; export type AdoPatOptions = { @@ -53,7 +53,7 @@ export const adoPat = async ( ...authCommand, `ado`, `pat`, - `--prompt-hint ${isWsl() ? options.promptHint : `"${options.promptHint}"`}`, // We only use spawn for WSL. spawn does not does not require prompt hint to be wrapped in quotes. exec does. + `--prompt-hint ${isLinux() ? options.promptHint : `"${options.promptHint}"`}`, // We only use spawn for Linux (includes WSL). spawn does not require prompt hint to be wrapped in quotes. exec does. `--organization ${options.organization}`, `--display-name ${options.displayName}`, ...options.scope.map((scope) => `--scope ${scope}`), @@ -77,7 +77,7 @@ export const adoPat = async ( try { let result; - if (isWsl()) { + if (isLinux()) { try { result = spawnSync(command[0], command.slice(1), { encoding: "utf-8" }); diff --git a/packages/ado-npm-auth-lib/src/azureauth/azureauth-command.ts b/packages/ado-npm-auth-lib/src/azureauth/azureauth-command.ts index f4a6a464..f17e2b07 100644 --- a/packages/ado-npm-auth-lib/src/azureauth/azureauth-command.ts +++ b/packages/ado-npm-auth-lib/src/azureauth/azureauth-command.ts @@ -1,4 +1,4 @@ -import { isWsl } from "../utils/is-wsl.js"; +import { isLinux } from "../utils/is-wsl.js"; let memo: string[] | undefined = undefined; @@ -30,7 +30,7 @@ export const azureAuthCommand = (): { env: Record; } => { if (!memo) { - memo = isWsl() ? ["azureauth.exe"] : npxAzureAuthCommand; + memo = isLinux() ? ["azureauth"] : npxAzureAuthCommand; } return { command: memo, env: npxEnv }; diff --git a/packages/ado-npm-auth-lib/src/azureauth/is-azureauth-installed.test.ts b/packages/ado-npm-auth-lib/src/azureauth/is-azureauth-installed.test.ts index 9cc90e0f..e730fe96 100644 --- a/packages/ado-npm-auth-lib/src/azureauth/is-azureauth-installed.test.ts +++ b/packages/ado-npm-auth-lib/src/azureauth/is-azureauth-installed.test.ts @@ -6,7 +6,7 @@ import * as utils from "../utils/is-wsl.js"; vi.mock("../utils/is-wsl.js", async () => { return { - isWsl: vi.fn(), + isLinux: vi.fn(), }; }); @@ -29,7 +29,7 @@ test("when azure auth is not installed", async () => { stderr: "", }) as any, ); - vi.mocked(utils.isWsl).mockReturnValue(false); + vi.mocked(utils.isLinux).mockReturnValue(false); const azureAuthInstalled = await isAzureAuthInstalled(); @@ -45,7 +45,7 @@ test("when azure auth is installed", async () => { stderr: "", }) as any, ); - vi.mocked(utils.isWsl).mockReturnValue(false); + vi.mocked(utils.isLinux).mockReturnValue(false); const azureAuthInstalled = await isAzureAuthInstalled(); @@ -54,19 +54,19 @@ test("when azure auth is installed", async () => { expect(azureAuthInstalled).toBe(true); }); -test("when azure auth is installed on windows", async () => { +test("when azure auth is installed on linux", async () => { vi.mocked(exec).mockReturnValue( Promise.resolve({ stdout: "0.8.5", stderr: "", }) as any, ); - vi.mocked(utils.isWsl).mockReturnValue(true); + vi.mocked(utils.isLinux).mockReturnValue(true); const azureAuthInstalled = await isAzureAuthInstalled(); expect(vi.mocked(exec)).toBeCalled(); - expect(vi.mocked(exec)).toBeCalledWith("azureauth.exe --version", { + expect(vi.mocked(exec)).toBeCalledWith("azureauth --version", { env: expect.any(Object), }); diff --git a/packages/ado-npm-auth-lib/src/azureauth/is-supported-platform-and-architecture.ts b/packages/ado-npm-auth-lib/src/azureauth/is-supported-platform-and-architecture.ts index 54c8557d..2cc09554 100644 --- a/packages/ado-npm-auth-lib/src/azureauth/is-supported-platform-and-architecture.ts +++ b/packages/ado-npm-auth-lib/src/azureauth/is-supported-platform-and-architecture.ts @@ -1,19 +1,18 @@ import { arch, platform } from "node:os"; -import { isWsl } from "../utils/is-wsl.js"; /** - * Determines if the currently running platform is supported by azureauth. Currently, supported platforms are Windows, Mac & WSL + * Determines if the currently running platform is supported by azureauth. Currently, supported platforms are Windows, Mac & Linux (includes WSL) * @returns { boolean } if the current platform is supported by azureauth */ export const isSupportedPlatformAndArchitecture = (): boolean => { const supportedPlatformsAndArchitectures: Record = { win32: ["x64"], darwin: ["x64", "arm64"], + linux: ["x64", "arm64"], }; return ( - isWsl() || - (supportedPlatformsAndArchitectures[platform()] && - supportedPlatformsAndArchitectures[platform()].includes(arch())) + supportedPlatformsAndArchitectures[platform()] !== undefined && + supportedPlatformsAndArchitectures[platform()].includes(arch()) ); }; diff --git a/packages/ado-npm-auth-lib/src/utils/is-wsl.ts b/packages/ado-npm-auth-lib/src/utils/is-wsl.ts index c7636113..057f569a 100644 --- a/packages/ado-npm-auth-lib/src/utils/is-wsl.ts +++ b/packages/ado-npm-auth-lib/src/utils/is-wsl.ts @@ -7,3 +7,11 @@ import { release, platform } from "node:os"; export const isWsl = () => { return platform() === "linux" && release().toLowerCase().includes("wsl"); }; + +/** + * Determine if the current machine's platform is Linux (includes WSL) + * @returns { boolean } if the current platform is Linux + */ +export const isLinux = () => { + return platform() === "linux"; +}; diff --git a/packages/node-azureauth/src/install.ts b/packages/node-azureauth/src/install.ts index 54e27843..b65d192b 100644 --- a/packages/node-azureauth/src/install.ts +++ b/packages/node-azureauth/src/install.ts @@ -4,7 +4,7 @@ import fs from "node:fs"; import { DownloaderHelper } from "node-downloader-helper"; import decompress from "decompress"; -const AZURE_AUTH_VERSION = "0.8.4"; +const AZURE_AUTH_VERSION = "0.9.4"; async function download(url: string, saveDirectory: string): Promise { const downloader = new DownloaderHelper(url, saveDirectory); @@ -29,7 +29,7 @@ const AZUREAUTH_INFO = { name: "azureauth", // https://github.com/AzureAD/microsoft-authentication-cli/releases/download/${AZUREAUTH_INFO.version}/azureauth-${AZUREAUTH_INFO.version}-osx-arm64.tar.gz // https://github.com/AzureAD/microsoft-authentication-cli/releases/download/${AZUREAUTH_INFO.version}/azureauth-${AZUREAUTH_INFO.version}-osx-x64.tar.gz - // https://github.com/AzureAD/microsoft-authentication-cli/releases/download/${AZUREAUTH_INFO.version}/azureauth-${AZUREAUTH_INFO.version}-win10-x64.zip + // https://github.com/AzureAD/microsoft-authentication-cli/releases/download/${AZUREAUTH_INFO.version}/azureauth-${AZUREAUTH_INFO.version}-win-x64.zip url: "https://github.com/AzureAD/microsoft-authentication-cli/releases/download/", version: AZURE_AUTH_VERSION, }; @@ -37,7 +37,6 @@ const AZUREAUTH_INFO = { const AZUREAUTH_NAME_MAP: any = { def: "azureauth", win32: "azureauth.exe", - linux: "azureauth.exe", }; export const AZUREAUTH_NAME = @@ -67,17 +66,15 @@ export const install = async () => { // if platform is missing, download source instead of executable const DOWNLOAD_MAP: any = { win32: { - x64: `azureauth-${AZUREAUTH_INFO.version}-win10-x64.zip`, + x64: `azureauth-${AZUREAUTH_INFO.version}-win-x64.zip`, }, darwin: { x64: `azureauth-${AZUREAUTH_INFO.version}-osx-x64.tar.gz`, arm64: `azureauth-${AZUREAUTH_INFO.version}-osx-arm64.tar.gz`, }, - // TODO: support linux when the binaries are available - // linux: { - // def: "azureauth.exe", - // x64: "azureauth-${AZUREAUTH_INFO.version}-win10-x64.zip", - // }, + // Linux releases are distributed as .deb packages which require system-level + // installation (e.g. dpkg) rather than simple archive extraction. Linux users + // should install azureauth via the .deb package and ensure it is in PATH. }; if (platform in DOWNLOAD_MAP) { // download the executable