CI/CD for PHP from Scratch: Step-by-Step Pipeline Setup Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why do you need CI/CD if you're not a robot?

\n\n

Imagine: Friday evening, you've just finished a feature, upload the code to the server via FTP (yes, that still happens), and... the site crashes with a white screen of death. Sound familiar? But if you had a CI/CD pipeline for PHP, everything would happen automatically: tests would fail at the push stage, the code wouldn't fly to production, and you'd calmly go drink tea.

\n\n

Continuous Integration and Continuous Delivery (or Deployment) are not just trendy abbreviations. They are your personal assistant that checks code, runs tests, lints, builds artifacts, and deploys to the server. In this article, I'll show you how to set up a CI/CD pipeline for PHP from scratch using GitHub Actions. No abstractions — only real code and working examples.

\n\n

What is a CI/CD pipeline and why a PHP developer needs it

\n\n

A CI/CD pipeline is a sequence of automated steps that run every time you push code to a repository. This is especially relevant for PHP because:

\n\n
    \n
  • PHP is a dynamic language, and many errors (typos, incorrect types) only surface at runtime.
  • \n
  • Deployment is often done "on the fly" — via SCP, rsync, or even FTP (a cry from the heart).
  • \n
  • Teams grow, and manual checks become a bottleneck.
  • \n
\n\n

By setting up CI/CD for PHP, you get:

\n
    \n
  • Automatic testing with every push.
  • \n
  • Code style checking (PSR-12, your internal standard).
  • \n
  • Automatic deployment to staging/production.
  • \n
  • Notifications in Telegram/Slack about build status.
  • \n
\n\n

Choosing a tool: Why GitHub Actions?

\n\n

There are many options: Jenkins, GitLab CI, Bitbucket Pipelines, CircleCI. But for setting up a CI/CD pipeline for PHP from scratch, I recommend GitHub Actions. Why?

\n\n
    \n
  • Free for public repositories (and 2000 minutes per month for private ones — more than enough).
  • \n
  • Everything in one place — code, issues, actions.
  • \n
  • A huge ecosystem of ready-made actions — no need to reinvent the wheel.
  • \n
\n\n

But if you use GitLab — the principles are the same, just the YAML syntax is different. Let's go.

\n\n

Step 1: Repository structure and basic files

\n\n

For demonstration, let's take a typical PHP project on Laravel (but the approach works for any framework). Your structure should look like this:

\n\n
my-php-app/\n├── .github/\n│   └── workflows/\n│       └── ci-cd.yml\n├── src/\n├── tests/\n├── composer.json\n├── phpunit.xml\n└── .php_cs.dist (if using PHP-CS-Fixer)
\n\n

Create the folder .github/workflows/ and the file ci-cd.yml — this is the heart of your pipeline.

\n\n

Step 2: Basic YAML — Continuous Integration (CI)

\n\n

Let's start simple: running tests and linting on every push to main or pull request. Here's a minimal CI/CD pipeline for PHP:

\n\n
name: PHP CI/CD Pipeline\n\non:\n  push:\n    branches: [ main, develop ]\n  pull_request:\n    branches: [ main ]\n\njobs:\n  build-and-test:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@v2\n        with:\n          php-version: '8.2'\n          extensions: mbstring, pdo, sqlite, gd\n          coverage: xdebug\n\n      - name: Install dependencies\n        run: composer install --prefer-dist --no-progress\n\n      - name: Run PHP CS Fixer (Lint)\n        run: vendor/bin/php-cs-fixer fix --dry-run --diff\n\n      - name: Run PHPStan (Static Analysis)\n        run: vendor/bin/phpstan analyse src --level=5\n\n      - name: Run Tests\n        run: vendor/bin/phpunit --coverage-text
\n\n

What's happening here?

\n
    \n
  • checkout — fetches the code.
  • \n
  • setup-php —

Blogs

Book Recommendations