mirror of
https://github.com/cypress-io/cypress.git
synced 2026-01-06 06:29:45 -06:00
* wip: system test to reproduce * system test for alsa stderr * split cypress from 3rd party stderr at parent process to electron child * rm garbage warning regexes * fix newline behavior when parsing internal stderr * migrate left over console errors * clean up system test name * fix typed import * extract stderr splitting to separate pkg so runner can use @packages/error * rm new err log from packherd-quire * handle backpressure * docs * some unit tests & coverage for stderr-filtering * unit tests * no longer test regexp specific output in spawn unit tests * filter enabled debug namespaces rather than just cypress namespacesc * revise stream splitting et al * try to fix v8 snapshot build?? * fix console.log assertion * add missing eslint config * rm unused spies * fix regexp for optional leading wsp and ansi on debug entries * update unit tests because sinon * lint * colon.. * build stderr-filtering before checking if binary exists * adds TagStream transform stream, fixes stderr from child proc config * add build-prod script for stderr-filtering * changelog * properly handle backpressure in prefixed content transform stream * use standard tsconfig? * better tsconfig * Add pkgStderrFiltering to monorepoPaths * add \"files\" manifest * pipe all stderr to stderr when CYPRESS_INTERNAL_DEBUG_ELECTRON is enabled * rm explicit build of stderr-filtering in check-if-binary-exists step * ensure all dependencies of scripts/ are built before scripts are executed in the check-if-binary-exists command * fix dev version ref * swap logic * add stdin piping * fix exec name on the run-on-dependencies command to be more useful * use correct env * rm obsolete type refs * simplify stderr-filtering public iface, pipe cy-in-cy stderr through filtering tx * bust cache * fix mocks * fix v8-snapshot * move stderrfiltering to dev pkg in cli * skip integrity check in ci, if they are out of date things should fail anyway * copypasta over a portion of stderr-filtering to cli, since cli cannot import @packages * Delete issues.md * rm special filtering for cy in cy * rm too narrow rules file --------- Co-authored-by: Jennifer Shehane <shehane.jennifer@gmail.com> Co-authored-by: Jennifer Shehane <jennifer@cypress.io> Co-authored-by: Bill Glesias <bglesias@gmail.com>
195 lines
5.0 KiB
JavaScript
195 lines
5.0 KiB
JavaScript
const cp = require('child_process')
|
|
const os = require('os')
|
|
const path = require('path')
|
|
const debugElectron = require('debug')('cypress:electron')
|
|
const Promise = require('bluebird')
|
|
const minimist = require('minimist')
|
|
const inspector = require('inspector')
|
|
const execa = require('execa')
|
|
const paths = require('./paths')
|
|
const install = require('./install')
|
|
let fs = require('fs-extra')
|
|
|
|
const debugStderr = require('debug')('cypress:internal-stderr')
|
|
|
|
fs = Promise.promisifyAll(fs)
|
|
|
|
const { filter, DEBUG_PREFIX } = require('@packages/stderr-filtering')
|
|
|
|
/**
|
|
* If running as root on Linux, no-sandbox must be passed or Chrome will not start
|
|
*/
|
|
const isSandboxNeeded = () => {
|
|
// eslint-disable-next-line no-restricted-properties
|
|
return (os.platform() === 'linux') && (process.geteuid() === 0)
|
|
}
|
|
|
|
module.exports = {
|
|
installIfNeeded () {
|
|
return install.check()
|
|
},
|
|
|
|
install (...args) {
|
|
debugElectron('installing %o', { args })
|
|
|
|
return install.package.apply(install, args)
|
|
},
|
|
|
|
getElectronVersion () {
|
|
return install.getElectronVersion()
|
|
},
|
|
|
|
/**
|
|
* Returns the Node version bundled inside Electron.
|
|
*/
|
|
getElectronNodeVersion () {
|
|
debugElectron('getting Electron Node version')
|
|
|
|
const args = []
|
|
|
|
if (isSandboxNeeded()) {
|
|
args.push('--no-sandbox')
|
|
}
|
|
|
|
// runs locally installed "electron" bin alias
|
|
const localScript = path.join(__dirname, 'print-node-version.js')
|
|
|
|
debugElectron('local script that prints Node version %s', localScript)
|
|
|
|
args.push(localScript)
|
|
|
|
const options = {
|
|
preferLocal: true, // finds the "node_modules/.bin/electron"
|
|
timeout: 10000, // prevents hanging Electron if there is an error for some reason
|
|
}
|
|
|
|
debugElectron('Running Electron with %o %o', args, options)
|
|
|
|
return execa('electron', args, options)
|
|
.then((result) => result.stdout)
|
|
},
|
|
|
|
icons () {
|
|
return install.icons()
|
|
},
|
|
|
|
cli (argv = []) {
|
|
const opts = minimist(argv)
|
|
|
|
debugElectron('cli options %j', opts)
|
|
|
|
const pathToApp = argv[0]
|
|
|
|
if (opts.install) {
|
|
return this.installIfNeeded()
|
|
}
|
|
|
|
if (pathToApp) {
|
|
return this.open(pathToApp, argv)
|
|
}
|
|
|
|
throw new Error('No path to your app was provided.')
|
|
},
|
|
|
|
open (appPath, argv, cb) {
|
|
debugElectron('opening %s', appPath)
|
|
|
|
appPath = path.resolve(appPath)
|
|
const dest = paths.getPathToResources('app')
|
|
|
|
debugElectron('appPath %s', appPath)
|
|
|
|
debugElectron('dest path %s', dest)
|
|
|
|
// make sure this path exists!
|
|
return fs.accessAsync(appPath)
|
|
.then(() => {
|
|
debugElectron('appPath exists %s', appPath)
|
|
|
|
// clear out the existing symlink
|
|
return fs.removeAsync(dest)
|
|
}).then(() => {
|
|
const symlinkType = paths.getSymlinkType()
|
|
|
|
debugElectron('making symlink from %s to %s of type %s', appPath, dest, symlinkType)
|
|
|
|
return fs.ensureSymlinkAsync(appPath, dest, symlinkType)
|
|
}).then(() => {
|
|
const execPath = paths.getPathToExec()
|
|
|
|
if (isSandboxNeeded()) {
|
|
argv.unshift('--no-sandbox')
|
|
}
|
|
|
|
// we have an active debugger session
|
|
if (inspector.url()) {
|
|
const dp = process.debugPort + 1
|
|
const inspectFlag = process.execArgv.some((f) => f === '--inspect' || f.startsWith('--inspect=')) ? '--inspect' : '--inspect-brk'
|
|
|
|
argv.unshift(`${inspectFlag}=${dp}`)
|
|
} else {
|
|
const opts = minimist(argv)
|
|
|
|
if (opts.inspectBrk) {
|
|
if (process.env.CYPRESS_DOCKER_DEV_INSPECT_OVERRIDE) {
|
|
argv.unshift(`--inspect-brk=${process.env.CYPRESS_DOCKER_DEV_INSPECT_OVERRIDE}`)
|
|
} else {
|
|
argv.unshift('--inspect-brk=5566')
|
|
}
|
|
}
|
|
}
|
|
|
|
debugElectron('spawning %s with args', execPath, argv)
|
|
|
|
if (debugElectron.enabled) {
|
|
// enable the internal chromium logger
|
|
argv.push('--enable-logging')
|
|
}
|
|
|
|
const spawned = cp.spawn(execPath, argv, { stdio: 'pipe' })
|
|
.on('error', (err) => {
|
|
// If electron is throwing an error event, we need to ensure it's
|
|
// printed to console.
|
|
// eslint-disable-next-line no-console
|
|
console.error(err)
|
|
|
|
return process.exit(1)
|
|
})
|
|
.on('close', (code, signal) => {
|
|
debugElectron('electron closing %o', { code, signal })
|
|
|
|
if (signal) {
|
|
debugElectron('electron exited with a signal, forcing code = 1 %o', { signal })
|
|
code = 1
|
|
}
|
|
|
|
if (cb) {
|
|
debugElectron('calling callback with code', code)
|
|
|
|
return cb(code)
|
|
}
|
|
|
|
debugElectron('process.exit with code', code)
|
|
|
|
return process.exit(code)
|
|
})
|
|
|
|
if ([1, '1'].includes(process.env.ELECTRON_ENABLE_LOGGING)) {
|
|
spawned.stderr.pipe(process.stderr)
|
|
} else {
|
|
spawned.stderr.pipe(filter(process.stderr, debugStderr, DEBUG_PREFIX))
|
|
}
|
|
|
|
spawned.stdout.pipe(process.stdout)
|
|
process.stdin.pipe(spawned.stdin)
|
|
|
|
return spawned
|
|
}).catch((err) => {
|
|
// eslint-disable-next-line no-console
|
|
console.debug(err.stack)
|
|
|
|
return process.exit(1)
|
|
})
|
|
},
|
|
}
|