Skip to content

Commit

Permalink
fix: Add support for system node 17 (#19094)
Browse files Browse the repository at this point in the history
  • Loading branch information
Blue F authored Dec 2, 2021
1 parent 4630ef4 commit 6b19381
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 60 deletions.
60 changes: 40 additions & 20 deletions packages/server/lib/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const inspector = require('inspector')
const errors = require('../errors')
const util = require('./util')
const pkg = require('@packages/root')
const semver = require('semver')

let pluginsProcess = null
let registeredEvents = {}
Expand Down Expand Up @@ -37,6 +38,43 @@ const registerHandler = (handler) => {
handlers.push(handler)
}

const getChildOptions = (config) => {
const childOptions = {
stdio: 'pipe',
env: {
...process.env,
NODE_OPTIONS: process.env.ORIGINAL_NODE_OPTIONS || '',
},
}

if (config.resolvedNodePath) {
debug('launching using custom node version %o', _.pick(config, ['resolvedNodePath', 'resolvedNodeVersion']))
childOptions.execPath = config.resolvedNodePath
}

// https://github.com/cypress-io/cypress/issues/18914
// If we're on node version 17 or higher, we need the
// NODE_ENV --openssl-legacy-provider so that webpack can continue to use
// the md4 hash function. This would cause an error prior to node 17
// though, so we have to detect node's major version before spawning the
// plugins process.

// To be removed on update to webpack >= 5.61, which no longer relies on
// node's builtin crypto.hash function.
if (semver.satisfies(config.resolvedNodeVersion, '>=17.0.0')) {
childOptions.env.NODE_OPTIONS += ' --openssl-legacy-provider'
}

if (inspector.url()) {
childOptions.execArgv = _.chain(process.execArgv.slice(0))
.remove('--inspect-brk')
.push(`--inspect=${process.debugPort + 1}`)
.value()
}

return childOptions
}

const init = (config, options) => {
debug('plugins.init', config.pluginsFile)

Expand Down Expand Up @@ -82,28 +120,9 @@ const init = (config, options) => {
const pluginsFile = config.pluginsFile || path.join(__dirname, 'child', 'default_plugins_file.js')
const childIndexFilename = path.join(__dirname, 'child', 'index.js')
const childArguments = ['--file', pluginsFile, '--projectRoot', options.projectRoot]
const childOptions = {
stdio: 'pipe',
env: {
...process.env,
NODE_OPTIONS: process.env.ORIGINAL_NODE_OPTIONS || '',
},
}

if (config.resolvedNodePath) {
debug('launching using custom node version %o', _.pick(config, ['resolvedNodePath', 'resolvedNodeVersion']))
childOptions.execPath = config.resolvedNodePath
}
const childOptions = getChildOptions(config)

debug('forking to run %s', childIndexFilename)

if (inspector.url()) {
childOptions.execArgv = _.chain(process.execArgv.slice(0))
.remove('--inspect-brk')
.push(`--inspect=${process.debugPort + 1}`)
.value()
}

pluginsProcess = cp.fork(childIndexFilename, childArguments, childOptions)

if (pluginsProcess.stdout && pluginsProcess.stderr) {
Expand Down Expand Up @@ -241,6 +260,7 @@ const _setPluginsProcess = (_pluginsProcess) => {
}

module.exports = {
getChildOptions,
getPluginPid,
execute,
has,
Expand Down
78 changes: 38 additions & 40 deletions packages/server/test/unit/plugins/index_spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
require('../../spec_helper')

const _ = require('lodash')
const mockedEnv = require('mocked-env')
const cp = require('child_process')

Expand Down Expand Up @@ -47,6 +46,44 @@ describe('lib/plugins/index', () => {
sinon.stub(util, 'wrapIpc').returns(ipc)
})

context('#getChildOptions', () => {
it('uses system Node when available', () => {
const config = {
resolvedNodePath: '/my/path/to/system/node',
}

const childOptions = plugins.getChildOptions(config)

expect(childOptions.execPath).to.eq(config.resolvedNodePath)
})

it('uses bundled Node when cannot find system Node', () => {
const config = {}

const childOptions = plugins.getChildOptions(config)

expect(childOptions.execPath).to.eq(undefined)
})

// https://github.com/cypress-io/cypress/issues/18914
it('includes --openssl-legacy-provider in node 17+', () => {
const childOptions = plugins.getChildOptions({
resolvedNodeVersion: 'v17.1.0',
})

expect(childOptions.env.NODE_OPTIONS).to.contain('--openssl-legacy-provider')
})

// https://github.com/cypress-io/cypress/issues/18914
it('does not include --openssl-legacy-provider in node <=16', () => {
const childOptions = plugins.getChildOptions({
resolvedNodeVersion: 'v16.31.0',
})

expect(childOptions.env.NODE_OPTIONS).not.to.contain('--openssl-legacy-provider')
})
})

context('#init', () => {
it('uses noop plugins file if no pluginsFile', () => {
// have to fire "loaded" message, otherwise plugins.init promise never resolves
Expand Down Expand Up @@ -79,45 +116,6 @@ describe('lib/plugins/index', () => {
})
})

it('uses system Node when available', () => {
ipc.on.withArgs('loaded').yields([])
const systemNode = '/my/path/to/system/node'
const config = {
pluginsFile: 'cypress-plugin',
nodeVersion: 'system',
resolvedNodeVersion: 'v1.2.3',
resolvedNodePath: systemNode,
}

return plugins.init(config, getOptions())
.then(() => {
const options = {
stdio: 'pipe',
execPath: systemNode,
}

expect(_.omit(cp.fork.lastCall.args[2], 'env')).to.eql(options)
})
})

it('uses bundled Node when cannot find system Node', () => {
ipc.on.withArgs('loaded').yields([])
const config = {
pluginsFile: 'cypress-plugin',
nodeVersion: 'system',
resolvedNodeVersion: 'v1.2.3',
}

return plugins.init(config, getOptions())
.then(() => {
const options = {
stdio: 'pipe',
}

expect(_.omit(cp.fork.lastCall.args[2], 'env')).to.eql(options)
})
})

it('calls any handlers registered with the wrapped ipc', () => {
ipc.on.withArgs('loaded').yields([])
const handler = sinon.spy()
Expand Down

3 comments on commit 6b19381

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 6b19381 Dec 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/9.1.1/circle-develop-6b19381f7949476b164f64c684c636f4743b98e3/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 6b19381 Dec 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AppVeyor has built the win32 x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/9.1.1/appveyor-develop-6b19381f7949476b164f64c684c636f4743b98e3/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 6b19381 Dec 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/9.1.1/circle-develop-6b19381f7949476b164f64c684c636f4743b98e3/cypress.tgz

Please sign in to comment.