Repository: cypress-io/cypress-docker-images
Pull request #1353: feat: add geckodriver to factory process
Author: login: MikeMcC399
Labels: name: type: enhancement
name: topic: build process
Created: 2025-05-19T10:53:50Z | Merged: 2025-05-23T14:49:18Z

- closes https://github.com/cypress-io/cypress-docker-images/issues/1351

## Situation

The [mozilla/geckodriver](https://github.com/mozilla/geckodriver) is required to test Firefox. It is not part of the Firefox distribution, nor is it included in Cypress. If the driver is unavailable, then testing against Firefox fails. This is typically the case in an air-gapped environment.

If an attempt is made to run Cypress against a Firefox browser in a Cypress Docker container using `cypress/browsers` or `cypress/included` images, Cypress tries to download [mozilla/geckodriver](https://github.com/mozilla/geckodriver). In an air-gapped environment (no Internet access) the download fails and it is not possible to test against Firefox. The same applies to any Docker images built for Firefox with the current version of `cypress/factory`.

Secondly, in a regular environment with Internet connectivity, and no cached version of the [mozilla/geckodriver](https://github.com/mozilla/geckodriver) stored in the Docker image, the driver version defaults to the latest, which means that the test configuration with Firefox is non-deterministic.

## Assessment

Cypress uses the npm wrapper package [geckodriver](https://www.npmjs.com/package/geckodriver), bundled into the Cypress binary, in order to ensure the availability of the [mozilla/geckodriver](https://github.com/mozilla/geckodriver) driver for Firefox testing.

By manually installing the [mozilla/geckodriver](https://github.com/mozilla/geckodriver) in a Docker build process, and then setting the [geckodriver](https://github.com/webdriverio-community/node-geckodriver) environment variable [GECKODRIVER_PATH](https://github.com/webdriverio-community/node-geckodriver/blob/main/README.md#customgeckodriverpath), the wrapper package is instructed not to download and to use the locally stored driver instead.

If the [mozilla/geckodriver](https://github.com/mozilla/geckodriver) can first be built into a Cypress Docker image in an environment **with** Internet connectivity, the Docker image can later be used in an environment **without** Internet to test against Firefox.

## Change

Introduce a new Cypress build parameter `GECKODRIVER_VERSION` to direct the Cypress factory build process to install the corresponding version of [mozilla/geckodriver](https://github.com/mozilla/geckodriver) into a Cypress Docker image being built. The driver is stored in the [GECKODRIVER_PATH](https://github.com/webdriverio-community/node-geckodriver/blob/main/README.md#customgeckodriverpath) `/opt/geckodriver/geckodriver`.

The published images `cypress/browsers` and `cypress/included` are left unchanged, with no `geckodriver` pre-installed. An enhancement to these images is left for a follow-on PR.

This is a backwards-compatible feature addition.

### Detailed changes

- Bump `FACTORY_VERSION`

- Add documentation to [factory/README.md](https://github.com/cypress-io/cypress-docker-images/blob/master/factory/README.md) with new `GECKODRIVER_VERSION` section

- Update the [CONTRIBUTING](https://github.com/cypress-io/cypress-docker-images/blob/master/CONTRIBUTING.md) document

- Add the Cypress Docker parameter `GECKODRIVER_VERSION` to [factory/.env](https://github.com/cypress-io/cypress-docker-images/blob/master/factory/.env) to specify a version of the driver package `mozilla/geckodriver` from [mozilla/geckodriver](https://github.com/mozilla/geckodriver) in the [Cypress Docker factory build process](https://github.com/cypress-io/cypress-docker-images/blob/master/factory/README.md). The default is set to the current latest version `0.36.0`.

- Add install scripts for `mozilla/geckodriver` to the `cypress/factory` image so that the installation is compatible with use by the npm wrapper package [geckodriver](https://www.npmjs.com/package/geckodriver) bundled in the Cypress binary (see https://github.com/cypress-io/cypress/blob/develop/packages/server/package.json) since [cypress@13.15.1](https://docs.cypress.io/app/references/changelog#13-15-1).

- Use new install scripts in [factory/factory.Dockerfile](https://github.com/cypress-io/cypress-docker-images/blob/master/factory/factory.Dockerfile), setting [GECKODRIVER_PATH](https://github.com/webdriverio-community/node-geckodriver/blob/main/README.md#customgeckodriverpath) to `/opt/geckodriver/geckodriver`

- Harmonize the use of `platformFilename` for `Firefox` and `geckodriver` scripts. (Filename conventions are different for the two different package downloads.)

- Add new build compose services to [factory/docker-compose.yml](https://github.com/cypress-io/cypress-docker-images/blob/master/factory/docker-compose.yml) and to [factory/test-project/docker-compose.yml](https://github.com/cypress-io/cypress-docker-images/blob/master/factory/test-project/docker-compose.yml)

- Add [CircleCI tests](https://github.com/cypress-io/cypress-docker-images/blob/master/circle.yml)

- Add `Dockerfile.factory` to the following example directories to allow easier local testing:
  - [examples/basic](https://github.com/cypress-io/cypress-docker-images/tree/master/examples/basic)
  - [examples/basic--mini](https://github.com/cypress-io/cypress-docker-images/tree/master/examples/basic--mini)
  - [examples/firefox-esr](https://github.com/cypress-io/cypress-docker-images/tree/master/examples/firefox-esr)



Diff:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 079690ea5d..dd64f99b13 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -61,13 +61,13 @@ docker compose run --build --rm test-factory-all-included
 
 The [factory/.env](./factory/.env) in the `master` branch should be maintained with the latest stable and supported versions. An exception is the `FACTORY_DEFAULT_NODE_VERSION` which should be set to the [Node.js Active LTS](https://nodejs.org/en/about/previous-releases) version, not the "Current" version.
 
-To publish a new image for `factory`, `base`, `browsers`, or `included`, open a PR with the desired version(s) updated in the [factory/.env](./factory/.env) file. If you change any of the following environment variables in [factory/.env](./factory/.env), then you should also bump the `FACTORY_VERSION` in the same file and make a note of the change in the factory [CHANGELOG](./factory/CHANGELOG.md):
+To publish a new image for `factory`, `base`, `browsers`, or `included`, open a PR with the desired version(s) updated in the [factory/.env](./factory/.env) file. If you change installation scripts or any of the following environment variables in [factory/.env](./factory/.env), then you should also bump the `FACTORY_VERSION` in the same file and make a note of the change in the factory [CHANGELOG](./factory/CHANGELOG.md):
 
 - `BASE_IMAGE`
 - `FACTORY_DEFAULT_NODE_VERSION`
 - `YARN_VERSION`
 
-You should not change the `FACTORY_VERSION` or make an entry into the factory [CHANGELOG](./factory/CHANGELOG.md) if you are only changing browser versions or the Cypress version.
+You should not change the `FACTORY_VERSION` or make an entry into the factory [CHANGELOG](./factory/CHANGELOG.md) if you are only changing browser versions, geckodriver version or the Cypress version.
 
 Once the PR is merged into the `master` branch, the corresponding images will be pushed to [Docker Hub](https://hub.docker.com/u/cypress) and to the [Amazon ECR (Elastic Container Registry) Public Gallery](https://gallery.ecr.aws/cypress-io) via an automated script run through [CircleCI](circle.yml). Please check that the CI jobs pass after merge. Any CI failure can cause the release process to be interrupted.
 
diff --git a/circle.yml b/circle.yml
index fbb22a20bc..df5fc24058 100644
--- a/circle.yml
+++ b/circle.yml
@@ -260,6 +260,7 @@ workflows:
                   test-factory-cypress-included-electron,
                   test-factory-cypress-included-electron-non-root-user,
                   test-factory-cypress-included-firefox,
+                  test-factory-cypress-included-firefox-geckodriver,
                   test-factory-cypress-included-firefox-non-root-user,
                   test-factory-all-included-electron-only,
                 ]
@@ -280,6 +281,7 @@ workflows:
                   test-factory-cypress-included-electron-non-root-user,
                   test-factory-cypress-included-chrome,
                   test-factory-cypress-included-firefox,
+                  test-factory-cypress-included-firefox-geckodriver,
                   test-factory-cypress-included-firefox-non-root-user,
                   test-factory-cypress-included-edge,
                   test-factory-all-included,
diff --git a/examples/basic-mini/Dockerfile.factory b/examples/basic-mini/Dockerfile.factory
new file mode 100644
index 0000000000..d11f5ac4fd
--- /dev/null
+++ b/examples/basic-mini/Dockerfile.factory
@@ -0,0 +1,3 @@
+FROM cypress/factory
+COPY . /opt/app
+WORKDIR /opt/app
diff --git a/examples/basic/Dockerfile.factory b/examples/basic/Dockerfile.factory
new file mode 100644
index 0000000000..27abdd09aa
--- /dev/null
+++ b/examples/basic/Dockerfile.factory
@@ -0,0 +1,4 @@
+FROM cypress/factory
+COPY . /opt/app
+WORKDIR /opt/app
+RUN npx cypress install # Install Cypress binary into image
diff --git a/examples/firefox-esr/Dockerfile.factory b/examples/firefox-esr/Dockerfile.factory
new file mode 100644
index 0000000000..c016a25682
--- /dev/null
+++ b/examples/firefox-esr/Dockerfile.factory
@@ -0,0 +1,6 @@
+FROM cypress/factory
+COPY . /opt/app
+WORKDIR /opt/app
+RUN apt-get update                 # Update package index
+RUN apt-get install firefox-esr -y # Install Firefox ESR
+RUN npx cypress install            # Install Cypress binary
diff --git a/factory/.env b/factory/.env
index 6e187e99f9..4006a7c240 100644
--- a/factory/.env
+++ b/factory/.env
@@ -18,7 +18,7 @@ NODE_VERSION="${FACTORY_DEFAULT_NODE_VERSION}"
 
 # Update the FACTORY_VERSION to deploy cypress/factory if you make changes to
 # BASE_IMAGE, FACTORY_DEFAULT_NODE_VERSION, YARN_VERSION, factory.Dockerfile or installScripts
-FACTORY_VERSION='5.8.4'
+FACTORY_VERSION='5.9.0'
 
 # Chrome versions: https://www.ubuntuupdates.org/package/google_chrome/stable/main/base/google-chrome-stable
 # Linux/amd64 only
@@ -35,6 +35,12 @@ EDGE_VERSION='136.0.3240.76-1'
 # Linux/amd64 for all versions, Linux/arm64 for versions 136.0 and above
 FIREFOX_VERSION='138.0.4'
 
+# Geckodriver versions: https://github.com/mozilla/geckodriver/releases
+# Geckodriver documentation: https://firefox-source-docs.mozilla.org/testing/geckodriver/index.html
+# Linux/amd64 and Linux/arm64 for all versions
+# Minimum version is 0.34.0
+GECKODRIVER_VERSION='0.36.0'
+
 # Yarn versions: https://www.npmjs.com/package/yarn and
 # Yarn v1 Classic only https://classic.yarnpkg.com/latest-version
 # Yarn Modern (versions 2 and above) are not supported https://yarnpkg.com/
diff --git a/factory/CHANGELOG.md b/factory/CHANGELOG.md
index cfd5d68ff1..cb68578660 100644
--- a/factory/CHANGELOG.md
+++ b/factory/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Change log
 
+## 5.9.0
+
+- Added ability to install geckodriver with `GECKODRIVER_VERSION`. Addresses [#1351](https://github.com/cypress-io/cypress-docker-images/issues/1351).
+
 ## 5.8.4
 
 - Updated default node version from `22.15.1` to `22.16.0`. Addressed in [#1358](https://github.com/cypress-io/cypress-docker-images/pull/1358).
diff --git a/factory/README.md b/factory/README.md
index d200335afe..00ac2ebfe3 100644
--- a/factory/README.md
+++ b/factory/README.md
@@ -6,6 +6,7 @@
 - Yarn v1 Classic
 - Chrome
 - Firefox
+- geckodriver
 - Edge
 - Cypress
 
@@ -67,7 +68,7 @@ Example: `CYPRESS_VERSION='13.11.0'`
 
 ### CHROME_VERSION
 
-The version of Chrome to install. If the `ARG` variable is unset or an empty string, Chrome is not installed. The exact version must be used, no wildcards or shorthands are supported.
+The version of Google Chrome to install. If the `ARG` variable is unset or an empty string, Chrome is not installed. The exact version must be used, no wildcards or shorthands are supported.
 
 Example: `CHROME_VERSION='131.0.6778.264-1'`
 
@@ -77,7 +78,7 @@ This browser is currently available only for the `Linux/amd64` platform.
 
 ### FIREFOX_VERSION
 
-The version of Firefox to install. If the `ARG` variable is unset or an empty string, Firefox is not installed. The exact version must be used, no wildcards or shorthands are supported.
+The version of Mozilla Firefox to install. If the `ARG` variable is unset or an empty string, Firefox is not installed. The exact version must be used, no wildcards or shorthands are supported.
 
 Example: `FIREFOX_VERSION='134.0'`
 
@@ -85,9 +86,17 @@ Example: `FIREFOX_VERSION='134.0'`
 
 This browser is available for the `Linux/amd64` platform in all versions, and for the `Linux/arm64` platform in Firefox `136.0` and above.
 
+### GECKODRIVER_VERSION
+
+The version of [Mozilla geckodriver](https://firefox-source-docs.mozilla.org/testing/geckodriver/index.html) to install. If the `ARG` variable is unset or an empty string, the `geckodriver` is not installed. The exact version must be used, no wildcards or shorthands are supported. A minimum version `0.34.0` is required.
+
+Example: `GECKODRIVER_VERSION='0.36.0'`
+
+[Mozilla geckodriver releases](https://github.com/mozilla/geckodriver/releases) provides drivers for both `Linux/amd64` and `Linux/arm64` platforms. Cypress release [13.15.1](https://docs.cypress.io/app/references/changelog#13-15-1), and above, require `geckodriver` when testing Firefox. If `GECKODRIVER_VERSION` is not defined, Cypress uses the npm wrapper package [geckodriver](https://www.npmjs.com/package/geckodriver) to download [Mozilla geckodriver](https://github.com/mozilla/geckodriver) at run-time. Specifying `GECKODRIVER_VERSION` is advised if testing in an air-gapped environment, and to use a defined version of `geckodriver`.
+
 ### EDGE_VERSION
 
-The version of Edge to install. If the `ARG` variable is unset or an empty string, Edge is not installed. The exact version must be used, no wildcards or shorthands are supported.
+The version of Microsoft Edge to install. If the `ARG` variable is unset or an empty string, Edge is not installed. The exact version must be used, no wildcards or shorthands are supported.
 
 Example: `EDGE_VERSION='131.0.2903.112-1'`
 
diff --git a/factory/docker-compose.yml b/factory/docker-compose.yml
index 5c09b70019..b5afd2e7c1 100644
--- a/factory/docker-compose.yml
+++ b/factory/docker-compose.yml
@@ -112,6 +112,20 @@ services:
         - ${REPO_PREFIX-}cypress/firefox:${FIREFOX_VERSION}
     command: firefox --version
 
+  firefox-geckodriver:
+    image: ${REPO_PREFIX-}cypress/firefox-geckodriver
+    build:
+      target: default_image
+      context: .
+      args:
+        NODE_VERSION: ${NODE_VERSION}
+        FACTORY_VERSION: ${FACTORY_VERSION}
+        FIREFOX_VERSION: ${FIREFOX_VERSION}
+        GECKODRIVER_VERSION: ${GECKODRIVER_VERSION}
+      tags:
+        - ${REPO_PREFIX-}cypress/firefox-geckodriver:${FIREFOX_VERSION}-${GECKODRIVER_VERSION}
+    command: firefox --version
+
   # webkit:
   #   image: ${REPO_PREFIX-}cypress/webkit
   #   build:
@@ -179,6 +193,21 @@ services:
         - ${REPO_PREFIX-}cypress/cypress-firefox:cypress-${CYPRESS_VERSION}-firefox-${FIREFOX_VERSION}
     command: node -v
 
+  cypress-firefox-geckodriver:
+    image: ${REPO_PREFIX-}cypress/cypress-firefox-geckodriver
+    build:
+      target: default_image
+      context: .
+      args:
+        NODE_VERSION: ${NODE_VERSION}
+        FACTORY_VERSION: ${FACTORY_VERSION}
+        CYPRESS_VERSION: ${CYPRESS_VERSION}
+        FIREFOX_VERSION: ${FIREFOX_VERSION}
+        GECKODRIVER_VERSION: ${GECKODRIVER_VERSION}
+      tags:
+        - ${REPO_PREFIX-}cypress/cypress-firefox:cypress-${CYPRESS_VERSION}-firefox-${FIREFOX_VERSION}-geckodriver-${GECKODRIVER_VERSION}
+    command: node -v
+
   ## Test image
   test-node-default:
     build:
diff --git a/factory/factory.Dockerfile b/factory/factory.Dockerfile
index 8f9851e9a3..d8357690b4 100644
--- a/factory/factory.Dockerfile
+++ b/factory/factory.Dockerfile
@@ -103,6 +103,16 @@ ONBUILD ARG FIREFOX_VERSION
 
 ONBUILD RUN node /opt/installScripts/firefox/install-firefox-version.js ${FIREFOX_VERSION}
 
+# Install Geckodriver: optional
+# Used with Firefox
+ONBUILD ARG GECKODRIVER_VERSION
+# If geckodriver is installed, make it available to npm package geckodriver
+# See https://github.com/webdriverio-community/node-geckodriver/blob/main/README.md#customgeckodriverpath
+# Path is only set if geckodriver is installed
+# see Dockerfile environment variable syntax https://docs.docker.com/reference/dockerfile/#environment-replacement
+ONBUILD ENV GECKODRIVER_PATH=${GECKODRIVER_VERSION:+/opt/geckodriver/geckodriver}
+ONBUILD RUN node /opt/installScripts/geckodriver/install-geckodriver-version.js ${GECKODRIVER_VERSION}
+
 # TODO: Globally installed webkit currently isn't found, see issue https://github.com/cypress-io/cypress/issues/25344
 # Install Webkit: optional
 # ONBUILD ARG WEBKIT_VERSION
diff --git a/factory/installScripts/firefox/default.sh b/factory/installScripts/firefox/default.sh
index c71132e959..afad91022a 100755
--- a/factory/installScripts/firefox/default.sh
+++ b/factory/installScripts/firefox/default.sh
@@ -4,7 +4,7 @@
 #
 # $1: version (example: 136.0)
 # $2: compression (xz or bz2)
-# $3: platform (linux-x86_64 or linux-aarch64)
+# $3: platformFilename (linux-x86_64 or linux-aarch64)
 
 apt-get update \
   && apt-get install -y \
diff --git a/factory/installScripts/firefox/install-firefox-version.js b/factory/installScripts/firefox/install-firefox-version.js
index 32f6c61fa5..9b8ad79d15 100755
--- a/factory/installScripts/firefox/install-firefox-version.js
+++ b/factory/installScripts/firefox/install-firefox-version.js
@@ -9,14 +9,14 @@ if (!firefoxVersion) {
 }
 
 const architecture = process.arch
-let platform
+let platformFilename
 
 switch (architecture) {
   case 'x64':
-    platform = 'linux-x86_64'
+    platformFilename = 'linux-x86_64'
     break
   case 'arm64':
-    platform = 'linux-aarch64'
+    platformFilename = 'linux-aarch64'
     if (firefoxVersion >= '136.0') {
       break
     }
@@ -41,8 +41,8 @@ if (firefoxVersion >= '135.0') {
   compression = 'xz'
 }
 
-// Insert logic here if needed to run a different install script based on chrome version.
-const install = spawn(`${__dirname}/default.sh`, [firefoxVersion, compression, platform], { stdio: 'inherit' })
+// Insert logic here if needed to run a different install script based on Firefox version.
+const install = spawn(`${__dirname}/default.sh`, [firefoxVersion, compression, platformFilename], { stdio: 'inherit' })
 
 install.on('error', function (error) {
   console.log('child process errored with ' + error.toString())
diff --git a/factory/installScripts/geckodriver/default.sh b/factory/installScripts/geckodriver/default.sh
new file mode 100755
index 0000000000..7761832495
--- /dev/null
+++ b/factory/installScripts/geckodriver/default.sh
@@ -0,0 +1,12 @@
+#! /bin/bash
+
+# geckodriver for Firefox does not have a Debian package, so instead we download the tar to unzip.
+#
+# $1: version (example: 0.36.0)
+# $2: platformFilename (linux64 or linux-aarch64)
+
+wget --no-verbose -O /tmp/geckodriver.tar.gz https://github.com/mozilla/geckodriver/releases/download/v${1}/geckodriver-v${1}-${2}.tar.gz \
+  && mkdir -p /opt/geckodriver \
+  && tar -C /opt/geckodriver -xaf /tmp/geckodriver.tar.gz \
+  && chown -R root:root /opt/geckodriver \
+  && rm /tmp/geckodriver.tar.gz \
diff --git a/factory/installScripts/geckodriver/install-geckodriver-version.js b/factory/installScripts/geckodriver/install-geckodriver-version.js
new file mode 100755
index 0000000000..d4fdbe7bc7
--- /dev/null
+++ b/factory/installScripts/geckodriver/install-geckodriver-version.js
@@ -0,0 +1,50 @@
+#!/usr/bin/node
+const { spawn } = require('child_process')
+
+const geckodriverVersion = process.argv.slice(2)[0]
+
+if (!geckodriverVersion) {
+  console.log('No geckodriver version provided, skipping geckodriver install')
+  process.exit(0)
+}
+
+// See https://firefox-source-docs.mozilla.org/testing/geckodriver/Support.html for compatibility matrix
+// geckodriver < 0.34.0 only supports up to Firefox 120, which is no longer supported by Cypress
+const MIN_GECKO = '0.34.0'
+
+if (geckodriverVersion < MIN_GECKO) {
+  console.log(`geckodriver version ${geckodriverVersion} provided, minimum version ${MIN_GECKO} required, skipping geckodriver install`)
+  process.exit(0)
+}
+
+const architecture = process.arch
+// Platform filenames taken from https://github.com/mozilla/geckodriver/releases
+let platformFilename
+
+switch (architecture) {
+  case 'x64':
+    platformFilename = 'linux64'
+    break
+  case 'arm64':
+    platformFilename = 'linux-aarch64'
+    break
+
+  default:
+    console.log(`Unsupported architecture ${architecture} for geckodriver installation, skipping install`)
+    process.exit(0)
+}
+
+console.log(`Installing geckodriver version ${geckodriverVersion} for ${architecture}`)
+
+// Insert logic here if needed to run a different install script based on geckodriver version.
+const install = spawn(`${__dirname}/default.sh`, [geckodriverVersion, platformFilename], { stdio: 'inherit' })
+
+install.on('error', function (error) {
+  console.log('child process errored with ' + error.toString())
+  process.exit(1)
+})
+
+install.on('exit', function (code) {
+  console.log('child process exited with code ' + code.toString())
+  process.exit(code)
+})
diff --git a/factory/test-project/docker-compose.yml b/factory/test-project/docker-compose.yml
index b0b5ea4db4..52960892e9 100644
--- a/factory/test-project/docker-compose.yml
+++ b/factory/test-project/docker-compose.yml
@@ -48,6 +48,16 @@ services:
       context: .
     command: npm run test -- -b firefox
 
+  test-factory-firefox-geckodriver:
+    build:
+      args:
+        NODE_VERSION: ${NODE_VERSION}
+        FIREFOX_VERSION: ${FIREFOX_VERSION}
+        GECKODRIVER_VERSION: ${GECKODRIVER_VERSION}
+        BASE_TEST_IMAGE: cypress/factory:${FACTORY_VERSION}
+      context: .
+    command: npm run test -- -b firefox
+
   test-factory-edge:
     build:
       args:
@@ -100,6 +110,18 @@ services:
       context: .
     command: cypress run -b firefox
 
+  test-factory-cypress-included-firefox-geckodriver:
+    build:
+      args:
+        NODE_VERSION: ${NODE_VERSION}
+        CYPRESS_VERSION: ${CYPRESS_VERSION}
+        FIREFOX_VERSION: ${FIREFOX_VERSION}
+        GECKODRIVER_VERSION: ${GECKODRIVER_VERSION}
+        BASE_TEST_IMAGE: cypress/factory:${FACTORY_VERSION}
+      dockerfile: included.Dockerfile
+      context: .
+    command: cypress run -b firefox
+
   test-factory-cypress-included-firefox-non-root-user:
     user: node
     build:


Reviews:
user: login: AtofStryker
body: Gave everything a test locally. This looks great @MikeMcC399. Thank you!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T14:30:27Z
user: login: MikeMcC399
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-23T14:55:25Z

Review comments:
diff_hunk: @@ -0,0 +1,50 @@
+#!/usr/bin/node
+const { spawn } = require('child_process')
+
+const geckodriverVersion = process.argv.slice(2)[0]
+
+if (!geckodriverVersion) {
+  console.log('No geckodriver version provided, skipping geckodriver install')
+  process.exit(0)
+}
+
+// See https://firefox-source-docs.mozilla.org/testing/geckodriver/Support.html for compatibility matrix
+// geckodriver < 0.34.0 only supports up to Firefox 120, which is no longer supported by Cypress
+const MIN_GECKO = '0.34.0'
+
+if (geckodriverVersion < MIN_GECKO) {
+  console.log(`geckodriver version ${geckodriverVersion} provided, minimum version ${MIN_GECKO} required, skipping geckodriver install`)
path: factory/installScripts/geckodriver/install-geckodriver-version.js
user: login: AtofStryker
body: Would `console.error` be more appropriate? I think we use `log` in similar error contexts so likely a no.

```suggestion
  console.error(`geckodriver version ${geckodriverVersion} provided, minimum version ${MIN_GECKO} required, skipping geckodriver install`)
```
created_at: 2025-05-23T14:06:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,50 @@
+#!/usr/bin/node
+const { spawn } = require('child_process')
+
+const geckodriverVersion = process.argv.slice(2)[0]
+
+if (!geckodriverVersion) {
+  console.log('No geckodriver version provided, skipping geckodriver install')
+  process.exit(0)
+}
+
+// See https://firefox-source-docs.mozilla.org/testing/geckodriver/Support.html for compatibility matrix
+// geckodriver < 0.34.0 only supports up to Firefox 120, which is no longer supported by Cypress
+const MIN_GECKO = '0.34.0'
+
+if (geckodriverVersion < MIN_GECKO) {
+  console.log(`geckodriver version ${geckodriverVersion} provided, minimum version ${MIN_GECKO} required, skipping geckodriver install`)
path: factory/installScripts/geckodriver/install-geckodriver-version.js
user: login: MikeMcC399
body: The risk with using `error` is that it kills the whole build. I've gone with `log` for consistency and to make sure that the build doesn't get killed if the version is too low. Simply skipping and logging the fact is less intrusive.

In general the build process does not do consistency checks across all parameters. It's left to the user to make sure they choose sensible combinations. See comments under https://github.com/cypress-io/cypress-docker-images/tree/master/factory#version-testing
created_at: 2025-05-23T14:55:25Z
author_association: COLLABORATOR

PR comments:
user: login: cypress-app-bot
created_at: 2025-05-19T10:54:08Z
body: - Create a [Draft Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests) if your PR is not ready for review. [Mark the PR as **Ready for Review**](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review) when you're ready for a Cypress team member to review the PR.
author_association: NONE
user: login: MikeMcC399
created_at: 2025-05-19T10:55:22Z
body: Preview documentation

- https://github.com/MikeMcC399/cypress-docker-images/blob/add/factory-geckodriver/factory/README.md#geckodriver_version
author_association: COLLABORATOR
user: login: MikeMcC399
created_at: 2025-05-19T11:09:24Z
body: ## Tests

### CircleCI tests

Include additional `test-factory-cypress-included-firefox-geckodriver` tests for `amd64` and `arm64`

### Local tests

Test with Docker Desktop Linux `4.41.2` under Ubuntu `24.04.2` LTS, `amd64`

```shell
cd factory
docker compose build factory
cd ..
```

#### Build tests


```shell
cd examples/basic
docker build -f Dockerfile.factory --build-arg GECKODRIVER_VERSION=0.36.0 -t firefox-test .
cd ../..
```

- use `--progress plain` to see skipped messages
- use `--no-cache` to repeat test

 | `GECKODRIVER_VERSION` | Build message      |
 | --------------------- | ------------------ |
 | `0.36.0`              | Success            |
 | `0.34.0`              | Success            |
 | `0.99.0`              | Fail 404 Not Found |
 | `0.33.0`              | Skip               |

#### Run tests

Build custom images with network connected:

Edit: updated builds to latest versions

```shell
cd examples/basic
npm ci
docker build -f Dockerfile.factory \
--build-arg FIREFOX_VERSION=138.0.4 --build-arg GECKODRIVER_VERSION=0.36.0 \
-t firefox-browsers-test .

cd ../basic-mini
docker build -f Dockerfile.factory \
--build-arg CYPRESS_VERSION=14.4.0 --build-arg FIREFOX_VERSION=138.0.4 --build-arg GECKODRIVER_VERSION=0.36.0 \
-t firefox-included-test .

docker build -f Dockerfile.factory \
--build-arg CYPRESS_VERSION=13.15.0 --build-arg FIREFOX_VERSION=138.0.4 \
-t firefox-included-13.15.0-test .

cd ../firefox-esr
npm ci
docker build -f Dockerfile.factory --build-arg GECKODRIVER_VERSION=0.36.0 \
-t firefox-esr-test .

cd ../..
```

Disconnect network and run each image:

```shell
cd examples/basic
docker run -it --rm --entrypoint bash -v .:/app -w /app firefox-browsers-test -c "npx cypress run -b firefox"

cd ../basic-mini
docker run -it --rm --entrypoint cypress -v .:/app -w /app firefox-included-test run -b firefox
docker run -it --rm --entrypoint cypress -v .:/app -w /app -u node firefox-included-test run -b firefox # test non-root
docker run -it --rm --entrypoint cypress -v .:/app -w /app firefox-included-13.15.0-test run -b firefox

cd ../firefox-esr
docker run -it --rm --entrypoint bash -v .:/app -w /app firefox-esr-test -c "npx cypress run -b firefox"

cd ../..
```

author_association: COLLABORATOR
user: login: MikeMcC399
created_at: 2025-05-21T17:31:23Z
body: Temporarily in draft state, to avoid race condition with `cypress/factory:latest` tage, as versioning is manually maintained and a new PR #1358 is pending with a lower `FACTORY_VERSION`.
author_association: COLLABORATOR
user: login: AtofStryker
created_at: 2025-05-21T18:07:29Z
body: @MikeMcC399 I'm hoping to take a look at this either today or tomorrow 
author_association: CONTRIBUTOR
user: login: MikeMcC399
created_at: 2025-05-21T18:34:10Z
body: @AtofStryker 

> @MikeMcC399 I'm hoping to take a look at this either today or tomorrow

I'm happy to hear that! 

I've put the PR back into review after resolving the minor conflicts.
author_association: COLLABORATOR
user: login: MikeMcC399
created_at: 2025-05-22T16:41:00Z
body: - Please make sure that issue https://github.com/cypress-io/cypress-docker-images/issues/1359 is resolved before merging this PR, otherwise there will be a missing `cypress/factory:5.8.4` image in the sequence
author_association: COLLABORATOR
user: login: MikeMcC399
created_at: 2025-05-22T18:13:58Z
body: Re-tested locally with latest commit and running containers successfully without network connection.
author_association: COLLABORATOR