Conversation
- Add dagger_runner.py with run_dagger_pipeline, run_dagger_test, detect_project - Support Python, Node, Rust, Go project detection - Add CLI subcommand: swe-af dagger --pipeline lint|test|build|full - Support services: postgres, redis, mysql, mongodb - Add docs/DAGGER.md with usage documentation - Update coder prompt with Dagger tool instructions
|
oooo this is very interesting, might sky-rocket the quality, will give it a review soon :) |
|
I may have pushed this branch prematurely, feel free to give this the most brutal feedback you can come up with for a better version :) My main idea was to use dagger to improve SWE-AF's CICD itself by enabling ephemeral docker container builds of the project itself that will reduce CICD time 99% of the second run. I think the DAG implementation of Dagger matches perfectly with the DAG workflows of AgentField. An additional idea is allowing Agents to use the dagger subsystem for testing their workflows in isolated containers and I am fairly sure that is not working in the PR and I don't yet understand how it would interface with AgentField, I still need to understand how it works but I should be able to figure it out by end of the week. An alternative to container isolation I am interested in exploring is using a child project of dagger named container-use https://github.com/dagger/container-use which has better scaffolding for agentic container isolation. |
AbirAbbas
left a comment
There was a problem hiding this comment.
Review: Dagger CI/CD Integration
Hey Andrew — really cool concept, the DAG alignment between Dagger and AgentField is spot on and this could be a massive win for agent self-validation. Leaving detailed inline comments below. The main blocker is the top-level import dagger which would break SWE-AF startup for every existing deployment that doesn't have dagger-io installed.
Summary of findings:
- 1 blocker: Hard
import daggerat module top level breaks startup without the dep - 2 bugs:
timeout_secondsnever wired up;run_pipeline_directmissingbuild/fullbranches (CLI advertises them) - Several improvements needed: service bindings only handle 2/4 services, poetry PATH glob, coder prompt references unusable API, code duplication between direct and reasoner paths
Happy to pair on any of these if useful!
| import os | ||
| from enum import Enum | ||
|
|
||
| import dagger |
There was a problem hiding this comment.
Blocker: Top-level import dagger makes dagger-io a hard runtime dependency for all of SWE-AF. Since __init__.py unconditionally imports this module, any existing deployment without dagger-io installed will crash on startup with ModuleNotFoundError.
Suggestion: Lazy-import dagger inside the functions that need it, or guard with a try/except that sets a DAGGER_AVAILABLE flag:
try:
import dagger
DAGGER_AVAILABLE = True
except ImportError:
DAGGER_AVAILABLE = FalseThen check DAGGER_AVAILABLE at the start of each reasoner and return a clear error dict instead of crashing.
|
|
||
| try: | ||
| async with dagger.Connection( | ||
| dagger.Config(timeout=120, execute_timeout=None) |
There was a problem hiding this comment.
Bug: timeout_seconds is accepted as a parameter (default 600) but never used here. This line hardcodes timeout=120 and execute_timeout=None regardless of what the caller passes. Same issue at line 947 in run_pipeline_direct.
Suggestion:
async with dagger.Connection(
dagger.Config(timeout=timeout_seconds, execute_timeout=timeout_seconds)
) as client:| ) | ||
| container = container.with_env_variable( | ||
| "PATH", | ||
| "/root/.cache/pypoetry/virtualenvs/*/bin:/usr/local/bin:/usr/bin:/bin", |
There was a problem hiding this comment.
Bug: The literal * in PATH won't glob-expand when set as an env variable — it'll stay as the literal string */bin. Poetry commands in the container will fail because the virtualenv bin/ won't be on PATH.
Suggestion: Either use poetry run to prefix commands (e.g., poetry run pytest -v) which handles the virtualenv automatically, or resolve the actual venv path after poetry install:
container = container.with_exec(
["sh", "-c", "export PATH=$(poetry env info -p)/bin:$PATH"]
)| ).with_exec(["pip", "install", "--quiet", "-e", ".[dev]"]) | ||
|
|
||
| # Add services | ||
| for svc in services: |
There was a problem hiding this comment.
Bug: This service binding loop only handles postgres and redis, silently ignoring mysql and mongodb even though get_service_container() (line 269) supports all four and the docs/schema advertise them.
Same issue in build_node_pipeline (line 404) and the lint fast-path (line 335).
Suggestion: Add elif branches for mysql and mongodb:
elif svc == DaggerService.MYSQL.value:
container = container.with_service_binding("mysql", service_container.as_service())
container = container.with_env_variable(
"DATABASE_URL", "mysql://root:test@mysql:3306/test"
)
elif svc == DaggerService.MONGODB.value:
container = container.with_service_binding("mongodb", service_container.as_service())
container = container.with_env_variable(
"MONGO_URL", "mongodb://test:test@mongodb:27017"
)Or extract this into a shared helper to avoid repeating it 3 times.
| lint_result = None | ||
| success = True | ||
|
|
||
| if pipeline_type == DaggerPipelineType.LINT: |
There was a problem hiding this comment.
Bug: run_pipeline_direct only handles lint and test pipeline types, but the CLI (__main__.py) exposes --pipeline build and --pipeline full as valid choices. Running swe-af dagger --pipeline build will silently skip all pipeline logic, return success=True with no build executed, and report a misleading summary.
Suggestion: Either add build/full/custom branches here, or better yet, eliminate run_pipeline_direct entirely and have the CLI call run_dagger_pipeline directly (it already works without the AgentField server). That also eliminates the code duplication between these two ~100-line functions.
| You have access to Dagger pipelines for isolated CI/CD validation. Use these | ||
| to verify your work in clean containers before committing: | ||
|
|
||
| **Available Dagger Tools (call via app.call):** |
There was a problem hiding this comment.
Issue: Coder agents are Claude Code subprocess instances — they have shell, file, and search tools but no Python app object. The app.call("run_dagger_pipeline", ...) examples here can't be used by the agents as written.
Suggestion: Reference the CLI instead, which agents can invoke via their Bash tool:
**Running Dagger from your tools:**
Use your Bash tool to invoke Dagger CLI:
```bash
# Run tests in isolated container
python -m swe_af dagger --pipeline test --path /path/to/worktree
# Full CI (build + test + lint)
python -m swe_af dagger --pipeline full --path /path/to/worktree
# With a database service
python -m swe_af dagger --pipeline test --services postgres --path /path/to/worktree
| if result.get("lint_result"): | ||
| lr = result["lint_result"] | ||
| print(f"\nLint:") | ||
| print(f" Issues: {lr.get('total_issues', 0)}") |
There was a problem hiding this comment.
Bug: DaggerLintResult schema has no total_issues field — it has issues: list[dict]. This .get('total_issues', 0) always returns 0.
Suggestion: Use len(lr.get('issues', [])) instead.
|
Really like the direction here — giving agents isolated, reproducible environments for the testing they already do is a clear win. One thing to flag: the pipeline builders currently only work for Python and Node ( Would be great to add |
Summary
Validation
make checkx
Behavior Impact
Notes
Any rollout notes, migration notes, or follow-ups.