Skip to content

Kubernetes Dockerless build drops .devsy-internal during StreamMount and fails before build starts #1108

Description

@joshyorko

Summary

On Devsy 1.15.0 with the Kubernetes provider, a Dockerfile-backed devcontainer can fail before the Dockerless build starts because the generated .devsy-internal build artifacts are excluded from the streamed workspace mount.

Observed error:

dockerless build: rename dir: open /workspaces/.dockerless/.devsy-internal: no such file or directory

I reproduced this with https://github.com/joshyorko/actions against a Kubernetes context where the equivalent Skevetter DevPod 0.26.1 flow gets through the Dockerless build successfully.

Reproducer

Workspace:

https://github.com/joshyorko/actions

The repo contains a Dockerfile-backed .devcontainer/devcontainer.json, so the Kubernetes provider correctly falls back to Dockerless.

Run:

devsy workspace up https://github.com/joshyorko/actions

Environment from the failing run:

  • Devsy Desktop / CLI: 1.15.0
  • provider: Kubernetes
  • Kubernetes context: ror
  • namespace: devsy
  • Dockerless image: ghcr.io/devsy-org/dockerless:0.2.0
  • architecture: amd64

Actual behavior

Devsy successfully:

  1. clones the repository;
  2. resolves .devcontainer/Dockerfile;
  3. resolves the Python base image;
  4. calculates the prebuild hash;
  5. creates the PVC and Kubernetes pod;
  6. injects the Devsy agent;
  7. streams the workspace into /workspaces/actions.

The pod is configured with:

DOCKERLESS_CONTEXT=/workspaces/actions
DOCKERLESS_DOCKERFILE=/workspaces/actions/.devsy-internal/Dockerfile-without-features

The workspace upload reaches ~102 MB, then setup fails immediately:

Copy .../actions into DevContainer /workspaces/actions
Uploaded 102.69 MB
dockerless build: rename dir: open /workspaces/.dockerless/.devsy-internal: no such file or directory

Dockerless never reaches its actual build command.

Expected behavior

The generated Dockerless build information should survive the host -> Kubernetes workspace handoff so that prepareBuildDirectory can find either:

/workspaces/actions/.devsy-internal

or the fallback:

/workspaces/.dockerless/.devsy-internal

and then start the Dockerless build.

Likely regression / code-path evidence

The Dockerless fallback creates generated build artifacts under the context path:

// pkg/devcontainer/build.go

devsyInternalFolder := filepath.Join(contextPath, config.DevsyContextFeatureFolder)
err := os.MkdirAll(devsyInternalFolder, 0o755)
...
devsyDockerfile = filepath.Join(devsyInternalFolder, "Dockerfile-without-features")

DevsyContextFeatureFolder is the generated .devsy-internal directory.

However, pkg/agent/tunnelserver/tunnelserver.go currently applies build-artifact exclusions when streaming a mount:

excludes := append(t.workspaceIgnoreExcludes(), config.BuildArtifactExcludes()...)
...
extract.WriteTarExclude(buf, mount.Source, false, excludes)

and pkg/devcontainer/config/artifacts.go defines:

var buildArtifactNames = []string{
    DevsyContextFeatureFolder,
}

So .devsy-internal is generated locally and then explicitly excluded from the mount stream that carries the workspace into the Kubernetes pod.

Inside the pod, prepareBuildDirectory then cannot find the build directory at the workspace path and falls back to /workspaces/.dockerless/.devsy-internal, which is also absent, producing the observed rename dir failure.

Working control: Skevetter DevPod

I ran the same joshyorko/actions workspace through Skevetter's DevPod 0.26.1 using the Kubernetes provider and the same Kubernetes context.

DevPod's analogous StreamMount only applies its workspace / .devpodignore exclusions; it does not add an equivalent build-artifact exclusion for .devpod-internal.

That run successfully reaches:

Copy .../actions/content into DevContainer /workspaces/actions
Uploaded 98.90 MB
starting dockerless build: /.dockerless/dockerless build ...
...
dockerless build completed

Suggested fix direction

StreamMount should not blanket-exclude .devsy-internal when that stream is also responsible for transporting the generated Dockerless build artifacts required by the Kubernetes fallback.

Possible approaches:

  • do not apply BuildArtifactExcludes() to this Dockerless workspace stream; or
  • explicitly seed/persist .devsy-internal into /workspaces/.dockerless before excluding it from the normal workspace payload.

The key invariant is that the generated Dockerless build directory must exist in one of the locations expected by prepareBuildDirectory before DockerlessBuild runs.

Acceptance criteria

  • A fresh Kubernetes-provider workspace up for a Dockerfile-backed devcontainer reaches the Dockerless build instead of failing in prepareBuildDirectory.
  • .devsy-internal is available at the workspace build context or the documented Dockerless fallback location inside the pod.
  • Existing cleanup behavior still removes generated build artifacts after setup.
  • Add a regression test covering streamed mounts + Dockerless generated build artifacts so BuildArtifactExcludes() cannot remove the only copy needed by the in-pod builder.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions