🗡️ Beyond GitOps Pipelines
A Problem Without a Single Solution
Imagine you're managing CI/CD pipelines across multiple projects. Some use GitHub Actions, others rely on GitLab CI, and your infrastructure team swears by their custom Kubernetes-based workflows (shoutout to the Tekton guys out there!). You're constantly rewriting the same deployment logic in different YAML dialects, debugging platform-specific quirks, and wondering: why isn't there a universal way to define pipelines?
Then you discover Dagger.
But before you jump ship from your current CI/CD solution, let's talk about what Dagger actually is, how it compares to GitHub Actions and GitLab CI, and whether it's the right fit for your team.
What is Dagger?
Dagger is a programmable CI/CD engine that lets you write your pipelines in real programming languages (Go, Python, TypeScript) instead of YAML. It's platform-agnostic — you can run the exact same pipeline on GitHub Actions, GitLab CI, your local machine, or any other CI/CD system.
Think of it as infrastructure-as-code for pipelines themselves. Instead of learning YAML syntax for each platform, you write actual code with proper logic, reusability, and testing.
Here's what a Dagger pipeline looks like in Go:
package main
import (
"context"
"fmt"
"dagger.io/dagger"
)
func build(ctx context.Context, src *dagger.Directory) (*dagger.Container, error) {
return dag.Container().
From("golang:1.20").
WithDirectory("/src", src).
WithWorkdir("/src").
WithExec([]string{"go", "build", "-o", "app", "./cmd"}).
Sync(ctx)
}
func test(ctx context.Context, src *dagger.Directory) (string, error) {
return dag.Container().
From("golang:1.20").
WithDirectory("/src", src).
WithWorkdir("/src").
WithExec([]string{"go", "test", "./..."}).
Stdout(ctx)
}
Run it locally with dagger call build --src ., on GitHub with a shell step, or on GitLab with the same command. One source of truth.
The Three-Way Comparison
| Aspect | Dagger | GitHub Actions | GitLab CI |
|---|---|---|---|
| Language | Go, Python, TypeScript | YAML + JS/Shell | YAML + Shell |
| Platform lock-in | None | GitHub-only | GitLab-only |
| Local execution | Yes, via Docker | No (not really) | Limited |
| Ecosystem | Tiny atm | Massive marketplace | Solid built-ins |
| Learning curve | Moderate (needs programming) | Low (YAML) | Low–moderate |
| Maturity (2023) | 0.x, APIs still changing | Production-ready | Production-ready |
| Debugging | Run locally, full logs | Push-and-pray | Push-and-pray |
| K8s integration | Growing | Basic | Deep |
| Best for | Complex multi-platform pipelines | GitHub-native projects | GitLab + K8s teams |
GitHub Actions
Incredibly convenient if you live in the GitHub ecosystem. The marketplace has pre-built actions for nearly everything, and setting up a basic pipeline takes minutes. But you're locked to GitHub, YAML gets unwieldy for complex logic, and debugging means pushing commits to see what happens.
GitLab CI
Arguably the most feature-rich option. Deep Kubernetes integration, powerful caching, built-in container registry, and a cleaner YAML syntax than GitHub Actions. If your infrastructure lives in GitLab and Kubernetes, it's genuinely excellent. Same lock-in problem though — switching platforms means rewriting everything.
Where Dagger Differs
Dagger's pitch is simple: write your pipeline once in a real language, run it anywhere. You get type safety, testable pipeline logic, proper conditionals and loops, and — crucially — local execution. No more pushing a commit just to see if your CI config works.
Dagger: Pros
Dagger can scale on virtually any CI/CD platform because your pipeline is just code running in containers. There's no vendor lock-in — the same pipeline definition works on GitHub, GitLab, Jenkins, or your laptop. Local execution via Docker means you can iterate on pipeline logic without pushing commits, which is a genuine productivity win. And because you're writing real code, you get type checking, unit tests for your pipelines, and proper abstractions.
Try It — At Least as a POC
I tested Dagger as a proof of concept, and as a Go developer, it's genuinely fun to use. Seeing your pipeline execute locally and being able to step through it like regular code is a great experience. If you're a DevOps person who lives in pipelines, you'll probably love it.
But here's the reality: most developers just want CI/CD that works. They don't want to tinker with it. And from what I've seen, people get nervous when you take away the familiar pipeline UI of their GitHub or GitLab instance — Dagger feels like another black box to them. On top of that, if you already have well-crafted, working pipelines, rebuilding them from scratch in Dagger is a significant effort with unclear payoff.
That said, I'd encourage everyone to at least give it a try — especially if you're starting fresh with new pipelines for a new project. That's where Dagger's strengths actually shine.