nx: Changes to package-lock.json trigger an Affected on all packages
Current Behavior
Update one dependency that affects only one package
run npx nx print-affected --select=projects --base=main
will print all packages
Expected Behavior
Update one dependency that affects only one package
run npx nx print-affected --select=projects --base=main
should print only the affected package
GitHub Repo
https://github.com/pedrolourencoribeiro/nx-affected
Steps to Reproduce
- clone git repo https://github.com/pedrolourencoribeiro/nx-affected
- checkout zod-update
- install dependencies (
npm i) - run
npx nx print-affected --select=projects --base=main
Nx Report
> NX Report complete - copy this into the issue template
Node : 16.18.0
OS : darwin arm64
npm : 8.19.2
nx : 15.7.2
@nrwl/linter : 15.7.2
@nrwl/workspace : 15.7.2
@nrwl/cli : 15.7.2
@nrwl/devkit : 15.7.2
@nrwl/eslint-plugin-nx : 15.7.2
@nrwl/js : 15.7.2
@nrwl/tao : 15.7.2
typescript : 4.8.4
Failure Logs
No response
Additional Information
This was changed in the version 15.4.0 => https://github.com/nrwl/nx/pull/13960#discussion_r1055559215 I don’t fully know the reason but this is blocking us from upgrading to a new version since we have quite a lot of packages and we want to know what is really affected when updating a dependency. Is there a workaround for this? From looking at the code nothing came to my mind but maybe there is.
Thank you for all the work btw the project is amazing and its saving us a lot of time 🙇♂️ Ps: I’m available to contribute to this if needed 😃
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 7
- Comments: 52 (25 by maintainers)
Another problem with this: so let’s say you have 100 projects in your monorepo (could be much lower). You want to update a single dependency to a new version. Now you want to know which projects would be updated by this change so you can do proper regression testing… currently all 100 projects would be shown as affected, but wouldn’t it be nice if you could run nx:affected and determine which projects are actually using that dependency and run your regression testing on only those projects?
the pnpm workspace workflow definitely seems to not be ideal here.
Adding a package to an app or package in the workspace ends up marking the entire repo as affected. Would love to find a way to resolve this without ignoring the changes
We have a yarn.lock and it seems to work adding yarn.lock to the .nxignore file. Now we only get the affected services/packages as expected. Perhaps there will be some side affects that i’m not considering?
Our pipeline looks roughly like this:
nx affected --target=versionnx affected --targets=lint,test,build,dockernx affected --target=deploy--dryRunnx affected --target=upgradeSo when one lib or app adds one dependency, say via
pnpm install --filter {my-lib} {some-dependency}, the lockfile makes everything affected, triggering a release cycle for all projects in the repo, and a full rebuild.I understand your pain and can inform you that solution is on the way.
We are implementing a logic to restrict hash scope for custom targets.
This would for example allow you to specify that your docker push target is not affected by any changes in the installed packages and solely depends on the project’s built artifact.
But even still, let’s say I use docker cache. I still have to build and push all new containers as my development environment builds and pushes containers tagged with their git hash. That means not only to I have to build and push, but I also have all of my kubernetes pods restart and reload a new container even though nothing in the apps have changed.
I am having the same issue, this is a big problem:(
Not yet
Currently, there is no way to extract that information as far as I know. The calculation happens in realtime as you execute the target. But maybe @FrozenPandaz would know more.
Btw. the
print-affectedis deprecated. You should use nx showIt’d be great to have an article/tutorial with examples of a docker (nx-container) and/or npm (semver & ngx-deploy-npm) target that uses the
externalDependenciesoption.It’s usually docker push or npm publishing that will suffer when the lockfile affects every project.
Ok I do see that the build task is cached but what I do not understand how building and pushing a docker container stamped with the version number (git hash) and updating kubernetes can be a cachable operation. If changing a single dependency of one project, updates the lock file then all of my deploy targets will run, which due to be docker image builds, push and kubernetes updates will have to run as I do not see how caching can work for that. Unless the image is actually built and pushed, updating kubernetes with the new version will fail as it won’t be able to find the image.
This also causes very high resource usage on our kubernetes cluster as all of the pods need to roll over.
@meeroslav @meeroslav
Creating a
.nxignorewith contentdoesn’t work for me. The cache is invalided if I change any
integrityhash value. Example:The cache is invalided for all commands. Also, for packages that don’t depend on this library.
nx version: 16.2.2
I am using custom commands from package.json, not executors. Is there any workaround for it? This is a huge problem for my team. We are migrating to nx, and we will plan to keep adding more packages and split the existing code. The CI times will grow instead of shrink.
I’m still keeping this closed as the affected works as expected, but caching is currently a bit limiting (which is why we are making changes to it)
I am happy to tell you we are actually working on a solution for this. It’s currently in the design phase but you should expect it in a few weeks.
In the meantime, you can use
.nxignoreas @smailc suggested.We have an existing monorepo with ~60 services and ~60 packages that we added nx to. Some operations do not use caching:
typecheck- we separated typechecking to another job using npm scripttsc --noEmitand useesbuildduringbuildstep. AFAIK there is no official executor to perform typechecking only, so even though we have caching enabled for this step, it won’t workdeployjobs (for each environment) - this is not cachable, it deploys different projects using serverless framework / ecs / eks. Updating a single dependency now causes 60 services to deploywait_for_deploymentstep that queries the status of deployments for each service until it’s in a stable state@ianldgs, changing project’s
package.jsonshould mark that project as affected, sincepackage.jsonis a file belonging to that project.Hey all,
The logic behind this is not as trivial as you would have expected.
Explanation
The reason why
print-affectedand theaffecteditself mark all the projects is because every change in the lock file can affect all of them. You runnxcommands via executors (e.g.nx:run-commandsor@nrwl/js:tsc). Without knowing what target (and what executor) you are running it’s impossible to tell whether the project is affected or not so it’s safer to mark it as (potentially) affected.Imagine you have a
reactapp, and you updaterxjs. Although your project might not depend on it, you might have an executor that looks like this:Now each build of your app is actually affected by changes in the
rxjs.Caching to the rescue
Despite every project is marked as affected, once you run the actual command (or task) we will have more information and can at that point decide if the project had actually changed or not. The task consists of the following parameters:
@nrwl/jsand everything it depends on)If your target hasn’t been affected by the change, you will get instant replay from the cache, otherwise as long as any of those is different we will run the full command.
Known executors only
This unfortunately only works with known executors (e.g.
@nrwl/*) where we can guarantee the list of dependencies. For all the other executors, including thenx:run-commandswe will fall back to all affected mode since we have no idea what that executor might be running and which packages it depends on.Workaround
There is a workaround that will land in v16 where you can skip checking
package.jsonand lock files. In yournx.jsonyou need to add the following:This will disable all the checks so your graph will no longer have any of the external packages included as a node.