Advertisement

Home/Coding & Tech Skills

How to Set Up a Basic CI Pipeline for a Side Project in 30 Minutes

coding-tech-skills · Coding & Tech Skills

Advertisement

Last Saturday, I pushed a commit to a side project I hadn’t touched in six weeks, crossed my fingers, and watched three tests I forgot I’d written fail in eleven seconds. Not because the code was broken—because I’d changed a dependency version and never re-ran the suite. That’s the exact moment a bare-bones CI pipeline earns its keep. In the twenty-nine minutes it took me to set one up the next morning, I saved myself from repeating that same brainless mistake every time I opened that repo. Here’s how you can do the same for your own side project—no DevOps badge required.

Advertisement

Why Your Side Project (Yes, Even That One) Needs CI Right Now

I hear it all the time: “It’s just a weekend project—why would I bother with CI?” The honest answer is that a three-second automated check beats a twenty-minute manual re-run every single time. When you’re coding alone, you don’t have a teammate to catch the typo that breaks the import or the config that only works on your machine. A CI pipeline runs those checks in a clean environment, exactly the way they’d run on a server or a teammate’s laptop. It also forces you to keep your build and test commands explicit and repeatable—which means you can pick up the project three months later without guessing how to run it. And let’s be real: a green “passing” badge on your README looks clean and tells anyone who stumbles on your repo that you care about quality. That matters more than you think.

What You'll Actually Need Before We Start the 30-Minute Clock

Here’s the short, non-intimidating list: a GitHub account, a codebase that runs locally (any language works—Node, Python, Go, Ruby, whatever), and basic comfort typing commands in a terminal. That’s it. You don’t need Docker, Kubernetes, or a credit card. If you’ve ever run npm test or python -m pytest from your project directory, you’re overqualified. I’m assuming you have a repo already pushed to GitHub—even a private one works—and that you know how to open a file in your code editor. Everything else I’ll walk through line by line.

Step 1: Pick Your CI Provider and Connect Your Repo (5 Minutes)

For a side project, GitHub Actions is the easiest choice because it’s built right into GitHub. You don’t need to create another account or configure webhooks. If your repo is on GitLab, GitLab CI is equally straightforward. I’ll focus on GitHub Actions here, but the same YAML pattern works everywhere. Open your repo in a browser, click the “Actions” tab at the top, and you’ll see a “set up a workflow yourself” button. Click it. GitHub creates a new file at .github/workflows/main.yml and opens it in a web editor. That’s your pipeline. You’ve already spent about ninety seconds.

Step 2: Write a Simple YAML Config That Actually Runs Your Tests (10 Minutes)

Delete the placeholder content and paste this for a Node.js project (adjust for Python or Ruby—I’ll show you how in a second):

name: CI
on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm test

Here’s what each line does: on: [push] tells GitHub to run this every time you push any branch. runs-on: ubuntu-latest gives you a clean Linux virtual machine. The first two uses steps check out your code and install Node 20. npm ci installs dependencies exactly from your lockfile (faster and more reliable than npm install). npm test runs whatever test script you have in package.json. For Python, swap those two uses lines for actions/setup-python@v5 and change the commands to pip install -r requirements.txt and pytest. Commit this file directly to the default branch, and the pipeline triggers automatically.

Step 3: Add a Build Step and a Quick Linter to Catch Messy Code (10 Minutes)

Tests alone don’t catch everything—they won’t tell you that you left a console.log in production code or that your formatting is inconsistent. Add a linter step right after the test command. For Node, add npx eslint src/ after npm test. For Python, add flake8 . (install flake8 in your requirements file first). If you don’t have a linter config yet, install the tool locally once and run it with --init or just copy a minimal config from the tool’s docs. This step adds maybe three lines to your YAML and catches style issues that tests miss. I also recommend adding a build step if your project compiles (TypeScript, SASS, etc.): npx tsc --noEmit for TypeScript or npm run build. The full YAML now looks like this:

      - run: npm ci
      - run: npm test
      - run: npx eslint src/
      - run: npx tsc --noEmit

Commit the updated file. The pipeline will re-run on the next push.

What Happens When You Push: The CI Flow in Action (5 Minutes)

Push a commit and go to the “Actions” tab in your repo. You’ll see a new workflow run with a yellow circle (running), a green checkmark (success), or a red X (failure). Click into a run to see each step’s log. When a step fails, the log shows exactly which command returned a non-zero exit code and what error message it printed. I’ve seen beginners panic at a red X—don’t. Read the last few lines of the failed step. Nine times out of ten, it’s a missing dependency, a syntax error, or a test that was already failing locally but you didn’t notice. Fix the issue, commit, and push again. The pipeline re-runs automatically. That’s the whole loop.

Common Pitfalls (And How to Sidestep Them in Under a Minute)

The most frequent mistake is forgetting to commit your lockfile (package-lock.json or requirements.txt). Without it, npm ci fails. Second: mismatched Node or Python versions. If your local machine runs Node 22 but your YAML says node-version: '18', you might get failures from deprecated APIs. Keep versions aligned. Third: secrets. If your tests call an API that needs a key, don’t hardcode it. Go to your repo’s Settings > Secrets and variables > Actions, add the secret, then reference it in your YAML as ${{ secrets.MY_SECRET }}. That keeps it out of your code and logs. Finally, if your pipeline runs longer than five minutes for a simple side project, check that you’re not running an entire test suite on every push when a subset would do—but honestly, for a hobby project, speed barely matters.

Next-Level Tweaks When Your 30 Minutes Are Up (Optional, But Fun)

Once you have the basic green checkmark, consider adding a status badge to your README. In your repo’s Actions tab, click the three-dot menu on the workflow, select “Create status badge,” copy the Markdown, and paste it at the top of your README. It looks like a little shield and tells visitors the build status at a glance. Another easy upgrade: add a deploy step that pushes to Netlify or Vercel after a successful build. GitHub Actions has pre-built actions for both—just add another step that runs their CLI commands. You can find templates by searching the GitHub Marketplace. None of this is required, but it turns a simple CI pipeline into a mini DevOps system that deploys your side project automatically.

Practical takeaway: Spend the next half hour setting up this three-step pipeline—test, lint, build—on your most active side project. The first time it catches a stupid error you would have pushed to production, you’ll wonder why you didn’t do it sooner. Bookmark this article if you want the YAML snippets handy for your next repo.