Skip to content

feat: Dagger module spike — ske-operator CI - #44

Draft
shano wants to merge 3 commits into
mainfrom
spike/dagger-ske-operator-test
Draft

feat: Dagger module spike — ske-operator CI#44
shano wants to merge 3 commits into
mainfrom
spike/dagger-ske-operator-test

Conversation

@shano

@shano shano commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

What this is

Spike from Research Friday: port `test-ske-operator.yaml` to a Dagger Go module in the `ci` repo, structured to make Dagger's value prop concrete rather than just being a shell script in Go syntax.

Setup

```bash
cd dagger/
dagger develop # generates dagger.gen.go, pins SDK version
```

`dag`, `*Directory`, `*Secret`, `*Container` come from the generated file — the module won't compile until `dagger develop` runs.

The four functions

Function What it produces
`ske-operator-build` `*Container` — the built operator image as a typed artifact
`ske-operator-unit` unit test output — no cluster needed
`ske-operator-e2e` e2e output — accepts the pre-built `*Container`
`ske-operator-all` runs unit + e2e in parallel, building exactly once

Why this structure (not just WithExec chains)

Typed artifacts — no registry round-trip

In GHA, passing a built Docker image from one job to the next requires pushing to a registry. Here, `SkeOperatorBuild` returns a `*Container`. `SkeOperatorE2e` calls `image.AsTarball()` and mounts the OCI tar directly into the DIND daemon via `docker load`. The image flows as a typed Go value. A release function would do the same: accept the same `*Container` and push it to GHCR — no rebuild.

Structural caching

`WithMountedCache` volumes are content-addressed by input hash. If `go.mod` didn't change, modules aren't re-downloaded. Both `SkeOperatorUnit` and `SkeOperatorE2e` share the same `ske-operator-go-mod` and `ske-operator-go-build` volumes — whichever runs first warms the cache for the other. In GHA this is a bolted-on `actions/cache` that you manage manually.

Parallelism is idiomatic Go

`SkeOperatorAll` calls `SkeOperatorBuild` once then fans out to unit and e2e via goroutines. No `needs:` arrays, no artifact upload/download between jobs.

e2e improvements over GHA

Problem GHA Dagger
Cold image pulls Images pulled inside cluster on pod start Pre-pulled + loaded into Kind before deploy
cert-manager timing race `WaitForKratixCerts` helper (added in #1248) Explicit `kubectl wait --for=condition=Available` gate before ske-operator deploy
Runner variance Sprinters AZ exhaustion kills the cluster DIND service is fully contained; runner state can't corrupt cluster
Image handoff Push to GHCR, pull in next job `image.AsTarball()` → `docker load` — no registry

Where this goes next

Once validated, the `ske-operator` job in `test-ske.yaml` becomes:

```yaml

  • name: Run ske-operator tests
    run: |
    dagger -m ./dagger call ske-operator-all
    --source=./enterprise-kratix/ske-operator
    --github-token=env:GITHUB_TOKEN
    --ske-license-token=env:SKE_LICENSE_TOKEN
    ```

The release pipeline would extend the same module: `SkeOperatorRelease(image *Container, version string)` — accepting the cached `*Container` from `SkeOperatorBuild` and pushing it to GHCR without rebuilding.

Known unknowns

  • `dagger develop` resolves cleanly against current Dagger version
  • Unit test path runs green locally (`SkeOperatorUnit`)
  • DIND + Kind interaction works with Dagger's engine (`SkeOperatorE2e`) — main unknown; some engine versions need `InsecureRootCapabilities` tuning
  • `AsTarball` → `docker load` handoff works correctly with the DIND service binding

Adds ci/dagger/ — a Go Dagger module replicating test-ske-operator.yaml
with three structural improvements over the GHA version:

- unit: golang:1.26 container with cached go modules, build artefacts,
  and envtest binaries; warm runs ~30s vs ~3min cold
- e2e: pre-pulls cert-manager images before cluster creation and loads
  them into Kind, eliminating the cold-pull timing window
- e2e: explicitly waits for all cert-manager deployments Available before
  deploying ske-operator (fixes recurring CrashLoopBackOff root cause)
- e2e: Kind cluster in DIND service, insulating tests from runner variance

Run 'dagger develop' from ci/dagger/ to generate dagger.gen.go and pin
the SDK version before building or calling.
shano added 2 commits July 27, 2026 16:22
Restructure the module to make Dagger's value prop concrete:

- SkeOperatorBuild returns *Container (typed artifact, content-addressed)
- SkeOperatorE2e accepts *Container via AsTarball() + docker load —
  no registry push needed to pass the image between pipeline stages
- SkeOperatorAll builds once then runs unit + e2e concurrently in Go
  goroutines, sharing go-mod and go-build cache volumes between both

Comments explain what the GHA equivalent would require at each step
where Dagger's typed pipeline diverges from the shell-script approach.
main.go was using bare Container/Directory/Secret which are not
re-exported into the main package. Prefix with dagger. and re-run
dagger develop to regenerate dagger.gen.go dispatch code with correct
type assertions. go build ./... now passes clean.
@shano
shano marked this pull request as draft July 29, 2026 08:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants