Let's Connect

Laptop showing a GitHub repository page

A client once told me deploys at their company took a full afternoon and a prayer. We replaced that with a pipeline where merging to main puts code in production in under eight minutes, safely. This is the shape of that pipeline, which I now reuse across projects.

Stage 1: prove the code works

  • Pest/PHPUnit test suite against real MySQL and Redis services in the workflow
  • Static analysis with PHPStan/Larastan — catches whole bug classes before review
  • Pint for code style, so formatting never appears in code review again
  • Frontend build (npm ci && npm run build) to catch asset breakage early

Stage 2: build an artifact, not a hope

The pipeline produces one deployable artifact: dependencies installed with --no-dev, assets compiled, version stamped. The exact bytes that passed the tests are the bytes that ship. Building on the server from git pull invites drift, and I have stopped doing it entirely.

Stage 3: deploy without downtime

Releases unpack into a timestamped directory; storage and .env are symlinked in; migrations run with --force; then a current symlink flips atomically and PHP-FPM reloads with OPcache reset. Users never see a mid-deploy state. Rollback is pointing current at the previous release — seconds, not minutes.

The guardrails

Production deploys only from main, protected by required status checks. A health-check step curls the site after the symlink flip and fails loudly (Slack webhook) if anything is off. Migrations are written to be backward-compatible for one release, which makes rollbacks genuinely safe.

Deploys should be boring. If a deploy is exciting, the pipeline has failed.Md Raihan Hasan