Skip to content
Helpful functions to manage monorepos (using Yarn Workspaces)
Branch: master
Clone or download
mrtnzlml and kiwicom-github-bot Shipit: check for corrupted Git repositories
kiwicom-source-id: c07fa22c055a31c91426f3020d989f19eecd3928
Latest commit dc0559b Apr 18, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
bin Monorepo: add new ShellCommand Apr 16, 2019
src Shipit: check for corrupted Git repositories Apr 19, 2019
.npmignore NPM publisher: use 'npm-packlist' instead of custom ignore rules Mar 28, 2019
LICENSE Shipit: check for corrupted Git repositories Apr 19, 2019
README.md
package.json Shipit: check for corrupted Git repositories Apr 19, 2019

README.md

This package contains many useful utilities to work with JavaScript monorepo.

This package is opinionated in many ways and it expects similar monorepo setup to how Universe works in Incubator tribe (see: https://gitlab.skypicker.com/incubator/universe 🔐). This monorepo is not just several projects next to each other. It shares common executors for Flow, Eslint and Tests. This means that individual projects do not have their own scripts for running these tools (can change in the future). It also relies on Yarn Workspaces.

Do you like our open source? We are looking for skilled JavaScript developers to help us build it. Check our open positions: https://jobs.kiwi.com/

Installation

yarn add --dev @kiwicom/monorepo

Usage

findRootPackageJson, findRootPackageJsonPath

It finds the root package.json file in the monorepo (must contain Yarn Workspaces). It is useful if you need to know where is the root or you need to access root package.json because of workspaces definition for example.

const rootPackageJSON = findRootPackageJson();

It memoizes the result internally so when you call it for the second time you'll get the result instantly. Function findRootPackageJson returns the file content (object) but function findRootPackageJsonPath returns only the path.

Working with Workspaces

Workspaces utility allows you to access information about workspaces anywhere in the monorepo. You can for example iterate all workspaces:

import { Workspaces } from '@kiwicom/monorepo';

// OR `iterateWorkspacesInPath` if you need to work with workspaces only in one path

Workspaces.iterateWorkspaces(packageJSONLocation => {
  test(packageJSONLocation, () => {
    // $FlowAllowDynamicImport
    const packageJson = require(packageJSONLocation);
    expect(packageJson.private).not.toBeUndefined();
  });
});

There is also synchronous version without callbacks:

import { Workspaces } from '@kiwicom/monorepo';

const packageJSONLocations = Workspaces.getWorkspacesSync();

// [ '/absolute/path/src/packages/js/package.json',
//   '/absolute/path/src/packages/monorepo/package.json' ]
console.warn(packageJSONLocations);

Working with changes (Git) (unstable)

TODO

Glob (unstable)

TODO

Working with shell commands (ShellCommand) (unstable)

Shell command utility gives you the ability to work with shell while using friendly API and Flow types. Moreover it throws exceptions when the underlying child process fails for whatever reason so you can react easily. Basic usage:

import { ShellCommand } from '@kiwicom/monorepo';

new ShellCommand(
  null, // optional current working directory (defaults to `process.cwd`)
  'git',
  'status',
).runSynchronously();

You can optionally set additional command properties:

new ShellCommand(null, 'git', 'am')
  .setOutputToScreen() // prints on screen instead of returning the value
  .setStdin('input value')
  .setNoExceptions() // hides all errors - potentially dangerous!
  .runSynchronously();

This command currently supports only synchronous execution and therefore it's recommended to use it only for simple scripts and tools (not for production traffic). Please note that many system commands technically support parallel execution but there can be some hidden limitations. For example Git uses single file .git/index.lock for locks and you may run into issues when executing some operations in parallel:

Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes
are terminated then try again.

Binary monorepo-run-tests

This binary script is our tests executor for monorepo environments. It tries to find relevant changes to test based on Git history and Yarn Workspaces. It currently expects .jest.config.js in the project root. Usage (package.json):

{
  "scripts": {
    "test": "monorepo-run-tests"
  }
}

And just run it as usual (yarn run test). You should see something like this:

$ universe [master] yarn run test
yarn run v1.13.0
$ monorepo-run-tests
DIRTY WORKSPACES:  Set { '_components' }
PATHS TO TEST:  Set { 'src/components', 'src/apps', 'src/relay', 'src/translations' }
Running tests in timezone: UTC
 PASS  src/components/stylesheet/__tests__/PlatformStyleSheet-test.js
 PASS  src/translations/__tests__/Translation-test.js
 ...
 PASS  src/components/__tests__/Price-test.js (5.494s)

Test Suites: 10 passed, 10 total
Tests:       25 passed, 25 total
Snapshots:   20 passed, 20 total
Time:        6.582s, estimated 12s
Ran all test suites matching /src\/components|src\/apps|src\/relay|src\/translations|src\/components\/Icon.js/i.
✨  Done in 7.99s.

As you can see it detected some changes in _components workspace and it tries to resolve any other affected workspace (seems like for example src/relay is using _components workspace so it must be tested as well). It can happen that there are no changes to run.

Binary monorepo-babel-node

This binary allows you to run scripts just like with babel-node except it takes into account correct Babel configuration (upward mode by default) and it doesn't ignore our own Yarn Workspace dependencies while transpiling (node_modules/@kiwicom/*). Usage (package.json):

{
  "scripts": {
    "test-bc": "monorepo-babel-node ./scripts/test-bc.js"
  }
}

Where scripts/test-bc.js is normal JS file with all the modern JS features.

There are currently two Node.js flags enabled: --inspect and --inspect-brk. Rest of the flags are forwarded to the executed script.

You can’t perform that action at this time.