cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
46.59k stars 3.15k forks source link

Run Cypress Headless Without Binary #1232

Open arahansen opened 6 years ago

arahansen commented 6 years ago

Current behavior:

npm install cypress downloads the cypress app binary

Desired behavior:

npm install cypress (or something like npm install @cypress/headless) does not install a binary, and only installs necessary dependencies for running tests headlessly on CI.

Additional Info (images, stack traces, etc)

Our CI configuration is pretty strict about what can be externally downloaded. It would be great if cypress could be run without needing to whitelist the cypress domain.

craig-dae commented 4 years ago

@kentan88 We gave up. Ran into too many issues. Decided that Lambda is the wrong place to run something like this. Cypress should run in a container, not a Lambda.

Lambdas are meant to run arbitrary code quickly, with auto-scaling. It is not meant to replicate the functionality of an OS. The only reason we were using a Lambda in the first place was because we got top-down direction to try it first. We concluded that it was not worth it, and have moved to containers, and got things working in a few days.

WinstonN commented 3 years ago

yep, i've given up too. moved to puppeteer got it working in no time. I'm also looking at https://github.com/microsoft/playwright

I still use cypress for E2E testing though, and love it, so no shade at them :)

JesterXL commented 3 years ago

For those using AWS, they started a new service embedding Puppeteer called Canary. It still uses Lambda and has the same workflow of smaller scripts to monitor your UI's and API's or other systems.

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries.html

tomardern commented 3 years ago

AWS have recently announced support for containers . I've been having a play over the last few evenings, and unfortunately, I'm unable to get the official cypress docker image to run on AWS Lambda.

The main errors I'm getting are: gpu_data_manager_impl_private.cc(445) GPU process isn't usable. Goodbye.

Things I've attempted so far:

Any ideas?

Full Logs ``` prctl(PR_SET_NO_NEW_PRIVS) failed prctl(PR_SET_NO_NEW_PRIVS) failed 2020-12-07T20:28:04.691Z cypress:ts Running without ts-node hook in environment "production" 2020-12-07T20:28:05.354Z cypress:server:appdata path: /tmp/Cypress/cy/production/browsers 2020-12-07T20:28:05.357Z cypress:server:util:node_options NODE_OPTIONS check failed, forking { NODE_OPTIONS: '--max-http-header-size=1048576 ', ORIGINAL_NODE_OPTIONS: '' } prctl(PR_SET_NO_NEW_PRIVS) failed prctl(PR_SET_NO_NEW_PRIVS) failed [293:1207/202805.687892:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 1 time(s) [293:1207/202805.688745:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 2 time(s) [293:1207/202805.689172:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 3 time(s) [293:1207/202805.689581:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 4 time(s) [293:1207/202805.689939:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 5 time(s) [293:1207/202805.712128:ERROR:bus.cc(393)] Failed to connect to the bus: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory [293:1207/202805.711553:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 6 time(s) [293:1207/202805.724103:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 7 time(s) [293:1207/202805.730855:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 8 time(s) [293:1207/202805.744682:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 9 time(s) [293:1207/202805.744705:FATAL:gpu_data_manager_impl_private.cc(445)] GPU process isn't usable. Goodbye. 2020-12-07T20:28:05.749Z cypress:ts Running without ts-node hook in environment "production" 2020-12-07T20:28:06.576Z cypress:server:appdata path: /tmp/Cypress/cy/production/browsers 2020-12-07T20:28:06.579Z cypress:server:util:node_options NODE_OPTIONS check passed, not forking { NODE_OPTIONS: '--max-http-header-size=1048576 ' } 2020-12-07T20:28:06.579Z cypress:server:util:node_options restoring NODE_OPTIONS { NODE_OPTIONS: '--max-http-header-size=1048576 ', ORIGINAL_NODE_OPTIONS: '' } 2020-12-07T20:28:06.845Z cypress:server:cypress starting cypress with argv [ '/cypress-cache/6.0.0/Cypress/Cypress', '--no-sandbox', '--smoke-test', '--ping=90' ] 2020-12-07T20:28:06.845Z cypress:server:args argv array: [ '/cypress-cache/6.0.0/Cypress/Cypress', '--no-sandbox', '--smoke-test', '--ping=90' ] 2020-12-07T20:28:06.846Z cypress:server:args parsed argv options { options: { _: [ '/cypress-cache/6.0.0/Cypress/Cypress' ], sandbox: false, 'smoke-test': true, smokeTest: true, ping: 90 } } 2020-12-07T20:28:06.848Z cypress:server:args argv parsed: { _: [ '/cypress-cache/6.0.0/Cypress/Cypress' ], sandbox: false, smokeTest: true, ping: 90, invokedFromCli: false, cwd: '/cypress-cache/6.0.0/Cypress/resources/app/packages/server' } 2020-12-07T20:28:06.849Z cypress:server:util:proxy found proxy environment variables { npm_config_proxy: '', npm_config_https_proxy: '', npm_config_noproxy: '' } 2020-12-07T20:28:06.849Z cypress:server:args options { _: [ '/cypress-cache/6.0.0/Cypress/Cypress' ], sandbox: false, smokeTest: true, ping: 90, invokedFromCli: false, cwd: '/cypress-cache/6.0.0/Cypress/resources/app/packages/server', config: {} } 2020-12-07T20:28:06.849Z cypress:server:args argv options: { _: [ '/cypress-cache/6.0.0/Cypress/Cypress' ], sandbox: false, smokeTest: true, ping: 90, invokedFromCli: false, cwd: '/cypress-cache/6.0.0/Cypress/resources/app/packages/server', config: {}, pong: 90 } 2020-12-07T20:28:06.849Z cypress:server:cypress from argv [ '/cypress-cache/6.0.0/Cypress/Cypress', '--no-sandbox', '--smoke-test', '--ping=90' ] got options { _: [ '/cypress-cache/6.0.0/Cypress/Cypress' ], sandbox: false, smokeTest: true, ping: 90, invokedFromCli: false, cwd: '/cypress-cache/6.0.0/Cypress/resources/app/packages/server', config: {}, pong: 90 } [306:1207/202807.011775:ERROR:bus.cc(393)] Failed to connect to the bus: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory [306:1207/202807.020126:WARNING:audio_manager_linux.cc(68)] Falling back to ALSA for audio output. PulseAudio is not available or could not be initialized. 2020-12-07T20:28:07.028Z cypress:server:appdata path: /tmp/Cypress/cy/production 2020-12-07T20:28:07.066Z cypress:server:cypress starting in mode smokeTest with options { _: [ '/cypress-cache/6.0.0/Cypress/Cypress' ], sandbox: false, smokeTest: true, ping: 90, invokedFromCli: false, cwd: '/cypress-cache/6.0.0/Cypress/resources/app/packages/server', config: {}, pong: 90 } 2020-12-07T20:28:07.069Z cypress:server:cypress running Electron currently 2020-12-07T20:28:07.071Z cypress:server:cypress about to exit with code 0 ```
dandobrescu commented 3 years ago

Is this happening for both chromium and electron? If it's because of chromium, perhaps you can start it without GPUhttps://stackoverflow.com/questions/61773844/the-gpu-process-has-crashed-x-times-error-using-chromedriver-and-chrome-in-hea


From: Tom Ardern notifications@github.com Sent: Monday, December 7, 2020 9:39 PM To: cypress-io/cypress cypress@noreply.github.com Cc: Dan Dobrescu dandobrescu@studyportals.com; Mention mention@noreply.github.com Subject: Re: [cypress-io/cypress] Run Cypress Headless Without Binary / on AWS Lambda? (#1232)

AWS have recently announced support for containers https://aws.amazon.com/blogs/aws/new-for-aws-lambda-container-image-support/ . I've been having a play over the last few evenings, and unfortunately, I'm unable to get the official cypress docker image to run on AWS Lambda.

The main errors I'm getting are: gpu_data_manager_impl_private.cc(445) GPU process isn't usable. Goodbye.

Things I've attempted so far:

Any ideas?

Full Logs

prctl(PR_SET_NO_NEW_PRIVS) failed prctl(PR_SET_NO_NEW_PRIVS) failed 2020-12-07T20:28:04.691Z cypress:ts Running without ts-node hook in environment "production" 2020-12-07T20:28:05.354Z cypress:server:appdata path: /tmp/Cypress/cy/production/browsers 2020-12-07T20:28:05.357Z cypress:server:util:node_options NODE_OPTIONS check failed, forking { NODE_OPTIONS: '--max-http-header-size=1048576 ', ORIGINAL_NODE_OPTIONS: '' } prctl(PR_SET_NO_NEW_PRIVS) failed prctl(PR_SET_NO_NEW_PRIVS) failed [293:1207/202805.687892:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 1 time(s) [293:1207/202805.688745:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 2 time(s) [293:1207/202805.689172:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 3 time(s) [293:1207/202805.689581:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 4 time(s) [293:1207/202805.689939:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 5 time(s) [293:1207/202805.712128:ERROR:bus.cc(393)] Failed to connect to the bus: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory [293:1207/202805.711553:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 6 time(s) [293:1207/202805.724103:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 7 time(s) [293:1207/202805.730855:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 8 time(s) [293:1207/202805.744682:WARNING:gpu_process_host.cc(1267)] The GPU process has crashed 9 time(s) [293:1207/202805.744705:FATAL:gpu_data_manager_impl_private.cc(445)] GPU process isn't usable. Goodbye. 2020-12-07T20:28:05.749Z cypress:ts Running without ts-node hook in environment "production" 2020-12-07T20:28:06.576Z cypress:server:appdata path: /tmp/Cypress/cy/production/browsers 2020-12-07T20:28:06.579Z cypress:server:util:node_options NODE_OPTIONS check passed, not forking { NODE_OPTIONS: '--max-http-header-size=1048576 ' } 2020-12-07T20:28:06.579Z cypress:server:util:node_options restoring NODE_OPTIONS { NODE_OPTIONS: '--max-http-header-size=1048576 ', ORIGINAL_NODEOPTIONS: '' } 2020-12-07T20:28:06.845Z cypress:server:cypress starting cypress with argv [ '/cypress-cache/6.0.0/Cypress/Cypress', '--no-sandbox', '--smoke-test', '--ping=90' ] 2020-12-07T20:28:06.845Z cypress:server:args argv array: [ '/cypress-cache/6.0.0/Cypress/Cypress', '--no-sandbox', '--smoke-test', '--ping=90' ] 2020-12-07T20:28:06.846Z cypress:server:args parsed argv options { options: { : [ '/cypress-cache/6.0.0/Cypress/Cypress' ], sandbox: false, 'smoke-test': true, smokeTest: true, ping: 90 } } 2020-12-07T20:28:06.848Z cypress:server:args argv parsed: { _: [ '/cypress-cache/6.0.0/Cypress/Cypress' ], sandbox: false, smokeTest: true, ping: 90, invokedFromCli: false, cwd: '/cypress-cache/6.0.0/Cypress/resources/app/packages/server' } 2020-12-07T20:28:06.849Z cypress:server:util:proxy found proxy environment variables { npm_config_proxy: '', npm_config_https_proxy: '', npm_confignoproxy: '' } 2020-12-07T20:28:06.849Z cypress:server:args options { : [ '/cypress-cache/6.0.0/Cypress/Cypress' ], sandbox: false, smokeTest: true, ping: 90, invokedFromCli: false, cwd: '/cypress-cache/6.0.0/Cypress/resources/app/packages/server', config: {} } 2020-12-07T20:28:06.849Z cypress:server:args argv options: { : [ '/cypress-cache/6.0.0/Cypress/Cypress' ], sandbox: false, smokeTest: true, ping: 90, invokedFromCli: false, cwd: '/cypress-cache/6.0.0/Cypress/resources/app/packages/server', config: {}, pong: 90 } 2020-12-07T20:28:06.849Z cypress:server:cypress from argv [ '/cypress-cache/6.0.0/Cypress/Cypress', '--no-sandbox', '--smoke-test', '--ping=90' ] got options { : [ '/cypress-cache/6.0.0/Cypress/Cypress' ], sandbox: false, smokeTest: true, ping: 90, invokedFromCli: false, cwd: '/cypress-cache/6.0.0/Cypress/resources/app/packages/server', config: {}, pong: 90 } [306:1207/202807.011775:ERROR:bus.cc(393)] Failed to connect to the bus: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory [306:1207/202807.020126:WARNING:audio_managerlinux.cc(68)] Falling back to ALSA for audio output. PulseAudio is not available or could not be initialized. 2020-12-07T20:28:07.028Z cypress:server:appdata path: /tmp/Cypress/cy/production 2020-12-07T20:28:07.066Z cypress:server:cypress starting in mode smokeTest with options { : [ '/cypress-cache/6.0.0/Cypress/Cypress' ], sandbox: false, smokeTest: true, ping: 90, invokedFromCli: false, cwd: '/cypress-cache/6.0.0/Cypress/resources/app/packages/server', config: {}, pong: 90 } 2020-12-07T20:28:07.069Z cypress:server:cypress running Electron currently 2020-12-07T20:28:07.071Z cypress:server:cypress about to exit with code 0

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/cypress-io/cypress/issues/1232#issuecomment-740166946, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AMCQCBI2LRS5KSAO2DPB433STU4PRANCNFSM4EN3RIGQ.

tomardern commented 3 years ago

@dandobrescu I've tried using these flags on both the electron flags (via ELECTRON_EXTRA_LAUNCH_ARGS env) and for chrome via the before:browser:launch

--disable-dev-shm-usage // disable /dev/shm tmpfs usage on Lambda
--disable-gpu
--single-process 
--no-zygote // helps avoid zombies
--no-sandbox
--disable-setuid-sandbox
--user-data-dir=/tmp/chrome-user-data
--disable-software-rasterizer
--ignore-gpu-blacklist
--disable-gpu-compositing
--ignore-certificate-errors
--data-path=/tmp/data-electron-path
--hide-scrollbars

and I'm still getting GPU errors such as : FATAL:gpu_data_manager_impl_private.cc(445)] GPU process isn't usable. Goodbye. and Failed to connect to the bus: Failed to connect to socket /var/run/dbus/system_bus_socket...

dandobrescu commented 3 years ago

With a brief google search seems like it's also a bug in chromium ignoring the gpu flags. It seems that there are also some environment variables that may also work, but it depends on the chromium version you have.

My two cents would be to isolate the issue by trying to open a page in chromium headless, independently of Cypress, and see if it works - and if it does, get the optimal parameters that you could run it with. Or Electron, this one has it's own bugs regarding disabling the GPU, but at least you have two different browsers that could eventually tell you if the problem is from running headless browsers or from the Cypress setup.

kevinold commented 3 years ago

@tomardern Would you have an example repo with your Dockerfile, lambda and any other relevant files with the modifications you've mentioned?

kevinold commented 3 years ago

@tomardern @WinstonN Would you have an example repo with your Dockerfile, lambda and any other relevant files with the modifications you've mentioned?

tomardern commented 3 years ago

@kevinold Sorry for late reply. I've added the files here - https://gist.github.com/tomardern/822642988be2851beef930f94ba62fa2

kevinold commented 3 years ago

@tomardern Thanks for the gist. That said, it is difficult to diagnose and assist with limited structure and missing files from the overall project.

In order to investigate this further, please provide a git repo with all applicable files that can be deployed via Serverless, AWS SAM, or other utility to AWS.

WinstonN commented 3 years ago

This should be possible now, since AWS lambda supports container images - see https://aws.amazon.com/blogs/aws/new-for-aws-lambda-container-image-support/

I recommend starting fresh, using the above link documentation

When this thread was created lambda did not support container images, and the route that I went was simply not feasible, since I wanted to run this at scale (millions of invocations)

I therefore went the puppeteer / playwright route which works fine

Hope this helps, and good luck!

smccarthy-godaddy commented 3 years ago

Has anyone gotten this working yet?

smccarthy-godaddy commented 3 years ago

@tomardern I have been trying to get this working the past few days. I have it working for Selenium (on AWS Lambda) by using these Chrome flags: [ '--disable-background-timer-throttling', '--disable-breakpad', '--disable-client-side-phishing-detection', '--disable-cloud-import', '--disable-default-apps', '--disable-dev-shm-usage', '--disable-extensions', '--disable-gesture-typing', '--disable-hang-monitor', '--disable-infobars', '--disable-notifications', '--disable-offer-store-unmasked-wallet-cards', '--disable-offer-upload-credit-cards', '--disable-popup-blocking', '--disable-print-preview', '--disable-prompt-on-repost', '--disable-setuid-sandbox', '--disable-speech-api', '--disable-sync', '--disable-tab-for-desktop-share', '--disable-translate', '--disable-voice-input', '--disable-wake-on-wifi', '--enable-async-dns', '--enable-simple-cache-backend', '--enable-tcp-fast-open', '--disable-webgl', '--hide-scrollbars', '--ignore-gpu-blacklist', '--media-cache-size=33554432', '--metrics-recording-only', '--mute-audio', '--no-default-browser-check', '--no-first-run', '--no-pings', '--no-sandbox', '--no-zygote', '--password-store=basic', '--prerender-from-omnibox=disabled', '--use-mock-keychain', '--single-process', '--headless', '--disable-gpu', '--user-data-dir=/tmp/user-data', '--data-path=/tmp/data-path', '--homedir=/tmp', '--disk-cache-dir=/tmp/cache-dir', '--remote-debugging-port=9222', "--window-size=1920,1080" ]

I also use the version of Chrome from https://github.com/alixaxel/chrome-aws-lambda (I do an npm i for this package@version and take the chrome binary out of node_modules). Do any of these flags or specific version of Chrome work for you ?

kevinold commented 3 years ago

The Cypress DX Team has examined this landscape and determined a recommended approach.

We recommend that the orchestration be performed by AWS CodeBuild combined with the Cypress Dashboard (vs a command-and-control/fan-out pattern based approach).

This has been implemented in the Cypress Real World App using the build-matrix of AWS CodeBuild's Batch Build feature with a parallelization of 25 machines, for example.

Please refer to this buildspec.yml:

https://github.com/cypress-io/cypress-realworld-app/blob/develop/buildspec.yml

In the buildspec, we are:

Reference:

AWS CodeBuild now supports parallel and coordinated executions of a build project https://aws.amazon.com/about-aws/whats-new/2020/07/aws-codebuild-now-supports-parallel-and-coordinated-executions-of-a-build-project/

smccarthy-godaddy commented 3 years ago

@kevinold Is that above solution you posted about today, to get it to run in AWS Lambda ?

kevinold commented 3 years ago

@smccarthy-godaddy Yes, technically CodeBuild uses Lambda's to run the container, but abstracts that away from you.

smccarthy-godaddy commented 3 years ago

@kevinold I tried looking at the cypress-realworld-app. I see it uses public.ecr.aws/s9l6w2o6/cypress-browsers-node14.15.0-chrome86-ff82. Does this public image do something special to get Cypress to work on Lambda ? For example, how does it get around the xvfb issues mentioned above in this issue? Thank you !

kevinold commented 3 years ago

@smccarthy-godaddy

The public image is simply one of our Cypress Docker Image hosted in a Public ECR.

I mentioned in my previous message that we will be creating a Cypress Public ECR to house most, if not all of our images currently on DockerHub.

In the buildspec, we are:

In the meantime, you can clone Cypress Docker Image repo and use this browsers/node14.15.0-chrome86-ff82 or any other browsers image and compile and push it up to your own AWS ECR (Public or Private).

One note is that you will need to adjust the build.sh line to remove the slashes and colons (AWS ECR's do not allow these characters):

Before:

LOCAL_NAME=cypress/browsers:node14.15.0-chrome86-ff82

After:

LOCAL_NAME=cypress-browsers-node14.15.0-chrome86-ff82
stevenlafl commented 3 years ago

I did manage to run Cypress in Lambda myself.. but it's complicated. Before I forget, I wanted to brain-dump this here and outline the challenges I encountered and how I solved them.

Lambda has a maximum of 512mb /tmp space, it mounts read-only all other directories, has a maximum layer size of 250mb, and it has no GPU or multithreading capabilities. There is no shared-space memory: /dev/shm doesn’t exist, and dbus access is forbidden. This makes it very hard to run most things. Cypress and all its binaries are large, and using either layers or /tmp space maximum was a non-starter because Cypress goes beyond even that. I couldn’t fit it in multiple layers, and because Cypress needs write access I’d have to move it all to /tmp anyways, defeating the 512mb maximum. So to save space, I decided to build a docker container for this implementation with Cypress binaries and other dependencies separated out as much as possible. As a result, I had to:

  1. Install a special version of Chromium that uses the swiftshader GL library (https://github.com/alixaxel/chrome-aws-lambda/tree/master/bin)
  2. Chromium will complain even when launched with --version, so I faked the version number output via an “echo” in a shell script that I aliased to /opt/bin/chromium which runs the real chromium binary if the argument isn’t --version. This allows Cypress to detect and use it without generating an error
  3. Other environment variables like XDG_CONFIG_HOME set to /tmp style paths
  4. I needed special command-line arguments to disable a few features (which you’ll find in the repo above) added to Chromium when it started, so I put those in the"before:browser:launch" section of the plugins/index.js file.
  5. Add similar same command-line arguments via ELECTRON_EXTRA_LAUNCH_ARGS environment variable, or Cypress will say that "GPU process has died" a bunch of times and fail before you even run tests.
  6. Install cypress globally via npm, and set the npm cache and Cypress cache directories via environment variables to point to a different directory (in our case /opt/nodejs/.npm and /opt/nodejs/.cypress)
  7. Patch the cypress binary to replace occurrences of /dev/shm to /tmp/shm
  8. Make the lambda function handler chdir into the /tmp space, and then copy the test project’s cypress and node_modules folders, cypress.json, package.json and package-lock.json files there prior to attempting to require any NPM modules. The function also creates some directories under /tmp that are expected, like the chrome user-data directory and fake /tmp/shm

Right now, my /tmp space total is around 124MB, which leaves some room for screenshots and video output. I did add output of video to s3 and observed the result. Right now, for some reason, the video freezes frame at "loading tests," I suspect I'll have to do some more work to get that going properly, but underneath it all I can confirm that the tests run and are returning the desired result.

Anteneh82 commented 3 years ago

@stevenlafl can you share your docker file and handler function ?

stevenlafl commented 2 years ago

@stevenlafl can you share your docker file and handler function ?

I sure can, here is the repository I wrote it under https://github.com/mobomo/cypress-qa

Last I checked this was working. But you might have to insert your own tests, I might have removed those.

TechFounder commented 2 years ago

@stevenlafl Hi just saw your post and repo. Are you using SAM as a substitute for AWS CodeBuild that Kevinold@cypress is recommending? What's the tradeoff of using one and not the other? I've not had experience with either. Thanks!

nhayes84 commented 1 year ago

If anyone is still interested I managed to get cypress to run both headless and headed using chromium on an AWS Lambda using a docker image. It's a .Net container image and the Dockerfile looks like this:

FROM public.ecr.aws/lambda/dotnet:6 as chrome
RUN yum install -y unzip && \   
    curl -Lo "/tmp/chrome-linux.zip" "https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Linux_x64%2F1027016%2Fchrome-linux.zip?alt=media" && \        
    unzip /tmp/chrome-linux.zip -d /opt/

FROM public.ecr.aws/lambda/dotnet:6

WORKDIR /var/task

# Dependencies for Cypress
RUN curl --silent --location https://rpm.nodesource.com/setup_16.x | bash -
RUN yum install -y xorg-x11-server-Xvfb gtk2-devel gtk3-devel libnotify-devel GConf2 nss libXScrnSaver alsa-lib binutils nodejs gdk-pixbuf2

# Install Cypress
RUN unset NODE_OPTIONS
ENV CYPRESS_CACHE_FOLDER=/opt/.cache/Cypress
ENV XDG_CONFIG_HOME=/tmp
ENV HOME=/tmp
ENV NODE_PATH=/var/task/node_modules 

# Speed up builds by not having to redownload cypress
RUN npm install -g npm@8.19.2
RUN npm install --unsafe-perm=true --allow-root cypress@10.8.0 --save-dev
RUN npm install typescript --save-dev

RUN npx cypress verify

RUN rm -rf /opt/.cache/Cypress/10.8.0/Cypress/resources/app/packages/server/lib/environment.js
COPY environment.js /opt/.cache/Cypress/10.8.0/Cypress/resources/app/packages/server/lib/environment.js

RUN rm -rf /opt/.cache/Cypress/10.8.0/Cypress/resources/app/packages/server/lib/browsers/chrome.js
COPY chrome.js /opt/.cache/Cypress/10.8.0/Cypress/resources/app/packages/server/lib/browsers/chrome.js

#Install chrome
RUN yum install atk cups-libs gtk3 libXcomposite alsa-lib \
    libXcursor libXdamage libXext libXi libXrandr libXScrnSaver \
    libXtst pango at-spi2-atk libXt xorg-x11-server-Xvfb which procps \
    xorg-x11-xauth xorg-x11-utils dbus-glib dbus-glib-devel -y

COPY --from=chrome /opt/chrome-linux /opt/chrome

ENV PATH="/var/task:/opt:/opt/chrome:/opt/.cache/Cypress/10.8.0/Cypress:${PATH}"
ENV DISPLAY=":99"
RUN chmod +x /opt/chrome

COPY "bin/Release/lambda-publish"  .

I had to edit the environment.js & chrome.js file to include the following additional flags, I tried to add these in the cypress.config.js file but it never picked them up:

    '--window-size=1920,1080',
    '--force-device-scale-factor=1',
    '--lang=en-GB',
    '--no-sandbox',
    '--incognito',
    '--disable-gpu', // to disable hardware acceleration             
    '--single-process',
    '--no-zygote',
    '--disable-dev-tools',
    '--remote-debugging-port=9222',
    '--disable-setuid-sandbox',
    '--ignore-certificate-errors',
    '--hide-scrollbars',
    '--disable-extensions',
    '--disable-logging',
    '--log-level=3',    
    '--disable-features=VizDisplayCompositor',
    '--disable-features=NetworkService',
    '--dns-prefetch-disable',
    '--disable-extensions',

These flags worked with headed chrome in lambdas when running selenium tests

Finally I started Xvfb with the following:

"Xvfb $DISPLAY -nolisten inet6 -nolisten tcp -nolisten unix -screen 0 1920x1080x24 +extension RANDR >/dev/null 2>&1 &"
"for i in 1 2 3 4 5; do /usr/bin/xdpyinfo -display $DISPLAY >/dev/null 2>&1 && break || sleep '1s'; done" //wait for Xvfb to start
"/usr/bin/xdpyinfo -display $DISPLAY >/dev/null 2>&1 && echo 'In use' || echo 'Free'"; //Check Xvfb has started 

Then run the following cypress run command:

$(npm bin)/cypress run --config '{"video":false,"specPattern":[\"**/actions.cy.js"]}' --project /tmp --browser /opt/chrome/chrome --headed --reporter junit --reporter-options mochaFile=/tmp/result.xml

Note: I copied the spec file to a Test directory in /tmp and copied the cypress.config.js to /tmp

Once the test completes I returned the content of the results xml.

It might not be what people are looking for but thought I'd share in case it helps anyone

manv6 commented 1 year ago

@nhayes84 I'm interested to run cypress in lambda, without any luck yet. Can you give some more deets

  1. Where exactly are you starting xvfb ? from the lambda function itself ?
  2. What are the environment.js and chrome.js files that you copy from your repo when building docker image?
  3. Is the last line COPY "bin/Release/lambda-publish" . copying the lambda function ?

is this going to work with lambda/node docker image ? i.e. public.ecr.aws/lambda/nodejs:14-x86_64

nhayes84 commented 1 year ago

@manv6 Yes Xvfb is started at the beginning of the lambda function however if you don't want to start it yourself just remove ENV DISPLAY=":99" form the dockerfile. You will need to modify the xvfb.js file (found: ./node_modules/cypress/lib/exec/xvfb.js) to include the following additional arguments: '-nolisten', 'inet6', '-nolisten', 'tcp', '-nolisten', 'unix', '+extension', 'RANDR'

The environment.js and chrome.js files are local copies of the files which are installed by cypress. I have just created copies and added the additional flags as mentioned in my original post. You can find them here:

I downloaded the cypress zip file and found them that way. I found it easier to modify them locally then copy them in the dockerfile rather than try to edit them directly in the dockerfile.

Finally yes the last line is copying the lambda function along with the cypress.config.js and spec file. This is default functionality when you create a .Net image container using visual studio.

The key thing for me to get it working was the changes to the environment.js and chrome.js files. Adding the flags allowed me to get past the various gpu errors.

I don't see why you can't get it working with a node docker image, you'd just need to find the locations of the files I've modified and see if changing them works. Hope this helps.

xavierrobitaille commented 1 year ago

@manv6 @nhayes84, here are my two cents. Would love to hear what you think.

I thought I needed to run Cypress on a Lambda, but I am now thinking of using AWS CodeBuild instead. My use case:

I thought it would be easy to run cypress on a lambda, given that I am already successfully running automated cypress tests in AWS CodeBuild (codebuild spawns some kind of lambda / EC2). I didn't anticipate there would be so many issues to get something similar running in a lambda.

After reading through this thread, I think I will be better off setting up my status checks inside of AWS CodeBuild (it's easy to trigger CodeBuild from a scheduler, and the cypress team has paved the way to use cypress in AWS CodeBuild).

Xavier

https://featherfinance.com

manv6 commented 1 year ago

@xavierrobitaille I never gone CodeBuild way cause it is too costy for my needs. I used to run everything in ECS and in parallel but I have a delay in provisioning the ec2 instances. I'm running up to 90 parallel tasks.

That's why I prefer lambdas(cheaper and faster) BUT I cannot make it work yet. I will try @nhayes84 solution asap

manv6 commented 1 year ago

@nhayes84 unfortunately this solution doesn't work on AWS Lambda with lambda nodejs image :( I did everything as described with but the base image.

Where are you running your lambda ? can we take it offline and give you some more details ? evlastos@gmail.com

stevenlafl commented 1 year ago

@manv6 have you tried the Lambda setup in the repository I posted? If that isn't working I'll have to update it.

manv6 commented 1 year ago

@stevenlafl just tried it prctl(PR_SET_NO_NEW_PRIVS) failed [34:1005/090621.623467:FATAL:zygote_communication_linux.cc(254)] Cannot communicate with zygote all the same as you suggest in your repo but cypress 10.8.0

it seems to me that the ELECTRON_EXTRA_LAUNCH_ARGS from handler never loaded

ignore above lines

just managed to load browser args but now I'm getting another error Timed out waiting for the browser to connect. Retrying... is this because of cypress version. ? can you check your suggestion with cypress 10 ?

magJ commented 1 year ago

After a lot of trial and error, I've managed to get cypress to run from a Lambda using a container image and chromium as a browser.

For anyone trying to do the same thing, I've put together a full example project you can refer to.

https://github.com/magJ/cypress-lambda-example

manv6 commented 1 year ago

@magJ tried your solution and only works in aws if you patch Cypress to write in /tmp/shm instead of /dev/shm like below:

Add below block after npm install

# Patch Cypress binary to not use /dev/shm RUN echo $'#!/bin/bash \n\ position=$(strings -t d /opt/cypress/10.10.0/Cypress/Cypress | grep "/dev/shm" | cut -d" " -f1) \n\ for i in $position; do \n\ echo -n "/tmp/shm/" | dd bs=1 of=/opt/cypress/10.10.0/Cypress/Cypress seek="$i" conv=notrunc \n\ done' >> /opt/patch.sh RUN chmod +x /opt/patch.sh RUN /opt/patch.sh

magJ commented 1 year ago

@magJ tried your solution and only works in aws if you patch Cypress to write in /tmp/shm instead of /dev/shm

@manv6 The example as-is works fine for me without patching cypress, I guess since it's using chromium, patching cypress like you demonstrated might makes it work without installing another browser I suppose?

Edit: I've now implemented this electron patching in my repo, electron now works locally when ipc is disabled, but still having problems with it on lambda.

maqtulio commented 5 months ago

Any updates on this?