researchgate/spire

Spire#postinstall hook fails to load spire plugins

Rendez opened this issue Β· 3 comments

πŸ› Bug Report

package.json#postinstall on spire package executes spire command ./bin/spire.js hook postinstall causing spire.js to load plugins from that root onwards. This means we can't install plugins that aren't within a "node_modules" path, because process.cwd() (part of context.cwd) is referring to the spire folder instead of my root project.

How to reproduce

Take the next example:

my-project
 β”œ package.json [spire is a dependency & spire config defines a local plugin too]
 β”” node_modules
    β”” spire
       β”” package.json [scripts > postinstall defined here]

The call to resolveConfig within spire/index.js will try to resolve the plugins' paths and on that will use context.cwd() which is set to: my-project/node_modules/spire. instead of my-project as I would expect if I have my local plugin defined as such:

"spire": {
    "extends": "@researchgate/spire-config",
    "plugins": [
      "spire-plugin-semantic-release",
      "<rootDir>/.spire/spire-plugin-tslint"
    ]
  },

Note that spire will resolve my local plugin as being under my-project/node_modules/spire/.spire/spire-plugin-tslint, and that's exactly the issue.
By the way. I am also unsure whether spire-plugin-semantic-release is at this point picked up magically or not, but it doesn't throw an error...

Expected behavior

All plugins should be picked up starting from the real npm root, which is my-project, but npm scripts execute under the scope of each module. There's a way to modify this behavior for the spire package, and that would be to define an ENV variable so that we could set $INIT_CWD to the same place where my-project's yarn.lock lives. The other would be to directly search for plugins starting from the bottom.

From the npm docs: https://docs.npmjs.com/cli/run-script

Scripts are run from the root of the module, regardless of what your current working directory is when you call npm run. If you want your script to use different behavior based on what subdirectory you’re in, you can use the INIT_CWD environment variable, which holds the full path you were in when you ran npm run.

hey @Rendez, yep that's defenitly a bug. I'll take a look into how to resolve this in package-independent way as both yarn and npm already sets thier own INIT_CWD and we need to ensure that they behave same way in monorepos.

Alright so I did a bit of experimenting and found it to be a bit trickier then we thought:

  • INIT_CWD would always point out to root-level INIT_CWD where you executed yarn or npm command first, which results in the wrong resolution with nested/spawned calls (can be reproduced with tests which are created & executed in tmp directory);
  • It's possible to run spire via npx or as a plain executable, which doesn't set INIT_CWD and therefore requires maintaining two sources of input (not a big deal tho).

I'll look a bit further into that, meanwhile @Rendez do you maybe have a minimal repro setup I can use as a reference? I'd like to make a test case based on it as well.

I've created #17 which potentially addresses that issue. Regarding this one β€”

I am also unsure whether spire-plugin-semantic-release is at this point picked up magically or not, but it doesn't throw an error...

We're using node's resolution mechanism which is predictable for any node_modules, so it's always a safe way to go. Only local configs/plugins resolutions are affected by this bug.