3 min read

How To Fix orchestra/testbench Permissions Error In GitHub Actions

How To Fix orchestra/testbench Permissions Error In GitHub Actions

I was recently setting up GitHub Actions CI for one of my Laravel packages which adds a layered cache driver for Laravel.

The tests had been running fine locally but when running in GitHub CI they all failed with this error:

Exception: The /home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/orchestra/testbench-core/laravel/bootstrap/cache directory must be present and writable.

/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/laravel/framework/src/Illuminate/Foundation/PackageManifest.php:178
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/orchestra/testbench-core/src/Foundation/PackageManifest.php:174
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/laravel/framework/src/Illuminate/Foundation/PackageManifest.php:137
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/laravel/framework/src/Illuminate/Foundation/PackageManifest.php:107
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/orchestra/testbench-core/src/Foundation/PackageManifest.php:107
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/laravel/framework/src/Illuminate/Foundation/PackageManifest.php:90
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/laravel/framework/src/Illuminate/Foundation/PackageManifest.php:79
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/RegisterFacades.php:26
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/orchestra/testbench-core/src/Concerns/CreatesApplication.php:426
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/orchestra/testbench-core/src/Concerns/CreatesApplication.php:247
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/orchestra/testbench-core/src/TestCase.php:122
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/orchestra/testbench-core/src/Concerns/ApplicationTestingHooks.php:72
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/orchestra/testbench-core/src/Concerns/Testing.php:45
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/laravel/framework/src/Illuminate/Collections/helpers.php:224
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/orchestra/testbench-core/src/functions.php:117
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/laravel/framework/src/Illuminate/Collections/helpers.php:224
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/orchestra/testbench-core/src/Concerns/Testing.php:57
/home/runner/work/laravel-multi-cache/laravel-multi-cache/vendor/orchestra/testbench-core/src/TestCase.php:51
/home/runner/work/laravel-multi-cache/laravel-multi-cache/tests/MultiStoreTest.php:24

"directory must be present and writable" shows us that it's likely a permissions issue. The user running phpunit doesn't have write access to the directory.

For reference, here is my pipelines.yaml file:

name: pipeline

# https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#concurrency
concurrency:
  group: ${{ github.ref_name }}
  cancel-in-progress: true

on:
  push:
  workflow_dispatch:

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Install dependencies
        uses: php-actions/composer@v6
        with:
          php_version: 8.1

      - name: Run tests
        run: vendor/bin/phpunit

It's odd that it wants to write to the vendor directly, but that seems to just be how testbench works. You can change it, but that means providing your own demo Laravel installation for the tests.

On the other side, the question is why can't we write to the vendor directory? I added these steps to my pipeline.yaml file to find out:

# Show who the current user is
- run: whoami
# Show the owner of the directroy in question
- run: ls -la vendor/orchestra/testbench-core/laravel/bootstrap

Here's the result:

The tests run as a user called runner, but the cache directory is owned by root.

I found an open issue for the php-actions/composer package asking about why the dependencies are installed as root. There is no resolution as of yet.

So we're stuck with two issues:

  • orchestra/testbench unusually wants to write to the vendor directory. Changing this seems like more hassle than it's worth.
  • Our runner user can't write to the directory because php-actions/composer will only run as (and install the dependencies as) root.

The Workaround

To solve this issue we can just change the owner of the vendor directory after the dependencies are installed. Add this line to your pipeline.yaml just after the php-actions/composer@v6 step

- run: sudo chown -R $USER:$USER $GITHUB_WORKSPACE/vendor
The complete list of steps with the change.

Now we have a happy pipeline!