Yarn workspaces best practice when using shared library - lerna

I have a common (or not so coomon) scenario for yarn workspaces and didn't find the right guide for me online.
yarn workspaces look like that:
- monorepo
- packages
- client
- admin
- theme
- lib
Client is used as our endusers, it is a react project
Admin is used as backoffice for admin users and it is build in react too
Theme is used for all the UI kit (components) and storybook. We use the UI kit in client and admin
project and this is classic "monorepo style" (lerna) to share components between 2 projects. This folder should be shared only for this project.
Lib is used for all API and shared "Business logic" between multiple projects. I have 4 project which use the same lib functionality for API requests, Authentication, Redux and more.
Additional information:
monorepo is root repository with .gitmodules
Each sub folder is a different git repository
We use workspaces in order to have easy development on theme and on the client and admin project on the same time.
Questions:
We run yarn start only in client project and admin project. Both projects are using the same theme and same lib functionality. Because the lib is shared with other projects, it is updated on a weekly base:
How I can prevent from it to be updated from project to project? should I work with tags in git repository or should I remove lib from the monorepo worksapce and to work with it as npm package (the whole point is to have easy development process when we change the lib file we do not need to npm update it again and again.
If lib will be npm package, How can I tell monorepo to use workspaces when I run yarn start and to use the npm version when I run yarn build?
Please advice on the best practices for this scenario.
Thanks in advance,
Leo.

FINAL ANSWER:
I found the best solution for me and I tried it for 6 weeks during development (best practice).
I ended up with this structure:
monorepo // git MAIN repository
packages
client // git sub repository
admin // git sub repository
theme // git sub repository
lib // git sub repository
The client and admin use the theme as yarn workspaces https://classic.yarnpkg.com/en/docs/workspaces/
lib is used as Git npm package with git+ssh://git#gitlab.com:xxxx/xxx/lib.git#v1.0.1
The main/sub repositories structure gives me the ability the manage version control for each project separately and on the same time to use shared "theme" (workspaces) and "lib" core (npm) by versions.
Tip:
For easy development I recommend to add the lib as yarn workspace because when we run yarn start it hot reload the changes in real time. When we do yarn build we use the lib as npm package with an ssh link.
Good luck!
Leo.

Here is my personal preferences.
- monorepo
- packages
- client
- admin
- core
I think lib can be moved to core, and theme are more like npm package to me.

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

Does yarn link follow yarn-links in dependencies?

I am using yarn 1.22.10.
I am developing a project which uses a yarn-linked dependency named module-one which in turn yarn-links to a dependency named module-two.
Is yarn able to follow these yarn link chains?
According to yarn documentation ,
a package can be linked into another project.
So if module-one is a package which is developed using module-two and then module-one is further called into another project using yarn link, technically it should work provided module-one is a package containing its own package.json.
But I would like to suggest not to use yarn link in a chain like wise because during production if dependency module-two modifies/updates/returns error and these changes are not translated to module-one; then the project might suffer and will return with unexpected errors/exceptions which will be pain to track and rectify.
Therefore I would like to suggest that you must install the module-two as dependency in module-one and then yarn link module-one to your project.

How to remove yarn workspaces correctly?

I configured 2 workspaces in package.json e.g example and gatsby-theme but later I found I was actually developing a gatsby-starter so I removed the example workspace that depended on the latter workspace from package.json.
I wonder if I moved all files from gatsby-theme/ to the project root directory and overwrote the package.json and other files with gatsby-theme's, does it become a project that could be managed with both npm and yarn?

Gitlab CI - Auto DevOps job failed, Unable to select a buildpack for a Go project?

My Gitlab CI Auto DevOps job failed with
Status: Downloaded newer image for gliderlabs/herokuish:latest
-----> Unable to select a buildpack
ERROR: Job failed: exit code 1
I've gone through
Auto DevOps and
Getting started with Auto DevOps
and am still not sure where I should put the buildpack.
Mine should be heroku-buildpack-go, which I've lost track where I get that from.
My repo consist only a single-character README.md, and the "Hello, playground" main.go.
Conclusion:
Thanks to David's comprehensive explanation, I was able to get DevOps started with correct buildpack:
From this I would conclude that your single .go file at the root of the directory tree does not meet the activation criteria for auto-building Go projects. I'd suggest picking one of the dependency managers in the requirements above and modifying your project to support it.
FTA, I just did touch go.mod then git add & git push and the AutoDevops started building my GO project indeed.
However it seems to me that Gitlab AutoDevops is not able to build any GO projects very easily, as I get the following error (with project variable TRACE=true):
...
!! The go.mod file for this project does not specify a Go version
!!
!! Defaulting to go1.11.1
!!
!! For more details see: https://devcenter.heroku.com/articles/go-apps-with-modules#build-configuration
!!
-----> Installing go1.11.1
-----> Fetching go1.11.1.linux-amd64.tar.gz... done
!! Installing package '.' (default)
!!
!! To install a different package spec add a comment in the following form to your `go.mod` file:
!! // +heroku install ./cmd/...
!!
!! For more details see: https://devcenter.heroku.com/articles/go-apps-with-modules#build-configuration
!!
-----> Running: go install -v -tags heroku .
go: cannot determine module path for source directory /tmp/build (outside GOPATH, no import comments)
ERROR: Job failed: exit code 1
The easier solution is to use .gitlab-ci.yml file instead, documented in
https://blog.boatswain.io/post/build-go-project-with-gitlab-ci/
(and followed up at Gitlab CI - Start Shared Runner for normal repos).
From the AutoDevops documentation:
Auto Build creates a build of the application in one of two ways:
If there is a Dockerfile, it will use docker build to create a Docker image.
Otherwise, it will use Herokuish and Heroku buildpacks to automatically detect and build the application into a Docker image.
Then looking at the build activation criteria, as per the Heroku Go buildpack documentation:
This buildpack will detect your repository as Go if you are using either:
go modules
dep
govendor
glide
GB
Godep
Or more specifically for godep, govendor or GB:
The Heroku Go buildpack is used when an application meets one of the following requirements:
has a Godeps/Godeps.json file, identifying the application as being managed by godep;
has a vendor/vendor.json file, identifying the application as being managed by govendor;
has a src directory, which has sub directories, contains one or more .go files, identifying the application as being managed by gb.
From this I would conclude that your single .go file at the root of the directory tree does not meet the activation criteria for auto-building Go projects. I'd suggest picking one of the dependency managers in the requirements above and modifying your project to support it. After that AutoDevops should start building your project.
If you are still having issues after that, this debugging note might help:
After making sure that the project meets the buildpack requirements;
if it still fails, setting a project variable TRACE=true will enable verbose logging which​ may help to continue troubleshooting.

What's the recommended way of building ELKI's current development status?

I forked ELKI from https://github.com/elki-project because I want to keep up to date with the latest development status while making my own changes and additions to the source (which I will possibly provide via pull request if it's sensible).
I followed the instructions in the README.md to package it with mvn package but there was no .jar created in elki/target/ - when checking out the release0.7.1 branch, it worked and I could start the minigui with java -cp elki-0.7.1.jar de.lmu.ifi.dbs.elki.application.ELKILauncher.
Is there a recommended way to try out the latest changes on the master?
We are currently in the process of modularizing ELKI.
But mvn package does create .jar files in elki/target/ here:
elki/target/elki-0.7.2-SNAPSHOT.jar
elki/target/elki-0.7.2-SNAPSHOT-javadoc.jar
elki/target/elki-0.7.2-SNAPSHOT-sources.jar
elki/target/dependency/elki-core-dbids-0.7.2-SNAPSHOT.jar
elki/target/dependency/elki-core-dbids-int-0.7.2-SNAPSHOT.jar
elki/target/dependency/elki-core-util-0.7.2-SNAPSHOT.jar
elki/target/dependency/elki-docutil-0.7.2-SNAPSHOT.jar
elki/target/dependency/elki-logging-0.7.2-SNAPSHOT.jar
elki/target/dependency/hamcrest-core-1.3.jar
elki/target/dependency/javaparser-core-2.3.0.jar
elki/target/dependency/junit-4.12.jar
elki/target/dependency/trove4j-3.0.3.jar
The main jar, ./elki/target/elki-0.7.2-SNAPSHOT.jar is runnable, but will only include the command line interface because of modularization - the minigui is optional now.
If you want a all-in-one bundle (as distributed on the web site), you need to enable the Maven profile bundle in addition to the functionality you want to include (e.g. mvn -Psvg,svm,uncertain,bundle package).

Resources