This is part of an ongoing series I am writing as I work my way through the modern web stack from a WordPress developer’s perspective. It is for people who, like me, have built on the web for years and still hit words in a modern stack they could not confidently define. The goal is broad literacy, not deep mastery: by the end you should be able to read any modern stack list and know what each piece does.
Each post comes with an audio companion (10-15 minutes, generated via NotebookLM) for gym or commute listening. Press play below if that suits you better than reading.
The way most WordPress shops still deploy code in 2026 would have looked normal in 2005. You connect to the server with FileZilla or scp. You upload changed files. You hope you uploaded the right ones. You SSH in and run wp cache flush. You realise you forgot one file. You upload it. You hope nothing else needs uploading. You close the FTP client. You wait for a client to call about the bug you introduced.
This is not a critique of WordPress culture so much as an observation about what the platform never solved. Modern web development looks completely different. You write code, commit it to git, push to a branch, and a pipeline takes care of everything else: running tests, building the production bundle, deploying to staging, running smoke tests, deploying to production, notifying you when each step succeeds or fails. The phrase for this is CI/CD: continuous integration, continuous deployment.
This module is the orientation. What CI/CD actually is, what GitHub Actions does, why teams without it eventually adopt it, and what changes for WordPress people the day they wire up their first pipeline.
CI/CD is two related ideas bolted together.
Continuous integration is the discipline of merging code changes into a shared branch frequently, with automated checks running on every change. The “checks” are tests, type-checking, linting, build verification — anything that catches “this change is broken” before a human reviews it. The big idea: keep the main branch always deployable.
Continuous deployment extends CI by automating the deployment itself. When code lands on the main branch, the pipeline deploys it to production without manual intervention. (Continuous delivery is the same idea but with an explicit approval gate before production; the difference is mostly semantic.)
In practice, a modern CI/CD pipeline runs on every push to a branch and looks something like:
- Check out the code
- Install dependencies
- Run the type-checker
- Run the linter
- Run unit tests
- Build the production bundle
- Run integration tests against the build
- If on main, deploy to production
- Notify Slack / Discord of success or failure
Each step is defined in a YAML file in the repo. The CI service (GitHub Actions, GitLab CI, CircleCI) reads the YAML, spins up a fresh environment, and runs the steps in order. If any step fails, the pipeline stops and reports the failure.
This is the actual mechanism behind “deploy by git push.” You push code. The pipeline does the rest.
The WordPress Analogue
Mental model: GitHub Actions is to your code what cron jobs are to your server, except they fire on events you choose and run somewhere off your infrastructure.
WordPress sites have nothing like CI/CD by default. The platform was designed when “deploy” meant “FTP files to a server” and that mental model still dominates much of the ecosystem. Even modern WordPress hosts (Kinsta, WP Engine) build their deployment flows around git pushes to their own systems, not around a pipeline you control.
The shift is: in a CI/CD world, the deployment is your code, versioned alongside the rest of the project, reviewable in pull requests. The pipeline configuration is in the repo. New team members can read it and understand how the project deploys. There is no tribal knowledge about “you have to FTP to the right folder.”
The CI/CD services to know
The main CI/CD services in 2026:
| Service | Strength | Pricing | Best for |
|---|---|---|---|
| GitHub Actions | Tight GitHub integration, huge marketplace of pre-built actions | 2,000 free minutes/month for public repos; per-minute pricing for private | Default for projects already on GitHub |
| GitLab CI | First-class CI built into GitLab, strong on Docker workflows | Generous free tier | Teams on GitLab; large monorepos |
| CircleCI | Fast, mature, strong macOS/iOS support | Pay-as-you-go | iOS/Android pipelines, larger teams |
| Buildkite | Self-hosted agents on your infrastructure | Per-agent pricing | Teams that need to run CI on private infrastructure |
| Vercel / Netlify built-in | Triggers automatically on git push | Bundled with hosting | Simple Next.js / static deploys without separate CI |
| Cloudflare Workers + git | Built into Cloudflare Pages | Bundled | Cloudflare-hosted projects |
For most WordPress veterans coming to the modern stack: GitHub Actions. Almost every modern project lives on GitHub already, the marketplace of pre-built actions covers the common cases, and the YAML configuration is well-documented.
A minimal GitHub Actions workflow lives at .github/workflows/deploy.yml and looks like this:
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- uses: pnpm/action-setup@v3
with:
version: 9
- run: pnpm install --frozen-lockfile
- run: pnpm typecheck
- run: pnpm test
- run: pnpm build
- name: Deploy to Vercel
run: pnpm dlx vercel deploy --prod --token ${{ secrets.VERCEL_TOKEN }}This runs on every push to main: installs dependencies, type-checks, tests, builds, deploys. The secrets.VERCEL_TOKEN is a credential stored in GitHub’s secret manager so the token never appears in the repo.
For Vercel / Netlify / Cloudflare Pages, you often skip the explicit deploy step entirely — those platforms watch your repo and deploy automatically. You still run CI to gate the deploy on tests passing, but the deploy itself happens on the host.
What This Changes for WordPress People
Three practical wins once you wire up your first pipeline.
The first is no more “did I upload that file.” Once the pipeline owns deployment, the only question is whether the code is on main. If it is, it is deployed. If it is not, it is not. The cognitive overhead of remembering what state the production server is in goes to zero.
The second is preview deploys per pull request. Vercel and Netlify give you a unique URL per PR, deployed automatically from the PR branch. Clients can review changes on a real URL before merge. This is genuinely transformative for client work; you stop emailing screenshots and start sending links.
The third is the test coverage conversation becomes real. Once tests run on every push, you start writing more of them, because the friction is zero and the feedback is immediate. WordPress culture historically had weak test coverage because the tests had no consistent place to run; CI/CD fixes that by giving them a place.
For WordPress projects specifically, you can wire CI/CD into the deploy flow even if you stay on Kinsta or WP Engine. Run linting, PHPStan, and unit tests on every push. Build a production-ready ZIP. Deploy via Kinsta’s API or SSH. The pipeline shape is identical; only the deploy target changes.
Secrets, caches, and other traps
A handful of traps.
Secrets management is its own discipline. Never commit API keys, database credentials, or tokens to git. Use the CI service’s secret store. Rotate secrets when team members leave. If a secret ends up in the repo by accident, treat it as compromised and rotate immediately; git history makes secrets hard to truly remove.
Slow pipelines kill the workflow. A pipeline that takes 15 minutes is barely useful. Aim for 3-5 minutes for typical projects. Cache dependencies aggressively. Parallelise jobs that do not depend on each other. The faster the feedback loop, the more useful CI/CD is.
Flaky tests destroy trust. A pipeline that fails 20% of the time for reasons unrelated to your code change teaches the team to ignore failures. Aggressively fix or remove flaky tests. A reliable amber light is worse than a reliable red one.
Deploy gates need thought. “Deploy to production on every push to main” works for projects where main is rarely broken. For larger teams, an explicit approval step before production is often safer. The right answer depends on team size and how mature your testing is.
Cost can surprise you. GitHub Actions free tier is generous but private-repo minutes add up. A poorly configured workflow that runs for 30 minutes on every push to every branch can burn through the quota fast. Monitor usage, especially after adding new jobs.
Level up your CI/CD
If you want to develop real CI/CD muscle, a few resources worth your time.
YouTube, gym or commute friendly:
- “GitHub Actions in 100 Seconds” by Fireship, then “GitHub Actions for Beginners” by TechWorld with Nana (~30 min).
- “CI/CD Explained” by Codedamn or similar (search for one with at least 100k views, the model is well-covered).
Official docs worth bookmarking:
- GitHub Actions docs. The “Quickstart” and “Understanding workflows” pages cover most of what you need. The marketplace is where you find pre-built actions for almost any common task.
- GitHub Actions reusable workflows. Once you have more than two projects, you will want to share workflow logic across them. This is how.
- 12-factor app. Not CI-specific, but the principles around environment variables, dependencies, and process model directly inform good CI/CD practice.
Next post in the series moves to observability: what replaces SSH-ing in to tail -f error_log when the production server is no longer somewhere you can log into.

Leave a Reply