postInstall Script in box.json running after each dependency is installed as well as my package. Is that expected?

Hi All,

The title asically sums it up but I have a package which I would like to have run a custom command when it is complete. That is working but it is also running after each dependency is installed as well so my configuration command is running 4 times for 1 install. Is that expected? Is there a “When everything is installed please run this once” hook in the lifecycle. Let me know if this isn’t making any sense. Here is an excerpt of the box.json:

Hi Dan, you’re probably one of the first people to use that package script so I think this is an opportunity for us to tweak it a bit :slight_smile:

Basically, postInstall is just using the current working directory every time it fires. My original idea was that the main package “asking” for the install would have an opportunity to respond to any dependency that was installed into it. But it sounds like you’re expecting the package script to run in the package that was just installed-- not the package that it was installed into. Is that correct?

That sort of makes a bit of sense (and honestly I didn’t look at what npm does before throwing this in). This is a very simple change. In fact, I already made it locally, but then I figured all the “XXXInstall” package scripts should be reviewed and I’m not quite sure what directory they should run in. And by “run in” I mean, CommandBox looks for a box.json in that directory to see if there’s a matching package script there. All of these previously just used the current working directory of the shell.

  • preInistall - This doesn’t have access to the installation directory yet since it hasn’t been calculated yet. Perhaps run in the directory of the package requesting the installation? This would at least follow down the rabbit hole as nested dependencies were installed.
  • onInstall - Same as above. Installation path isn’t calculated yet (just the endpoint). Should we run in the package asking for the dependency?
  • postInstall - This can be changed to run in install directory of the package that was just installed, which is what I believe you’re expecting.
  • preUninstall - Should this be changed to run inside the package directory that’s about to be uninstalled? Seems like that would match what we have above.
  • postUninstall - The package that was just installed doesn’t exist any longer, so perhaps we should run this from the containing package. Note, that currently this doesn’t fire for every nested dependency if dealing with modules. We just just delete the parent package since they’re all nested. It doesn’t HAVE to be that way-- it just seemed like a clever shortcut at the time.
    Please provide your thoughts categorically. Also, if anyone is actually using any of these package scripts right now, I’d love to hear about it. Especially since we’re talking about changing how they work!

Thanks!

~Brad

ColdBox/CommandBox Developer Advocate
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Hi Brad,

I like the thought process. I have no idea what npm does so I’m not comparing although I guess there is an argument to be made to be consistent unless there is a reason not to be (I’ve heard that Ortus tends to like conventions J ).

Here is what I’m trying to accomplish.

I am installing a package (Package A) via commandBox which is going to be a web-based app. The package installation handles placing the folders and files in the correct location and then fires a commandBox module (CBModuleA) for additional configurations like datsources, admin users etc. For safety’s sake, CBModuleA is going to be a dependency of Package A to ensure that it is installed along with the 4 other dependencies which may or may not be necessary. If CBModuleA is not there, the current postInstall will break.

At the moment there are two issues on the table:

  1. If Package A’s postInstall script depends on 2 dependencies, it will fail after the first one installs because it will have 1 dependency but not the 2nd, correct?

  2. Even if PackageA’s postInstall script only needs 1 of the dependencies, the postInstall Script will still run after each dependency is installed so the same configuration is run 5 times which, since it’s a wizard, makes for an irritated user even if nothing “breaks”.

I like your idea of the package being able to interact with the dependencies though.

What if there are two Life Cycle hooks –

  1. postInstall which runs as is, after each dependency is installed

  2. postAllDependencyInstalls which only runs once after all the dependencies are installed.

That way the package can still interact with all of the dependencies as they are installed but also be able to have a hook that can take care of all of the dependencies and only run once.

I don’t know if I’m making any sense but is that clear at least to start with?

Dan

FWIW, I had a use case similar to Dan’s and attempted to use the “postinstall” script to solve it. I tried a few different things and couldn’t get my script to fire. I gave up and started working on something else. While installing a different package inside the package with my Postinstall script, suddenly my script fired!

I was expecting my script to run after my package (and all its dependencies) had been installed. (Just once) I was not expecting my script to run when it did.

Postinstall to me applies to the package itself, not dependencies or packages installed later.

Pretty sure npm works this way as well.

Thanks!
Joel C.

Hi Brad,

I like the thought process. I have no idea what npm does so I’m not comparing although I guess there is an argument to be made to be consistent unless there is a reason not to be (I’ve heard that Ortus tends to like conventions J ).

Here is what I’m trying to accomplish.

I am installing a package (Package A) via commandBox which is going to be a web-based app. The package installation handles placing the folders and files in the correct location and then fires a commandBox module (CBModuleA) for additional configurations like datsources, admin users etc. For safety’s sake, CBModuleA is going to be a dependency of Package A to ensure that it is installed along with the 4 other dependencies which may or may not be necessary. If CBModuleA is not there, the current postInstall will break.

At the moment there are two issues on the table:

<![if !supportLists]>1) <![endif]>If Package A’s postInstall script depends on 2 dependencies, it will fail after the first one installs because it will have 1 dependency but not the 2nd, correct?

<![if !supportLists]>2) <![endif]>Even if PackageA’s postInstall script only needs 1 of the dependencies, the postInstall Script will still run after each dependency is installed so the same configuration is run 5 times which, since it’s a wizard, makes for an irritated user even if nothing “breaks”.

I like your idea of the package being able to interact with the dependencies though.

What if there are two Life Cycle hooks –

<![if !supportLists]>1. <![endif]>postInstall which runs as is, after each dependency is installed

<![if !supportLists]>2. <![endif]>postAllDependencyInstalls which only runs once after all the dependencies are installed.

That way the package can still interact with all of the dependencies as they are installed but also be able to have a hook that can take care of all of the dependencies and only run once.

I don’t know if I’m making any sense but is that clear at least to start with?

Dan

> Postinstall to me applies to the package itself, not dependencies or packages installed later.

Thanks for the feedback Don. I think this helps confirm that we need to change this to match what you expected.

Thanks!

~Brad

ColdBox/CommandBox Developer Advocate
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Ditto on what Don says. My suggestion about keeping it as is was to keep backwards compatibility if needed but I agree that to me “postInstall” means the package itself.

A use case which I think confirms this happened today when I started the embedded server for a project when I was not in its root folder (i.e. I ran “server start projectB” when I was in projectA’s root folder). Because CB end ended up installing the CFEngine needed, the post Install script for Project A ran after the CFEngine package was installed.

Dan

I think this makes sense. I’ll try to do a commentary on the other interceptor points as well.

Dan

I think this makes sense. I’ll try to do a commentary on the other interceptor points as well.

Dan