All Posts
Currently bookingWant one like this?

Tell us what you're building. We'll come back with a plan.

Contact Us
DevOps

The CI/CD Stack We Set Up on Day One of Every Project

Post snapshot
9 mins read
Reading time
February 12, 2026
Published
DevOps
Category
Mark P.
Written by
The CI/CD Stack We Set Up on Day One of Every Project

Why Day-One CI Matters

The teams that ship slowly are not the teams writing slow code. They're the teams that deferred CI until "after we have something working" and then never came back to it. By month two, every deploy is a manual SSH session, every PR breaks main twice a week, and every database migration is a small terror.

We set up CI before we set up the database. The cost is a single morning. The payoff is every subsequent deploy for the life of the project.

GitHub Actions Over Everything

We've shipped projects on CircleCI, GitLab CI, Buildkite, and homegrown Jenkins. GitHub Actions wins on almost every dimension that matters for the agency work we do: free for our usage tier, fast cold starts, native to where the code already lives, huge ecosystem of pre-built actions.

The one place GitHub Actions struggles is very large monorepos. For everything else, the answer is "use GitHub Actions and stop deliberating."

The Day-One Baseline

Every new repo we open gets the same five-workflow baseline:

1. PR validation—lint, typecheck, test, build. Runs on every push to any branch.

2. Preview deploy—on PR open, deploys to a unique URL like `pr-123.staging.example.com`.

3. Staging deploy—on merge to `main`, deploys automatically to the staging environment.

4. Production deploy—manual trigger only, with required reviewer approval and a typed confirmation.

5. Nightly cleanup—prunes preview environments older than seven days.

Total time to set up from scratch on a new project: 90 minutes if we're being unhurried.

Preview Deploys Per PR

This single feature does more for team velocity than any other piece of infrastructure we ship. Every pull request gets a unique, isolated URL with the branch's code running against a fresh database. Designers can review. Product can click around. QA can break things. Clients can see progress without us having to schedule a demo.

The unique URL is in the PR description, posted by the workflow as a comment. The database is reset on every push to the branch. The environment is destroyed automatically seven days after the PR closes.

We've watched teams who switched to per-PR previews cut their average PR cycle time in half within two weeks.

The Migration Safety Net

The single most-feared deploy is the one with a database migration. Most production incidents at small companies trace back to a migration that worked locally and failed on real data.

Our migration workflow has three gates:

  • The migration runs against a fresh copy of production data nightly. If it fails, the workflow alerts us before the human even opens the PR.
  • The migration runs against the staging database on every merge to main, in a transaction that rolls back, so we see both the schema change and any data drift.
  • The production migration runs in a separate workflow that requires a typed confirmation token and a second reviewer.

This catches roughly 90% of migration mistakes before they reach production. The remaining 10% catch us through the second-reviewer step.

Production Deploy Gates

We never auto-deploy to production. Some readers will disagree—and for high-frequency consumer products with deep observability, continuous deployment to prod is the right answer. For the agency work we do, where production failures impact a client's business directly, we want a human in the loop.

The production workflow requires:

  • A green PR validation run
  • A successful staging deploy at the same commit
  • A typed confirmation matching the commit SHA
  • A second reviewer who isn't the author

The whole flow takes 90 seconds when nothing's wrong and saves us from a category of incidents we've watched other teams suffer through.

What We Don't Do

A few patterns we intentionally avoid:

  • We don't run end-to-end tests on every PR. They're slow and flaky. We run them nightly and on release branches.
  • We don't gate merges on coverage thresholds. They incentivize the wrong behavior.
  • We don't run the full test suite locally pre-commit. The CI does it; locally we run only the directly-touched tests.

Less is more in CI. Every check you add is a check someone will eventually skip because "it's flaky" and "we need to ship."

Total Setup Time: 90 Minutes

That's the headline. Ninety minutes of work, one time, at the beginning of a project, saves weeks of pain over the life of that project. We've never regretted a single CI setup. We have regretted, many times, the projects where we deferred it.

Written by

Mark P.

⚙️ Writes about devops at LevelByte. Built things at startups and agencies for the last decade.

Work with us
Let's build some software

Let’s buildsomethingreal.

From 0 to production, we're the engineering partneryour team deserves.

LevelByte
( © 2026 LevelByte. All rights reserved. )
All Systems Operational