The Philosophical Developer — Chapter 15: The Pipeline
2026-07-09 · 4 min read
The Pipeline

Last chapter we coded infrastructure with OpenTofu — five modules, seven tests, all passing. But a test suite that runs locally is a habit, not a guarantee. The difference between discipline and assurance is automation.
Code without a pipeline is a promise. Code with a pipeline is a proof.
Pipeline code lives in the local-cloud repo on GitHub.
The Problem
Every change to the local-cloud stack went through this flow:
- Edit a module
- Run
tofu testmanually - Push the commit
- Hope it still works on someone else’s machine
Fragile. Depends on human memory. Depends on your machine having the same Floci state as everyone else’s.
A CI pipeline removes all three dependencies.
Why Dagger
Traditional CI is YAML sprawl — repetitive steps, copy-paste boilerplate, no local testing. You write the pipeline, pray it works, then push and wait for the runner to tell you what you got wrong.
Dagger solves this by treating pipelines as code. You define your CI in Go, run it locally with dagger call, and the same pipeline executes in CI. No “works on my machine” gap.
The Pipeline Stages
The Pipeline module has four stages, each corresponding to a OpenTofu command:
1. fmt — Style Enforcement
tofu fmt -check -recursive .
Enforces consistent HCL formatting across all modules. No formatting, no merge. This is the lint gate — cheap, fast, catches the noise before real work begins.
2. validate — Schema Check
tofu init && tofu validate
Run per-module. Validates that the HCL parses, references are correct, and all required attributes are present. Catches typos, missing providers, and misconfigured blocks.
3. test — Behavior Contracts
tofu test
The heart of the pipeline. Each module has a .tftest.hcl file with assertions. The pipeline runs all tests in plan mode (idempotent, no side effects) and blocks the PR if any fail.
4. plan — Preview
tofu plan -no-color
Runs only after all tests pass. Shows the full execution plan — what would be created, modified, or destroyed. The output is captured as a build artifact for review.
GitHub Actions Integration
The pipeline is triggered by a GitHub Actions workflow that fires on pushes to main and PRs touching infrastructure/**:
name: 'OpenTofu CI'
on:
pull_request:
paths:
- 'infrastructure/**'
push:
branches: [main]
paths:
- 'infrastructure/**'
permissions:
contents: read
jobs:
tofu-ci:
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: pipeline
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run Dagger pipeline
uses: dagger/dagger-for-github@v7
with:
version: '0.21.7'
verb: call
args: >-
fmt-check validate-modules test-modules integration-plan
The workflow checks out the repo, sets the working directory to pipeline/ where the Go module lives, and runs all four functions sequentially. If any stage fails, the entire pipeline fails and the PR is blocked.
Local Development
The same pipeline runs locally via Dagger from the pipeline/ directory:
cd pipeline
dagger call fmt-check
dagger call validate-modules
dagger call test-modules
dagger call integration-plan
Each function runs in an isolated container with OpenTofu installed. The infrastructure files are loaded from ../infrastructure relative to the module. No manual tofu init or tofu test needed — the pipeline manages everything.
The Pipeline as Documentation
A well-written pipeline is documentation you can execute. Every stage is a statement about what the team values:
- fmt says: consistency matters
- validate says: correctness matters
- test says: contracts matter
- plan says: awareness matters
The pipeline is the single source of truth for how infrastructure code is validated. No one can claim “I didn’t know we needed to run tests.” The pipeline enforces it impartially.
What’s Next
With the pipeline in place, the local-cloud stack has:
- A local development environment (Floci + k3s + registry)
- Infrastructure as code (OpenTofu modules with TDD)
- Automated validation (CI/CD pipeline)
The next chapter will bring these together — deploying actual workloads onto the k3s cluster, using the pipeline to validate every change, and proving that a local-first approach to cloud infrastructure is not just possible, but practical.
Also on LinkedIn.