Accept absolute host paths as command arguments#1
Conversation
Commands set `HostWorkingDir: true`, which maps the host current working
directory into the container, but arguments are passed through verbatim — an
absolute *host* path (e.g. from an IDE external tool or an AI agent) arrives
inside the container unchanged and fails to resolve.
Add a shared helper, module-developer/lib/host-paths.sh, that rewrites such
arguments to their in-container equivalent by stripping leading path components
until the remainder resolves under ${DDEV_APPROOT}. It is host-root agnostic
(no docroot assumption) and a no-op for relative paths, flags, already-resolved
container paths, and paths that do not resolve under the project root.
Every command in commands/web/ sources the helper and normalizes its arguments
immediately after binary resolution. Adds tests/host-path-args.bats and
documents the behavior in README.md and AGENTS.md.
AI-assisted by Claude Code
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the four-line normalization block in every command with one line:
source /mnt/ddev_config/module-developer/lib/init.sh
Rename module-developer/lib/host-paths.sh to module-developer/lib/init.sh and
move the normalization into it. init.sh is sourced with no arguments, so inside
it "$@" is the caller's positional parameters and a top-level `set --` rewrites
the calling command's "$@" in place — giving each command host-path
normalization with no per-command boilerplate. init.sh is also the designated
home for future shared global utilities.
Update install.yaml to ship lib/init.sh, and README.md and AGENTS.md to describe
the single-source-line invariant. The end-to-end Bats coverage in
tests/host-path-args.bats (absolute path rewritten, relative passed through,
unresolvable left unchanged, real command receives the container path) is
unchanged and still passes.
AI-assisted by Claude Code
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rebased onto the maintainer's merge of main. On top of the new checks and
parallel-lint commands:
- Source module-developer/lib/init.sh in checks and parallel-lint so absolute
host paths work for them too. checks sources it before argument parsing so an
absolute TARGET is normalized before it builds "${TARGET}/**/*.css" for
stylelint (a glob the per-command normalization deliberately leaves untouched).
Plus the earlier review feedback:
- AGENTS.md "Adding a new command" now includes the init.sh step.
- Document longest-suffix-match and its coincidental-suffix limitation in
init.sh and README; note the normalized-args array is unset and the
DDEV_MODULE_DEVELOPER_* vars are plain unexported shell variables.
- Add Bats coverage for flags + absolute path, multiple absolute path
arguments, and an absolute path containing spaces.
- eslint: binary resolution before the init.sh source, matching all commands.
AI-assisted by Claude Code
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The ddev/github-action-add-on-test action installs its Bats tooling via
`brew install`. Recent Homebrew releases enable a Bubblewrap build sandbox that
fails to initialise on GitHub's runners ("Bubblewrap is installed but cannot
create a rootless sandbox"), aborting the job during setup before any test runs.
Set HOMEBREW_NO_SANDBOX=1 at the job level so the install succeeds.
AI-assisted by Claude Code
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The previous attempt set HOMEBREW_NO_SANDBOX, which only affects the macOS sandbox-exec sandbox. On Linux runners the Bubblewrap sandbox is controlled by HOMEBREW_NO_SANDBOX_LINUX, which is the variable Homebrew's own error message recommends. AI-assisted by Claude Code Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI fix: Homebrew Bubblewrap sandbox failureA heads-up on the two CI commits I pushed ( Symptom: the The job aborted in ~54s (a normal run is ~2–3 min). This is not a test regression — an earlier run on this PR and the Fix: disable Homebrew's Linux sandbox at the job level — the variable Homebrew's own error message recommends: jobs:
tests:
env:
HOMEBREW_NO_SANDBOX_LINUX: "1"(My first attempt used Result: both matrix jobs pass again — Note this is independent of the absolute-host-path feature in this PR — it would hit |
Add information about intended use of init.sh and the potential for path-stripping
This is an upstream problem, and I pushed a new release for our action https://github.com/ddev/github-action-add-on-test/releases/tag/v2.4.4 |
Summary
Every command sets
## HostWorkingDir: true, which maps the host's current working directory into the container. Command arguments, however, are passed through verbatim — so an absolute host path (e.g./Users/me/Sites/project/web/modules/custom/foo) arrives inside the container unchanged and fails to resolve, because the project is mounted at${DDEV_APPROOT}(/var/www/html).This is awkward for IDE "external tools", file watchers, and AI agents, which naturally work with full host paths.
This PR adds a small shared helper,
module-developer/lib/host-paths.sh, that rewrites absolute host-path arguments to their in-container equivalent. Every command incommands/web/sources it and normalizes"$@"immediately after binary resolution and before any defaulting/exec.How it works
ddev_normalize_host_pathsstrips leading path components from an absolute argument until the remainder resolves under${DDEV_APPROOT}. This is host-root agnostic — no docroot or host-prefix assumption — so paths anywhere in the project (including a top-levelrecipes/directory) are handled.It is a no-op for:
web/modules/custom/foo),--standard=Drupal),Known limitation
Absolute paths containing glob wildcards (e.g.
/abs/path/**/*.cssforstylelint) are left untouched, since the path cannot be matched by an existence test as it stands. Pass those patterns relative to the project root. This is documented in the README.Tests
Adds
tests/host-path-args.bats(4 tests, all passing locally) covering: absolute host path rewritten to the container path, relative path passed through unchanged, unresolvable absolute path left untouched, andphpcsrewriting an absolute argument. Verified end-to-end on a real DDEV Drupal project: an absolute host path produces output identical to the relative equivalent, whereas a raw un-rewritten host path fails with a path-not-found error.Docs
README.md— new "Absolute host paths" subsection.AGENTS.md— helper added to the repo layout, a new "normalize host-path arguments" step, and a contributor invariant.AI-assisted by Claude Code.