Comparing version 9.5.1 to 9.5.2
@@ -21,3 +21,4 @@ "use strict"; | ||
const p = chalk.cyan; // urls | ||
const p = chalk.cyan; | ||
const red = chalk.red; // urls | ||
@@ -54,50 +55,61 @@ const link = chalk.blue.underline; // to be exported | ||
methods.start = (options = {}) => { | ||
methods.start = async (options = {}) => { | ||
const args = ['--mode=info']; | ||
return spawn.start(args, { | ||
await spawn.start(args, { | ||
dev: options.dev | ||
}).then(() => { | ||
}); | ||
console.log(); | ||
const proxyVars = methods.findProxyEnvironmentVariables(); | ||
if (_.isEmpty(proxyVars)) { | ||
console.log('Proxy Settings: none detected'); | ||
} else { | ||
console.log('Proxy Settings:'); | ||
_.forEach(proxyVars, (value, key) => { | ||
console.log('%s: %s', key, g(value)); | ||
}); | ||
console.log(); | ||
const proxyVars = methods.findProxyEnvironmentVariables(); | ||
console.log('Learn More: %s', link('https://on.cypress.io/proxy-configuration')); | ||
console.log(); | ||
} | ||
if (_.isEmpty(proxyVars)) { | ||
console.log('Proxy Settings: none detected'); | ||
} else { | ||
console.log('Proxy Settings:'); | ||
const cyVars = formatCypressVariables(); | ||
_.forEach(proxyVars, (value, key) => { | ||
console.log('%s: %s', key, g(value)); | ||
}); | ||
if (_.isEmpty(cyVars)) { | ||
console.log('Environment Variables: none detected'); | ||
} else { | ||
console.log('Environment Variables:'); | ||
console.log(); | ||
console.log('Learn More: %s', link('https://on.cypress.io/proxy-configuration')); | ||
console.log(); | ||
} | ||
}).then(() => { | ||
const cyVars = formatCypressVariables(); | ||
_.forEach(cyVars, (value, key) => { | ||
console.log('%s: %s', key, g(value)); | ||
}); | ||
} | ||
if (_.isEmpty(cyVars)) { | ||
console.log('Environment Variables: none detected'); | ||
} else { | ||
console.log('Environment Variables:'); | ||
console.log(); | ||
console.log('Application Data:', p(util.getApplicationDataFolder())); | ||
console.log('Browser Profiles:', p(util.getApplicationDataFolder('browsers'))); | ||
console.log('Binary Caches: %s', p(state.getCacheDir())); | ||
console.log(); | ||
const osVersion = await util.getOsVersionAsync(); | ||
const buildInfo = util.pkgBuildInfo(); | ||
const isStable = buildInfo && buildInfo.stable; | ||
console.log('Cypress Version: %s', g(util.pkgVersion()), isStable ? g('(stable)') : red('(pre-release)')); | ||
console.log('System Platform: %s (%s)', g(os.platform()), g(osVersion)); | ||
console.log('System Memory: %s free %s', g(prettyBytes(os.totalmem())), g(prettyBytes(os.freemem()))); | ||
_.forEach(cyVars, (value, key) => { | ||
console.log('%s: %s', key, g(value)); | ||
}); | ||
} | ||
}).then(() => { | ||
if (!buildInfo) { | ||
console.log(); | ||
console.log('Application Data:', p(util.getApplicationDataFolder())); | ||
console.log('Browser Profiles:', p(util.getApplicationDataFolder('browsers'))); | ||
console.log('Binary Caches: %s', p(state.getCacheDir())); | ||
}).then(() => { | ||
console.log('This is the', red('development'), '(un-built) Cypress CLI.'); | ||
} else if (!isStable) { | ||
console.log(); | ||
return util.getOsVersionAsync().then(osVersion => { | ||
console.log('Cypress Version: %s', g(util.pkgVersion())); | ||
console.log('System Platform: %s (%s)', g(os.platform()), g(osVersion)); | ||
console.log('System Memory: %s free %s', g(prettyBytes(os.totalmem())), g(prettyBytes(os.freemem()))); | ||
}); | ||
}); | ||
console.log('This is a', red('pre-release'), 'build of Cypress.'); | ||
console.log('Build info:'); | ||
console.log(' Commit SHA:', g(buildInfo.commitSha)); | ||
console.log(' Commit Branch:', g(buildInfo.commitBranch)); | ||
console.log(' Commit Date:', g(buildInfo.commitDate)); | ||
} | ||
}; | ||
module.exports = methods; |
@@ -46,4 +46,7 @@ "use strict"; | ||
}).then(binaryVersions => { | ||
const buildInfo = util.pkgBuildInfo(); | ||
let packageVersion = util.pkgVersion(); | ||
if (!buildInfo) packageVersion += ' (development)';else if (!buildInfo.stable) packageVersion += ' (pre-release)'; | ||
const versions = { | ||
package: util.pkgVersion(), | ||
package: packageVersion, | ||
binary: binaryVersions.binary || 'not installed', | ||
@@ -50,0 +53,0 @@ electronVersion: binaryVersions.electronVersion || 'not found', |
@@ -9,4 +9,2 @@ "use strict"; | ||
const url = require('url'); | ||
const path = require('path'); | ||
@@ -49,92 +47,14 @@ | ||
const getNpmArgv = () => { | ||
const json = process.env.npm_config_argv; | ||
const { | ||
buildInfo, | ||
version | ||
} = require('../../package.json'); | ||
if (!json) { | ||
return; | ||
} | ||
function _getBinaryUrlFromBuildInfo({ | ||
commitSha, | ||
commitBranch | ||
}) { | ||
return `https://cdn.cypress.io/beta/binary/${version}/${os.platform()}-${arch()}/${commitBranch}-${commitSha}/cypress.zip`; | ||
} | ||
debug('found npm argv json %o', json); | ||
try { | ||
return JSON.parse(json).original || []; | ||
} catch (e) { | ||
return []; | ||
} | ||
}; // attempt to discover the version specifier used to install Cypress | ||
// for example: "^5.0.0", "https://cdn.cypress.io/...", ... | ||
const getVersionSpecifier = (startDir = path.resolve(__dirname, '../..')) => { | ||
const argv = getNpmArgv(); | ||
if ((process.env.npm_package_resolved || '').endsWith('cypress.tgz')) { | ||
return process.env.npm_package_resolved; | ||
} | ||
if (argv) { | ||
const tgz = _.find(argv, t => t.endsWith('cypress.tgz')); | ||
if (tgz) { | ||
return tgz; | ||
} | ||
} | ||
const getVersionSpecifierFromPkg = dir => { | ||
debug('looking for versionSpecifier %o', { | ||
dir | ||
}); | ||
const tryParent = () => { | ||
const parentPath = path.resolve(dir, '..'); | ||
if (parentPath === dir) { | ||
debug('reached FS root with no versionSpecifier found'); | ||
return; | ||
} | ||
return getVersionSpecifierFromPkg(parentPath); | ||
}; | ||
return fs.readJSON(path.join(dir, 'package.json')).catch(() => ({})).then(pkg => { | ||
const specifier = _.chain(['dependencies', 'devDependencies', 'optionalDependencies']).map(prop => _.get(pkg, `${prop}.cypress`)).compact().first().value(); | ||
return specifier || tryParent(); | ||
}); | ||
}; // recurse through parent directories until package.json with `cypress` is found | ||
return getVersionSpecifierFromPkg(startDir).then(versionSpecifier => { | ||
debug('finished looking for versionSpecifier', { | ||
versionSpecifier | ||
}); | ||
return versionSpecifier; | ||
}); | ||
}; | ||
const betaNpmUrlRe = /^\/beta\/npm\/(?<version>[0-9.]+)\/(?<platformSlug>.+?)\/(?<artifactSlug>.+?)\/cypress\.tgz$/; // convert a prerelease NPM package .tgz URL to the corresponding binary .zip URL | ||
const getBinaryUrlFromPrereleaseNpmUrl = npmUrl => { | ||
let parsed; | ||
try { | ||
parsed = url.parse(npmUrl); | ||
} catch (e) { | ||
return; | ||
} | ||
const matches = betaNpmUrlRe.exec(parsed.pathname); | ||
if (parsed.hostname !== 'cdn.cypress.io' || !matches) { | ||
return; | ||
} | ||
const { | ||
version, | ||
artifactSlug | ||
} = matches.groups; | ||
parsed.pathname = `/beta/binary/${version}/${os.platform()}-${arch()}/${artifactSlug}/cypress.zip`; | ||
return parsed.format(); | ||
}; | ||
const alreadyInstalledMsg = () => { | ||
@@ -242,33 +162,60 @@ if (!util.isPostInstall()) { | ||
}; | ||
/** | ||
* Returns the version to install - either a string like `1.2.3` to be fetched | ||
* from the download server or a file path or HTTP URL. | ||
*/ | ||
const start = (options = {}) => { | ||
debug('installing with options %j', options); | ||
_.defaults(options, { | ||
force: false | ||
}); | ||
function getVersionOverride({ | ||
envVarVersion, | ||
buildInfo | ||
}) { | ||
// let this environment variable reset the binary version we need | ||
if (envVarVersion) { | ||
return envVarVersion; | ||
} | ||
const pkgVersion = util.pkgVersion(); | ||
let needVersion = pkgVersion; | ||
let binaryUrlOverride; | ||
debug('version in package.json is', needVersion); // let this environment variable reset the binary version we need | ||
if (buildInfo && !buildInfo.stable) { | ||
logger.log(chalk.yellow(stripIndent` | ||
${logSymbols.warning} Warning: You are installing a pre-release build of Cypress. | ||
if (util.getEnv('CYPRESS_INSTALL_BINARY')) { | ||
// because passed file paths are often double quoted | ||
// and might have extra whitespace around, be robust and trim the string | ||
const trimAndRemoveDoubleQuotes = true; | ||
const envVarVersion = util.getEnv('CYPRESS_INSTALL_BINARY', trimAndRemoveDoubleQuotes); | ||
debug('using environment variable CYPRESS_INSTALL_BINARY "%s"', envVarVersion); | ||
Bugs may be present which do not exist in production builds. | ||
if (envVarVersion === '0') { | ||
debug('environment variable CYPRESS_INSTALL_BINARY = 0, skipping install'); | ||
logger.log(stripIndent` | ||
This build was created from: | ||
* Commit SHA: ${buildInfo.commitSha} | ||
* Commit Branch: ${buildInfo.commitBranch} | ||
* Commit Timestamp: ${buildInfo.commitDate} | ||
`)); | ||
logger.log(); | ||
return _getBinaryUrlFromBuildInfo(buildInfo); | ||
} | ||
} | ||
function getEnvVarVersion() { | ||
if (!util.getEnv('CYPRESS_INSTALL_BINARY')) return; // because passed file paths are often double quoted | ||
// and might have extra whitespace around, be robust and trim the string | ||
const trimAndRemoveDoubleQuotes = true; | ||
const envVarVersion = util.getEnv('CYPRESS_INSTALL_BINARY', trimAndRemoveDoubleQuotes); | ||
debug('using environment variable CYPRESS_INSTALL_BINARY "%s"', envVarVersion); | ||
return envVarVersion; | ||
} | ||
const start = async (options = {}) => { | ||
debug('installing with options %j', options); | ||
const envVarVersion = getEnvVarVersion(); | ||
if (envVarVersion === '0') { | ||
debug('environment variable CYPRESS_INSTALL_BINARY = 0, skipping install'); | ||
logger.log(stripIndent` | ||
${chalk.yellow('Note:')} Skipping binary installation: Environment variable CYPRESS_INSTALL_BINARY = 0.`); | ||
logger.log(); | ||
return Promise.resolve(); | ||
} | ||
binaryUrlOverride = envVarVersion; | ||
logger.log(); | ||
return; | ||
} | ||
_.defaults(options, { | ||
force: false, | ||
buildInfo | ||
}); | ||
if (util.getEnv('CYPRESS_CACHE_FOLDER')) { | ||
@@ -284,12 +231,18 @@ const envCache = util.getEnv('CYPRESS_CACHE_FOLDER'); | ||
const installDir = state.getVersionDir(pkgVersion); | ||
const pkgVersion = util.pkgVersion(); | ||
const versionOverride = getVersionOverride({ | ||
envVarVersion, | ||
buildInfo: options.buildInfo | ||
}); | ||
const versionToInstall = versionOverride || pkgVersion; | ||
debug('version in package.json is %s, version to install is %s', pkgVersion, versionToInstall); | ||
const installDir = state.getVersionDir(pkgVersion, options.buildInfo); | ||
const cacheDir = state.getCacheDir(); | ||
const binaryDir = state.getBinaryDir(pkgVersion); | ||
return validateOS().then(isValid => { | ||
if (!isValid) { | ||
return throwFormErrorText(errors.invalidOS)(); | ||
} | ||
}).then(() => { | ||
return fs.ensureDirAsync(cacheDir); | ||
}).catch({ | ||
if (!(await validateOS())) { | ||
return throwFormErrorText(errors.invalidOS)(); | ||
} | ||
await fs.ensureDirAsync(cacheDir).catch({ | ||
code: 'EACCES' | ||
@@ -302,20 +255,7 @@ }, err => { | ||
`); | ||
}).then(() => { | ||
return Promise.all([state.getBinaryPkgAsync(binaryDir).then(state.getBinaryPkgVersion), getVersionSpecifier()]); | ||
}).then(([binaryVersion, versionSpecifier]) => { | ||
if (!binaryUrlOverride && versionSpecifier) { | ||
const computedBinaryUrl = getBinaryUrlFromPrereleaseNpmUrl(versionSpecifier); | ||
}); | ||
const binaryPkg = await state.getBinaryPkgAsync(binaryDir); | ||
const binaryVersion = await state.getBinaryPkgVersion(binaryPkg); | ||
if (computedBinaryUrl) { | ||
debug('computed binary url from version specifier %o', { | ||
computedBinaryUrl, | ||
needVersion | ||
}); | ||
binaryUrlOverride = computedBinaryUrl; | ||
} | ||
} | ||
needVersion = binaryUrlOverride || needVersion; | ||
debug('installed version is', binaryVersion, 'version needed is', needVersion); | ||
const shouldInstall = () => { | ||
if (!binaryVersion) { | ||
@@ -337,3 +277,3 @@ debug('no binary installed under cli version'); | ||
if (binaryVersion === needVersion || !util.isSemver(needVersion)) { | ||
if (binaryVersion === versionToInstall || !util.isSemver(versionToInstall)) { | ||
// our version matches, tell the user this is a noop | ||
@@ -345,75 +285,74 @@ alreadyInstalledMsg(); | ||
return true; | ||
}).then(shouldInstall => { | ||
// noop if we've been told not to download | ||
if (!shouldInstall) { | ||
debug('Not downloading or installing binary'); | ||
return; | ||
} | ||
}; // noop if we've been told not to download | ||
if (needVersion !== pkgVersion) { | ||
logger.log(chalk.yellow(stripIndent` | ||
${logSymbols.warning} Warning: Forcing a binary version different than the default. | ||
The CLI expected to install version: ${chalk.green(pkgVersion)} | ||
if (!shouldInstall()) { | ||
return debug('Not downloading or installing binary'); | ||
} | ||
Instead we will install version: ${chalk.green(needVersion)} | ||
if (envVarVersion) { | ||
logger.log(chalk.yellow(stripIndent` | ||
${logSymbols.warning} Warning: Forcing a binary version different than the default. | ||
These versions may not work properly together. | ||
`)); | ||
logger.log(); | ||
} // see if version supplied is a path to a binary | ||
The CLI expected to install version: ${chalk.green(pkgVersion)} | ||
Instead we will install version: ${chalk.green(versionToInstall)} | ||
return fs.pathExistsAsync(needVersion).then(exists => { | ||
if (exists) { | ||
return path.extname(needVersion) === '.zip' ? needVersion : false; | ||
} | ||
These versions may not work properly together. | ||
`)); | ||
logger.log(); | ||
} | ||
const possibleFile = util.formAbsolutePath(needVersion); | ||
debug('checking local file', possibleFile, 'cwd', process.cwd()); | ||
return fs.pathExistsAsync(possibleFile).then(exists => { | ||
// if this exists return the path to it | ||
// else false | ||
if (exists && path.extname(possibleFile) === '.zip') { | ||
return possibleFile; | ||
} | ||
const getLocalFilePath = async () => { | ||
// see if version supplied is a path to a binary | ||
if (await fs.pathExistsAsync(versionToInstall)) { | ||
return path.extname(versionToInstall) === '.zip' ? versionToInstall : false; | ||
} | ||
return false; | ||
}); | ||
}).then(pathToLocalFile => { | ||
if (pathToLocalFile) { | ||
const absolutePath = path.resolve(needVersion); | ||
debug('found local file at', absolutePath); | ||
debug('skipping download'); | ||
const rendererOptions = getRendererOptions(); | ||
return new Listr([unzipTask({ | ||
progress: { | ||
throttle: 100, | ||
onProgress: null | ||
}, | ||
zipFilePath: absolutePath, | ||
installDir, | ||
rendererOptions | ||
})], { | ||
rendererOptions | ||
}).run(); | ||
} | ||
const possibleFile = util.formAbsolutePath(versionToInstall); | ||
debug('checking local file', possibleFile, 'cwd', process.cwd()); // if this exists return the path to it | ||
// else false | ||
if (options.force) { | ||
debug('Cypress already installed at', installDir); | ||
debug('but the installation was forced'); | ||
} | ||
if ((await fs.pathExistsAsync(possibleFile)) && path.extname(possibleFile) === '.zip') { | ||
return possibleFile; | ||
} | ||
debug('preparing to download and unzip version ', needVersion, 'to path', installDir); | ||
const downloadDir = os.tmpdir(); | ||
return downloadAndUnzip({ | ||
version: needVersion, | ||
installDir, | ||
downloadDir | ||
}); | ||
}) // delay 1 sec for UX, unless we are testing | ||
.then(() => { | ||
return Promise.delay(1000); | ||
}).then(displayCompletionMsg); | ||
}); | ||
return false; | ||
}; | ||
const pathToLocalFile = await getLocalFilePath(); | ||
if (pathToLocalFile) { | ||
const absolutePath = path.resolve(versionToInstall); | ||
debug('found local file at', absolutePath); | ||
debug('skipping download'); | ||
const rendererOptions = getRendererOptions(); | ||
return new Listr([unzipTask({ | ||
progress: { | ||
throttle: 100, | ||
onProgress: null | ||
}, | ||
zipFilePath: absolutePath, | ||
installDir, | ||
rendererOptions | ||
})], { | ||
rendererOptions | ||
}).run(); | ||
} | ||
if (options.force) { | ||
debug('Cypress already installed at', installDir); | ||
debug('but the installation was forced'); | ||
} | ||
debug('preparing to download and unzip version ', versionToInstall, 'to path', installDir); | ||
const downloadDir = os.tmpdir(); | ||
await downloadAndUnzip({ | ||
version: versionToInstall, | ||
installDir, | ||
downloadDir | ||
}); // delay 1 sec for UX, unless we are testing | ||
await Promise.delay(1000); | ||
displayCompletionMsg(); | ||
}; | ||
@@ -423,4 +362,3 @@ | ||
start, | ||
_getVersionSpecifier: getVersionSpecifier, | ||
_getBinaryUrlFromPrereleaseNpmUrl: getBinaryUrlFromPrereleaseNpmUrl | ||
_getBinaryUrlFromBuildInfo | ||
}; | ||
@@ -427,0 +365,0 @@ |
@@ -82,3 +82,7 @@ "use strict"; | ||
const getVersionDir = (version = util.pkgVersion()) => { | ||
const getVersionDir = (version = util.pkgVersion(), buildInfo = util.pkgBuildInfo()) => { | ||
if (buildInfo && !buildInfo.stable) { | ||
version = ['beta', version, buildInfo.commitBranch, buildInfo.commitSha].join('-'); | ||
} | ||
return path.join(getCacheDir(), version); | ||
@@ -85,0 +89,0 @@ }; |
@@ -341,2 +341,6 @@ "use strict"; | ||
pkgBuildInfo() { | ||
return pkg.buildInfo; | ||
}, | ||
pkgVersion() { | ||
@@ -343,0 +347,0 @@ return pkg.version; |
{ | ||
"name": "cypress", | ||
"version": "9.5.1", | ||
"version": "9.5.2", | ||
"main": "index.js", | ||
@@ -67,2 +67,8 @@ "scripts": { | ||
"types": "types", | ||
"buildInfo": { | ||
"commitBranch": "develop", | ||
"commitSha": "5db2cd996834043b3c825625cf0100957e14a663", | ||
"commitDate": "2022-03-14T18:42:32.000Z", | ||
"stable": true | ||
}, | ||
"description": "Cypress.io end to end testing tool", | ||
@@ -93,2 +99,2 @@ "homepage": "https://github.com/cypress-io/cypress", | ||
] | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
34
2757373
71853