Upgrade Dagger
How to upgrade the Dagger engine and CLI across all components in BlumeOps. The ordering matters — upgrading in the wrong sequence creates a chicken-and-egg problem where CI can’t build its own replacement.
Overview
Dagger versions are pinned in multiple places. The runner job image (which executes CI workflows) contains the Dagger CLI, and the module’s dagger.json declares the engine version. These must match — if the CLI is older than the engine version, Dagger refuses to run.
Key insight: Upgrade the runner container first (with the new CLI but the old engine version), deploy it, and then bump the engine version. This avoids needing a local build to break the cycle.
Files to update
| File | What | Phase |
|---|---|---|
containers/runner-job-image/Dockerfile | CONTAINER_APP_VERSION (CLI version) | 1 |
service-versions.yaml | runner-job-image version and last-reviewed | 1 |
mise.toml | dagger tool version | 2 |
dagger.json | engineVersion | 2 |
.dagger/uv.lock | SDK dependency lock (regenerated automatically) | 2 |
docs/reference/tools/dagger.md | Version references in documentation | 2 |
argocd/manifests/forgejo-runner/deployment.yaml | RUNNER_LABELS image tag | 2 |
Procedure
Phase 1: Upgrade the runner job image
The runner job image contains the Dagger CLI binary. Upgrading it first means the current CI (still on the old engine version) can build and publish the new image normally.
-
Update
containers/runner-job-image/Dockerfile:ARG CONTAINER_APP_VERSION=<new-version> -
Update
service-versions.yaml— bumpcurrent-versionandlast-reviewedforrunner-job-image. -
Commit and push to main. The
Build Containerworkflow triggers automatically (it watchescontainers/**), building and publishing the new runner-job-image with the updated Dagger CLI. -
Verify the build succeeds — check the workflow run on Forgejo. Note the image tag from the build output (format:
v<version>-<sha>).
Phase 2: Upgrade the module and deploy the new runner
Once the Phase 1 build completes, upgrade the module engine version and deploy the new runner in a single commit. None of these paths trigger CI workflows automatically, so there is no race condition.
-
Update
mise.toml:dagger = "<new-version>" -
Run
mise installto get the new CLI locally. -
Update
dagger.json:"engineVersion": "v<new-version>" -
Regenerate the SDK lock file — run any
dagger callcommand (e.g.,dagger call --helpordagger functions). This updates.dagger/uv.lockif SDK dependencies changed. -
Update
docs/reference/tools/dagger.md— bump the version in the Quick Reference table and any version references in the body text. -
Update
argocd/manifests/forgejo-runner/deployment.yaml— set theRUNNER_LABELSvalue to use the new image tag from Phase 1:value: "k8s:docker://registry.ops.eblu.me/blumeops/runner-job-image:<tag>" -
Commit and push to main.
-
Sync the forgejo-runner app:
argocd app sync forgejo-runner -
Verify the runner is healthy:
argocd app get forgejo-runner -
Test CI by triggering a workflow (e.g., manual dispatch of
Build BlumeOps).
Why the order matters
The Dagger CLI refuses to run a module whose engineVersion is newer than the CLI version. If you upgrade dagger.json first:
- CI tries to run
dagger callwith the old CLI - The module declares a newer engine version
- Dagger exits with a version mismatch error
- The
Build Containerworkflow can’t run — so you can’t build the new runner image via CI - You’re stuck: the runner can’t build its own replacement
By upgrading the CLI in the runner image first (Phase 1), the current engine version (old) still works fine with the newer CLI. Phase 2 combines the engine version bump with the runner deployment in a single commit — this is safe because none of the changed paths (dagger.json, mise.toml, argocd/manifests/forgejo-runner/) trigger CI workflows automatically. Just sync the forgejo-runner app before triggering any workflows.
Changelog
Add a changelog fragment: docs/changelog.d/+upgrade-dagger-<version>.<type>.md
Use type infra for routine upgrades. Include both the old and new versions in the description.
Related
- dagger — Dagger reference card
- build-container-image — How container builds work
- update-tooling-dependencies — General tooling update procedure
- forgejo — CI/CD platform