Frontend & Architecture8 min read

CI/CD Pipeline Setup for Laravel Applications

Md Shahed Alam
Md Shahed Alam
January 2, 2025
CI/CD Pipeline Setup for Laravel Applications

Before I set up CI/CD on my projects, deploying felt like a ritual. SSH into the server, pull the code, run migrations, hope nothing breaks. Sometimes it did break. Sometimes I forgot a step. Sometimes I deployed code that had not been tested.

CI/CD removes the human from the deployment process. Every push runs the tests. If they pass, the code deploys automatically. If they fail, nothing goes to production.

Here is how to set it up with GitHub Actions — it is free for public repos and has a generous free tier for private ones.

The workflow file

Create .github/workflows/laravel.yml in your project:

yaml
name: Laravel CI/CD

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:
      mysql:
        image: mysql:8.0
        env:
          MYSQL_DATABASE: testing
          MYSQL_ROOT_PASSWORD: password
        ports:
          - 3306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup PHP 8.3
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: mbstring, pdo, pdo_mysql, redis
      
      - name: Install Composer dependencies
        run: composer install --no-interaction --prefer-dist --optimize-autoloader
      
      - name: Prepare environment
        run: |
          cp .env.example .env.testing
          php artisan key:generate --env=testing
      
      - name: Run migrations
        run: php artisan migrate --env=testing --force
        env:
          DB_CONNECTION: mysql
          DB_HOST: 127.0.0.1
          DB_PORT: 3306
          DB_DATABASE: testing
          DB_USERNAME: root
          DB_PASSWORD: password
      
      - name: Run tests
        run: php artisan test --parallel
        env:
          DB_CONNECTION: mysql
          DB_HOST: 127.0.0.1
          DB_PORT: 3306
          DB_DATABASE: testing
          DB_USERNAME: root
          DB_PASSWORD: password
  
  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy to server
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/myapp
            git pull origin main
            composer install --no-dev --optimize-autoloader
            php artisan migrate --force
            php artisan config:cache
            php artisan route:cache
            php artisan view:cache
            php artisan queue:restart
            echo "Deployment complete"

Setting up secrets

In your GitHub repository, go to Settings → Secrets and variables → Actions. Add:

  • SERVER_HOST — your server's IP address
  • SERVER_USER — the SSH username
  • SSH_PRIVATE_KEY — your private SSH key

Never put these values directly in the workflow file.

What happens now

Every time you push to main:

  1. 1GitHub spins up a fresh Ubuntu server
  2. 2Installs PHP and your dependencies
  3. 3Runs your migrations against a test database
  4. 4Runs all your tests
  5. 5If everything passes, SSHes into your server and deploys

If any test fails, the deploy step is skipped. Broken code never reaches production.

Zero-downtime deployments

The simple deployment above has a brief moment where the app is in an inconsistent state (new code, old cache). For zero-downtime, look into Deployer or Laravel Envoy — they deploy to a new directory and switch a symlink atomically.

But for most projects, the simple approach is fine. The deployment takes about 30 seconds and happens at a time you choose (when you push to main).

Once you have CI/CD, you will never want to go back to manual deployments.

CI/CDLaravelDevOpsGitHub Actions

Ready to build something great?

Let's talk about your project. We will give you honest advice, a clear plan, and a fair price. No pressure, no sales pitch.

Free consultation
No commitment required
Response within 24 hours