Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically retry verify and run commands on Linux if suspect DISPLAY problem #4165

Merged
merged 22 commits into from
May 13, 2019

Conversation

bahmutov
Copy link
Contributor

@bahmutov bahmutov commented May 9, 2019

  • closes Presence of DISPLAY env var causes "Cypress failed to start" #4034
  • if the first verify retry fails, reruns with our XVFB. If still fails, shows error message with first and second errors
  • should display a warning message if gets a display error on the first verify attempt
  • should retry cypress run if there is suspected display error (shows warning as well)

cypress run warning on Linux if DISPLAY is set before re-running with our XVFB

⚠ Warning: Cypress process has finished very quickly with an error,
which might be related to a potential problem with how the DISPLAY is configured.

DISPLAY was set to "test-display"

We will attempt to spin our XVFB server and run Cypress again.

Note: to see how it performs, spin a Docker container (instructions in a comment below) and

  • to see cypress verify use
node -e 'require("./cli/lib/tasks/verify").start({force: true})'
  • to see spawn cypress run use
node -e 'require("./cli/lib/exec/spawn").start(["--run-project", "."], {dev: true})

@bahmutov bahmutov requested a review from brian-mann May 9, 2019 01:26
@bahmutov bahmutov requested a review from kuceb May 9, 2019 14:48
it('expects solution to be a string', () => {
const error = {
description: 'description',
solution: 42,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

42 is never a good answer

@bahmutov
Copy link
Contributor Author

bahmutov commented May 9, 2019

ughh, what is going on with Win32 build

15:00:18 #buildPackages win32
npm run all build -- --serial --skip-packages cli
> cypress@3.3.0 all C:\projects\cypress
> node ./scripts/run.js "build" "--serial" "--skip-packages" "cli"
npm ERR! file undefined
npm ERR! path undefined
npm ERR! code ELIFECYCLE
npm ERR! errno ENOENT
npm ERR! syscall spawn undefined
npm ERR! cypress@3.3.0 all: `node ./scripts/run.js "build" "--serial" "--skip-packages" "cli"`
npm ERR! spawn undefined ENOENT
npm ERR! 
npm ERR! Failed at the cypress@3.3.0 all script.

@bahmutov
Copy link
Contributor Author

bahmutov commented May 9, 2019

found that we can detect X11 problem using a flag

root@eabed8eaef87:/cypress/cli# ../packages/electron/dist/Cypress/Cypress --enable-logging
[215:0509/165930.091489:WARNING:browser_main_loop.cc(275)] <unknown>: Could not open X display
[215:0509/165930.091727:WARNING:browser_main_loop.cc(275)] Gtk: cannot open display: 99
root@eabed8eaef87:/cypress/cli# 

so need to switch this PR to enable logging during verify step

@bahmutov bahmutov changed the title Console error with more clarity about Linux DISPLAY variable WIP: Console error with more clarity about Linux DISPLAY variable May 9, 2019
@bahmutov
Copy link
Contributor Author

bahmutov commented May 9, 2019

the way to see this locally (via Docker)

  • run Docker in the cypress root folder
docker run -it -v $PWD:/cypress -w /cypress cypress/browsers:node8.9.3-chrome73
  • in the container install global Cypress binary (so you have something to verify)
npm i -g cypress@3.2.0
  • set binary as environment variable pointing at the newly installed binary
export CYPRESS_RUN_BINARY=/root/.cache/Cypress/3.2.0/Cypress/Cypress
  • set DISPLAY variable to something and start node
export DISPLAY=99
node
  • load verify task module and execute it
var verify = require('./cli/lib/tasks/verify')
verify.start({force: true})

If the verify code uses --enable-logging then you should see the good message

  cypress:cli smoke test command: /root/.cache/Cypress/3.2.0/Cypress/Cypress --smoke-test --ping=471 --enable-logging +1ms
  cypress:cli Smoke test failed: { Error: Command failed: /root/.cache/Cypress/3.2.0/Cypress/Cypress --smoke-test --ping=471 --enable-logging
[769:0509/181151.619094:WARNING:browser_main_loop.cc(258)] Gtk: cannot open display: 99


    at makeError (/cypress/cli/node_modules/execa/index.js:172:9)
    at Promise.all.then.arr (/cypress/cli/node_modules/execa/index.js:277:16)
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:228:7)
  code: 1,
  stdout: '',
  stderr: '[769:0509/181151.619094:WARNING:browser_main_loop.cc(258)] Gtk: cannot open display: 99\n',
  failed: true,
  signal: null,
  cmd: '/root/.cache/Cypress/3.2.0/Cypress/Cypress --smoke-test --ping=471 --enable-logging',
  timedOut: false,
  killed: false } +82ms
 ✖  Verifying Cypress can run /root/.cache/Cypress/3.2.0/Cypress
   → Cypress Version: 0.0.0
Unhandled rejection Error: Cypress failed to start.

This is usually caused by a missing library or dependency.

The error below should indicate which dependency is missing.

https://on.cypress.io/required-dependencies

If you are using Docker, we provide containers with all required dependencies installed.

We have noticed that DISPLAY variable is set to "99"
This might be a problem if X11 server is not responding.

https://github.com/cypress-io/cypress/issues/4034

Try deleting the DISPLAY variable and running the command again.

----------

[769:0509/181151.619094:WARNING:browser_main_loop.cc(258)] Gtk: cannot open display: 99

----------

Platform: linux (Debian - 8.11)
Cypress Version: 0.0.0

A nice way to iterate over the code (because the local source code folder has been mounted into Docker container) is to run this line, which goes around require cache

node -e 'require("./cli/lib/tasks/verify").start({force: true})'

const issueUrl = util.getGitHubIssueUrl(4034)

const message = stripIndent`
DISPLAY environment variable is set to ${process.env.DISPLAY} on Linux
Copy link
Contributor Author

Choose a reason for hiding this comment

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

being verbose is good, hopefully, someone reads it and understand the problem, even if we work around it using our XVFB

@bahmutov
Copy link
Contributor Author

bahmutov commented May 9, 2019

uggh, if we enable Cypress logging during full cypress spawn, there is a lot of extra stuff displayed

  cypress:server:cypress starting cypress with argv [ '/cypress/packages/electron/dist/Cypress/Cypress', '--cwd=/cypress', '--config={}', '--enable-logging' ] +0ms
[4598:0509/220121.170576:ERROR:bus.cc(395)] Failed to connect to the bus: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory
  cypress:server:cypress starting in mode interactive +3s
libudev: udev_has_devtmpfs: name_to_handle_at on /dev: Operation not permitted
[4598:0509/220139.987910:ERROR:bus.cc(395)] Failed to connect to the bus: Address does not contain a colon
[4598:0509/220140.032274:ERROR:bus.cc(395)] Failed to connect to the bus: Address does not contain a colon
[4598:0509/220140.630393:INFO:CONSOLE(73528)] "%cDownload the React DevTools for a better development experience: https://fb.me/react-devtools
You might need to use a local HTTP server (instead of file://): https://fb.me/react-devtools-faq", source: file:///cypress/packages/desktop-gui/dist/app.js (73528)
Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged.

(Cypress:4598): dconf-WARNING **: failed to commit changes to dconf: Address element '/dev/null' does not contain a colon (:)
[4598:0509/220233.220295:ERROR:bus.cc(395)] Failed to connect to the bus: Address does not contain a colon
GET /__/ 200 217.315 ms - -

@bahmutov bahmutov changed the title WIP: Console error with more clarity about Linux DISPLAY variable Automatically retry verify and run commands on Linux if suspect DISPLAY problem May 13, 2019
@@ -16,18 +27,54 @@ Cypress Version: 1.2.3
`

exports['errors individual has the following errors 1'] = [
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the names of the errors are now sorted before snapshotting

@@ -102,6 +108,39 @@ const smokeTestFailure = (smokeTestCommand, timedOut) => {
}
}

const invalidDisplayError = {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

a complex error that has both the display error and the follow-up error

solution: '',
solution: stripIndent`
See discussion and possible solutions at
${chalk.blue(util.getGitHubIssueUrl(1281))}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

at least give the relevant issue url

// assuming that if there the solution is a function it will handle
// error message and (optional previous error message)
if (is.fn(obj.solution)) {
const text = obj.solution(msg, prevMessage)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

if error solution property is a function, let it form the full error text

if (os.platform() === 'linux' && process.env.DISPLAY) {
// make sure we use the latest DISPLAY variable if any
debug('passing DISPLAY', process.env.DISPLAY)
options.env.DISPLAY = process.env.DISPLAY
Copy link
Contributor Author

Choose a reason for hiding this comment

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

otherwise a new value from XVFB will not take effect

// else pass it along!
process.stderr.write(data)
})
child.stderr &&
Copy link
Contributor Author

Choose a reason for hiding this comment

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

just a little bit of reformatting

}

return userFriendlySpawn()

return userFriendlySpawn(os.platform() === 'linux')
Copy link
Contributor Author

Choose a reason for hiding this comment

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

if we are on Linux, and there is a display problem, we should attempt handling it once

return spawn()
.catch({ displayError: true, platform: 'linux' }, (e) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

handle display error once

solution: 42,
}

return expect(formErrorText(error)).to.be.rejected
Copy link
Contributor Author

Choose a reason for hiding this comment

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

chai-as-promised is nice

@@ -33,6 +33,7 @@
"clean-deps": "npm run all clean-deps && rm -rf node_modules",
"docker": "./scripts/run-docker-local.sh",
"lint-js": "eslint --fix scripts/*.js packages/ts/*.js cli/*.js cli/**/*.js",
"lint-changed": "git diff --name-only | grep '\\.js$' | xargs npx eslint --fix",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

little utility to fix all changes JS files before committing

@@ -72,6 +72,10 @@ module.exports = {

debug("spawning %s with args", execPath, argv)

if debug.enabled
# let's see everything Electron spits back
argv.push("--enable-logging")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

when running with DEBUG=cypress:electron it would be nice to see everything

fn = (code) ->
## juggle up the totalFailed since our outer
## promise is expecting this object structure
debug("electron finished with", code)
resolve({totalFailed: code})
cypressElectron.open(".", require("./util/args").toArray(options), fn)
electronFinished = Number(new Date())
Copy link
Contributor Author

Choose a reason for hiding this comment

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

detect display or missing dependency problem by noticing how quickly Electron exits. If we suspect display or missing dependency problem then return a special exit code

kuceb
kuceb previously requested changes May 13, 2019
Cypress failed to start.

First, we have tried to start Cypress using your DISPLAY settings
but his the following problem:
Copy link
Contributor

Choose a reason for hiding this comment

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

typo

@bahmutov bahmutov requested a review from kuceb May 13, 2019 18:00
@kuceb
Copy link
Contributor

kuceb commented May 13, 2019

Did the same driver-integration test just fail twice?

@bahmutov
Copy link
Contributor Author

did it?

1) src/cy/commands/actions/type #type value changing [contenteditable] can type into an iframe with designmode = 'on':
     CypressError: Timed out retrying: expected false to equal true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Presence of DISPLAY env var causes "Cypress failed to start"
2 participants