Summary
During install of drupal-code-quality (v1.0.6), the Phase 3 "JS toolchain dependencies" step fails to install the DCQ npm dev-dependencies, but the installer continues and reports the Node toolchain as successfully installed. A user who does not read the console output line-by-line is left without ESLint / Prettier / Stylelint / CSpell tooling while believing it is present.
There are two distinct problems. The more important one for reproducing the failure is Bug 1 (a version-compatibility issue), which is separate from the cosmetic shell-escaping in Bug 2.
Bug 1 — a pinned dependency version cannot be resolved
The installer requests eslint-plugin-yml@^1.19.1 alongside eslint@^8.57.1. Recent eslint-plugin-yml majors declare a peer dependency on eslint@^9, which conflicts with DCQ's pinned eslint@^8.57.1, so the install cannot resolve.
The working fix (confirmed locally) was to pin the plugin down:
ddev npm install --save-dev cspell eslint eslint-config-airbnb-base eslint-config-prettier \
eslint-plugin-import eslint-plugin-jsdoc eslint-plugin-no-jquery eslint-plugin-prettier \
eslint-plugin-yml@^1 prettier stylelint stylelint-config-standard stylelint-order stylelint-prettier
eslint-plugin-yml@^1 selects a build whose peer range still includes eslint 8. This added 459 packages with no errors. Suggested change: align the pinned eslint-plugin-yml constraint with the pinned eslint version so the declared dependency set actually resolves.
Bug 2 — version constraints are escaped with a literal backslash
Separately, the install command shell-escapes the caret in each constraint:
ddev npm install --save-dev --package-lock cspell@\^9.8.0 eslint@\^8.57.1 ... stylelint-prettier@\^5.0.3
npm reads the backslash literally:
npm error code EINVALIDTAGNAME
npm error Invalid tag name "\^9.8.0" of package "cspell@\^9.8.0": Tags may not have any characters that encodeURIComponent encodes.
npm treats \^9.8.0 as a dist-tag rather than a semver range. Constraints should reach npm unescaped (build the name@range tokens as an argv array rather than a shell string, or quote the whole token instead of escaping the caret).
Bug 3 — the failure is non-fatal and success is reported anyway
After the failed versioned install, the installer runs a bare ddev npm install:
Installing JS deps in project root using npm (this may take several minutes).
Running: /opt/homebrew/bin/ddev npm install
removed 132 packages, and audited 1 package in 175ms
found 0 vulnerabilities
Node toolchain installed (project root).
That bare install only reconciles already-declared dependencies (note "removed 132 packages" — nothing DCQ-related was added). Despite this, the installer prints Node toolchain installed (project root). and the final summary lists:
What was installed:
...
- Node toolchain (ESLint, Prettier, Stylelint)
So the exit is "success" and the summary claims the toolchain is present, even though the required dev-deps were never installed.
Suggested changes
- Fix the version constraint (Bug 1): align
eslint-plugin-yml with the pinned eslint@^8.57.1 (e.g. eslint-plugin-yml@^1) so the dependency set resolves.
- Fix the quoting (Bug 2): pass
name@range arguments to npm without shell-escaping the ^.
- Do not report success after a failed install (Bug 3): make the npm-install failure fatal, or after the install verify the required packages are actually present and print a prominent warning (and omit the toolchain from the "What was installed" summary) if any are missing. Do not treat a bare
ddev npm install as satisfying the requirement.
The core concern: the current behavior can leave users without the code-quality tooling while telling them it was installed.
Environment
- drupal-code-quality: v1.0.6 (installed from UltraBob/ddev-drupal-code-quality)
- Host: macOS (Darwin, arm64 — homebrew ddev at /opt/homebrew/bin/ddev)
- npm run inside DDEV web container
Summary
During install of drupal-code-quality (v1.0.6), the Phase 3 "JS toolchain dependencies" step fails to install the DCQ npm dev-dependencies, but the installer continues and reports the Node toolchain as successfully installed. A user who does not read the console output line-by-line is left without ESLint / Prettier / Stylelint / CSpell tooling while believing it is present.
There are two distinct problems. The more important one for reproducing the failure is Bug 1 (a version-compatibility issue), which is separate from the cosmetic shell-escaping in Bug 2.
Bug 1 — a pinned dependency version cannot be resolved
The installer requests
eslint-plugin-yml@^1.19.1alongsideeslint@^8.57.1. Recenteslint-plugin-ymlmajors declare a peer dependency oneslint@^9, which conflicts with DCQ's pinnedeslint@^8.57.1, so the install cannot resolve.The working fix (confirmed locally) was to pin the plugin down:
eslint-plugin-yml@^1selects a build whose peer range still includes eslint 8. This added 459 packages with no errors. Suggested change: align the pinnedeslint-plugin-ymlconstraint with the pinnedeslintversion so the declared dependency set actually resolves.Bug 2 — version constraints are escaped with a literal backslash
Separately, the install command shell-escapes the caret in each constraint:
npm reads the backslash literally:
npm treats
\^9.8.0as a dist-tag rather than a semver range. Constraints should reach npm unescaped (build thename@rangetokens as an argv array rather than a shell string, or quote the whole token instead of escaping the caret).Bug 3 — the failure is non-fatal and success is reported anyway
After the failed versioned install, the installer runs a bare
ddev npm install:That bare install only reconciles already-declared dependencies (note "removed 132 packages" — nothing DCQ-related was added). Despite this, the installer prints
Node toolchain installed (project root).and the final summary lists:So the exit is "success" and the summary claims the toolchain is present, even though the required dev-deps were never installed.
Suggested changes
eslint-plugin-ymlwith the pinnedeslint@^8.57.1(e.g.eslint-plugin-yml@^1) so the dependency set resolves.name@rangearguments to npm without shell-escaping the^.ddev npm installas satisfying the requirement.The core concern: the current behavior can leave users without the code-quality tooling while telling them it was installed.
Environment