Skip to main content

Sebastiaan Luca

Deploy to Vapor using GitHub Actions

April 24, 2020
2 minute read

Set up a push-to-deploy workflow to Vapor by using GitHub Actions.

If you're a Laravel Vapor user and your code resides on GitHub, you can now use a free GitHub Actions workflow to automatically deploy your project to Vapor just like Envoyer does. This means you won't have to build and deploy it locally any longer, but it'll get deployed whenever you push to a branch.

To get started we have to require the Vapor CLI in our project so the GitHub workflow has access to it:

composer require laravel/vapor-cli

Once that's included, we can set up the GitHub workflow itself by creating a .github/workflows/deploy.yml file in our project:

name: Test and deploy to Vapor
on:
  push:
  pull_request:
jobs:
  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v2
      - name: Cache dependencies
        uses: actions/cache@v1
        with:
          path: ~/.composer/cache/files
          key: dependencies-composer-${{ hashFiles('composer.json') }}
      - name: Set up PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: 7.4
          extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, mysql
      - name: Copy environment config file
        run: php -r "file_exists('.env') || copy('.env.testing', '.env');"
      - name: Validate Composer
        run: composer validate
      - name: Install Composer dependencies
        run: composer install --prefer-dist --no-interaction --no-suggest
      - name: Run Tests
        run: ./vendor/bin/phpunit --verbose
        env:
          APP_ENV: testing
      - name: Upload artifacts
        uses: actions/upload-artifact@master
        if: failure()
        with:
          name: Logs
          path: ./storage/logs
  deploy:
    name: Deploy to Vapor
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master'
    needs:
      - test
    steps:
      - name: Check out code
        uses: actions/checkout@v2
      - name: Validate Composer
        run: composer validate
      - name: Install Composer dependencies
        run: composer install --prefer-dist --no-interaction --no-suggest --no-dev
      - name: Deploy code
        run: ./vendor/bin/vapor deploy ${{ env.APP_ENV }} --commit="${{ github.sha }}"
        env:
          APP_ENV: ${{ github.ref == 'refs/heads/master' && 'production' || 'staging' }}
          VAPOR_API_TOKEN: ${{ secrets.VAPOR_API_TOKEN }}
      - name: Upload artifacts
        uses: actions/upload-artifact@master
        if: failure()
        with:
          name: Logs
          path: ./storage/logs

Note: if you want to skip running your test suite and just deploy to Vapor, you can delete the entire test section under jobs (including the test key). If you only keep the deploy job, it will do just that.

There are many blog posts and docs out there explaining the use of the format and steps (like this one by Freek and another one by Dries, so I won't go into much detail here.

Basically, we have two jobs, test and deploy that run some steps (actions if you will). Whenever we push to a branch or a pull request is created, they'll check out the code, install the Composer packages, and do their thing.

The deploy job will only run when we push to either the develop or master branch. And based on that branch, we also determine the Vapor command to execute. It'll either execute

./vendor/bin/vapor deploy staging

or

./vendor/bin/vapor deploy production

By also setting up the Vapor API token as a GitHub secret, we allow Vapor to access our projects from inside the CI container.

And that's about it! Commit your code and push to GitHub to have it automatically pick up the configuration and run the actions for you.

If you have any questions, feel free to tweet and I'll get back to you.