<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Liam Gough</title>
    <description>The latest articles on DEV Community by Liam Gough (@liam_gough).</description>
    <link>https://dev.to/liam_gough</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1804962%2F7102825c-e337-47aa-a181-167eb504908a.png</url>
      <title>DEV Community: Liam Gough</title>
      <link>https://dev.to/liam_gough</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/liam_gough"/>
    <language>en</language>
    <item>
      <title>I Hate Jenkins (Sorry Not Sorry) — So I Built My Own CI/CD Platform</title>
      <dc:creator>Liam Gough</dc:creator>
      <pubDate>Fri, 08 May 2026 19:30:54 +0000</pubDate>
      <link>https://dev.to/liam_gough/i-hate-jenkins-sorry-not-sorry-so-i-built-my-own-cicd-platform-4o8g</link>
      <guid>https://dev.to/liam_gough/i-hate-jenkins-sorry-not-sorry-so-i-built-my-own-cicd-platform-4o8g</guid>
      <description>&lt;p&gt;I want to tell you about the moment I gave up on Jenkins.&lt;/p&gt;

&lt;p&gt;It wasn't dramatic. There was no explosion, no catastrophic failure. It was a Tuesday afternoon, I was three hours deep into debugging a Groovy script in a Jenkinsfile, and I realised I had completely lost the plot. I wasn't writing software anymore. I was maintaining a CI/CD system that had become its own full-time job.&lt;/p&gt;

&lt;p&gt;That was the day I started building &lt;strong&gt;Callahan CI&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem With Jenkins (You Already Know This)
&lt;/h2&gt;

&lt;p&gt;If you've used Jenkins seriously, you already know the pain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The plugin ecosystem is enormous, poorly maintained, and a constant source of breakage&lt;/li&gt;
&lt;li&gt;The Groovy DSL is powerful but arcane — it feels like a different job from the rest of your work&lt;/li&gt;
&lt;li&gt;The UI is dated in a way that goes beyond aesthetics — it's genuinely hard to understand what's happening&lt;/li&gt;
&lt;li&gt;Running it locally for development feels like setting up a server farm&lt;/li&gt;
&lt;li&gt;Configuration lives in a dozen different places and none of them are obvious&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub Actions solved some of this — YAML is at least readable, and the marketplace is better curated. But then you're fully cloud-dependent, your secrets live somewhere you can't see, and the per-minute billing adds up faster than you expect on a side project.&lt;/p&gt;

&lt;p&gt;I wanted something that ran on my laptop. No cloud. No agents. No plugin marketplace. Just: I push code, something builds it, and I find out what broke.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Callahan CI&lt;/strong&gt; is a single Go binary. You clone the repo, run &lt;code&gt;./start.sh dev&lt;/code&gt;, and you have a working CI/CD platform on &lt;code&gt;localhost:3000&lt;/code&gt;. Everything — the API, the pipeline runner, the WebSocket log stream, the dashboard — is in that one process. State lives in a SQLite file.&lt;/p&gt;

&lt;p&gt;It reads a &lt;code&gt;Callahanfile.yaml&lt;/code&gt; (GitHub Actions-compatible syntax, so migration is low friction), executes your build steps as native shell processes, streams logs in real time, and stores results.&lt;/p&gt;

&lt;p&gt;That's the boring part. Here's the part I actually care about.&lt;/p&gt;




&lt;h2&gt;
  
  
  The AI Layer
&lt;/h2&gt;

&lt;p&gt;When I started building this I knew I wanted AI involved, but I didn't want the usual "AI assistant" bolted on as an afterthought. I wanted agents that do specific jobs at specific moments in the pipeline, without you having to ask.&lt;/p&gt;

&lt;p&gt;There are four:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Architect
&lt;/h3&gt;

&lt;p&gt;You describe your pipeline in plain English. The Architect writes the &lt;code&gt;Callahanfile.yaml&lt;/code&gt; for you — jobs, steps, deploy stages, AI flags — and commits it back to the repo. If you already have a Jenkinsfile or a GitHub Actions workflow, it can migrate that too.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Debugger
&lt;/h3&gt;

&lt;p&gt;When a build fails, you click &lt;strong&gt;AI Explain Failure&lt;/strong&gt;. The Debugger reads the failed job's logs and your pipeline config, and returns a short root cause with a concrete next step. No more scrolling through 800-line stack traces at 11pm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DIAGNOSIS: Build failed because npm couldn't find package.json.
The repo is a Go project — language detection fell through to the
JS default. Replace the build step with: go build ./...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. The Reviewer
&lt;/h3&gt;

&lt;p&gt;This one runs automatically on every build. It reads the diff for the commit that triggered the build and writes a structured code review — severity, finding, fix suggestion. For PR builds, it posts the review as a comment on the originating GitHub or GitLab PR. No action required on your part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;FINDING&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;23&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="n"&gt;hashed&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;MD5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Use&lt;/span&gt; &lt;span class="n"&gt;bcrypt&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;argon2id&lt;/span&gt; &lt;span class="n"&gt;instead&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. The Analyst
&lt;/h3&gt;

&lt;p&gt;If Trivy and Semgrep are on your machine, Callahan runs them on every build, parses the JSON output, and renders findings as expandable cards sorted by severity. If neither is installed, it falls back to an LLM source review. Either way, findings get posted to the PR alongside the code review.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[CRITICAL] GitHub Personal Access Token found in internal/auth/auth.go:14
→ rotate the token, move it to project secrets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;p&gt;In case you're curious:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Go 1.22, Gin, SQLite (WAL mode), &lt;code&gt;sync.RWMutex&lt;/code&gt; for thread safety&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Next.js 15 with SWC&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLM&lt;/strong&gt;: Groq (&lt;code&gt;llama-3.3-70b-versatile&lt;/code&gt;) by default, but Claude, GPT-4o, and Ollama are all wired in — switch in settings without a rebuild&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhooks&lt;/strong&gt;: HMAC-verified GitHub push/PR and GitLab push/MR&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containerisation&lt;/strong&gt;: Docker Compose if you want one-command setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Works fully offline if you point it at Ollama. No data leaves your machine unless you choose a cloud LLM provider.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Compares
&lt;/h2&gt;

&lt;p&gt;I'm not going to pretend this replaces Jenkins for a 200-engineer org. It doesn't. Here's an honest comparison:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Callahan&lt;/th&gt;
&lt;th&gt;Jenkins&lt;/th&gt;
&lt;th&gt;GitHub Actions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Runs locally&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;~ Self-hosted runners&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single binary&lt;/td&gt;
&lt;td&gt;✔ Go + SQLite&lt;/td&gt;
&lt;td&gt;✖ JVM + plugins&lt;/td&gt;
&lt;td&gt;✖ Cloud&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI code review&lt;/td&gt;
&lt;td&gt;✔ Built in&lt;/td&gt;
&lt;td&gt;✖&lt;/td&gt;
&lt;td&gt;✖&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security scanning&lt;/td&gt;
&lt;td&gt;✔ Trivy + Semgrep&lt;/td&gt;
&lt;td&gt;✖ Plugin&lt;/td&gt;
&lt;td&gt;✖ Action&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Posts to PRs&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;~ Plugin&lt;/td&gt;
&lt;td&gt;✔ Native&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works offline&lt;/td&gt;
&lt;td&gt;~ With Ollama&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;✖&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The honest target audience: solo developers and small teams who want their CI on their machine, with AI parts that actually work rather than being a demo feature.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trying It
&lt;/h2&gt;

&lt;p&gt;Docker is the fastest path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Callahan-ci/Callahan
&lt;span class="nb"&gt;cd &lt;/span&gt;Callahan
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
&lt;span class="c"&gt;# Add an LLM key to .env (or skip for Ollama)&lt;/span&gt;
docker compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
open http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From source if you have Go 1.22+ and Node 18+:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Callahan-ci/Callahan
&lt;span class="nb"&gt;cd &lt;/span&gt;Callahan
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'GROQ_API_KEY=your-key'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .env
./start.sh dev
open http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full docs at &lt;a href="https://callahanci.com" rel="noopener noreferrer"&gt;callahanci.com&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The Jenkinsfile migration tool is next on the roadmap — paste a Jenkinsfile, get a &lt;code&gt;Callahanfile.yaml&lt;/code&gt; back. Given how many teams are stuck on Jenkins not because they love it but because migration feels expensive, I think there's real value there.&lt;/p&gt;

&lt;p&gt;Authentication and multi-user support is also in progress — right now it's single-user local, which is fine for solo dev use but limits teams.&lt;/p&gt;




&lt;h2&gt;
  
  
  Honest Bit at the End
&lt;/h2&gt;

&lt;p&gt;The codebase was built with significant AI assistance throughout. I designed the architecture, made every product decision, and understand and own every part of it — but I want to be transparent rather than pretend I typed every line by hand. That feels like the right thing to say in 2026.&lt;/p&gt;

&lt;p&gt;If you try it and something is broken, &lt;a href="https://github.com/Callahan-ci/Callahan/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt;. If you have feedback, &lt;a href="https://github.com/Callahan-ci/Callahan/discussions" rel="noopener noreferrer"&gt;start a discussion&lt;/a&gt;. I read everything.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Callahan CI is MIT licensed. Star the repo if it looks useful — it genuinely helps with visibility.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Website: &lt;a href="https://callahanci.com" rel="noopener noreferrer"&gt;callahanci.com&lt;/a&gt; · Repo: &lt;a href="https://github.com/Callahan-ci/Callahan" rel="noopener noreferrer"&gt;github.com/Callahan-ci/Callahan&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cicd</category>
      <category>devops</category>
      <category>go</category>
    </item>
  </channel>
</rss>
