The Philosophical Developer — Chapter 15: The Pipeline

2026-07-09 · 4 min read

The Pipeline

CI/CD 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:

  1. Edit a module
  2. Run tofu test manually
  3. Push the commit
  4. 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.