Skip to content

feat: COW workspace caching for local runs#26

Merged
markovejnovic merged 25 commits into
mainfrom
feat/caching
May 27, 2026
Merged

feat: COW workspace caching for local runs#26
markovejnovic merged 25 commits into
mainfrom
feat/caching

Conversation

@markovejnovic
Copy link
Copy Markdown
Contributor

@markovejnovic markovejnovic commented May 26, 2026

No description provided.

Add build_host_config helper and start_long_lived_with_mounts method to
DockerClient so containers can mount host workspace directories via
HostConfig bind mounts. This enables the COW workspace caching feature
to bind-mount overlay filesystems into build containers.
Introduces WorkspaceManager that manages per-step workspace directories
for a single pipeline run. Auto-selects between clone strategy (macOS
APFS / Linux reflink / fallback cp) and overlay strategy (fuse-overlayfs)
based on platform detection from hm-util::cow. The rest of the system
only sees workspace_path() — strategy is transparent.
- Add duplicate step_key guard in WorkspaceManager
- Add tests for create_workspace_from_cache and duplicate key
- Deduplicate start_long_lived via delegation to start_long_lived_with_mounts
When RunContext.workspace is Some, DockerRunner dispatches to a new
run_step_cow path that bind-mounts the host workspace directory into
the container instead of extracting a tar archive and committing a
docker snapshot. This eliminates the tar extraction and docker commit
overhead for the COW execution mode.
Persist completed step workspaces to ~/.harmont/cache/workspaces/ and
restore them on cache hits, replacing Docker image-based caching when
running in COW mode. Stale cache directories from previous keys are
evicted after a successful build.
manual_let_else, missing_errors_doc, missing_panics_doc, expect_used,
redundant_closure_for_method_calls, unnecessary_unwrap, collapsible_if.
…tance

COW mode now commits container images after each step, so child steps
inherit system-level changes (apt-get installs, rustup, etc.) via
Docker image lineage while workspace files propagate via COW bind mounts.
Remove --cow flag, non-COW Docker tar-extract path, Docker-image-only
cache backend, and associated dead code. COW bind mounts + Docker image
commits for system state is now the default and only mode.

-465 lines removed.
FUSE mounts are only visible to the mounting user by default. Docker
daemon runs as root so it can't bind-mount from fuse-overlayfs paths.
Adding allow_other fixes this. The probe now also tests a real mount
with allow_other so it falls back gracefully when user_allow_other
is not enabled in /etc/fuse.conf.

CI workflows updated to uncomment user_allow_other in /etc/fuse.conf.
diagnose_strategies() probes each COW backend and reports availability
with reasons. WorkspaceManager warns at startup when falling back to
FullCopy and logs which strategies were tried and why they failed.
Docker containers run as root but fuse-overlayfs runs as the host
user. Without UID squashing, the FUSE daemon can't create files
owned by UID 0 in the upper dir, causing EPERM on mkdir inside
bind-mounted overlays.
@markovejnovic markovejnovic marked this pull request as ready for review May 27, 2026 07:52
@markovejnovic markovejnovic merged commit ec8a772 into main May 27, 2026
23 checks passed
@markovejnovic markovejnovic deleted the feat/caching branch May 27, 2026 07:53
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.

1 participant