Angular e2e tests failing in GitHub actions because of Chrome vs Chromedriver version mismatch

Viewed 1592

My open source Angular project had a successfull GitHub action to lint, build, test, and e2eeverything. However, since a short while, I'm seeing this:

[00:20:01] I/launcher - Running 1 instances of WebDriver
[00:20:01] I/direct - Using ChromeDriver directly...
[00:20:07] E/launcher - session not created: This version of ChromeDriver only supports Chrome version 85
  (Driver info: chromedriver=85.0.4183.87 (cd6713ebf92fa1cacc0f1a598df280093af0c5d7-refs/branch-heads/4183@{#1689}),platform=Linux 5.3.0-1034-azure x86_64)
[00:20:07] E/launcher - SessionNotCreatedError: session not created: This version of ChromeDriver only supports Chrome version 85
  (Driver info: chromedriver=85.0.4183.87 (cd6713ebf92fa1cacc0f1a598df280093af0c5d7-refs/branch-heads/4183@{#1689}),platform=Linux 5.3.0-1034-azure x86_64)
    at Object.checkLegacyResponse (/home/runner/work/sample-angular-oauth2-oidc-with-auth-guards/sample-angular-oauth2-oidc-with-auth-guards/node_modules/selenium-webdriver/lib/error.js:546:15)
    at parseHttpResponse (/home/runner/work/sample-angular-oauth2-oidc-with-auth-guards/sample-angular-oauth2-oidc-with-auth-guards/node_modules/selenium-webdriver/lib/http.js:509:13)
    at /home/runner/work/sample-angular-oauth2-oidc-with-auth-guards/sample-angular-oauth2-oidc-with-auth-guards/node_modules/selenium-webdriver/lib/http.js:441:30
    at processTicksAndRejections (internal/process/task_queues.js:97:5)

To a degree this makes sense, because the GitHub image contains Chrome 84, and it seems that version 85 of chromedriver is being downloaded. But it also does not make sense, since Angular uses webdriver-manager which I presume should manage the right version of chromedriver? Why is it installing the wrong version? Or do I have things backwards?

My situation should be reproducible by forking the repository and setting up the same GitHub Actions, here's the relevant bits of workflow:

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2

    # Based on: https://docs.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows#example-using-the-cache-action
    - name: Cache node modules
      uses: actions/cache@v2
      env:
        cache-name: cache-node-modules
      with:
        # npm cache files are stored in `~/.npm` on Linux/macOS
        path: ~/.npm
        key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.os }}-build-${{ env.cache-name }}-
          ${{ runner.os }}-build-
          ${{ runner.os }}-

    - name: Install dependencies
      run: npm ci

    - name: Linting
      run: npm run lint

    - name: Build
      run: npm run build -- --prod

    - name: Tests
      run: npm run e2e -- --configuration=ci

The angular.json target is simple too:

"e2e": {
  "builder": "@angular-devkit/build-angular:protractor",
  "options": {
    "protractorConfig": "e2e/protractor.conf.js",
    "devServerTarget": "sample-auth-guards:serve"
  },
  "configurations": {
    "production": {
      "devServerTarget": "sample-auth-guards:serve:production"
    },
    "ci": {
      "devServerTarget": "sample-auth-guards:serve:production",
      "protractorConfig": "e2e/protractor-ci.conf.js"
    }
  }
}

I tried updating all NPM devdependencies, but that didn't help.

I've also tried setting webdriverUpdate=false in the workflow (presuming that since the image from GitHub claims to have Chrome 84 and the associated chromedriver version), but that leads to:

[16:43:43] I/launcher - Running 1 instances of WebDriver
[16:43:44] I/direct - Using ChromeDriver directly...
[16:43:44] E/direct - Error code: 135
[16:43:44] E/direct - Error message: Could not find update-config.json. Run 'webdriver-manager update' to download binaries.
[16:43:44] E/direct - Error: Could not find update-config.json. Run 'webdriver-manager update' to download binaries.

Many "solutions" (for example this related SO thread) suggest updating chromedriver to a specific chrome version. But that's not what I want, because then whenever GitHub updates their image I'll be in the same problem again.

Also important to note: I'd love to have a CI-specific solution. Developers (i.e. me) will have latest Chrome on their machine usually, so running npm run e2e should still give me the right chromedriver for my machine.

Bottom line: how can I make an Angular project download the right version of chromedriver? That is: the one that belongs to the version of Chrome installed on the machine?

2 Answers

Issue is with protractor not github actions. It seems like this issue happens a lot. Basically protractor updates chrome driver to latest before chrome comes out with stable version so the disparity causes this setup to break. As you already mentioned currently protractor is downloading version 85 but chrome version is 84.

Source: https://github.com/angular/protractor/issues/5460

Forked your code and found two solutions

Solution 1: Update google chrome to latest inside workflow

  - run: sudo apt-get install google-chrome-stable

This will install current latest stable version of google chrome which is 85. Appears to have been released so this allows you to run everything normally. For future reference, this only worked because chrome finally released 85 as stable version, if not, we would have run into the same issue and we would have had to do same version extraction setup as we do in solution 2.

Pipeline showing that it worked: https://github.com/meroware/sample-angular-oauth2-oidc-with-auth-guards/actions/runs/230800136

If you want to do an actual fix where you don't have to worry about versioning parity then you can do the following.

Solution 2: Run inside docker to make sure our builds are clean

Pipeline showing that it worked: https://github.com/meroware/sample-angular-oauth2-oidc-with-auth-guards/runs/1046824367

Workflow Code Url: https://github.com/meroware/sample-angular-oauth2-oidc-with-auth-guards/blob/master/.github/workflows/ci-workflow.yml

Here is a quick snippet of the changes

     container:
        image: ubuntu:trusty
     steps:
     - uses: actions/checkout@v2
     - name: Use Node.js
       uses: actions/setup-node@v1
       with:
         node-version: '14.x'
     # Based on: https://docs.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows#example-using-the-cache-action
     - name: Cache node modules
       uses: actions/cache@v2
       env:
         cache-name: cache-node-modules
       with:
         # npm cache files are stored in `~/.npm` on Linux/macOS
         path: ~/.npm
         key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
         restore-keys: |
           ${{ runner.os }}-build-${{ env.cache-name }}-
           ${{ runner.os }}-build-
           ${{ runner.os }}-
     - name: Setup chrome driver environment
       run: |
         apt-get update # Remove if running outside container
         apt-get clean # Remove if running outside container
         apt-get install -y wget # Remove if running outside container
         wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - # Remove if running outside container
         echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list # Remove if running outside container
         apt-get -y update # Remove if running outside container
         apt-get install -y google-chrome-stable # If not running in docker then run this line with sudo
         VERSION=`google-chrome --version | egrep -o '[0-9]+.[0-9]+' | head -1` # Get chrome version that we just installed
         npm i webdriver-manager@latest -D # Install webdriver manager locally
         npm i chromedriver --chromedriver_version=$VERSION -D # Install chrome driver to the version that we got from google chrome installation above

I remixed the other answer into my final solution. I want to share it separately because for others it might also be as simple as these few lines:

- name: Update Chrome # See https://stackoverflow.com/q/63651059/419956
  run: |
    wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
    sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
    sudo apt-get update
    sudo apt-get --only-upgrade install google-chrome-stable

Somehow the image from GitHub Actions I was using needed Google's apt sources as well (even though it had Google Chrome already pre-installed), after that the update + install trick started to work fine.

Related