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

[Question]: How to cache on github actions? #7249

Closed
YonatanKra opened this issue Jun 21, 2021 · 53 comments
Closed

[Question]: How to cache on github actions? #7249

YonatanKra opened this issue Jun 21, 2021 · 53 comments

Comments

@YonatanKra
Copy link

Hi,
I've setup github actions on Linux and it works fine.
I'm now running the same tests on MacOS and the binaries are not the same, so caching the installation is not working (for obvious reasons).
What is the recommended way to cache the playwright binaries for MacOS on github actions?

@mxschmitt
Copy link
Member

General recommendation is to not cache them, since they are downloaded in less than 10 seconds. If you are still want to cache them, you find the locations here. The cache key should contain the OS and Playwright version.

@YonatanKra
Copy link
Author

YonatanKra commented Jun 21, 2021

It's taking ages to install playwright.
Around 8 minutes (on github actions MacOS machines).
So caching is the easiest solution I could think of - but it doesn't work.
I've cached these libraries and it still doesn't work.
Here's my code:

     - name: Cache playwright binaries
        uses: actions/cache@v2
        id: playwright-cache
        with:
          path: |
            ~/Library/Caches/ms-playwright
          key: vivid-cache-playwright

     - name: Install playwright deps
        if: steps.playwright-cache.outputs.cache-hit != 'true'
        run: yarn add playwright -D -W && yarn playwright install-deps

But on the actual tests run step, I get the following error: browserType.launch: Failed to launch webkit because executable doesn't exist at /Users/runner/Library/Caches/ms-playwright/webkit-1446/pw_run.sh.

When I list the folder, I can actually see the files but with webkit-1442.

Is there a way to install a certain webkit version?

@mxschmitt
Copy link
Member

Are you using self-hosted runners? If this problem is persistent on the hosted-runners, it might make sense to contact the GitHub Actions support. We run 50-100 jobs daily and didn't experience such big delays yet.

Also you are using a private NPM Registry, which might add delay. But the browsers are not getting downloaded over NPM, thats a normal http request then.

Running npx playwright install will automatically install the right version for you.

@YonatanKra
Copy link
Author

We are using the gha runners. We have no self hosted stuff. The strange thing is - the Mac machines run consistently slower in everything. The tests run roughly 50% longer and running yarn install takes around 300% longer (compared to similar jobs on Linux).

Anyway, I've managed to solve the issue.

On the Mac machine running the tests I've added this code:

     - name: Cache playwright binaries
        uses: actions/cache@v2
        id: playwright-cache
        with:
          path: |
            ~/Library/Caches/ms-playwright
            **/node_modules/playwright
          key: cache-playwright-macos

      - name: Install playwright deps
        if: steps.playwright-cache.outputs.cache-hit != 'true'
        run: yarn add playwright -D -W

Now it has a cache for playwright only. I runs a lot faster than the actual yarn add playwright.
Before the change:
image

After the change:
image

I will check what might be the issue with gha on mac for us as we thought it is a common issue for everyone. Thanks a lot!

@aslushnikov
Copy link
Collaborator

@YonatanKra 8 minutes! This is too much! We ourselves run installation on GHA-based macs, and it's never that bad. The whole npm ci for Playwright itself takes 1m including browser downloads.

Is it a public repo? Would you mind sharing a link to the GHA action so that I can look into logs?

@mxschmitt
Copy link
Member

Closing since the issue seems stale as part of the triage process. Please create a new issue if you still face any issues. 8 Minutes is definitely not as-designed but sounds more a infra issue.

@YonatanKra
Copy link
Author

@YonatanKra 8 minutes! This is too much! We ourselves run installation on GHA-based macs, and it's never that bad. The whole npm ci for Playwright itself takes 1m including browser downloads.

Is it a public repo? Would you mind sharing a link to the GHA action so that I can look into logs?

Hi,
Sorry for the late reply. It's a private repo, so I cannot share a link.
The long time might be due to jfrog artifactory. I'll check it out this week.

@jesstelford
Copy link

I extended the above caching logic to support new browser binaries as the version of Playwright changes. This works for yarn, but an equivalent should be possible with npm.

      - name: Install dependencies
        run: yarn

      # Figures out the version of playwright that's installed.
      # 1. Because we don't know what version yarn will resolve it to, we have
      #    to use `yarn why` to get the actually installed version.
      # 2. Because we're in a workspace, we need to make sure we get the version
      #    for the root and not any children, hence the `grep`. If not using
      #    workspaces, this can be skipped.
      # 3. jq comes pre-installed in the Ubuntu runner, so we use that to get
      #    the correct version string.
      # 4. Finally, we use sed to extract just the version number (eg; '1.22.0')
      # The result is stored in steps.playwright-version.outputs.version
      - name: Get installed Playwright version
        id: playwright-version
        run: echo "::set-output name=version::$(yarn why --json @playwright/test | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://')"

      # Attempt to restore the correct Playwright browser binaries based on the
      # currently installed version of Playwright (The browser binary versions
      # may change with Playwright versions).
      # Note: Playwright's cache directory is hard coded because that's what it
      # says to do in the docs. There doesn't appear to be a command that prints
      # it out for us.
      - uses: actions/cache@v3
        id: playwright-cache
        with:
          path: '~/.cache/ms-playwright'
          key: '${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.version }}'
          # As a fallback, if the Playwright version has changed, try use the
          # most recently cached version. There's a good chance that at least one
          # of the browser binary versions haven't been updated, so Playwright can
          # skip installing that in the next step.
          # Note: When falling back to an old cache, `cache-hit` (used below)
          # will be `false`. This allows us to restore the potentially out of
          # date cache, but still let Playwright decide if it needs to download
          # new binaries or not.
          restore-keys: |
            ${{ runner.os }}-playwright-

      # If the Playwright browser binaries weren't able to be restored, we tell
      # paywright to install everything for us.
      - name: Install Playwright's dependencies
        if: steps.playwright-cache.outputs.cache-hit != 'true'
        run: npx playwright install --with-deps

@birtles
Copy link

birtles commented Jul 1, 2022

It might be my version of yarn but yarn --why didn't produce anything with children in it for me so I ended up parsing yarn.lock instead:

echo "::set-output name=version::$(cat yarn.lock | grep "^\"@playwright\/test" --after-context 1 | tail -n 1 | sed 's/\s*version "\([0-9.]\+\)"/\1/')"

Furthermore, I found that while the above caches the downloaded versions, the playwright runtime dependencies still need to be installed. Hence, I ended up with the following for the last step:

      - name: Install Playwright with dependencies
        if: steps.playwright-cache.outputs.cache-hit != 'true'
        run: npx playwright install --with-deps

      - name: Install Playwright's dependencies
        if: steps.playwright-cache.outputs.cache-hit == 'true'
        run: npx playwright install-deps

@NikolayMakhonin
Copy link

yarn why --json @playwright/test | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://')

This is crossplatform version of this:

node -e "console.log(require('playwright/package.json').version)"

@jesstelford
Copy link

@NikolayMakhonin that only works if playwright and @playwright/test are version locked, but I don't think they are.

@andykenward
Copy link

yarn why --json @playwright/test | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://')

This is crossplatform version of this:

node -e "console.log(require('playwright/package.json').version)"

I think we would need to use npm ls @playwright/test or npm ls @playwright/test --json to get the version that's actually installed. Can someone help with how we can parse the output for the version number?

npm ls @playwright/test --json

{
  "version": "0.1.0",
  "name": "your-project-name",
  "dependencies": {
    "@playwright/test": {
      "version": "1.24.0",
      "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.24.0.tgz"
    }
  }
}

@chrisvariety
Copy link

@andykenward echo -n "::set-output name=version::$(npm ls @playwright/test --json | jq --raw-output '.dependencies["@playwright/test"].version')"

@andykenward
Copy link

@andykenward echo -n "::set-output name=version::$(npm ls @playwright/test --json | jq --raw-output '.dependencies["@playwright/test"].version')"

@chrisvariety Thank you. That's working for me.

  • node 16.16.0
  • npm 8.11.0

@YousefED
Copy link

YousefED commented Aug 4, 2022

@jesstelford Thanks for sharing your config! Just like @birtles, I'm wondering how this manages installing / caching the ubuntu dependencies. If I just cache ~/.cache/ms-playwright, a subsequent PW run will fail because the ubuntu dependencies are missing. Installing the dependencies is fairly slow (minutes), so I'm looking for a way to cache these besides just the browsers in the playwright cache directory

@jesstelford
Copy link

Hmm, I'm not sure about how GitHub Actions caches OS deps.

Perhaps if it's done in a seperate step, GitHub will cache the generated Docker image, making subsequent installs faster?

@jpoehnelt
Copy link

Hmm, I'm not sure about how GitHub Actions caches OS deps.

Perhaps if it's done in a seperate step, GitHub will cache the generated Docker image, making subsequent installs faster?

You can separate the two parts and cache the binaries but still install the host system dependencies.

- uses: actions/cache@v2
  id: playwright-cache
  with:
    path: |
      ~/.cache/ms-playwright
    key: ${{ runner.os }}-playwright-${{ hashFiles('**/package-lock.json') }}
- run: npm ci
- run: npx playwright install --with-deps
  if: steps.playwright-cache.outputs.cache-hit != 'true'
- run: npx playwright install-deps
  if: steps.playwright-cache.outputs.cache-hit == 'true'

https://justin.poehnelt.com/posts/caching-playwright-in-github-actions/

@bivainis
Copy link

bivainis commented Oct 5, 2022

if someone needs to set a cleaner version using npm:

- name: Get installed Playwright version
  id: playwright-version
  run: echo "::set-output name=version::$(npm ls @playwright/test | grep @playwright | sed 's/.*@//')" 

output

Linux-playwright-1.26.1

@gselsidi
Copy link

does any of this work anymore??? I've tried and it just keeps saying cache not found nor does it ever create it.....

@just-Bri
Copy link

Also wondering what @gselsidi asked.
Tried a few different things but nothing seems to work.
This helps a little bit but honestly not much:

- run: npx playwright install --with-deps
  if: steps.playwright-cache.outputs.cache-hit != 'true'
- run: npx playwright install-deps
  if: steps.playwright-cache.outputs.cache-hit == 'true'

@zkrzyzanowski
Copy link

zkrzyzanowski commented Nov 16, 2022

Also wondering what @gselsidi asked. Tried a few different things but nothing seems to work. This helps a little bit but honestly not much:

- run: npx playwright install --with-deps
  if: steps.playwright-cache.outputs.cache-hit != 'true'
- run: npx playwright install-deps
  if: steps.playwright-cache.outputs.cache-hit == 'true'

This worked for us after seeing some timeouts installing playwright today. Confirmed we're hitting the cache in our github actions.

- name: Cache Playwright
      uses: actions/cache@v3
      id: playwright-cache
      with:
        path: ~/.cache/ms-playwright
        key: ${{ runner.os }}-playwright-1.26.1

- name: Install Playwright
    if: steps.playwright-cache.outputs.cache-hit != 'true'
    run: pnpm dlx [email protected] install --with-deps

you could probably use the suggestion here to make it a little more robust and replace the hardcoded version # with whatever version you have in package.json

@gselsidi
Copy link

gselsidi commented Nov 16, 2022

I got it to work @zkrzyzanowski thing is how can we cache all the ubuntu library stuff? What's the path for that? This still takes massive amounts of time:

Get:60 http://azure.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 libavfilter7 amd64 7:4.4.2-0ubuntu0.22.04.1 [1496 kB] Get:61 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libcaca0 amd64 0.99.beta19-2.2ubuntu4 [224 kB] Get:62 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libcdio19 amd64 2.1.0-3build1 [63.3 kB] Get:63 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libcdio-cdda2 amd64 10.2+2.0.0-1build3 [16.7 kB] Get:64 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libcdio-paranoia2 amd64 10.2+2.0.0-1build3 [15.9 kB] Get:65 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 libdc1394-25 amd64 2.2.6-4 [88.8 kB] Get:66 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libiec61883-0 amd64 1.2.0-4build3 [25.9 kB] Get:67 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libjack-jackd2-0 amd64 1.9.20~dfsg-1 [293 kB] Get:68 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 libopenal-data all 1:1.19.1-2build3 [164 kB] Get:69 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 libsndio7.0 amd64 1.8.1-1.1 [29.3 kB] Get:70 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 libopenal1 amd64 1:1.19.1-2build3 [535 kB] Get:71 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libdecor-0-0 amd64 0.1.0-3build1 [15.1 kB] Get:72 http://azure.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libsdl2-2.0-0 amd64 2.0.20+dfsg-2ubuntu1.22.04.1 [582 kB] Get:73 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libxcb-shape0 amd64 1.14-3ubuntu3 [6158 B] Get:74 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libxv1 amd64 2:1.0.11-1build2 [11.2 kB] Get:75 http://azure.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 libavdevice58 amd64 7:4.4.2-0ubuntu0.22.04.1 [87.5 kB] Get:76 http://azure.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 ffmpeg amd64 7:4.4.2-0ubuntu0.22.04.1 [1696 kB] Get:77 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 fonts-freefont-ttf all 20120503-10build1 [2388 kB] Get:78 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-tlwg-loma-otf all 1:0.7.3-1 [107 kB] Get:79 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-unifont all 1:14.0.01-1 [3551 kB] Get:80 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-wqy-zenhei all 0.9.45-8 [7472 kB] Get:81 http://azure.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgdk-pixbuf2.0-common all 2.42.8+dfsg-1ubuntu0.2 [5530 B] Get:82 http://azure.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgdk-pixbuf-2.0-dev amd64 2.42.8+dfsg-1ubuntu0.2 [47.8 kB] Get:83 http://azure.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgdk-pixbuf-2.0-0 amd64 2.42.8+dfsg-1ubuntu0.2 [148 kB] Get:84 http://azure.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgdk-pixbuf2.0-bin amd64 2.42.8+dfsg-1ubuntu0.2 [14.2 kB] Get:85 http://azure.archive.ubuntu.com/ubuntu jammy-updates/main amd64 gir1.2-gdkpixbuf-2.0 amd64 2.42.8+dfsg-1ubuntu0.2 [9482 B] Get:86 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 liborc-0.4-0 amd64 1:0.4.32-2 [228 kB] Get:87 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libgstreamer-plugins-base1.0-0 amd64 1.20.1-1 [847 kB] Get:88 http://azure.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 gstreamer1.0-libav amd64 1.20.3-0ubuntu1 [103 kB] Get:89 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libcdparanoia0 amd64 3.10.2+debian-14build2 [49.3 kB] Get:90 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libvisual-0.4-0 amd64 0.4.0-17build2 [108 kB] Get:91 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 gstreamer1.0-plugins-base amd64 1.20.1-1 [712 kB] Get:92 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libaa1 amd64 1.4p5-50build1 [51.9 kB] Get:93 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libdv4 amd64 1.0.0-14build1 [61.9 kB]

@gselsidi
Copy link

Looks like all this caching stuff is pretty annoying and should probably use containers, I tried the default container and it's done super quickly.

@zkrzyzanowski
Copy link

I got it to work @zkrzyzanowski thing is how can we cache all the ubuntu library stuff? What's the path for that? This still takes massive amounts of time:

Get:60 http://azure.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 libavfilter7 amd64 7:4.4.2-0ubuntu0.22.04.1 [1496 kB] Get:61 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libcaca0 amd64 0.99.beta19-2.2ubuntu4 [224 kB] Get:62 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libcdio19 amd64 2.1.0-3build1 [63.3 kB] Get:63 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libcdio-cdda2 amd64 10.2+2.0.0-1build3 [16.7 kB] Get:64 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libcdio-paranoia2 amd64 10.2+2.0.0-1build3 [15.9 kB] Get:65 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 libdc1394-25 amd64 2.2.6-4 [88.8 kB] Get:66 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libiec61883-0 amd64 1.2.0-4build3 [25.9 kB] Get:67 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libjack-jackd2-0 amd64 1.9.20~dfsg-1 [293 kB] Get:68 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 libopenal-data all 1:1.19.1-2build3 [164 kB] Get:69 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 libsndio7.0 amd64 1.8.1-1.1 [29.3 kB] Get:70 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 libopenal1 amd64 1:1.19.1-2build3 [535 kB] Get:71 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libdecor-0-0 amd64 0.1.0-3build1 [15.1 kB] Get:72 http://azure.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libsdl2-2.0-0 amd64 2.0.20+dfsg-2ubuntu1.22.04.1 [582 kB] Get:73 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libxcb-shape0 amd64 1.14-3ubuntu3 [6158 B] Get:74 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libxv1 amd64 2:1.0.11-1build2 [11.2 kB] Get:75 http://azure.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 libavdevice58 amd64 7:4.4.2-0ubuntu0.22.04.1 [87.5 kB] Get:76 http://azure.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 ffmpeg amd64 7:4.4.2-0ubuntu0.22.04.1 [1696 kB] Get:77 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 fonts-freefont-ttf all 20120503-10build1 [2388 kB] Get:78 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-tlwg-loma-otf all 1:0.7.3-1 [107 kB] Get:79 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-unifont all 1:14.0.01-1 [3551 kB] Get:80 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-wqy-zenhei all 0.9.45-8 [7472 kB] Get:81 http://azure.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgdk-pixbuf2.0-common all 2.42.8+dfsg-1ubuntu0.2 [5530 B] Get:82 http://azure.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgdk-pixbuf-2.0-dev amd64 2.42.8+dfsg-1ubuntu0.2 [47.8 kB] Get:83 http://azure.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgdk-pixbuf-2.0-0 amd64 2.42.8+dfsg-1ubuntu0.2 [148 kB] Get:84 http://azure.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgdk-pixbuf2.0-bin amd64 2.42.8+dfsg-1ubuntu0.2 [14.2 kB] Get:85 http://azure.archive.ubuntu.com/ubuntu jammy-updates/main amd64 gir1.2-gdkpixbuf-2.0 amd64 2.42.8+dfsg-1ubuntu0.2 [9482 B] Get:86 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 liborc-0.4-0 amd64 1:0.4.32-2 [228 kB] Get:87 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libgstreamer-plugins-base1.0-0 amd64 1.20.1-1 [847 kB] Get:88 http://azure.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 gstreamer1.0-libav amd64 1.20.3-0ubuntu1 [103 kB] Get:89 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libcdparanoia0 amd64 3.10.2+debian-14build2 [49.3 kB] Get:90 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libvisual-0.4-0 amd64 0.4.0-17build2 [108 kB] Get:91 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 gstreamer1.0-plugins-base amd64 1.20.1-1 [712 kB] Get:92 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libaa1 amd64 1.4p5-50build1 [51.9 kB] Get:93 http://azure.archive.ubuntu.com/ubuntu jammy/main amd64 libdv4 amd64 1.0.0-14build1 [61.9 kB]

We had the ubuntu stuff download on the first run, then pulled from cache every run after. Either way it sounds like you found a solution based on your comment here

@dk-carma
Copy link

dk-carma commented Sep 5, 2023

Yes, same here using Playwright container in github and it's working like a charm 🎉 for all browsers including webkit:
sample code in action file:

on:
  workflow_dispatch:

jobs:
  run_vercel_tests:
    name: Run e2e tests
    container: mcr.microsoft.com/playwright:v1.36.2
  
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
         with:
           node-version: '18.x'

@Wisesaturn
Copy link

Thanks for the inputs on this. Here's what I've ended up with (hopefully will help others):

- name: Cache Node Modules
  uses: actions/cache@v3
  with:
    path: ~/.npm
    key: node-modules-${{ hashFiles('package-lock.json') }}

- name: Install Dependencies
  run: npm ci

- name: Store Playwright's Version
  run: |
    PLAYWRIGHT_VERSION=$(npm ls @playwright/test | grep @playwright | sed 's/.*@//')
    echo "Playwright's Version: $PLAYWRIGHT_VERSION"
    echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV

- name: Cache Playwright Browsers for Playwright's Version
  id: cache-playwright-browsers
  uses: actions/cache@v3
  with:
    path: ~/.cache/ms-playwright
    key: playwright-browsers-${{ env.PLAYWRIGHT_VERSION }}

- name: Setup Playwright
  if: steps.cache-playwright-browsers.outputs.cache-hit != 'true'
  run: npx playwright install --with-deps

- name: Run Tests
  run: npm run test:ci
  
- name: Store Artifacts from Failed Tests
  if: failure()
  uses: actions/upload-artifact@v2
  with:
    name: test-results
    path: test-results/
    retention-days: 7

Thanks a lot :)

@avetisk
Copy link

avetisk commented Jan 17, 2024

Just my 2 cents for getting playwright version in a very simple and short manner:

npx playwright -V | awk '{ print $2 }'

Or you can use cut -f 2 -d " " if you want.

@koynoyno
Copy link

@avetisk npm ls @playwright/test | grep @playwright | sed 's/.*@//' seems to perform a bit faster.

@mrclrchtr
Copy link

Yarn edition with disabled colors because of the following phenomenon:

image

  - name: Store Playwright's Version
    run: |
      PLAYWRIGHT_VERSION=$(YARN_ENABLE_COLORS=false yarn info @playwright/test | grep @playwright | sed 's/.*://')
      echo "Playwright's Version: $PLAYWRIGHT_VERSION"
      echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV
  - name: Cache Playwright Browsers for Playwright's Version
    id: cache-playwright-browsers
    uses: actions/cache@v3
    with:
      path: ~/.cache/ms-playwright
      key: playwright-browsers-${{ env.PLAYWRIGHT_VERSION }}
  - name: Setup Playwright Browsers
    if: steps.cache-playwright-browsers.outputs.cache-hit != 'true'
    run: yarn playwright install --with-deps

@mrclrchtr
Copy link

mrclrchtr commented Apr 12, 2024

Hmm it is not working.. - [pid=1505][err] /home/runner/.cache/ms-playwright/chromium-1112/chrome-linux/chrome: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory don't know, what the problem is. I will also switch to the docker image.

Edit: solution was here: #7249 (comment)

@hckhanh
Copy link

hckhanh commented May 31, 2024

I confirmed this script works for my case:

      - name: Get Playwright version
        run: echo "PLAYWRIGHT_VERSION=$(jq '.devDependencies["@playwright/test"]' package.json -r)" >> $GITHUB_ENV
      - name: Cache Playwright Browsers
        id: cache-playwright-browsers
        uses: actions/cache@v4
        with:
          path: ~/.cache/ms-playwright
          key: playwright-browsers-${{ runner.os }}-${{ env.PLAYWRIGHT_VERSION }}
      - name: Install Playwright with dependencies
        if: steps.cache-playwright-browsers.outputs.cache-hit != 'true'
        run: bun playwright install --with-deps
      - name: Install Playwright dependencies
        if: steps.cache-playwright-browsers.outputs.cache-hit == 'true'
        run: bun playwright install-deps
      - name: Download test build
        uses: actions/download-artifact@v4
        with:
          name: test-build
          path: dist/
      - name: Run Playwright tests
        run: bun playwright test -c playwright.service.config.ts --workers=20
        env:
          DOTENV_KEY: ${{ secrets.DOTENV_KEY }}
          PLAYWRIGHT_SERVICE_ACCESS_TOKEN: ${{ secrets.PLAYWRIGHT_SERVICE_ACCESS_TOKEN }}
          PLAYWRIGHT_SERVICE_URL: ${{ secrets.PLAYWRIGHT_SERVICE_URL }}
          PLAYWRIGHT_SERVICE_RUN_ID: ${{ github.run_id }}-${{ github.run_attempt }}-${{ github.sha }}
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: playwright-report
          path: playwright-report/

@vincerubinetti
Copy link

vincerubinetti commented Aug 13, 2024

General recommendation is to not cache them, since they are downloaded in less than 10 seconds.

Citation needed ;)

I don't want to sound entitled, but it would really be great if we had a first-party setup-playwright action (like many tools have) we could use to handle the complexities of this. Sure, it can be done in userland, but it seems pretty elaborate and brittle to changes with Playwright.

@vincerubinetti
Copy link

vincerubinetti commented Aug 13, 2024

      - name: Install Playwright with dependencies
        if: steps.playwright-cache.outputs.cache-hit != 'true'
        run: npx playwright install --with-deps

      - name: Install Playwright's dependencies
        if: steps.playwright-cache.outputs.cache-hit == 'true'
        run: npx playwright install-deps

Can someone more clearly explain why both of these are needed? I think the documentation makes it seem like those commands should be equivalent...

Shouldn't it be sufficient to just do npx playwright install on the cache hit? That is, the first command installs Playwright library itself AND the browsers (and OS-level library deps of each browser), and the second command installs JUST the Playwright library because the browsers were restored from cache? Is that the correct understanding?

I'm quite confused. Perhaps the docs could be updated to clarify exactly all the different pieces involved (playwright library itself, browsers, browser deps, playwright os deps, whatever), and which get installed (and where) with different commands.

@jukkatupamaki
Copy link

jukkatupamaki commented Aug 14, 2024

I tried to get the browsers caching working on Ubuntu but ran into errors regarding missing OS-level libs so living without caching for now.

The docs state that downloading browsers is as fast as loading them from cache; it takes 1 minute to finish just the npx playwright install-deps step in GitHub. Sounds like retrieving stuff from a cache would be a lot faster...

Update: After a couple of attempts I'm continuing with the Docker image provided by Playwright. It just does not make sense to manually do the caching. Also found this: https://radekmie.dev/blog/on-playwright-in-github-actions/

@dmail
Copy link

dmail commented Aug 20, 2024

If someone needs to get the playwright version and not @playwright/test version it can be done as follow:

  - name: Get installed Playwright version
     run: echo "PLAYWRIGHT_VERSION=$(npm ll -p --depth=0 playwright | grep -o '@.*')" >> $GITHUB_ENV

(Note that >> $GITHUB_ENV does not work on windows, see actions/runner#1636 (comment))

Then env.PLAYWRIGHT_VERSION can be used:

   with:
          path: "~/.cache/ms-playwright"
          key: "${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }}"

@dmail
Copy link

dmail commented Aug 21, 2024

If, like me, you:

  1. want to cache playwright browser binaries in a Github workflow
  2. run the workflow in linux, mac and windows
  3. use playwright directly, not @playwright/test

Here is the corresponding yml

- name: Install node modules
  run: npm install
  env:
    PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1

# Figures out the version of playwright that's installed.
# 1. Because we don't know what version npm will resolve it to
# 2. Because we're in a workspace, we need to make sure we get the version
#    for the root and not any children, hence the `grep`. If not using
#    workspaces, this can be skipped.
# The result is stored in $PLAYWRIGHT_VERSION
# https://github.com/microsoft/playwright/issues/7249#issuecomment-2299065930
# https://stackoverflow.com/a/33426237/24573072
# https://github.com/actions/runner/issues/1636#issuecomment-1024531638
- name: Detect Playwright version (Windows)
  if: runner.os == 'windows'
  run: echo "PLAYWRIGHT_VERSION=$(npm ll -p --depth=0 playwright | grep -o '@.*')" | Out-File -FilePath $env:GITHUB_ENV -Append
- name: Detect Playwright version (Linux and Mac)
  if: runner.os != 'windows'
  run: echo "PLAYWRIGHT_VERSION=$(npm ll -p --depth=0 playwright | grep -o '@.*')" >> $GITHUB_ENV
- name: Put $HOME in env
  if: runner.os == 'windows'
  run: echo "HOME=$HOME" | Out-File -FilePath $env:GITHUB_ENV -Append
# Attempt to restore the correct Playwright browser binaries based on the
# currently installed version of Playwright (The browser binary versions
# may change with Playwright versions).
# Note: Playwright's cache directory is hard coded because that's what it
# says to do in the docs. There doesn't appear to be a command that prints
# it out for us.
- name: Cache playwright binaries
  uses: actions/cache@v4
  id: playwright-cache
  with:
    # see https://playwright.dev/docs/browsers#managing-browser-binaries
    path: ${{ runner.os == 'Windows' && format('{0}{1}', env.HOME, '\AppData\Local\ms-playwright') || runner.os == 'Linux' && '~/.cache/ms-playwright' || '~/Library/Caches/ms-playwright' }}
    key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }}
    # As a fallback, if the Playwright version has changed, try use the
    # most recently cached version. There's a good chance that at least one
    # of the browser binary versions haven't been updated, so Playwright can
    # skip installing that in the next step.
    # Note: When falling back to an old cache, `cache-hit` (used below)
    # will be `false`. This allows us to restore the potentially out of
    # date cache, but still let Playwright decide if it needs to download
    # new binaries or not.
    restore-keys: |
      ${{ runner.os }}-playwright-
# If the Playwright browser binaries weren't able to be restored, we tell
# paywright to install everything for us.
- name: Install Playwright with dependencies
  if: steps.playwright-cache.outputs.cache-hit != 'true'
  run: npx playwright install --with-deps
# If browser binaries are available we ask playwright to install os specific deps
# For example on linux it will install ffmpeg, xvfb, and many more libs
- name: Install Playwright's dependencies
  if: steps.playwright-cache.outputs.cache-hit == 'true'
  run: npx playwright install-deps

@vincerubinetti
Copy link

vincerubinetti commented Sep 6, 2024

Okay I think I maybe understand this a little bit better now? I think the command/flag names are a bit confusing, and maybe there should be a first-party setup-playwright action, @mxschmitt?

But in the meantime, I've made this general-purpose composite action:

name: Install Playwright
description: Install Playwright and dependencies with cache

# https://github.com/microsoft/playwright/issues/7249

inputs:
  working-directory:
    description: Where to install Playwright
    default: ./
  browsers:
    description: Browsers to install
    default: chromium webkit firefox

outputs:
  version:
    description: Installed version of Playwright
    value: ${{ steps.version.outputs.version }}
  cache-hit:
    description: Whether cache for Playwright was found
    value: ${{ steps.cache.outputs.cache-hit }}

runs:
  using: composite
  steps:
    - name: Get Playwright version
      uses: actions/github-script@v7
      id: version
      with:
        script: |
          // https://github.com/actions/toolkit/issues/1624
          // const workingDirectory = core.getInput("working-directory");
          const workingDirectory = "${{ inputs.working-directory }}";
          console.debug("Specified working directory:", workingDirectory);
          if (workingDirectory) process.chdir(workingDirectory);
          console.debug("Actual working directory:", process.cwd());
          let version = "";
          try {
            version = require("@playwright/test/package.json").version;
          } catch (error) {
            console.log(error.message);
          }
          console.debug("Version:", version);
          if (version) {
            core.exportVariable("PLAYWRIGHT_VERSION", version);
            core.setOutput("version", version);
          } else core.setFailed("Couldn't get Playwright version");

    - name: Cache Playwright
      id: cache
      uses: actions/cache@v4
      with:
        path: ~/.cache/ms-playwright
        key: playwright-${{ env.PLAYWRIGHT_VERSION }}

    - name: Install Playwright and its dependencies
      shell: bash
      if: steps.cache.outputs.cache-hit != 'true'
      working-directory: ${{ inputs.working-directory }}
      run: npx playwright install ${{ inputs.browsers }} --with-deps

    - name: Install just Playwright's dependencies
      shell: bash
      if: steps.cache.outputs.cache-hit == 'true'
      working-directory: ${{ inputs.working-directory }}
      run: npx playwright install-deps

Drop it in e.g. /.github/actions/install-playwright/action.yaml. Per GitHub limitations, it must be in its own folder and named action.yaml or .yml. I think it has to be under /.github, but not necessarily in an /actions sub-folder.

Then to use it:

- name: Install packages
  run: npm install
  with:
    working-directory: ./some-subfolder-if-applicable

- name: Install Playwright
  id: install-playwright
  uses: ./.github/actions/install-playwright
  with:
    working-directory: ./some-subfolder-if-applicable
    browsers: chromium webkit

- run: echo Playwright version: "${{ steps.install-playwright.outputs.version }}"
- run: echo Playwright cached: "${{ steps.install-playwright.outputs.cache-hit }}"

@huehnerlady
Copy link

Is there maybe the possibility to also cache the dependencies and not only the browsers? 🤔

@hirasso
Copy link

hirasso commented Nov 12, 2024

@vincerubinetti Thank you so much for your action!! I've just set it up in one of my repos and it works like butter! 🧈

@vincerubinetti
Copy link

Is there maybe the possibility to also cache the dependencies and not only the browsers? 🤔

I could be very wrong about this, but this is my understanding. Please correct me if I'm wrong.

  • playwright install chromium - installs just "browsers"
  • playwright install-deps - installs just "dependencies"
  • playwright install chromium --with-deps - installs both "browsers" and "dependencies"

Where "browsers" means the specific browser executables, and "dependencies" means any system dependencies the browsers need, e.g. visual studio c++ redistributables on Windows. Because "dependencies" are installed in different places across the system and perhaps quite large, they're difficult to cache.

And then to interact with the browsers from tests and such, that's where you install the Playwright npm "packages", not to be confused with "dependencies" here.

Again, it'd be really good if the docs explained things at a high level like this.

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

No branches or pull requests