Collaboration on GitHub makes so many aspects of application development easier. Between code reviews and merging pull requests your team probably already has enough to worry about. Plus if members of your team are not developers, viewing the latest build of your project might prove to be challenging. Because of this GitHub actions become incredibly useful. Using GitHub actions you can trigger a deployment every time code is updated on one of your branches.

In this article, we will cover from start to finish how to build and deploy both your Laravel API and Vue JS single page application. First, let’s take a look at how this example project is structured.

/**
 */Project
 * /.github
 *    /workflows
 * /laravel-app
 * /vue-client
/*

For this example, let’s create a “continuous integration” action. What this means is that we have an environment set up just for our team to review the latest build of the project. So our master/main branch will be the base for this action.

To get started lets create our YAML file that holds all of our deployment information. We’ll call it ci.deployment.yml and let’s put it in ./github/workflows.

Here are the contents of that file:

name: Continuous Integration

on:
  push:
    branches:
      - 'main'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: Build Front End
        run: npm install && NODE_ENV=CI npm run build
        working-directory: ./vue-client
      - name: Wipe Project Dir
        uses: garygrossgarten/github-action-ssh@release
        with:
          command: rm -rf public_html/*;
          host: ${{secrets.SSH_HOST}}
          username: ${{secrets.SSH_USERNAME}}
          passphrase: ${{secrets.SSH_PASSWORD}}
          privateKey: ${{secrets.SSH_PRIVATE_KEY}}
          port: ${{secrets.SSH_PORT}}
      - name: FTP Deploy API
        uses: kevinpainchaud/simple-ftp-deploy-action@v1.1.0
        with:
          ftp_host: example.com
          ftp_username: ftp@example.com
          ftp_password: ${{secrets.FTP_PASSWORD}}
          local_source_dir: "/github/workspace/laravel-app"
          dist_target_dir: "/laravel-app"
          delete: "false"
          exclude: "'^tests/'"
      - name: FTP Deploy Front End
        uses: kevinpainchaud/simple-ftp-deploy-action@v1.1.0
        with:
          ftp_host: example.com
          ftp_username: ftp@example.com
          ftp_password: ${{secrets.FTP_PASSWORD}}
          local_source_dir: "/github/workspace/vue-client/dist"
          dist_target_dir: "/vue-client"
          delete: "false"
          exclude: ""
      - name: Run Post Deploy Script
        uses: garygrossgarten/github-action-ssh@release
        with:
          command: cd public_html/laravel-app; chmod 755 deploy/deploy.ci.sh; chmod o+x deploy/deploy.ci.sh; ./deploy/deploy.ci.sh; exit;
          host: ${{secrets.SSH_HOST}}
          username: ${{secrets.SSH_USERNAME}}
          passphrase: ${{secrets.SSH_PASSWORD}}
          privateKey: ${{secrets.SSH_PRIVATE_KEY}}
          port: ${{secrets.SSH_PORT}}

So, there’s a lot to unpack here. We’ll run through it step by step, don’t worry.

Here’s our first step:

- name: Build Front End
  run: npm install && NODE_ENV=CI npm run build
  working-directory: ./vue-client

This action builds the front end (our vue application). We set our working-directory so our run command runs inside that directory. We’re also setting our NODE_ENV to CI for this.

      - name: Wipe Project Dir
        uses: garygrossgarten/github-action-ssh@release
        with:
          command: rm -rf public_html/*;
          host: ${{secrets.SSH_HOST}}
          username: ${{secrets.SSH_USERNAME}}
          passphrase: ${{secrets.SSH_PASSWORD}}
          privateKey: ${{secrets.SSH_PRIVATE_KEY}}
          port: ${{secrets.SSH_PORT}}

Now we’re going to make use of some code that someone else wrote. As we often do in the programming world. Check out this repository for more information on how it works. Basically this command lets us SSH into our server. In this step, before each deploy we’re going to nuke the files that were previously deployed and replace them with our latest push. Important note: this is probably not a good idea if you are working with a live environment.

You have been warned.

The “with” part of each step allows us to provide variables for a GitHub action. You’ll notice here that we don’t actually have our private variables stored here in plain text. As you would guess, this is for security reasons. In some cases you might be using a public repository or you may not want everyone on your team to have access to some information. You can use GitHub secrets to achieve this, find out more about that here.

      - name: FTP Deploy API
        uses: kevinpainchaud/simple-ftp-deploy-action@v1.1.0
        with:
          ftp_host: example.com
          ftp_username: ftp@example.com
          ftp_password: ${{secrets.FTP_PASSWORD}}
          local_source_dir: "/github/workspace/laravel-app"
          dist_target_dir: "/laravel-app"
          delete: "false"
          exclude: "'^tests/'"
      - name: FTP Deploy Front End
        uses: kevinpainchaud/simple-ftp-deploy-action@v1.1.0
        with:
          ftp_host: example.com
          ftp_username: ftp@example.com
          ftp_password: ${{secrets.FTP_PASSWORD}}
          local_source_dir: "/github/workspace/vue-client/dist"
          dist_target_dir: "/vue-client"
          delete: "false"
          exclude: ""

In this step we use an FTP action to upload our Laravel API. After that, we upload only the dist folder of our Vue Client directory.

      - name: Run Post Deploy Script
        uses: garygrossgarten/github-action-ssh@release
        with:
          command: cd public_html/laravel-app; chmod 755 deploy/deploy.ci.sh; chmod o+x deploy/deploy.ci.sh; ./deploy/deploy.ci.sh; exit;
          host: ${{secrets.SSH_HOST}}
          username: ${{secrets.SSH_USERNAME}}
          passphrase: ${{secrets.SSH_PASSWORD}}
          privateKey: ${{secrets.SSH_PRIVATE_KEY}}
          port: ${{secrets.SSH_PORT}}

Now we’re going to use our SSH action to run a shell deploy script. First we need to make sure give that script the proper permissions. This shell script will do all of the setup we need for Laravel.

Inside of our laravel-app folder, create a folder called deploy and make a file called deploy.ci.sh.

Here’s what the contents of that file will look like:

#!/bin/sh -x

cp .env.ci .env
/opt/cpanel/ea-php74/root/bin/php /opt/cpanel/composer/bin/composer install
/opt/cpanel/ea-php74/root/bin/php artisan down
/opt/cpanel/ea-php74/root/bin/php artisan migrate:fresh --seed -v
/opt/cpanel/ea-php74/root/bin/php artisan storage:link
/opt/cpanel/ea-php74/root/bin/php artisan config:clear
/opt/cpanel/ea-php74/root/bin/php artisan cache:clear
/opt/cpanel/ea-php74/root/bin/php artisan route:clear
/opt/cpanel/ea-php74/root/bin/php artisan view:clear
/opt/cpanel/ea-php74/root/bin/php artisan up

First we copy our environment template for ci and then we run our installs.

You’ll notice that some of these commands look longer than they should be. Please note that these were specific to our environment. Normally you should just be able to use php as our command. Since we had multiple versions of PHP and the main version of PHP on our server was not the most up to date, we had to specify which version to use. You may be in the same boat, but you’ll have to poke around to find the correct path to the version of php you want to use on your server.

That’s all! On your next push you’ll be able to watch your Laravel and Vue JS project get deployed automatically.

Leave a Reply