Running Laravel Dusk on GitHub Actions

September 18th, 2024 • 5 minutes read time

Without wasting time, this article will have you set up and running your Dusk test suite on GitHub Actions. We'll also discuss security around any secret keys you may need. Let's take a look.

Once you're successfully running your tests locally, create a separate .env file for Dusk specifically. I find this much more accessible than declaring all the environment variables inside the GitHub Actions workflow (which we'll take a look at in a moment).

Create .env.dusk.ci and include everything you need:

APP_NAME=Codecourse
APP_ENV=ci
APP_KEY=
APP_DEBUG=true
APP_URL=http://127.0.0.1:8000

# More here

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=codecourse_testing
DB_USERNAME=root
DB_PASSWORD=root

REDIS_HOST=localhost
REDIS_PASSWORD=
REDIS_PORT=6379

# And more down here

I've included the items above, which you'll need to configure similarly. Most importantly is the APP_URL, and removing the APP_KEY. I've also updated the database configuration along with Redis. You'll want to tweak these depending on your needs (like the database name under DB_DATABASE).

Ensure the .env.dusk.ci file doesn't contain any secrets and commit .env.dusk.ci to your repository. If you have any secrets you don't want to commit, we'll cover that later.

Here's the full workflow I use for Codecourse. I've commented each section to explain what's happening, but feel free to remove them.

Create .github/workflows/dusk.yml in the root of your project:

# The name of your workflow. Name this however you like!
name: Dusk

# Run these tests on the push of code
on: [push]
jobs:
  dusk:
    # The operating system to run on
    runs-on: ubuntu-latest

    services:
      # Set up the Redis service (if you need it)
      redis:
        image: redis
          env:
            REDIS_HOST: localhost
            REDIS_PORT: 6379
        ports:
          - 6379:6379
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      # Checks out your repository so your workflow can access it
      - uses: actions/checkout@v4

      # Creates the MySQL database with "root" and "root" as the username and password respectively
      # The database has the same name we specified in .env.dusk.ci
      - name: Set up MySQL
        run: |
          sudo systemctl start mysql
          mysql --user="root" --password="root" -e "CREATE DATABASE \`codecourse_testing\` character set UTF8mb4 collate utf8mb4_bin;"

      # Setup PHP with a specific version (8.3)
      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'

      # Copy the .env.dusk.ci file we commited to the .env that'll be used by Laravel
      - name: Copy .env
        run: cp .env.dusk.ci .env

      # Install Composer dependencies without showing progress, with dist and an optimized autoload (both potentially faster)
      - name: Install Dependencies
        run: composer install --no-progress --prefer-dist --optimize-autoloader

      # Generate a new application key, which fills in APP_KEY in .env
      - name: Generate key
        run: php artisan key:generate

      # Install the Chrome binaries required for Dusk to run tests
      - name: Install Chrome binaries
        run: php artisan dusk:chrome-driver --detect

      # Start the Chrome driver so we're able to run browser tests with Chrome
      - name: Start Chrome Driver
        run: ./vendor/laravel/dusk/bin/chromedriver-linux &

      # Build assets. This could vary for your setup.
      - name: Build assets
        run: npm install && npm run build

      # Start a basic Laravel server with no reloading
      - name: Run Laravel Server
        run: php artisan serve --no-reload &

      # Run our Dusk test suite. This could be different if you don't use Pest (e.g. php artisan dusk)
      - name: Execute tests
        run: php artisan pest:dusk

      # If there's a failure, upload the Dusk screenshots as an artifact
      - name: Upload Screenshots
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: screenshots
          path: tests/Browser/screenshots

      # If there's a failure, upload the Dusk console logs as an artifact
      - name: Upload Console Logs
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: console
          path: tests/Browser/console

You'll likely have to tweak this configuration based on your environment, which can sometimes take a while. Take a moment to check each step and make sure it maps up.

Tip! You can use the act package to run GitHub actions locally using Docker. This saves time pushing your new workflow file to source control and waiting for feedback before tweaking again.

Once you've pushed the dusk.yml file to GitHub, your action should start to run. Prepare for it not to work the first time — there are likely a few things you'll need to tweak for your project. Inspect the output in the GitHub Actions workflow and make any necessary adjustments.

Earlier, we created a specific .env.dusk.ci file. I like this approach because it makes changing environment variables much easier and helps you to keep everything in sync with the current state of your application. However, it's not advisable to commit secret keys here.

Because we're working with end-to-end tests, you'll likely have services used in your application that depend on access to an API and, therefore, a secret.

Tip: In whatever service you're using (e.g. Algolia for search), create a new application on the services you're using specifically for end-to-end tests — otherwise, you'll end up with potentially muddy data in your production applications.

Ok, so how do we create a secret on GitHub to use in our Actions for Dusk?

Head to your GitHub repository and choose Settings and Secrets and Variables > Actions.

Under Repository secrets, click New repository secret.

blog/eO481g0a3V7Ad9DuV4C0Dc4h3PZXQ8IDTcIEvXQL.webp

Choose the name and value of the secret and hit Add secret. I'm just using the database password as an example for now.

blog/hwSBlGds88bVusPZGccsQZvmtqtNoq9SBzhJTHxm.webp

To use any secrets you've created in your workflow file, do something like this:

  - name: Set up MySQL
  run: |
	  sudo systemctl start mysql
	  mysql --user="root" --password="${{ secrets.DB_PASSWORD }}" -e "CREATE DATABASE \`inertia_dusk_testing\` character set UTF8mb4 collate utf8mb4_bin;"

Or, if you want to set an overall environment variable:

  jobs:
	dusk:
	  # The operating system to run on
	  runs-on: ubuntu-latest

	  env:
		DB_PASSWORD: ${{ secrets.DB_PASSWORD }}

Once you're done setting your secrets and adding them to your workflow, commit the workflow, and the action should now use the secrets defined within GitHub.

And that's it! Although setting up GitHub Actions for Laravel Dusk tests can be tricky, I hope this has helped you. Of course, there are always issues with updates to both GitHub Actions, software versions and Laravel changes. However, if you hit any issues with a solid base like this, tweaking things shouldn't be too tricky.

If you found this article helpful, you'll love our practical screencasts.
Author
Alex Garrett-Smith
Share :

Comments

No comments, yet. Be the first!