kcl: PushKustomizeBase / Run cannot resolve KCL path deps pointing outside `source`
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 62/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- docker, go
- Domain
- build-system, devops, testing
Research direction
Start by locating Kcl.Run and the RenderKustomizeBase and PushKustomizeBase callers that mount /src and set the workdir. Add coverage under kcl/tests/ for the standalone path-dependency scenario, then verify the sub-package renders with a wider source and workdir while existing calls without workdir still work.
Written by the indexing model from the issue text.
Description
Summary
Kcl.Run (and therefore RenderKustomizeBase / PushKustomizeBase) mounts the caller-supplied source directory to /src and runs kcl run <entrypoint> with workdir /src. This works for self-contained KCL packages, but silently breaks any package whose kcl.mod has a local path = "..." dependency that lives outside source — the parent directory isn't mounted in the container, so kcl run fails to resolve the dep.
This bites the moment you try to share KCL code between sibling packages in a monorepo, which is a fairly common layout.
Motivating real-world example
In stuttgart-things/dapr-workflows we want a shared deploy-base KCL module at the repo root and per-workflow consumers that depend on it:
```
dapr-workflows/
├── deploy-base/ # shared KCL module
│ ├── kcl.mod
│ ├── worker.k
│ ├── statestore.k
│ ├── secrets.k
│ └── ca.k
└── backstage-template-execution/
└── deploy/
├── kcl.mod # depends on ../../deploy-base
└── main.k
```
`deploy/kcl.mod`:
```toml
[package]
name = "backstage-template-execution-deploy"
edition = "v0.11.0"
version = "0.1.0"
[dependencies]
k8s = "1.31.2"
deploy_base = { path = "../../deploy-base" }
```
Local `kcl run main.k` inside `deploy/` works fine (kcl walks up two dirs and finds `deploy-base/`).
The equivalent dagger call — as used by our Taskfile — fails:
```bash
dagger call -m github.com/stuttgart-things/dagger/kcl push-kustomize-base \
--source ./backstage-template-execution/deploy \
--address ghcr.io/stuttgart-things/backstage-template-execution-kustomize \
--tag v0.0.1 \
--user env:GITHUB_USER \
--password env:GITHUB_TOKEN
```
…because only `./backstage-template-execution/deploy` is mounted at `/src`. `../../deploy-base` resolves to `/deploy-base` inside the container, which doesn't exist.
Minimal repro (standalone test data)
```bash
mkdir -p /tmp/kcl-pathdep/shared /tmp/kcl-pathdep/consumer
cd /tmp/kcl-pathdep
cat > shared/kcl.mod <<'TOML'
[package]
name = "shared"
edition = "v0.11.0"
version = "0.1.0"
TOML
cat > shared/lib.k <<'KCL'
greet = lambda name: str -> str {
"hello, " + name
}
KCL
cat > consumer/kcl.mod <<'TOML'
[package]
name = "consumer"
edition = "v0.11.0"
version = "0.1.0"
[dependencies]
shared = { path = "../shared" }
TOML
cat > consumer/main.k <<'KCL'
import shared.lib as lib
message = lib.greet("dagger")
KCL
Works locally:
cd consumer && kcl run main.k
=> message: hello, dagger
Fails via dagger:
dagger call -m github.com/stuttgart-things/dagger/kcl run \
--source ./consumer
=> ERROR resolving dependency 'shared': path '../shared' does not exist
```
Expected behavior
Callers should have a way to let `Run` / `RenderKustomizeBase` / `PushKustomizeBase` mount a wider directory as the build context while still rendering a specific sub-package.
Proposed fix — option A (preferred)
Add a `workdir` (or `subpath`) parameter to `Run`. Callers pass the repo root as `source` and a sub-path as `workdir`:
```go
func (m *Kcl) Run(
ctx context.Context,
source *dagger.Directory,
// +optional
ociSource string,
// Sub-path inside source to cd into before running kcl. Enables
// KCL packages with relative path deps pointing outside their own
// directory (e.g. shared modules in a monorepo).
// +optional
workdir string,
// ... rest unchanged
) (*dagger.File, error) {
// ...
if source != nil {
ctr = ctr.WithMountedDirectory("/src", source)
if workdir != "" {
ctr = ctr.WithWorkdir("/src/" + workdir)
} else {
ctr = ctr.WithWorkdir("/src")
}
}
// ...
}
```
Then `RenderKustomizeBase` and `PushKustomizeBase` forward the same new parameter. Usage becomes:
```bash
dagger call -m github.com/stuttgart-things/dagger/kcl push-kustomize-base \
--source . \
--workdir backstage-template-execution/deploy \
--address ghcr.io/stuttgart-things/backstage-template-execution-kustomize \
--tag v0.0.1 \
--user env:GITHUB_USER \
--password env:GITHUB_TOKEN
```
Backwards compatible — omit `--workdir` and behavior is identical to today.
Proposed fix — option B
Add a separate `contextDir` parameter that mounts at `/src` alongside the existing `source` which continues to point at the entrypoint package. Slightly uglier API (two directories, two mount points) but also backwards compatible.
Acceptance criteria
- The minimal standalone repro above renders successfully via `dagger call run --source . --workdir consumer`
- `PushKustomizeBase` accepts the same `workdir` and produces a kustomize base from the sub-package
- Existing callers (no `workdir` set) continue to work unchanged
- A test is added under `kcl/tests/` that exercises a path-dep sub-package
Workarounds until this lands
- Publish the shared module as an OCI KCL package (`kcl mod push oci://...`) and switch the dep from `path = "..."` to `oci = "..."`. Adds a publish step and a chicken-and-egg on first push.
- Vendor/symlink the shared module into each consumer's `deploy/` before calling dagger. Brittle and loses single-source-of-truth.
- Dominant language
- Go
- Stars
- 4
- Forks
- 0
- Avg merge
- 21h 53m
- Merged PRs (30d)
- 26
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from stuttgart-things/dagger
-
enhancement good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
stuttgart-things/dagger#311 ·
Maintainers usually reply within 1 day
-
Difficulty 3/5 1-2 days Newbie friendliness 72/100
stuttgart-things/dagger#400 · 1 comment ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 35/100
stuttgart-things/dagger#386 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 48/100
stuttgart-things/dagger#385 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
stuttgart-things/dagger#262 · 3 comments ·
Maintainers usually reply within 1 day
All issues in stuttgart-things/dagger
Similar issues
-
VLAgent `spec.k8sCollector.includePodLabels: false` has no effectPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
VictoriaMetrics/operator#2772 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Gaurav-Gosain/tuios#1316 ·
Maintainers usually reply within 1 day
-
area:auth documentation priority:low
Difficulty 1/5 1-3 hours Newbie friendliness 86/100
Maintainers usually reply within 1 day
-
Mend: dependency security vulnerability
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
kube-tarian/sigrun#203 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
kubernetes-csi/csi-driver-iscsi#485 ·
Maintainers usually reply within 1 day