Repository navigation
fix(dev-tooling): make path-scoped JS lint and format runs work on Shopware - #191
Merged
Martin Bens (SpiGAndromeda) merged 5 commits intoOct 11, 2026
Merged
Conversation
`stylelint_check`/`stylelint_fix` and `prettier_check`/`prettier_fix` on `js-admin-tooling`, and `stylelint_check`/`stylelint_fix` and `eslint_check`/`eslint_fix` on `js-storefront-tooling`, routed a call with `paths` to `stylelint:base`, `prettier:base`, `stylelint:app`, `eslint:app` and `eslint:components`. No Shopware `package.json` defines these scripts, so every such call refused. They now run `npm exec --no -- <binary>` with the flags of the aggregate script, after checking that `node_modules/.bin/<binary>` exists, because `npm exec --no` falls back to a global binary. Directory paths reach Stylelint and Prettier as a quoted pattern limited to the extensions the aggregate script lints, and are refused under ddev on a linked worktree. Components-tree ESLint paths are refused under a scope, Storefront Stylelint adds the core `--config` only without a scope, and a scoped config on a run without `paths` is refused when the script already passes one. Tests answer script probes from the `scripts` blocks of Shopware trunk instead of fixtures that defined the missing scripts. Co-Authored-By: Claude <noreply@anthropic.com>
The Administration and Storefront PreToolUse hooks matched only `npx <binary>` without flags, so `npm exec eslint`, `npm x eslint`, `node_modules/.bin/eslint`, `npx eslint@9` and `npm exec --no -c "cd ../.. && eslint …"` ran the tools past the MCP servers. `BINARY_INVOCATION` now covers `npx`, `npm exec` and `npm x` with the valueless flags `-y`, `--yes`, `--no`, `--no-install`, `-q`, `--quiet`, `--silent` and `--`, an `@version` suffix, and the `node_modules/.bin/` path. `runs_binary` also matches a `-c` or `--call` string that runs the binary. Both apply to `eslint`, `stylelint`, `prettier`, `jest`, `tsc` and `vitest`. `docs/mcp-enforcement.md` drops the claim that both `package.json` files declare `jest:base`, and documents that the hooks match each line on its own, with `git commit -F <file>` as the way around it. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Agent Skills ExportBuilt 7 skill packages: |
The local-binary probe, the directory detection and patterns, the ddev-worktree refusal and the Stylelint `--config` detector were copied into three or four JS server libraries, and the hook binary matcher into both JS hooks. They now live once in the new `shared/js_paths.sh` and `hooks/scripts/lib/js_binary.sh`, which only dev-tooling ships. `environment.sh` and the hook library `common.sh` stay untouched, because they are template copies that shopware-env also ships. The refusals of the shared pipeline name the tool: "Refusing to run `<tool>` with paths". Tests generate the hook rows from one form list, run the missing-binary probe through every environment wrapper, default to the trunk script layout with `jest:base` as an opt-in, and check the guard against the call log. The trunk fixtures get a README and a `regenerate.sh` that record their source commit. Co-Authored-By: Claude <noreply@anthropic.com>
The 4.1.1 entry named `prettier` and `tsc` as blocked by both hooks, but only the Administration hook blocks them. `mcp-enforcement.md` lists the blocked binary forms instead of one long paragraph and links to `reference.md` for routing, `reference.md` explains the ddev-worktree refusal once, and `AGENTS.md` lists `shared/js_paths.sh` and `hooks/scripts/lib/js_binary.sh`. Co-Authored-By: Claude <noreply@anthropic.com>
Martin Bens (SpiGAndromeda)
deleted the
fix/dev-tooling-js-path-scoped-npm-exec
branch
October 11, 2026 21:18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Path-scoped runs of the JS lint and format tools refused on every Shopware checkout.
stylelint_check/stylelint_fixandprettier_check/prettier_fixonjs-admin-tooling, andstylelint_check/stylelint_fixandeslint_check/eslint_fixonjs-storefront-tooling, routed a call withpathstostylelint:base,prettier:base,stylelint:app,eslint:appandeslint:components. No Shopwarepackage.jsondefines these scripts, so the tools answered withnpm script "stylelint:base" is not defined in package.jsonand refused.Path-scoped runs
pathsnow runs the package's own binary throughnpm exec --no -- <binary>, with the flags of the aggregate script (lint:scss,format,lint:js). The Storefront components tree runsnpm exec --no -c "cd ../.. && eslint …", aslint:jsdoes. Admin ESLint keepslint:debugging, which Shopware defines. Runs withoutpathsstill use the aggregate scripts.node_modules/.bin/<binary>exists, becausenpm exec --noruns a global binary of the same name when the package has none. A missing binary refuses with a message naming the binary and the directory the check ran in.<dir>/**/*.scssfor Admin Stylelint,<dir>/**/*.{scss,css}for Storefront Stylelint,<dir>/**/*.{js,ts,mjs}for Prettier. A directory whose name ends in such an extension gets the same pattern. Underddevon a linked worktree, directory and glob paths for these tools are refused, becauseddev execre-parses the command in the container shell, which would expand the pattern first.shopware. Storefront Stylelint adds the core--config stylelint.config.jsonly without a scope. A scope-selected Stylelint config on a run withoutpathsis refused when the aggregate script already passes--config, instead of handing Stylelint two--configflags.ddevworktree refusal, the--configcheck) lives inshared/js_paths.sh. This file belongs to dev-tooling and is not synced fromtemplates/.Hooks
npx <binary>without flags. They now also blocknpm execandnpm x, anode_modules/.bin/<binary>path, an@versionsuffix, the valueless flags-y,--yes,--no,--no-install,-q,--quiet,--silentand--, and a-c/--callstring that runs the binary. The binaries areeslint,stylelintandjeston both hooks,prettierandtscon the Administration hook, andviteston the Storefront hook.hooks/scripts/lib/js_binary.sh.docs/mcp-enforcement.mddocuments that the hooks match each line of a command on its own, so a commit message line such asnpx eslint now runsin a heredoc is blocked, and namesgit commit -F <file>as the way around it. It no longer claims that bothpackage.jsonfiles declarejest:base.Tests
scriptsblocks of Shopware trunk (plugin-tests/dev-tooling/fixtures/shopware-trunk/), and the npm fake fails an undefinednpm runthe way npm does. The previous fixtures defined the missing scripts, which is why the suite passed while every real call refused.regenerate.shin that directory rebuilds the fixtures from a Shopware checkout.