Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Framework: Adapt tooling to the isolated install layout
typeRoots drops its repo-root @types fallback, so a package using types it
never declared fails instead of borrowing them. Jest transforms through
.store/, and test-create-block gives wp-scripts a NODE_PATH fallback for the
bins it shells out to.

Storybook roots Vite at the repository root by default, which under the
isolated layout owns none of the dependencies its smoke tests resolve.

CI skips the node_modules cache on Windows, whose tar cannot restore the
isolated layout's links.
  • Loading branch information
manzoorwanijk committed Oct 1, 2026
commit 0e5a01239b59c50bdb84ba86f75d72e360e37586
7 changes: 5 additions & 2 deletions .github/setup-node/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ runs:
echo "NPM_VERSION=$(npm -v)" >> "$GITHUB_OUTPUT"
shell: bash

# Windows tar cannot restore the isolated layout's links, so always install there.
- name: Cache node_modules
id: cache-node_modules
if: ${{ inputs.cache == 'true' }}
if: ${{ inputs.cache == 'true' && runner.os != 'Windows' }}
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
# The key covers .npmrc because install-strategy decides the layout:
# a hoisted tree restored into an isolated checkout resolves nothing.
# List workspace node_modules explicitly to support all kinds of layouts - hoisted and isolated.
# A '**/node_modules' glob follows the isolated layout's symlinks and stalls the cache step.
# The eval package is not a workspace: it installs its own large tree from its own lockfile.
Expand All @@ -49,7 +52,7 @@ runs:
!test/ai-development/node_modules
tools/*/node_modules
widgets/*/node_modules
key: node_modules-${{ runner.os }}-${{ runner.arch }}-${{ steps.node-version.outputs.NODE_VERSION }}-npm-${{ steps.node-version.outputs.NPM_VERSION }}-${{ hashFiles('package-lock.json', 'patches/**') }}
key: node_modules-${{ runner.os }}-${{ runner.arch }}-${{ steps.node-version.outputs.NODE_VERSION }}-npm-${{ steps.node-version.outputs.NPM_VERSION }}-${{ hashFiles('package-lock.json', '.npmrc') }}

- name: Install npm dependencies
if: ${{ steps.cache-node_modules.outputs.cache-hit != 'true' }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,12 @@ You can start with this workspace settings file:
"**/node_modules/**": true,
"**/vendor/**": true
},
// Use TypeScript from the workspace instead of VS Code's built-in TypeScript version.
"js/ts.tsdk.path": "tools/build-scripts/node_modules/@typescript/native/lib",
// Use ESLint, Prettier and Stylelint from the respective paths.
"eslint.nodePath": "tools/eslint/node_modules",
"prettier.prettierPath": "packages/prettier-config/node_modules/prettier",
"stylelint.stylelintPath": "tools/stylelint/node_modules/stylelint",
"[php]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "obliviousharmony.vscode-php-codesniffer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ exports[`DependencyExtractionWebpackPlugin modules > Webpack \`no-default\` > sh
'dependencies' => array(

),
'version' => 'ef50aa650dbfb7d400af',
'version' => 'e92a9548b4a6bd2acd81',
'type' => 'module'
);
"
Expand Down Expand Up @@ -418,7 +418,7 @@ exports[`DependencyExtractionWebpackPlugin modules > Webpack \`runtime-chunk-sin
'dependencies' => array(
'@wordpress/blob'
),
'version' => '5822b2168d9a9ad0ab52',
'version' => '0b4be29a9a428b9e8608',
'type' => 'module',
'handle' => 'runtime-chunk-single-modules-a'
);
Expand Down Expand Up @@ -858,7 +858,7 @@ exports[`DependencyExtractionWebpackPlugin scripts > Webpack \`no-default\` > sh
'dependencies' => array(

),
'version' => '93d83bee525cbfa3ca27'
'version' => '9c20c9bd8e5f5841767b'
);
"
`;
Expand Down Expand Up @@ -1029,7 +1029,7 @@ exports[`DependencyExtractionWebpackPlugin scripts > Webpack \`runtime-chunk-sin
'dependencies' => array(
'wp-blob'
),
'version' => '10219f2e878437d6563a',
'version' => 'c4233136b50b85f54397',
'handle' => 'runtime-chunk-single-scripts-a'
);
"
Expand Down
5 changes: 5 additions & 0 deletions storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ const config: StorybookConfig = {
},
viteFinal: async ( viteConfig ) => {
return mergeConfig( viteConfig, {
/*
* Storybook roots Vite at this config directory's parent, the
* repository root, which owns none of the dependencies.
*/
root: import.meta.dirname,
Comment thread
manzoorwanijk marked this conversation as resolved.
Outdated
Comment thread
manzoorwanijk marked this conversation as resolved.
Outdated
resolve: {
alias: [
{
Expand Down
14 changes: 4 additions & 10 deletions tools/monorepo/tsconfig/tsconfig.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,11 @@
"resolveJsonModule": true,

/*
* `../typings` is this workspace's own. `@types` packages are not:
* a hoisted install puts them at the repo root, a linked one puts
* them in the workspace that declared them. Both are listed because
* TypeScript skips a type root that does not exist, so the preset
* serves either layout.
* `../typings` is this workspace's own. `@types` packages resolve from
* the project that declared them, so a package using types it never
* declared fails here instead of borrowing them from the root.
*/
"typeRoots": [
"../typings",
"${configDir}/node_modules/@types",
"../../../node_modules/@types"
],
"typeRoots": [ "../typings", "${configDir}/node_modules/@types" ],
"types": [],

"rootDir": "${configDir}/src",
Expand Down
19 changes: 18 additions & 1 deletion tools/validation/test-create-block.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,20 @@ function run( command, args, options = {} ) {
}
}

/*
* Under an isolated install layout, transitive deps are not hoisted to the root `node_modules/`.
* `@wordpress/scripts` shells out to webpack, eslint, etc. via `resolve-bin`,
* which calls `require.resolve` from its own location in the dep store and
* therefore can't see those sibling packages. Adding `packages/scripts/`'s
* own `node_modules/` as a `NODE_PATH` fallback lets Node find them.
*/
const NODE_PATH = [
Comment thread
manzoorwanijk marked this conversation as resolved.
Outdated
path.join( ROOT, 'packages/scripts/node_modules' ),
process.env.NODE_PATH,
]
.filter( Boolean )
.join( path.delimiter );

/**
* Resolve a bin via module resolution rather than a `node_modules/.bin` path,
* whose location depends on the install layout.
Expand Down Expand Up @@ -99,7 +113,10 @@ function wpCreateBlock( args, options = {} ) {
* @param {...string} args Command arguments forwarded to `wp-scripts`.
*/
function wpScripts( ...args ) {
run( process.execPath, [ WP_SCRIPTS, ...args ], { cwd: STATIC_BLOCK } );
run( process.execPath, [ WP_SCRIPTS, ...args ], {
cwd: STATIC_BLOCK,
env: { ...process.env, NODE_PATH },
} );
}

/**
Expand Down