🎉🎉 Larasense is officially launched 🎉🎉
- Your Hub for Laravel News, Trends & Updates

Deploy Laravel Project with GitHub Actions CI/CD Workflow

laravel
github-actions
ci-cd
Nabil Hassen
Nabil Hassen
Nov 26, 2024
Push from VS Code to your production server
Last updated on Nov 27, 2024
Table of contents:

Introduction

In this guide, you’ll learn how to set up a deploy script for your Laravel project and integrate it seamlessly with a GitHub Actions workflow. We’ll walk through crafting a deployment script for your production server and explain each step of a GitHub Actions pipeline that tests and deploys your application whenever changes are pushed to the main branch. By the end, you’ll have a reliable and repeatable process to keep your Laravel application up to date with minimal manual effort.

Laravel Deploy Script

First we need to write a Laravel deploy script that will be triggered from our GitHub Actions workflow. Make sure to store this file in your production server. Nothing fancy here, those are all commands that we use while developing. Have a look:

# Change your Laravel project directory
cd ~/mywebsite
 
# Turn on maintenance mode
php artisan down || true
 
# Pull the latest changes from the git repository
git pull origin main
 
# Install composer dependecies
composer install --no-interaction --no-dev
 
# Optimize filament components and blade icons
php artisan filament:optimize-clear
php artisan filament:optimize
 
# Optimize view, routes, events, configs
php artisan optimize:clear
php artisan optimize
 
# Clear caches
php artisan cache:clear
 
# Clear expired password reset tokens
php artisan auth:clear-resets
 
# Run database migrations
php artisan migrate --force
 
# Turn off maintenance mode
php artisan up
 
exit 0

GitHub Actions Workflow to Test & Deploy Laravel

Next, we will write our GitHub Actions workflow that does two things in particular; Runs tests, and deploys to server. In the root directory of your Laravel project, create .github folder and inside .github, create workflows folder. You will end up with a .github/workflows structure. Create a YAML file e.g. tests.yml and save it in the workflows folder.

This workflow will be triggered when changes are pushed to the main branch. Let's see the workflow:

name: mywebsite.com
 
on:
push:
branches: ["main"]
 
jobs:
test-and-deploy:
runs-on: ubuntu-latest
 
steps:
- name: Checkout code
uses: actions/checkout@v3
 
- name: Setup PHP
uses: shivammathur/setup-php@15c43e89cdef867065b0213be354c2841860869e
with:
php-version: "8.2"
 
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22.x"
cache: "npm"
 
- name: Copy .env
run: php -r "file_exists('.env') || copy('.env.example', '.env');"
 
- name: Install PHP Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
 
- name: Generate key
run: php artisan key:generate
 
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
 
- name: Install and Build Frontend Dependencies
run: |
npm install
npm run build --if-present
 
- name: Execute tests
run: composer test:ci
 
- name: Deploy to Server
uses: appleboy/[email protected]
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: cd scripts && sh deploy_script.sh

We will go through each step and understand what each step of the workflow does. Let's go.

Workflow Name: e.g. mywebsite.com

The workflow is triggered on any push to the main branch. The workflow performs testing and deployment for a Laravel application (it could be your website or an API server or anything else).

Trigger Event

  • on: push:
    • Runs this workflow whenever changes are pushed to the main branch.

Job: e.g. test-and-deploy

This job is executed on an Ubuntu environment (ubuntu-latest) and consists of multiple steps.

  1. Checkout Code
- name: Checkout code
uses: actions/checkout@v3
  • Action: Downloads the repository code to the runner.
  • Purpose: Ensures the workflow has access to the latest application files.
  1. Setup PHP
- name: Setup PHP
uses: shivammathur/setup-php@15c43e89cdef867065b0213be354c2841860869e
with:
php-version: "8.2"
  • Action: Sets up PHP version 8.2 on the runner (i.e. Ubuntu).
  • Purpose: Prepares the environment to execute PHP-based tasks such as running Laravel commands or installing dependencies.
  1. Set up Node.js
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22.x"
cache: "npm"
  • Action: Installs Node.js version 22.x and enables caching for npm.
  • Purpose: Provides the required Node.js environment to build and manage frontend assets.
  1. Copy .env File
- name: Copy .env
run: php -r "file_exists('.env') || copy('.env.example', '.env');"
  • Action: Checks if a .env file exists; if not, it creates one by copying from .env.example.
  • Purpose: Ensures that the application has the necessary environment configuration file.
  1. Install PHP Dependencies
- name: Install PHP Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
  • Action: Installs Laravel's PHP dependencies using Composer with optimized settings.
  • Purpose: Prepares backend dependencies for the Laravel application.
  1. Generate Application Key
- name: Generate key
run: php artisan key:generate
  • Action: Runs the key:generate Artisan command to create an encryption key.
  • Purpose: Ensures the Laravel application has a valid encryption key.
  1. Set Directory Permissions
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
  • Action: Sets writable permissions for storage and bootstrap/cache directories.
  • Purpose: Ensures these directories are writable for Laravel to store cached files and logs.
  1. Install and Build Frontend Dependencies
- name: Install and Build Frontend Dependencies
run: |
npm install
npm run build --if-present
  • Action:
    1. Installs frontend dependencies using npm install.
    2. Builds the frontend assets using npm run build if a build script is defined.
  • Purpose: Prepares and compiles the frontend assets.
  1. Execute Tests
- name: Execute tests
run: composer test
  • Action: Runs the PHP tests or any configured tests using a Composer command.
  • Purpose: Validates the application's functionality by executing automated tests.
  1. Deploy to Server
- name: Deploy to Server
uses: appleboy/[email protected]
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: cd scripts && sh deploy_script.sh
  • Action:
    • Connects to the deployment server via SSH using credentials stored as GitHub Secrets.
    • Executes the deployment script (deploy_script.sh) located in the scripts directory.
  • Purpose: Automates deployment to the production server.

Conclusion

With the deploy script and GitHub Actions workflow in place, managing your Laravel application's deployment becomes significantly more efficient and less error-prone. You’ve set up an automated process that handles everything from testing your code to deploying it to the production server with just a push to the main branch. This approach not only saves time but also ensures consistent deployments, allowing you to focus on building features rather than worrying about manual setups. Whether you’re maintaining a website or an API server, this streamlined workflow is a game-changer for Laravel developers.

Nabil Hassen
Nabil Hassen
Full Stack Web Developer

Stay Updated.

I'll you email you as soon as new, fresh content is published.

Thanks for subscribing to my blog.

Latest Posts