Minimal CI Checks for Side Projects

minimal-ci-checks-for-side-projects

Minimal CI Checks for Side Projects. A Build Next Stack field guide for learners shipping small projects.

The smallest CI that still catches embarrassment

Continuous integration for a side project should prevent public broken main—not replicate enterprise pipeline cosplay. Riley’s minimum bar on GitHub Actions:

  1. Install — lockfile-respecting dependency install
  2. Lint or format check — one, not twelve overlapping tools
  3. Test — unit tests if they exist; smoke test if not
  4. Build — only if you deploy artifacts from CI

Four steps, under five minutes total on free tier. Anything slower gets skipped on tired nights—and then CI becomes fiction.

Run the workflow on pull requests and pushes to main. Solo still benefits from PRs-to-self: a pause before merge, CI green as a ritual handshake.

One workflow file, pinned action versions

Keep a single .github/workflows/ci.yml. Pin action SHAs or major versions you bump intentionally—actions/checkout@v4, not floating @main. Riley comments at the top: Last green: 2026-05-26 on Ubuntu 22.04 after host image changes broke apt packages once.

Matrix builds across three Node versions are for libraries, not a personal todo app. Pick the runtime you actually use locally and document it in README. CI exists to catch forgot to push lockfile, not to prove compatibility with Node 16 you never run.

Cache dependencies if installs exceed ninety seconds; skip cache tuning if installs are fast. Premature cache optimization is a hobby inside a hobby.

Smoke tests when the test suite is thin

Greenfield side projects often have zero tests. Riley adds a smoke script that proves the app boots:

  • CLI — –help exits 0 and prints usage
  • API — start server in CI, curl -f localhost:PORT/health
  • Static site — npm run build and assert dist/index.html exists

Smoke tests are cheap insurance against missing imports and broken entrypoints. When real tests arrive, keep smoke as a fast first gate—fail in thirty seconds before the suite runs five minutes.

Secrets and forks: safe defaults

CI needs secrets for deploy—not for every PR from the internet. Riley uses GitHub environments: production secrets only on main branch workflows; PR workflows get no deploy keys. Read-only test tokens use repo secrets scoped to CI only.

Never echo secrets in logs. If a step prints env for debugging, remove it before merge. Fork PRs should not exfiltrate—disable workflow runs from forks or use pull_request_target only when you understand the risk; default is safer for solo public repos.

Rotate CI tokens when you rotate local .env keys. One leak surface is enough to monitor.

Fail loud, fix fast: notifications that matter

Wire CI failure to one channel you actually read—email, phone push from GitHub mobile, or a Telegram bot if you live there. Riley ignores Slack webhooks for side projects; another mute icon solves nothing.

When CI fails on main, fix or revert within twenty-four hours. Red main is a tax on every future commit. Revert-first culture applies solo too: unknown red is worse than losing a half-baked feature.

Flaky tests get deleted or quarantined with an issue link—not re-run until green. Flakiness erodes trust faster than no tests.

When to add deploy automation

Deploy from CI only after manual deploy succeeded three times the same way. Riley’s sequence:

  1. Document manual deploy in README.
  2. Script manual steps into scripts/deploy.sh run locally.
  3. Move script to CI with approval gate on production environment.

Automating a broken manual process multiplies pain. CI deploy is optional for portfolio sites that ship monthly; it is valuable when you fix typos weekly and hate FTP.

CI budget: time and cognitive load

Cap workflow complexity: if YAML exceeds sixty lines, extract composite actions or simplify. Riley reviews CI quarterly—remove steps that have not failed in six months. Unused SonarQube scans are vanity.

Measure median CI duration. Target under four minutes for feedback on PRs. Above ten minutes, developers—still you—stop waiting and merge anyway.

Minimal CI is a contract with future you: main means tested enough to show a friend, not certified for spacecraft.

Riley posts CI duration in README footnote—Typical CI: 3m20s—updated when workflow changes. Visible timing sets expectations for solo PRs-to-self the same way it does for teams.

Sample workflow skeleton Riley copies

New repo day one gets this trimmed YAML—adapt runtime, keep shape:

  • on: pull_request, push to main
  • jobs.test: checkout → setup Node 20 → npm ci → npm run lint → npm test → npm run build
  • timeout-minutes: 10 hard cap so hung jobs fail instead of billing silence

Comments in YAML explain non-obvious steps: why npm ci not install, which env vars are fake in CI. Comments feel redundant until you return after three months away from the stack.

Riley disables workflows entirely on archived repos via GitHub settings—prevents dependabot and action emails from zombie projects. Archive is a CI action too.

Local CI before push when bandwidth is slow

When hotel Wi-Fi makes remote CI painful, Riley runs act locally for smoke steps or a shell alias ci-local that mirrors the YAML commands in order. Local parity is not perfect—macOS vs Ubuntu—but catching lint failures before push saves round trips.

Document ci-local in README next to quick start. Future you on a train remembers one command instead of re-reading YAML.

Never treat local green as permission to skip remote CI on merge. Machines diverge; remote is the referee.

When CI fails on a dependency you did not touch, pin the transitive package or update lockfile in a dedicated commit—mixing with feature code hides cause during bisect later.

Branch protection without a team

Solo repos still benefit from GitHub branch protection on main: require status checks, disallow force push. Riley merges via PR even alone so CI runs on the combined diff. Direct pushes to main bypass CI when tired—that is when protection helps.

Protection feels bureaucratic until one bad merge at midnight. Settings take five minutes once; regret lasts longer.

Green main before the next feature branch

If your side project has no CI, add install plus one smoke step this week. Pin the runtime you use daily; skip matrix fantasies.

Let CI fail loudly to your phone once so you notice. Then fix red main the same day—solo repos rot when embarrassment is private.

Deploy automation can wait. Honest green checks on every merge cannot.