Sponsored Link
Looking for a unified way to  viewmonitor, and  debug Playwright Test Automation runs?
Try the Playwright Dashboard by today. Use the coupon code PWSOL10 for a 12 month 10% discount.

[Update v1.46] Is it possible to run only Playwright Tests that changed in GitHub actions on a pull request?

Good news everyone! This is now possible to do without any external scripts. It is all baked into the Playwright CLI.

Original solution

If you've been subscribed for some time you may have remembered the original solution. It included getting a list of the file names by running a narly git diff command and piping the results to grep and tr commands. Storing those file names to a CHANGED environment variable, and passing that into the npx playwright test ${{ env.CHANGED }}.

Is it possible to run only Playwright Tests that changed in GitHub actions on a pull request?
Have you ever been reviewing a peer’s pull request in GitHub, and asked yourself does this Playwright check even pass? Well, I have, and that is what inspired this post. In my workplace, I want to prevent failing tests from entering the main automation branch, but I also didn’t want

Updated solution

There was a flaw with my approach that I just accepted as I didn't see an easy way to solve the problem. I was only checking and building the CHANGED list of tests run from the *.spec files. This list didn't include any page object files, helpers, fixtures, or data factory files. This was a known risk in my case, but with the built in playwright command they have solved this problem. See version 1.46 release notes below.

New CLI option --only-changed will only run test files that have been changed since the last git commit or from a specific git "ref". This will also run all test files that import any changed files.

Running pre-commit and post-commit

One thing to note with this solution, the command --only-changed by itself will only run files that have been changed, but not yet committed. This is important as you commit files to your local branch this command will not pick up those test changes after committed.

In order to pick up changes on committed files you will need to pass in a reference branch to check against. --only-changed=main for example will check your local git changes and do a diff against the main branch and run those changes.

Example on playwright-api-test-demo

Let's update our playwright-api-test-demo repo with the changes both in our package.json file to create a new npm script npm run changed.

// package.json

...
  "scripts": {
   ...
    "changed": "npx playwright test --only-changed"
  },

We'll also update our on-pr-files-changed.yml file removing all the old CHANGED logic we previously implemented. The main thing we are adding is the --only-changed=origin/$GITHUB_BASE_REF. Using the $GITHUB_BASE_REF here instead of main as the branch will prevent an error I was receiving when running in CI when I was using --only-changed=origin/main as the release notes demonstrated. The specific error I received is below.

Error: Cannot detect changed files for --only-changed mode:
git diff main --name-only

fatal: ambiguous argument 'main': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

Error: Error: Cannot detect changed files for --only-changed mode: git diff main --name-only

fatal: ambiguous argument 'main': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

The changes that worked for me were adding the fetch-depth: 0 (the default is 1) and adding the --only-changed flag in my npx playwright test command.


name: Changed Files Playwright API Checks

on:
  pull_request:
    branches:
      - main
...
jobs:
  playwright-automation-checks:
...
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
...
      - name: Run Playwright tests
        run: |
          npx playwright test --only-changed=origin/$GITHUB_BASE_REF
....

The full example can be found below.

// on-pr-files-changed.yml

name: Changed Files Playwright API Checks

on:
  pull_request:
    branches:
      - main
permissions:
  contents: write
  pages: write
  id-token: write

jobs:
  playwright-automation-checks:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    timeout-minutes: 10
    runs-on: ubuntu-latest

    env:
      BASE_URL: ${{ github.event.inputs.base_url }}

    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v3
        with:
          node-version: 16

      - name: Cache node_modules
        uses: actions/cache@v3
        id: node-modules-cache
        with:
          path: |
            node_modules
          key: modules-${{ hashFiles('package-lock.json') }}
      - run: npm ci --ignore-scripts
        if: steps.node-modules-cache.outputs.cache-hit != 'true'

      - name: Get installed Playwright version
        id: playwright-version
        run: echo "PLAYWRIGHT_VERSION=$(node -e "console.log(require('./package-lock.json').dependencies['@playwright/test'].version)")" >> $GITHUB_ENV
      - name: Cache playwright binaries
        uses: actions/cache@v3
        id: playwright-cache
        with:
          path: |
            ~/.cache/ms-playwright
          key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }}
      - 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'

      - name: Run lint
        run: npm run lint
      - name: Run prettier
        run: npm run prettier

      - name: Set BASE_URL if not passed in
        if: env.BASE_URL == null
        run: |
          echo "BASE_URL=https://automationintesting.online/" >> $GITHUB_ENV

      - name: Run Playwright tests
        run: |
          echo "The github event is: ${{ github.event_name }}"
          URL=${{ env.BASE_URL }} npx playwright test --grep-invert @unsatisfactory --reporter=github --workers=1 --only-changed=origin/$GITHUB_BASE_REF

Using only-changed on monorepos

One thing to note in my research Pramod Yadav (go give him a follow on LinkedIn) reported a Bug in the GitHub Issues section of the Playwright repository. He attempted to implement this within a monorepo and found there were some extra steps to get things working. Specifically adding git config --global --add safe.directory '*' as a command that is run after checking out the code and before the playwright test execution.


name: Changed Files Playwright API Checks

on:
  pull_request:
    branches:
      - main
...
jobs:
  playwright-automation-checks:
...
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
          
      - name: Mark repo as safe
        run: git config --global --add safe.directory '*'
...
      - name: Run Playwright tests
        run: |
          npx playwright test --only-changed=origin/$GITHUB_BASE_REF
....

Thanks for reading! If you found this helpful, reach out and let me know on LinkedIn or consider buying me a cup of coffee. If you want more content delivered to you in your inbox subscribe below, and be sure to leave a ❤️ to show some love.