How to `lerna add` multiple dependencies at once and without having to move to root - lerna

How to lerna add multiple dependencies at once and without having to move to root? The current form of lerna add is quite inconvenient to use.

Related

How do I add shared dependencies to a monorepo using Yarn workspaces?

I am using Yarn's Workspaces feature to manage a monorepo. Some of the individual workspaces have their own dependencies defined in their own package.json, however I also have some shared dependencies (some are for testing the whole repo, some are used by all the workspaces). How do I declare these the correct way?
If I try to add them to the root package.json, Yarn gives me a warning. But adding the same dependency to all n workspaces (there are a lot and it's liable to grow) seems tedious and hard to maintain when upgrading dependencies.
Is the right thing to do to add the shared dependency (say, typescript, or jest or serverless) to every single individual workspace?
Using Yarn 1/classic.
I found also Yarn Workspaces: How and where should I install my dependencies? but it's unanswered
Yarn workspaces shared dependencies talks about using peer dependencies but the user is experiencing trouble
After a half-day search and trying, I found multiple ways to manage shared dependencies
1. Sync dependency version with syncpack
https://github.com/JamieMason/syncpack/
Given the fact that yarn workspaces will share the dependencies if their versions are the same (see https://classic.yarnpkg.com/lang/en/docs/workspaces/), all we have to do is to keep the dependency versions in sync to make dependencies sharing, which is exactly what syncpack does.
I found this is the least harmful way to make sharing dependencies works, while other methods require some degree of twisting package.json.
2. Use peer dependencies
For each package, set sharing dependencies as peerDependencies with version “*”, and set root workspace set the real dependencies. For example:
# ./package.json
{
...
"workspaces": ["packages/*"],
"dependencies": [
"some-lib": "^1.0.0",
]
}
# ./packages/pkg-a/package.json
{
...
"peerDependencies": [
"some-lib": "*",
]
}
and yarn install at workspace root.
3. Share script (require yarn v2)
See https://yarnpkg.com/getting-started/qa#how-to-share-scripts-between-workspaces
Miscellaneous
yarn provides workspace cli to add/remove package, see https://classic.yarnpkg.com/lang/en/docs/cli/workspace/
yarn workspace awesome-package add react react-dom --dev
yarn workspace web-project remove some-package

Prevent yarn from creating node_modules in monorepo root

I'm using yarn with monorepos that contain several packages. For examples packages foo and bar might be located in repo/foo and repo/bar within the monorepo root repo. The problem is that I sometimes accidentally run yarn without parameters in the repository root instead of the packages directories. This creates a repo/node_modules directory and a repo/yarn.lock file. Can I somehow prevent yarn from creating node_modules and yarn.lock in the repository root directory?

Docker multi-stage build and mounting/sharing from previous stage

I would like to use multi-stage builds to avoid downloading all the Maven dependencies required by my Java project every time I build the app.
I am thinking of resolving the Maven dependencies in a first stage, then building the app in a second stage which would require access to the dependencies downloaded in the previous stage.
If I understood well multi-stage builds I could copy files created in the first stage to the second stage, but ideally I would like to be able to "mount" or "share" the folder from the first stage where the dependencies live instead of copying the files, is it possible? Or is there a better way to achieve this?
Thanks.
EDIT:
This was the first stage I was thinking about
FROM some-image-with-maven AS maven-repo
WORKDIR /workspace/
COPY pom.xml .
RUN mvn -B -f pom.xml dependency:resolve
But since the pom file will be different most of the times (because I would like to share this stage across projects), the following step that resolves dependencies will download all of them again (instead of using a cached layer).
You can only copy stuff from the first stage if you are not using volumes. When using volumes, you can share data between stages which are basically separate container instances.
Since missing to clean up volumes is often not handled properly I suggest to keep to the copy strategy. There is no real benefit using bind-mount to share data over the copy approach.
I don't believe there's a way to do this currently. To share from one build stage to the next, the only option is to COPY files from one stage's directory to the current stage.
To use the first stage as a build cache and avoid copying all the dependencies, I'd run your build in that first stage. Or you can make a second intermediate stage that is FROM stage1name if you want additional separation between the stages. The output of your build can then be copied to the final layer, avoiding the need to copy all the build dependencies.
Answering from the future...
If using buildkit or compatible (most people probably are by now), you can mount a previous stage with a bind mount. Something like this would accomplish what the original post was asking:
FROM someimage as build
COPY pom.xml .
RUN mvn -Dmaven.repo.local=/.m2_repository -B -f pom.xml dependency:resolve
FROM runtimeimage
COPY pom.xml .
COPY src/ ./src/
RUN --mount=type=bind,from=build,source=/.m2_repository,target=/.m2_repository \
mvn package
But more to the point, there is also a cache mount that you can use instead and you would incur the cost of downloading all the deps on first run, but subsequent would be able to find those deps in the cache:
FROM runtimeimage
COPY pom.xml .
COPY src/ ./src/
RUN --mount=type=cache,target=/.m2_repository,sharing=locked \
mvn package

Maven for multiple modules

How do I run selected modules using parent pom in Maven like I have
<module>APP_1</module>
<module>web_1</module>
<module>service_1</module>
<module>schema_1</module>
<module>APP_2</module>
<module>web_2</module>
<module>service_2</module>
<<module>schema_2</module>
sometimes as developer if I want to build first module only so how should I achieve this task in parent pom?
First you have to make a decision.
Assuming that some of your child modules depend on other child modules you have to decide if you want to:
a) build one or more modules by themselves using the last built version of the dependent modules located in your ~/.m2/repository directory. This is super useful if you want to, say, rebuild the web_2 module which depends on the service_2 module, but service_2 is currently busted and won't compile. In this case do this:
mvn clean install --projects module-directory-name
or
b) you want to build a module and have maven recursively check all dependent modules to see if they need to be rebuilt. This is slower and safer typically. This command is:
mvn reactor:make -Dmake.artifacts=com.yourgroup:module-name
I use both of these at different times every day.
mvn reactor:make -Dmake.folders=barBusinessLogic
as described here

Maven, how to trigger install of parent from child module? (command prompt)

This is more of aesthetic question since I want to make my life easier. I have maven project structure like this:
foo-project (parent)
foo-business (child-module)
foo-dao (child-module)
foo-app (child-module)
I run my maven commands from command prompt, I want to trigger install of all project from maven module, meaning if I am in module dir I want to trigger install from there and not to navigate to parent pom dir.
Thank you
If you really want to make your life easier, separate your parent project (i.e. the one where you put common settings for your other projects) from your aggregator project (i.e. the one that has your other projects as modules). At that point the sole purpose of your aggregator project will be to let you build all your projects together, so run your builds from there.
With Maven, doing as Maven likes is always going to make your life easier than any other option.
Consider using Buildozer - an utility that I wrote some time ago in order to cleverly perform builds of given module, but building all "outdated" dependencies first.
It can be downloaded here: http://buildbox.sourceforge.net/buildozer/
It requires that you first register your modules (= create mapping between dir and GAV for each module), like this:
zer reg /home/pkozelka/my-common-modules /home/pkozelka/my-projects
or
cd /home/pkozelka/other-modules
zer reg .
then you go into any module and perform the build:
zcd my-server # this is 'chdir by artifactId', with bashcompletion on Linux
zer . # compiles all (transitive) dependency modules and then this one

Resources