Problem How It Works Benefits Get Started Ecosystem Deep Dive Contributing GitHub Repo
Open Source Apache 2.0 Go 1.25+

Stop debugging your pipeline.
Start shipping your code.

Containerized CI/CD pipelines defined in Go — identical builds on your laptop and in CI.

Your builds should just work

Every team hits the same wall. The build passes on your laptop but breaks in CI. A new developer joins and loses a day setting up their environment. A silent version mismatch ships a broken artifact to production.

You end up debugging your pipeline instead of building your product.

ContainifyCI eliminates this entire class of problems. Define your pipeline in Go, run it in containers, and get identical results everywhere — your machine, your teammate's machine, and CI.

$ engine-ci run

One command. No YAML. No drift. No surprises.

The old way vs. the ContainifyCI way

Without ContainifyCI

  • Hundreds of lines of YAML nobody wants to touch
  • "Works on my machine" but fails in CI
  • New developers spend hours setting up tooling
  • Different tool versions across environments
  • Pipeline logic scattered across shell scripts
  • Debugging means push-and-pray

With ContainifyCI

  • Pipeline defined in real, testable code
  • Identical builds on every machine, every time
  • New developers run one command and they're ready
  • Tool versions pinned in containers automatically
  • All build logic in one place, version-controlled
  • Debug locally before you push

Three steps to better builds

Step 1
✍️

Define

Write your build pipeline in Go — a real language with types, tests, and your IDE's full support. No more guessing if your YAML is valid.

Step 2
📦

Containerize

Every step runs inside a container with pinned tool versions. What runs on your laptop is exactly what runs in CI.

Step 3
🚀

Ship

One binary, zero dependencies. Works anywhere Docker or Podman runs — macOS, Linux, GitHub Actions, or your own infrastructure.

Why teams choose ContainifyCI

🔒

Builds that never drift

Containers lock down every tool version. The "but it works on my laptop" conversation is over.

Onboard in minutes, not days

New team members run engine-ci run and get the exact same build as everyone else. No setup wikis. No tribal knowledge.

🌐

One tool for every language

Go, Java, Python, and more through a modular extension system. Your team learns one workflow regardless of the stack.

🛡️

Security built in, not bolted on

Container image scanning, secret management, and automated dependency updates are part of the pipeline — not afterthoughts.

🏎️

Fast by default

Build steps run in parallel where possible. No configuration needed — ContainifyCI figures out what can run concurrently.

🔓

No vendor lock-in

Works with Docker and Podman. Runs in GitHub Actions, GitLab CI, or any environment with a container runtime. Your pipeline is yours.

Get started in 30 seconds

terminal
# 1. Install
go install github.com/containifyci/engine-ci@latest

# 2. Initialize your project
engine-ci init

# 3. Build — same result everywhere
engine-ci run

engine-ci init creates a .containifyci/containifyci.go file — your entire build pipeline in a single Go file that you can read, test, and version-control like any other code.

See it in action

Here's how dunebot — a real ContainifyCI project — defines its entire build and CI pipeline.

1. Define your build .containifyci/containifyci.go
package main

import (
    "os"

    "github.com/containifyci/engine-ci/client/pkg/build"
    "github.com/containifyci/engine-ci/protos2"
)

func main() {
    os.Chdir("../")
    opts := build.NewGoServiceBuild("dunebot")
    opts.Application = "dunebot"
    opts.File = "main.go"
    opts.Properties = map[string]*build.ListValue{
        "goreleaser": build.NewList("true"),
    }
    build.Serve(opts)
}
2. Wire it into GitHub Actions .github/workflows/pull-request.yaml
name: Pull Request
on:
  pull_request:
    branches: [main]

jobs:
  build:
    name: Build
    uses: containifyci/.github/.github/workflows/pull-request.yml@v1
    secrets: inherit
3. Add a release workflow .github/workflows/release.yaml
name: Release
on:
  push:
    branches: [main]
    paths-ignore: ['.github/**']

jobs:
  build-and-release:
    uses: containifyci/.github/.github/workflows/release.yml@v1
    secrets: inherit

One Go file for your build logic. Two tiny YAML files to connect it to GitHub Actions. The same engine-ci run command works locally and in CI — no divergence, no surprises.

See the full working example at containifyci/dunebot.

More than a build engine

ContainifyCI is a growing toolkit for modern CI/CD.

⚙️ Build Engine

engine-ci

The core — containerized CI/CD pipelines defined in Go

engine-java

Java & Maven build support

engine-python

Python build support

🛡️ Automation & Security

dunebot

GitHub App that auto-reviews and merges dependency PRs

feller

Secret management for GitHub Actions (Google Secret Manager, dotenv, and more)

secret-operator

One-time secret retrieval for secure cloud provisioning

🛠️ Developer Tools

go-self-update

Add auto-update capabilities to any Go CLI

dependabot-templater

Auto-generate Dependabot configs for multi-folder repos

Under the Hood

Why Go instead of YAML?

YAML Pipelines Go Pipelines (ContainifyCI)
Error detection Runtime — fails mid-build Compile time — fails before build starts
Testing Manual / none Unit tests with go test
IDE support Syntax highlighting only Full autocomplete, refactoring, go-to-definition
Reuse Copy-paste snippets Import packages, call functions
Debugging Push and pray Run locally, set breakpoints

Architecture

Your code (.containifyci/containifyci.go)
engine-ci CLI → Compiles to single binary
Container runtime (Docker / Podman)
Isolated build steps with pinned tool versions

engine-ci reads your build definition from .containifyci/containifyci.go, compiles it into a self-contained binary, and orchestrates containers to execute each build step in isolation. Tool versions are pinned inside the containers — not on the host machine.

Language support is modular. engine-java and engine-python are extensions that plug into the core. Adding support for a new language means writing a Go package that implements the build interface.

Key Integrations

🐳 Docker 🦭 Podman 🔍 Trivy 📦 GoReleaser 🔑 Feller 🤖 Dunebot ⚙️ GitHub Actions 🦊 GitLab CI

Contributing

ContainifyCI is open-source under the Apache License 2.0. We welcome every kind of contribution.

🚀

Use it

Try engine-ci on your project and tell us what breaks.

🔧

Fix it

Found a bug? PRs are always welcome.

🧩

Extend it

Build a language extension and share it with the community.

💬

Talk about it

Open issues, start discussions, share your experience.