From 6eba27d882d4964c223e2274ddd726ec56a49039 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 24 May 2024 23:27:00 +0200 Subject: [PATCH] chore: Improve the error message about download servers unavailability (#399) --- install-npm.js | 9 +++-- lib/storage-client/storage-client.js | 53 ++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/install-npm.js b/install-npm.js index 95e8b11c..8c508b85 100755 --- a/install-npm.js +++ b/install-npm.js @@ -36,9 +36,14 @@ async function main() { `The Chromedriver install script cannot be found at '${BUILD_PATH}'. ` + `Building appium-chromedriver package` ); - const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm'; + const isWindows = process.platform === 'win32'; + const npmCommand = `npm${isWindows ? '.cmd' : ''}`; try { - await exec(npmCommand, ['run', 'build'], {logger: log, cwd: __dirname}); + await exec(npmCommand, ['run', 'build'], { + logger: log, + cwd: __dirname, + shell: isWindows, + }); } catch (e) { throw new Error(`appium-chromedriver package cannot be built: ${util.inspect(e)}`); } diff --git a/lib/storage-client/storage-client.js b/lib/storage-client/storage-client.js index 7c25eafd..da36ba66 100644 --- a/lib/storage-client/storage-client.js +++ b/lib/storage-client/storage-client.js @@ -24,6 +24,13 @@ import {compareVersions} from 'compare-versions'; import semver from 'semver'; const MAX_PARALLEL_DOWNLOADS = 5; +const STORAGE_INFOS = /** @type {readonly StorageInfo[]} */ ([{ + url: GOOGLEAPIS_CDN, + accept: 'application/xml', +}, { + url: `${CHROMELABS_URL}/chrome-for-testing/known-good-versions-with-downloads.json`, + accept: 'application/json', +}]); const log = logger.getLogger('ChromedriverStorageClient'); @@ -60,19 +67,37 @@ export class ChromedriverStorageClient { * @returns {Promise} */ async retrieveMapping(shouldParseNotes = true) { - const [xmlStr, jsonStr] = await B.all([ - [GOOGLEAPIS_CDN, 'application/xml'], - [`${CHROMELABS_URL}/chrome-for-testing/known-good-versions-with-downloads.json`, 'application/json'], - ] - .map(([url, contentType]) => url - ? retrieveData(url, { + /** @type {(si: StorageInfo) => Promise} */ + const retrieveResponseSafely = async (/** @type {StorageInfo} */ {url, accept}) => { + try { + return await retrieveData(url, { 'user-agent': USER_AGENT, - accept: `${contentType}, */*`, - }, {timeout: this.timeout}) - : B.resolve() - )); + accept: `${accept}, */*`, + }, {timeout: this.timeout}); + } catch (e) { + log.debug(/** @type {Error} */(e).stack); + log.warn( + `Cannot retrieve Chromedrivers info from ${url}. ` + + `Make sure this URL is accessible from your network. ` + + `Original error: ${/** @type {Error} */(e).message}` + ); + } + }; + const [xmlStr, jsonStr] = await B.all(STORAGE_INFOS.map(retrieveResponseSafely)); + // Apply the best effort approach and fetch the mapping from at least one server if possible. + // We'll fail later anyway if the target chromedriver version is not there. + if (!xmlStr && !jsonStr) { + throw new Error( + `Cannot retrieve the information about available Chromedrivers from ` + + `${STORAGE_INFOS.map(({url}) => url)}. Please make sure these URLs are avilable ` + + `within your local network, check Appium server logs and/or ` + + `consult the driver troubleshooting guide.` + ); + } this.mapping = xmlStr ? await parseGoogleapiStorageXml(xmlStr, shouldParseNotes) : {}; - Object.assign(this.mapping, parseKnownGoodVersionsWithDownloadsJson(jsonStr)); + if (jsonStr) { + Object.assign(this.mapping, parseKnownGoodVersionsWithDownloadsJson(jsonStr)); + } return this.mapping; } @@ -392,3 +417,9 @@ export default ChromedriverStorageClient; * @typedef {import('../types').ChromedriverDetails} ChromedriverDetails * @typedef {import('../types').ChromedriverDetailsMapping} ChromedriverDetailsMapping */ + +/** + * @typedef {Object} StorageInfo + * @property {string} url + * @property {string} accept + */