From ca56b88926936cb45877847af94ab9dc3a9c09bf Mon Sep 17 00:00:00 2001 From: Bill Dengler Date: Fri, 1 Sep 2023 15:37:50 -0700 Subject: [PATCH] fix: Emit a warning when on an unsupported Windows platform (#1759) Some Windows Server versions (Nano Server and Server Core) lack the needed dependencies to run Chrome. This commit adds a check for this case (based on the information in https://github.com/microsoft/accessibility-insights-action/issues/1575#issuecomment-1528353206), displaying a warning in the console when it occurs. Specifically, it checks for the availability of the `Server-Media-Foundation` feature (only available on server editions, not client) with non-installed state. This commit adds a new dependency ([wmi-client](https://www.npmjs.com/package/wmi-client)) to `package.json`. In order to use this package and pass linting, we needed to create a declaration file for its types. This is `packages/ado-extension/src/wmic.d.ts`, which declares the `"wmi-client"` `module` and its `wmic` `class`. Addresses #1575. Co-authored-by: madalynrose --- packages/ado-extension/package.json | 3 +- .../src/install-runtime-dependencies.ts | 24 ++++++++++++ packages/ado-extension/src/wmic.d.ts | 37 +++++++++++++++++++ packages/ado-extension/webpack.config.js | 9 ++++- yarn.lock | 8 ++++ 5 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 packages/ado-extension/src/wmic.d.ts diff --git a/packages/ado-extension/package.json b/packages/ado-extension/package.json index 0c57c0e86..9f78cf1be 100644 --- a/packages/ado-extension/package.json +++ b/packages/ado-extension/package.json @@ -31,7 +31,8 @@ "@accessibility-insights-action/shared": "workspace:*", "applicationinsights": "^2.7.3", "azure-pipelines-task-lib": "^4.5.0", - "reflect-metadata": "^0.1.13" + "reflect-metadata": "^0.1.13", + "wmi-client": "^0.5.0" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^6.5.0", diff --git a/packages/ado-extension/src/install-runtime-dependencies.ts b/packages/ado-extension/src/install-runtime-dependencies.ts index bbe8023d9..e715d403d 100644 --- a/packages/ado-extension/src/install-runtime-dependencies.ts +++ b/packages/ado-extension/src/install-runtime-dependencies.ts @@ -5,6 +5,7 @@ import { execFileSync } from 'child_process'; import { argv } from 'process'; import { readdirSync } from 'fs'; import { join } from 'path'; +import WMIC from 'wmi-client'; export function installRuntimeDependencies(): void { console.log('##[group]Installing runtime dependencies'); @@ -33,5 +34,28 @@ export function installRuntimeDependencies(): void { cwd: __dirname, }); + if (process.platform === 'win32') { + // #1575: Windows Server Core and Nano Server do not have the needed + // dependencies to run Chrome. Try to detect this case and warn + // the user. + interface Feature { + InstallState: number; + Caption: string; + } + const wmi = new WMIC(); + + wmi.query( + `SELECT Caption,InstallState FROM Win32_OptionalFeature WHERE name="ServerMediaFoundation"`, + function (err: string, features: Feature[]) { + const INSTALLSTATE_INSTALLED = 1; + for (const feat of features) { + if (feat['InstallState'] !== INSTALLSTATE_INSTALLED) + console.log( + `##[warning]${feat['Caption']} is not installed! Verify that you are using a supported image (Server Core and Nano Server are not supported).`, + ); + } + }, + ); + } console.log('##[endgroup]'); } diff --git a/packages/ado-extension/src/wmic.d.ts b/packages/ado-extension/src/wmic.d.ts new file mode 100644 index 000000000..b76ba8969 --- /dev/null +++ b/packages/ado-extension/src/wmic.d.ts @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// #1575: This file is used to declare types for the wmi-client module that doesn't have type declarations. +// This module is used in install-runtime-dependencies.ts only on windows clients to check if +// the platform has the necessary dependencies to run Chrome. +declare module 'wmi-client' { + export = wmic; + class wmic { + constructor(options?: WMICOptions); + private _getArgs; + private _getArgsForLinux; + private _getArgsForWindows; + /** + * Prepeare WQL query + * @param wql + * @param namespace + * @param callback + * @returns {wmic} + */ + query(query: string, callback: (err: string, features: Feature[]) => void): wmic; + wql: string; + namespace: string; + private _exec; + private _wql2wmic; + } + + interface WMICOptions { + host: string | null; + username: string; + password: string; + namespace: string; + timeout: number; + wmic: string; + ntlm2: boolean; + cwd: string; + } +} diff --git a/packages/ado-extension/webpack.config.js b/packages/ado-extension/webpack.config.js index 4c5c528f5..e8dc954f0 100644 --- a/packages/ado-extension/webpack.config.js +++ b/packages/ado-extension/webpack.config.js @@ -15,7 +15,14 @@ module.exports = (env) => { ['index']: path.resolve('./src/index.ts'), }, // We special case MPL-licensed dependencies ('axe-core', '@axe-core/puppeteer') because we want to avoid including their source in the same file as non-MPL code. - externals: ['axe-core', 'accessibility-insights-report', 'accessibility-insights-scan', '@types/react', '@types/react-dom'], + externals: [ + 'axe-core', + 'accessibility-insights-report', + 'accessibility-insights-scan', + 'wmi-client', + '@types/react', + '@types/react-dom', + ], mode: 'development', module: { rules: [ diff --git a/yarn.lock b/yarn.lock index 17e665f81..3e0e720f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -42,6 +42,7 @@ __metadata: typescript: ^5.2.2 webpack: ^5.88.2 webpack-cli: ^5.1.4 + wmi-client: ^0.5.0 languageName: unknown linkType: soft @@ -12545,6 +12546,13 @@ __metadata: languageName: node linkType: hard +"wmi-client@npm:^0.5.0": + version: 0.5.0 + resolution: "wmi-client@npm:0.5.0" + checksum: 98b09856bc8948e913ece80be86bf70035cb39b7dff5a110b37eba3ebf029805839528e0013d14ad2424ab6a4af8a73d99ec09410323d8b1dd24c7eb460050d6 + languageName: node + linkType: hard + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": version: 7.0.0 resolution: "wrap-ansi@npm:7.0.0"