You know that feeling when you realize the thing you’ve been running from, the thing that seemed super hard, is actually way simpler than you thought?
Yeah. That was me with CI/CD.
Back when I earned a bit of cred at work, I used to “delegate” repo management and CI/CD. I say “delegate” because, honestly, I was just bad at it. The jargon, the layers of abstraction; it was all so damn annoying.
And if that’s not wild enough, I once tried to sit through a one-hour DevOps tutorial… and woke up at the 45-minute mark 😔
Eventually, I forced myself to think about CI/CD like a developer. And guess what? It’s stupid simple.
CI/CD is just... functions. Yep. Just functions. Let me show you.
This is for programmers like me; who "hate" CI/CD not because it’s evil, but because we’ve just been bad at it. Maybe it’s time to approach it like we would anything else: code first.
CI/CD
So yeah..CI/CD are just functions.
But not your usual functions. These are evented functions. You don’t run them manually; they get triggered by an event.
Now here’s the analogy:
A CI/CD pipeline has something called steps I like to call them mini-functions. Each step does one thing, just like a regular function.
For example:
// example.js
function downloadNodejs() {}
function setUpNodejs() {}
function checkOutTheRepo() {}
function runPnpmInstall() {}
function runPnpmRunTest() {}
These “steps” get composed into a higher-order function, aka a workflow:
function MyJavaScriptProjectWorkflow() {
function downloadNodejs() {}
function setUpNodejs() {}
function checkOutTheRepo() {}
function runPnpmInstall() {}
function runPnpmRunTest() {}
}
And this workflow only runs when you trigger an event:
event.emit("myevent")
What kind of events?
- A push
- A pull request
- A merge
- Basically, anything you do on a repo.
Now here’s the cool part; workflows can reuse other workflows. Instead of writing the setup logic yourself, you can use prebuilt actions like this:
function MyJavaScriptProjectWorkflow() {
uses: actions/setup-node@v4 // does downloadNodejs() + setUpNodejs()
uses: actions/checkout@v3 // does checkOutTheRepo()
function runPnpmInstall() {}
function runPnpmRunTest() {}
}
That’s pretty much the core of CI/CD.
But let’s build a real example so it sinks in.
Add Function CI Workflow
First, create a simple npm project with a test:
npm init -y
npm i -D mocha
Your file structure should look like this:
.github/
workflows/ci_add.yml
test/
app.js
main.js
.gitignore # add node_modules
In your package.json
, update the scripts:
"scripts": {
"test": "mocha"
}
Initialize a Git repo:
git init
Here’s your simple library:
main.js
export function add(a, b) {
return a + b;
}
test/app.js
import { equal } from 'assert';
import { add } from '../main.js';
describe("add", () => {
it("should add", () => {
const res = add(7, 12);
equal(19, res);
});
});
Run your test locally:
npm run test
All good? Now let’s define the CI workflow.
.github/workflows/ci_add.yml
name: Node.js Add CI
on:
push:
branches: [ main ]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install Dependencies
run: npm install
- name: Run Tests
run: npm test
Let’s break this down; our mini-functions (steps) do the following:
- Checkout the repo
- Set up Node.js v18
- Run
npm install
- Run tests with
npm test
When does this run?
on:
push:
branches: [ main ]
Yup; on a git push. That’s our event. A function triggered by a real-world action.
Push your code and watch the workflow in action:
git add .
git commit -m "ready set go"
// add your remote
git push -u origin main
Head to the Actions tab in your GitHub repo, you’ll see logs from your first CI workflow run. easy...
What you just did? That’s the CI part of CI/CD.
And CD? Honestly, it’s not that different. Whether you're publishing to npm (they’ve got an API + token), deploying to GitHub Pages, or pushing an app to Google Play; they all expose APIs. Just more evented functions.
CI/CD isn’t scary. It’s just code, functions reacting to events. Once you see it that way, all the DevOps jargon kind of melts away.
Let me know if this clicked, or if you’re still tempted to fall asleep during DevOps tutorials 😅
You can find me here on x
More Content:
Building Redis From Zero To Hero with Node.js - free
Top comments (11)
Love how you framed workflows as 'evented functions'that finally made CI/CD click for me too!
I am very glad it clicked! 😁 I was running away from CI for years.
Damn this was so good I didn't want it to end. Where is part 2? We need a part 2!
This made my day LOL! thank you! I am glad you loved it.
You can find prebuilt actions in the github marketplace
mhlungusk@gmail.com
Yes ofc we can. anytime
Thanks! I am glad you liked it 👍