зеркало из https://github.com/microsoft/lage.git
Making this repo into a monorepo in preparation of more granular work (#250)
* Turning lage into monorepo to prepare subdividing into pieces * getting rid of renovate for now * updated the root scripts to work * fixing up pipelines * moving many files around requires adjustments to beachball config * upgrade node version to allow docusaurus to consume newer node version * Change files * get rid of the extra docs: prefix * adding verbose logging
This commit is contained in:
Родитель
ce90567fcb
Коммит
c0d69c29e1
52
README.md
52
README.md
|
@ -1,59 +1,7 @@
|
|||
# lage
|
||||
|
||||
This is the UNSTABLE branch. All package published from this branch will be tagged as `lage@unstable`. When we have confirmed stability for v1.x branch, then we'll promote it to be stable.
|
||||
|
||||
Documentation is here: https://microsoft.github.io/lage/
|
||||
|
||||
## Overview
|
||||
|
||||
Your JS repo has gotten large enough that you have turned to using a tool to help you manage multiple packages inside a repository. That's great! However, you realized quickly that the tasks defined inside the workspace have to be run in package dependency order.
|
||||
|
||||
Lerna, Rush, wsrun and even pnpm will provide a simple way for you to run npm scripts to be run in a topological order. However, these tools will force you to run your tasks by script name one at a time. For example, all the `build` scripts will have to run first. Then all the `test` scripts run in the topological order.
|
||||
|
||||
This usually means that there are wasted CPU cycles in between `build` and `test`. We can achieve better pipelining the npm scripts if we had a way to say that `test` can run as soon as `build` are done for the package.
|
||||
|
||||
`lage` (Norwegian for "make", pronounced law-geh) solves this by providing a terse pipelining syntax. It has many features geared towards speeding up the task runner that we'll explore later.
|
||||
|
||||
## Quick Start
|
||||
|
||||
`lage` gives you this capability with very little configuration. First, let's install the `lage` utility. You can place this in your workspace's root `package.json` by running `yarn add`:
|
||||
|
||||
```
|
||||
yarn add -D lage
|
||||
```
|
||||
|
||||
Confirm with `yarn` that you are sure to add a package at the root level, you then place a root level script inside the `package.json` to run `lage`:
|
||||
|
||||
```
|
||||
{
|
||||
"scripts": {
|
||||
"build": "lage build",
|
||||
"test": "lage test"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Add a configuration file in the root to get started. Create this file at the root `lage.config.js`:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
pipeline: {
|
||||
build: ["^build"],
|
||||
test: ["build"],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Do not worry about the syntax for now. We will go over the configuration file in a coming section. You can now run this command:
|
||||
|
||||
```
|
||||
$ lage test
|
||||
```
|
||||
|
||||
`lage` will detect that you need to run `build` steps before `test`s are run.
|
||||
|
||||
|
||||
|
||||
# Contributing
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
||||
|
|
|
@ -8,9 +8,8 @@ module.exports = {
|
|||
'decks/**',
|
||||
'docs/**',
|
||||
'jasmine.json',
|
||||
'jest.config.js',
|
||||
'renovate.json',
|
||||
'tests/**',
|
||||
'packages/*/jest.config.js',
|
||||
'packages/*/tests/**',
|
||||
// This one is especially important (otherwise dependabot would be blocked by change file requirements)
|
||||
'yarn.lock',
|
||||
],
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "patch",
|
||||
"comment": "Moving to a monorepo. This will be a test publish",
|
||||
"packageName": "lage",
|
||||
"email": "ken@gizzar.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
module.exports = {
|
||||
title: "lage",
|
||||
description: "Monorepo task runner as beautiful as the Norwegian fjords",
|
||||
base: "/lage/",
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: "Home", link: "/" },
|
||||
{ text: "Guide", link: "/guide/" },
|
||||
{ text: "GitHub", link: "https://github.com/microsoft/lage" },
|
||||
],
|
||||
sidebar: [
|
||||
"/",
|
||||
"/guide/",
|
||||
"/guide/getting-started",
|
||||
"/guide/levels",
|
||||
"/guide/scopes",
|
||||
"/guide/cache",
|
||||
"/guide/remote-cache",
|
||||
"/guide/pipeline",
|
||||
"/guide/profile",
|
||||
"/guide/priority",
|
||||
"/guide/config",
|
||||
"/guide/cli",
|
||||
"/guide/migration"
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
[
|
||||
"mermaidjs",
|
||||
{
|
||||
gantt: {
|
||||
barHeight: 20,
|
||||
fontSize: 12,
|
||||
useWidth: 960,
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
Keep
|
|
@ -1 +0,0 @@
|
|||
$contentWidth ?= 960px
|
|
@ -1,23 +0,0 @@
|
|||
---
|
||||
home: true
|
||||
# heroImage: /hero.png
|
||||
heroText: A Beautiful JS Monorepo Task Runner
|
||||
tagline: Run all your npm scripts in topological order incrementally with cloud cache
|
||||
actionText: Get Started →
|
||||
actionLink: /guide/
|
||||
features:
|
||||
- title: Works with all workspace implementations
|
||||
details: "The workspace-agnostic task runner will run npm scripts for all workspace implementations out there: lerna, yarn, pnpm, rush"
|
||||
- title: Simple pipeline definition
|
||||
details: With a terse definition language, get going with builds within a few seconds
|
||||
- title: Speedy local incremental builds
|
||||
details: Because building once is painful enough, lage will remember what you've built before and skip steps that it has already performed before
|
||||
- title: Speedy CI build caches
|
||||
details: Based on the `backfill` utility, build output can be cached into the cloud for speedy CI builds as well
|
||||
- title: Scoped task runs
|
||||
details: Easily run npm tasks by specifying a scope of packages
|
||||
- title: Profile the task runners
|
||||
details: Generate a profile of tasks run by lage - import it inside Chrome or Edge to understand which tasks took the longest time
|
||||
|
||||
footer: MIT Licensed | Copyright © 2019-present Microsoft
|
||||
---
|
|
@ -1,18 +0,0 @@
|
|||
---
|
||||
title: Introducing Lage
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Your JS repo has gotten large enough that you have turned to using a tool to help you manage multiple packages inside a repository. That's great! However, you realized quickly that the tasks defined inside the workspace have to be run in package dependency order.
|
||||
|
||||
Lerna, Rush, wsrun and even pnpm will provide a simple way for you to run npm scripts to be run in a topological order. However, these tools will force you to run your tasks by script name one at a time. For example, all the `build` scripts will have to run first. Then all the `test` scripts run in the topological order.
|
||||
|
||||
This usually means that there are wasted CPU cycles in between `build` and `test`. We can achieve better pipelining the npm scripts if we had a way to say that `test` can run as soon as `build` are done for the package.
|
||||
|
||||
`lage` (Norwegian for "make", pronounced law-geh) solves this by providing a terse pipelining syntax. It has features specifically address large monorepos with high number of packages:
|
||||
|
||||
- package and task scopes
|
||||
- output caching
|
||||
- sound scheduling with package task pipeline
|
||||
- prioritization
|
|
@ -1,25 +0,0 @@
|
|||
# Caching
|
||||
|
||||
`lage` by default will cache tasks that it has already done recently locally on disk. As long as the source file and the command arguments have not changed, those cached results will be restored.
|
||||
|
||||
See [Remote Cache](./remote-cache) for details about speeding up local dev environment even further with a remote cache from Continuous Integration jobs.
|
||||
|
||||
## Turn off cache
|
||||
|
||||
Sometimes, this incremental behavior is not desired. You can override the caching behavior by using the `--no-cache` argument.
|
||||
|
||||
```
|
||||
$ lage build --no-cache
|
||||
```
|
||||
|
||||
## Resetting cache
|
||||
|
||||
Once in a while, the cache might need to be recreated from scratch. In those situations, you can reset the cache by passing in the `--reset-cache` argument to the command line.
|
||||
|
||||
```
|
||||
lage --reset-cache
|
||||
```
|
||||
|
||||
## Cache Options
|
||||
|
||||
Caching capability is provided by `backfill`. All of the configuration under the `cacheOptions` key is passed to `backfill`. For the complete documentation of `cacheOptions`, see the [`backfill` configuration documentation](https://github.com/microsoft/backfill#configuration)
|
|
@ -1,226 +0,0 @@
|
|||
---
|
||||
title: CLI usage
|
||||
---
|
||||
|
||||
# CLI usage
|
||||
|
||||
`lage` is meant to be run as a CLI. After installing `lage` inside the repository or globally, you can run the npm scripts from your repository like this:
|
||||
|
||||
```
|
||||
$ lage build
|
||||
```
|
||||
|
||||
## Caching
|
||||
|
||||
`lage` by default will skip tasks that it has already done recently. As long as the source file and the command called to `lage` has not changed, those packages will be skipped. Sometimes, this incremental behavior is not desired. You can override the caching behavior by using the `no-cache` argument.
|
||||
|
||||
```
|
||||
$ lage build --no-cache
|
||||
```
|
||||
|
||||
## Verbose
|
||||
|
||||
`lage` by default will hide the output from successful tasks. If you want to see the output as they are being generated, call `lage` with the `verbose` argument.
|
||||
|
||||
```
|
||||
$ lage build --verbose
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### CliOptions
|
||||
#### cache
|
||||
_type: boolean_
|
||||
|
||||
default: true, --no-cache will skip fetching cache or saving cache
|
||||
|
||||
`lage` by default will skip tasks that it has already done recently. As long as the source file and the command called to `lage` has not changed, those packages will be skipped. Sometimes, this incremental behavior is not desired. You can override the caching behavior by using the `no-cache` argument.
|
||||
|
||||
```
|
||||
$ lage build --no-cache
|
||||
```
|
||||
|
||||
|
||||
#### command
|
||||
_type: string[]_
|
||||
|
||||
positional arguments that specify which tasks to run
|
||||
|
||||
Commands are collected as an array like this:
|
||||
|
||||
```
|
||||
lage build test bundle
|
||||
```
|
||||
|
||||
This will tell `lage` to execute all three commands against all the packages
|
||||
|
||||
|
||||
#### concurrency
|
||||
_type: number_
|
||||
|
||||
number of parallel tasks that can be run at a time
|
||||
|
||||
By default, this is the number of CPU cores detected by `os.cpus().length`,
|
||||
change to any number to achieve desired concurrency.
|
||||
|
||||
#### continue
|
||||
_type: boolean_
|
||||
|
||||
default: false
|
||||
|
||||
Setting this allows lage to keep running even if a task has failed.
|
||||
When a failure happens in `--continue` mode, it halts all other dependent targets
|
||||
but continues to build as much as possible.
|
||||
|
||||
Example: `lage build --continue`
|
||||
|
||||
#### deps
|
||||
_type: boolean_
|
||||
|
||||
default: true, --no-deps will skip dependent packages and tasks
|
||||
|
||||
This has the semantic of running tasks up to what is specified in the command line
|
||||
such as with `--scope` or `--since`
|
||||
|
||||
|
||||
#### grouped
|
||||
_type: boolean_
|
||||
|
||||
Specify whether to make the console logger to group the logs per package task
|
||||
|
||||
Example: `lage --grouped`
|
||||
|
||||
|
||||
#### ignore
|
||||
_type: string[]_
|
||||
|
||||
Ignores certain files when calculating the scope with `--since`
|
||||
|
||||
Certain files might need to be changed during the preparation of a build
|
||||
job. In that situation, `lage` can ignore those files when calculating what
|
||||
has changed with the `--since` flag.
|
||||
|
||||
#### include-dependencies
|
||||
_type: boolean_
|
||||
|
||||
Include all transitive dependencies when running a command(s).
|
||||
This is useful for situations where you want to "set up" a package that relies on other packages being set up.
|
||||
|
||||
```
|
||||
lage setup --scope my-package --include-dependencies
|
||||
# my-package and all of its dependencies will be setup
|
||||
```
|
||||
|
||||
#### node
|
||||
_type: string[]_
|
||||
|
||||
node arguments to be passed into the npm lifecycle scripts
|
||||
|
||||
For example:
|
||||
|
||||
To increase the amount of memory to use for the npm tasks
|
||||
```
|
||||
lage --node="--max_old_space_size=8192"
|
||||
```
|
||||
|
||||
|
||||
#### only
|
||||
_type: boolean_
|
||||
|
||||
only run the commands, do not consider dependent tasks
|
||||
|
||||
For example, if `test` depends on `build`, `lage` will always run `build` before `test`.
|
||||
|
||||
You can type this `lage test --only` to skip running `build` task altogether. This is much
|
||||
like what is the default of `lerna` or `rush`.
|
||||
|
||||
|
||||
#### profile
|
||||
_type: boolean_
|
||||
|
||||
Creates a flamegraph-profile JSON for Chromium-based devtool
|
||||
|
||||
Pay attention to the output summary to find the location of the JSON file.
|
||||
|
||||
|
||||
#### reporter
|
||||
_type: string_
|
||||
|
||||
Specify whether to use the JSON Reporter to create a parsable log output
|
||||
|
||||
Example: `lage --reporter json`
|
||||
|
||||
Lage also supports emitting a [dgml](https://docs.microsoft.com/en-us/visualstudio/modeling/directed-graph-markup-language-dgml-reference?view=vs-2022) file by using the `info` command followed by the targets you want to generate the graph for and specifying the dgml reporter.
|
||||
|
||||
Example: `lage info build test --reporter dgml`
|
||||
|
||||
|
||||
#### resetCache
|
||||
_type: boolean_
|
||||
|
||||
--reset-cache will skip fetching cache, but will overwrite cache
|
||||
|
||||
```
|
||||
lage --reset-cache
|
||||
```
|
||||
|
||||
Will always run the tasks, while reseting the saved cache
|
||||
|
||||
|
||||
#### scope
|
||||
_type: string[]_
|
||||
|
||||
Which specific packages to consider as in scope for the run
|
||||
|
||||
This act as the "entry point" of the package-task graph traversal. To prevent
|
||||
running tasks for dependent package, use the `--no-deps` flag in combination.
|
||||
|
||||
You can specify multiple scoped packages like this:
|
||||
|
||||
```
|
||||
lage build --scope foo --scope bar --scope baz
|
||||
```
|
||||
|
||||
|
||||
#### since
|
||||
_type: string_
|
||||
|
||||
calculate which packages are in scope based on changed packages since a mergebase
|
||||
|
||||
This uses the `git diff ${target_branch}...` mechanism to identify which packages
|
||||
have changed. There is an assumption of all the input files for a package exist
|
||||
inside their respective package folders.
|
||||
|
||||
|
||||
#### to
|
||||
_type: string[]_
|
||||
|
||||
Scopes a list of packages, and not built their dependents (consuming packages).
|
||||
This implies `--scope` and `--no-deps`.
|
||||
|
||||
Just like the `--scope` argument, you can specify multiple packages like this:
|
||||
|
||||
```
|
||||
lage build --to foo --to bar
|
||||
```
|
||||
|
||||
|
||||
#### verbose
|
||||
_type: boolean_
|
||||
|
||||
Verbose mode, turns on all logging
|
||||
|
||||
`lage` by default will hide the output from successful tasks. If you want to see the
|
||||
output as they are being generated, call `lage` with the `verbose` argument.
|
||||
|
||||
```
|
||||
$ lage build --verbose
|
||||
```
|
||||
|
||||
#### safe-exit
|
||||
|
||||
_type: boolean_
|
||||
|
||||
Runs currently executing tasks to completion before exiting.
|
||||
This prevents the risk of having orphaned child processes running after
|
||||
`lage` has exited.
|
|
@ -1,99 +0,0 @@
|
|||
---
|
||||
title: Configuration
|
||||
---
|
||||
|
||||
Configuration is provided by [Cosmiconfig](https://www.npmjs.com/package/cosmiconfig), so `lage` configuration is very flexible! We recommend the use of a `lage.config.js` because it is both concise and flexible.
|
||||
|
||||
Create a `lage.config.js` file and place all your configurations there:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
pipeline: {
|
||||
build: ["^build"],
|
||||
test: ["build"],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
### CacheOptions
|
||||
|
||||
_type: BackfillCacheOptions & { environmentGlob: string[] }_
|
||||
### ConfigOptions
|
||||
#### cache
|
||||
_type: boolean_
|
||||
|
||||
Should cache be enabled
|
||||
|
||||
#### cacheOptions
|
||||
_type: [CacheOptions](#CacheOptions)_
|
||||
|
||||
Backfill cache options
|
||||
|
||||
#### ignore
|
||||
_type: string[]_
|
||||
|
||||
Which files to ignore when calculating scopes with --since
|
||||
|
||||
#### npmClient
|
||||
_type: "npm" | "yarn" | "pnpm"_
|
||||
|
||||
Which NPM Client to use when running npm lifecycle scripts
|
||||
|
||||
#### pipeline
|
||||
_type: [Pipeline](#Pipeline)_
|
||||
|
||||
Defines the task pipeline.
|
||||
|
||||
- Use a tasks's name with no prefix to denote a package-local dependency.
|
||||
- Prefix with `^` character to denote a direct topological dependency.
|
||||
- Prefix with `^^` to denote a transitive topological dependency (This includes tasks from dependencies of dependencies).
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
{
|
||||
build: ["^build"],
|
||||
test: ["build"],
|
||||
lint: []
|
||||
|
||||
bundle: ["^^transpile"],
|
||||
transpile: []
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### priorities
|
||||
_type: [Priority](#Priority)[]_
|
||||
|
||||
Optional priority to set on tasks in a package to make the scheduler give priority to tasks on the critical path for high priority tasks
|
||||
|
||||
#### repoWideChanges
|
||||
_type: string[]_
|
||||
|
||||
disables --since flag when any of this list of files changed
|
||||
|
||||
### Pipeline
|
||||
|
||||
|
||||
### Pipelines
|
||||
|
||||
_type: Map<string, [Pipeline](#Pipeline)>_
|
||||
### Priority
|
||||
#### package
|
||||
_type: string_
|
||||
|
||||
package name, as in package.json
|
||||
|
||||
#### priority
|
||||
_type: number_
|
||||
|
||||
priority, the higher the more priority; undefined priority means lowest priority
|
||||
|
||||
#### task
|
||||
_type: string_
|
||||
|
||||
task name, as listed in the `scripts` section of package.json
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
---
|
||||
title: Getting Started
|
||||
---
|
||||
|
||||
# Getting started
|
||||
|
||||
Getting started with `lage` is quite easy! There are 2 ways to do this: automated or manual
|
||||
|
||||
## Automated
|
||||
|
||||
### 1. Invoke the `lage init` command in the monorepo root to get started:
|
||||
|
||||
```
|
||||
npx lage init
|
||||
```
|
||||
|
||||
This will let `lage` install the latest version of lage into your repo as a one of the `devDependencies` at the root level.
|
||||
|
||||
Since `lage` is compatible with all the popular workspace managers, this can be applied to a `yarn`, `pnpm`, or `rush` workspace. `lage` is an excellent
|
||||
replacement for `lerna` in handling running tasks in your repo topologically.
|
||||
|
||||
### 2. Customize `lage.config.js`
|
||||
|
||||
The `init` command will also generate a default `lage.config.js`. This will likely need to be modified. In particular, pay attention to the `pipeline`
|
||||
configuration:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
pipeline: {
|
||||
build: ["^build"],
|
||||
test: ["build"],
|
||||
lint: [],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
You may or may not have these scripts in your packages' `package.json` files. Remember the `^` character is to indicate that the task is run in
|
||||
topological order.
|
||||
|
||||
To build with the freshly installed `lage` runner, type the following:
|
||||
|
||||
```
|
||||
npm run lage build
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
yarn lage build
|
||||
```
|
||||
|
||||
## Manual - Yarn and PNPM Workspaces
|
||||
|
||||
You can manually install `lage` as well.
|
||||
|
||||
### 1. Place `lage` in the `devDependencies` at the root level:
|
||||
|
||||
```json
|
||||
{
|
||||
"devDependencies": {
|
||||
...,
|
||||
"lage": "0.16.0",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Add a `lage.config.js` file to configure the pipeline:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
pipeline: {
|
||||
build: ["^build"],
|
||||
test: ["build"],
|
||||
lint: [],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Inside your monorepo, run `yarn` or `pnpm install`
|
||||
|
||||
```
|
||||
yarn
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
pnpm install
|
||||
```
|
||||
|
||||
### 4. Run `lage` commands
|
||||
|
||||
```
|
||||
yarn lage build
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
pnpm run lage build
|
||||
```
|
|
@ -1,196 +0,0 @@
|
|||
---
|
||||
title: How does `lage` work?
|
||||
---
|
||||
|
||||
# How does `lage` work?
|
||||
|
||||
So how does `lage` make builds faster? To fully appreciate how `lage` gives you the best build performance compared to other monorepo task runners, take a look at this example. Here we have a repo with this dependency graph:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
FooCore --> BuildTool
|
||||
BarCore --> BuildTool
|
||||
FooApp1 --> FooCore
|
||||
FooApp2 --> FooCore
|
||||
BarPage --> BarCore
|
||||
```
|
||||
|
||||
## Level 1: Typical Lerna or Workspace Runners
|
||||
|
||||
First, let's take a look at the typical workspace runners. `Lerna`, `pnpm recursive`, `rush` and `wsrun` all will run one task at a time. This creates a sort of "build phase" effect where `test` scripts are not allowed to run until `build`.
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
title Level 1: Typical Lerna or Workspace Runners
|
||||
dateFormat s
|
||||
axisFormat %S
|
||||
|
||||
section Total
|
||||
|
||||
prepare: active, total_prepare, 0, 30s
|
||||
build : active, total_build, after total_prepare, 50s
|
||||
test : active, total_test, after total_build, 25s
|
||||
|
||||
section BuildTool
|
||||
|
||||
prepare: bt_prepare, 0, 10s
|
||||
build : bt_build, after total_prepare, 10s
|
||||
test : bt_test, after total_build, 6s
|
||||
|
||||
section FooCore
|
||||
|
||||
prepare: fc_prepare, after bt_prepare, 10s
|
||||
build: fc_build, after bt_build, 15s
|
||||
test: fc_test, after total_build, 25s
|
||||
|
||||
section FooApp1
|
||||
|
||||
prepare: fa1_prepare, after fc_prepare, 10s
|
||||
build: fa1_build, after fc_build, 25s
|
||||
test: fa1_test, after total_build, 15s
|
||||
|
||||
section FooApp2
|
||||
|
||||
prepare: fa2_prepare, after fc_prepare, 10s
|
||||
build: fa2_build, after fc_build, 12s
|
||||
test: fa2_test, after total_build, 8s
|
||||
|
||||
section BarCore
|
||||
|
||||
prepare: bc_prepare, after bt_prepare, 10s
|
||||
build: bc_build, after bt_build, 10s
|
||||
test: bc_test, after total_build, 16s
|
||||
|
||||
section BarPage
|
||||
|
||||
prepare: bp_prepare, after bc_prepare, 10s
|
||||
build: bp_build, after bc_build, 25s
|
||||
test: bp_test, after total_build, 12s
|
||||
```
|
||||
|
||||
## Level 2: Scoping
|
||||
|
||||
One of the first way to speeding up build jobs is to use "scoping". Usually a change only affect a subset of the graph. We can get rid of the builds of `FooCore`, `FooApp1` and `FooApp2` if the only changes are inside `BarCore`. However, we'll note that `BarPage` is still affected, resulting in this.
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
title Level 2: Scoping
|
||||
dateFormat s
|
||||
axisFormat %S
|
||||
|
||||
section Total
|
||||
Level 1: 0, 105s
|
||||
prepare: active, total_prepare, 0, 30s
|
||||
build : active, total_build, after total_prepare, 45s
|
||||
test : active, total_test, after total_build, 16s
|
||||
|
||||
|
||||
section BuildTool
|
||||
prepare: bt_prepare, 0, 10s
|
||||
build : bt_build, after total_prepare, 10s
|
||||
test : bt_test, after total_build, 6s
|
||||
|
||||
section FooCore
|
||||
skipped: 0
|
||||
|
||||
section FooApp1
|
||||
skipped: 0
|
||||
|
||||
section FooApp2
|
||||
skipped: 0
|
||||
|
||||
section BarCore *
|
||||
prepare: bc_prepare, after bt_prepare, 10s
|
||||
build: bc_build, after bt_build, 10s
|
||||
test: bc_test, after total_build, 16s
|
||||
|
||||
section BarPage
|
||||
prepare: bp_prepare, after bc_prepare, 10s
|
||||
build: bp_build, after bc_build, 25s
|
||||
test: bp_test, after total_build, 12s
|
||||
```
|
||||
|
||||
## Level 3. Caching
|
||||
|
||||
To further improve build times, we can take advantage of build caches. If we had previously built certain packages, we should be able to speed up the build with a cache. Here, the `BarCore` packages have already been built and tested, and so
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
title Level 3: Caching
|
||||
dateFormat s
|
||||
axisFormat %S
|
||||
|
||||
section Total
|
||||
Level 1: 0, 105s
|
||||
Level 2: 0, 91s
|
||||
prepare: active, total_prepare, 0, 30s
|
||||
build : active, total_build, after total_prepare, 37s
|
||||
test : active, total_test, after total_build, 12s
|
||||
|
||||
section BuildTool
|
||||
prepare: bt_prepare, 0, 10s
|
||||
build : bt_build, after total_prepare, 10s
|
||||
test : bt_test, after total_build, 6s
|
||||
|
||||
section FooCore
|
||||
skipped: 0
|
||||
|
||||
section FooApp1
|
||||
skipped: 0
|
||||
|
||||
section FooApp2
|
||||
skipped: 0
|
||||
|
||||
section BarCore
|
||||
prepare: bc_prepare, after bt_prepare, 10s
|
||||
build: crit, bc_build, after bt_build, 2s
|
||||
test: crit, bc_test, after total_build, 2s
|
||||
|
||||
section BarPage *
|
||||
prepare: bp_prepare, after bc_prepare, 10s
|
||||
build: bp_build, after bc_build, 25s
|
||||
test: bp_test, after total_build, 12s
|
||||
```
|
||||
|
||||
## Level 4. Pipelining
|
||||
|
||||
Finally, the last thing we can do to speed things up is to break down the wall between build phases from the task runner. In `lage`, we define the relationship between scripts in the `pipeline` configuration.
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
title Level 4: Pipelining
|
||||
dateFormat s
|
||||
axisFormat %S
|
||||
|
||||
section Total
|
||||
Level 1: 0, 105s
|
||||
Level 2: 0, 91s
|
||||
Level 3: 0, 79s
|
||||
prepare: active, total_prepare, 0, 30s
|
||||
build : active, total_build, 10, 45s
|
||||
test : active, total_test, 20, 47s
|
||||
|
||||
section BuildTool
|
||||
prepare: bt_prepare, 0, 10s
|
||||
build : bt_build, after bt_prepare, 10s
|
||||
test : bt_test, after bt_build, 6s
|
||||
|
||||
section FooCore
|
||||
skipped: 0
|
||||
|
||||
section FooApp1
|
||||
skipped: 0
|
||||
|
||||
section FooApp2
|
||||
skipped: 0
|
||||
|
||||
section BarCore
|
||||
prepare: bc_prepare, after bt_prepare, 10s
|
||||
build: bc_build, after bt_build, 2s
|
||||
test: bc_test, after bc_build, 2s
|
||||
|
||||
section BarPage *
|
||||
prepare: bp_prepare, after bc_prepare, 10s
|
||||
build: bp_build, after bp_prepare, 25s
|
||||
test: bp_test, after bp_build, 12s
|
||||
```
|
|
@ -1,9 +0,0 @@
|
|||
# Migration Guide
|
||||
|
||||
## v0.x.y -> v1.0.0
|
||||
|
||||
Lage is graduating to 1.0.0! We have a breaking change. Namely, the remote cache mechanism is changing. See this [PR #172](https://github.com/microsoft/lage/pull/172) for details. The behavior is [described here](./remote-cache). The behavior is changed for remote cache:
|
||||
|
||||
1. `lage` only write to a remote cache if the environment variable `LAGE_WRITE_REMOTE_CACHE` is set to true
|
||||
2. remote cache now works as a fallback; always reading & writing to the local cache first
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
---
|
||||
title: Pipeline
|
||||
---
|
||||
|
||||
# Pipelining package tasks
|
||||
|
||||
In the traditional monorepo task runners, like `lerna`, each npm lifecycle script like `build` or `test` is run topologically or in parallel individually. Depending on the graph of the packages, CPU cores are left idle wasting developer time.
|
||||
|
||||
Futhermore, the developer is expected to keep track of an **implicit** graph of the tasks. For example, the developer is expected to understand that perhaps the `test` task is only available after `build` has completed.
|
||||
|
||||
`lage` gives developers a way to specify these relationships **explicitly**. The advantage here are two fold. First, incoming new developers can look at `lage.config.js` and understand how tasks are related. Second, `lage` can use this explicit declaration to perform an optimized build based on the abundant availability of multi-core processors.
|
||||
|
||||
## Defining a pipeline
|
||||
|
||||
To define the task dependency graph, use the `pipeline` key in the `lage.config.js`. For example, this is the default generated configuration when you run `npx lage init`:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
pipeline: {
|
||||
build: ["^build"],
|
||||
test: ["build"],
|
||||
lint: [],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Task dependency format
|
||||
|
||||
What you are declaring here in the `pipeline` object of the configuration is a dependency graph of tasks. The `test` task above depends on the `build` task of the same package. The dependencies of `test` is an array, so it actually can depend on multiple tasks. This may be more relevant in a more complex monorepo.
|
||||
|
||||
### Topological dependency
|
||||
|
||||
The `^` symbol explicitly declares that the task has a package-topological dependency on another task. For example, if `foo` package depends on `bar`, `lage build` will guarantee that the `build` task of `bar` will happen before `foo`'s `build` task.
|
||||
|
||||
### Empty dependency list
|
||||
|
||||
The `lint` task above has NO dependencies. This means that it can start whenever it can!
|
||||
|
||||
### Tasks that are in the `pipeline` but not in SOME `package.json`
|
||||
|
||||
Sometimes tasks declared in the `pipeline` are not present in all packages' `package.json` files. `lage` will automatically ignore those. No problem!
|
||||
|
||||
### Pipeline tasks are the only ones that `lage` knows about
|
||||
|
||||
`lage` will only account for tasks declared in the `pipeline` configuration. If it's not listed there, `lage` will not know how to run them.
|
||||
|
||||
### Specific package tasks
|
||||
|
||||
Sometimes it becomes necessary to manually place a package-task dependency on another package-task. This can occur especially in repos that are just coming off of a lerna or rush repository where the tasks are traditionally run in separate phases. Sometimes assumptions were made those repositories that are not expressable in the simple task pipeline configuration as seen above. For thoes cases, simply place those alongside with the rest of the pipeline configuration like this:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
pipeline: {
|
||||
build: ["^build"],
|
||||
test: ["build"],
|
||||
lint: [],
|
||||
"foo#build": ["bar#test"],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
In this example, we illustrate a `build` script of `foo` package depends on the `test` script of `bar`. The syntax is `[package]#[task]`.
|
||||
|
||||
This seems like it goes against the `test: ["build"]`, but it does not. Since `test` scripts does not have a topological dependency, it theoretically can get triggered anytime its own package's `build` script has finished! The general guidance is to get rid of these specific package-task to package-task dependency in the pipeline as quickly as possible so the builds can be optimized better.
|
|
@ -1,26 +0,0 @@
|
|||
---
|
||||
title: Priorities
|
||||
---
|
||||
|
||||
# Priorities
|
||||
|
||||
As your repo gets more and more complex, you'll need to do some some [profiling](./profile) to understand bottlenecks. Sometimes, the package tasks are not queued in the order that will produce the most optimized run times.
|
||||
|
||||
To manually pick a package task to be higher priority, simply place a [`priorities` configuration](./Config) in the `lage.config.js`:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
pipeline: { ... },
|
||||
priorities: [
|
||||
{
|
||||
package: 'foo',
|
||||
task: 'test',
|
||||
priority: 100
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The higher the priority number, the higher the priority. These numbers are relative with each other. Anything that is not listed in the priorities array means they are not prioritized.
|
||||
|
||||
> Note: an active research here is how to provide `lage` historical data to automatically prioritize in subsequent runs. PR's are welcome!
|
|
@ -1,25 +0,0 @@
|
|||
---
|
||||
title: Profiling `lage`
|
||||
---
|
||||
|
||||
# Profiling `lage`
|
||||
|
||||
A particularly complex monorepo can present opporunities for optimization. For example, when there are really large packages, it might be more efficient to break those up so the build can be split across different CPU cores. `lage` greatly enhances the ability for developers to see where the bottlenecks are.
|
||||
|
||||
To collect a profile of the `lage` run, simply run `lage` with the same arguments while adding the `--profile` argument.
|
||||
|
||||
```
|
||||
lage build test --profile
|
||||
```
|
||||
|
||||
## Using the profile
|
||||
|
||||
When the run is finished, a profile JSON file is produced. This file is to be imported into a Chromium-based browser's devtools Performance tab.
|
||||
|
||||
![import](../images/import.png)
|
||||
|
||||
## Sample of `lage` profile session
|
||||
|
||||
For example, you can see the following `lage` run of the [Fluent UI](https://developer.microsoft.com/en-us/fluentui/#/components) repo. You can see that there is a dip in the concurrency when building the `office-ui-fabric-react` package. This makes sense, because many internal packages depends on that one large package.
|
||||
|
||||
![sample-profile](../images/sample-profile.png)
|
|
@ -1,85 +0,0 @@
|
|||
# Remote Cache
|
||||
|
||||
As your repo grows in size and complexity, the build takes longer and longer even locally. `lage` elegantly provides an incremental build capability given a locally available cache. When we pair the caching capability of `lage` with a cloud storage provider, we can speed up local builds with remote cache made available by Continuous Integration, or CI, jobs.
|
||||
|
||||
The theory is that when the CI job runs, it'll produce a "last known good" cache to be uploaded in a cloud storage, like Azure Blob Storage. The remote cache has been made available both for build-over-build speed ups in future CI jobs, as well as the local first build scenario.
|
||||
|
||||
`lage` has a "fallback cache" mechansim. `lage` will look for cache in layers: first on disk, then on remote server. `lage` will fill the local cache with the remote one if there is a remote cache hit. Next, `lage` will save the locally built cache into the remote cache if the environment variable `LAGE_WRITE_REMOTE_CACHE` is set _and_ if the cache is not configured to use a local provider.
|
||||
|
||||
# Setting up remote cache - Azure Blob Storage
|
||||
|
||||
Follow these steps to set up a remote cache
|
||||
|
||||
## 1. Make sure to upgrade to latest `lage` (v1.0.0+)
|
||||
|
||||
See [migration guide](./migration)
|
||||
|
||||
```
|
||||
$ yarn upgrade lage
|
||||
```
|
||||
|
||||
## 2. Add `dotenv` as a dependency (for convenience, locally)
|
||||
|
||||
```
|
||||
$ yarn add -D dotenv
|
||||
```
|
||||
|
||||
## 3. Add `.env` in your `.gitignore` to make sure not to check those environment variables in
|
||||
|
||||
```
|
||||
$ touch .env
|
||||
```
|
||||
|
||||
```
|
||||
# .gitignore
|
||||
|
||||
.env
|
||||
node_modules
|
||||
lib
|
||||
dist
|
||||
```
|
||||
|
||||
## 4. Generate auth tokens from Azure storage account:
|
||||
|
||||
Prerequisite is to have a working Storage Account with Blob Storage Container created. Note that container name, it'll be needed for Step 5.
|
||||
|
||||
1. Select the following for a **read-only** connection string:
|
||||
![remote-cache-readonly](../images/remote-cache-readonly.png)
|
||||
2. Set the start & expiry time to something appropriate
|
||||
3. Click "Generate SAS and connection string" button
|
||||
4. Save the "connection string" - this is your **read-only** connection string
|
||||
5. Click on "Access Keys" tab on the left
|
||||
6. Click "show keys"
|
||||
7. Save the "connection string" - this is your **read-write** connection string (alternatively, you can create a read-write SAS connection string)
|
||||
|
||||
## 5. Modify the `.env` file with the remote cache connection information
|
||||
|
||||
```
|
||||
# .env file contents
|
||||
|
||||
## This is required as of right now
|
||||
BACKFILL_CACHE_PROVIDER="azure-blob"
|
||||
|
||||
## READ-ONLY SAS
|
||||
BACKFILL_CACHE_PROVIDER_OPTIONS={"connectionString":"the **read-only** connection string","container":"CONTAINER NAME"}
|
||||
```
|
||||
|
||||
## 6. Create a "secret" in the CI system for a Read/Write token
|
||||
|
||||
Here's an example snippet of Github Action with the correct environment variable set:
|
||||
|
||||
```yaml
|
||||
- run: yarn lage build test --verbose
|
||||
env:
|
||||
BACKFILL_CACHE_PROVIDER: azure-blob
|
||||
BACKFILL_CACHE_PROVIDER_OPTIONS: ${{ secrets.BACKFILL_CACHE_PROVIDER_OPTIONS }}
|
||||
LAGE_WRITE_REMOTE_CACHE: true
|
||||
```
|
||||
|
||||
Create a secret named "BACKFILL_CACHE_PROVIDER_OPTIONS":
|
||||
|
||||
```
|
||||
{"connectionString":"the **read-write** connection string","container":"CONTAINER NAME"}
|
||||
```
|
||||
|
||||
> Please note that without that `LAGE_WRITE_REMOTE_CACHE` environment variable, `lage` no longer uploads build caches to the remote server.
|
|
@ -1,27 +0,0 @@
|
|||
---
|
||||
title: Scoped builds
|
||||
---
|
||||
|
||||
# Scoped Builds
|
||||
|
||||
Scoping a task runner can speed up the process especially if there are distinct clusters of packages that are not related to each other within the repository. `lage` has a `scope` option that allows the task running to proceed up to the packages found that matches the `scope` argument. This is a string matcher based on the name of the packages (not the package path).
|
||||
|
||||
> It is important to note that depedendents and dependencies refer to the package & task.
|
||||
|
||||
## Scoped builds with all its dependents
|
||||
|
||||
By default, it is helpful to be able to run tasks on all affected packages within a scope. Packages that changed will affect downstream consumers. In this case, pass along the `scope` to build all the dependencies as well.
|
||||
|
||||
> Note: you can use wild card character: `*`. This is particularly helpful when packages are named by group or by scope.
|
||||
|
||||
```
|
||||
$ lage build --scope *build-tools*
|
||||
```
|
||||
|
||||
## Scoped builds with no dependent & their dependencies
|
||||
|
||||
Sometimes we want to run the tasks needed to satisfy the `build` script of all the packages that has the `build-tools` string in their names. Think of this as running tasks up and including the package matched in the scope. Simply add a `--no-deps` flag to run up to a package task.
|
||||
|
||||
```
|
||||
$ lage build --scope *build-tools* --no-deps
|
||||
```
|
Двоичные данные
docs-old/images/import.png
Двоичные данные
docs-old/images/import.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 60 KiB |
Двоичные данные
docs-old/images/remote-cache-readonly.png
Двоичные данные
docs-old/images/remote-cache-readonly.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 61 KiB |
Двоичные данные
docs-old/images/sample-profile.png
Двоичные данные
docs-old/images/sample-profile.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 176 KiB |
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "test-website",
|
||||
"name": "@lage/docs",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
|
8189
docs/yarn.lock
8189
docs/yarn.lock
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,12 @@
|
|||
// @ts-check
|
||||
|
||||
/** @type {import("lage").ConfigOptions} */
|
||||
module.exports = {
|
||||
pipeline: {
|
||||
"build": ["^build"],
|
||||
"test": [],
|
||||
"lint": [],
|
||||
"start": []
|
||||
},
|
||||
npmClient: "yarn"
|
||||
}
|
77
package.json
77
package.json
|
@ -1,77 +1,26 @@
|
|||
{
|
||||
"name": "lage",
|
||||
"version": "1.5.1",
|
||||
"description": "A monorepo task runner",
|
||||
"repository": {
|
||||
"url": "https://github.com/microsoft/lage"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"bin": {
|
||||
"lage": "bin/lage.js"
|
||||
"private": true,
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"packages/*",
|
||||
"docs"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"build": "lage build --scope=!@lage/docs --scope lage --verbose",
|
||||
"change": "beachball change",
|
||||
"checkchange": "beachball check",
|
||||
"decks:build": "marp -I decks --pdf -o docs/.vuepress/dist/decks",
|
||||
"docs": "vuepress dev docs --host localhost",
|
||||
"docs:build": "vuepress build docs",
|
||||
"gen-typedoc": "ts-node --transpile-only scripts/gen-typedoc.ts",
|
||||
"gh-pages": "gh-pages",
|
||||
"release": "beachball publish -y --tag unstable",
|
||||
"release:docs": "yarn gen-typedoc && yarn docs:build && yarn decks:build && yarn gh-pages -d docs/.vuepress/dist --dotfiles",
|
||||
"start": "tsc -w --preserveWatchOutput",
|
||||
"test": "jest"
|
||||
},
|
||||
"resolutions": {
|
||||
"mermaid": "8.6.4",
|
||||
"watchpack": "1.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": "^0.8.0",
|
||||
"abort-controller": "^3.0.0",
|
||||
"backfill": "^6.1.13",
|
||||
"backfill-cache": "^5.3.0",
|
||||
"backfill-config": "^6.2.0",
|
||||
"backfill-logger": "^5.1.3",
|
||||
"bullmq": "^1.50.2",
|
||||
"chalk": "^4.0.0",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"execa": "^4.0.3",
|
||||
"fast-glob": "^3.2.2",
|
||||
"git-url-parse": "^11.1.2",
|
||||
"ioredis": "^4.28.0",
|
||||
"npmlog": "^4.1.2",
|
||||
"p-graph": "^1.1.1",
|
||||
"p-limit": "^3.1.0",
|
||||
"p-profiler": "^0.2.1",
|
||||
"workspace-tools": "^0.18.2",
|
||||
"yargs-parser": "^18.1.3"
|
||||
"start": "lage start --scope=!@lage/docs --scope lage --verbose",
|
||||
"test": "lage test --scope !@lage/docs --scope lage --verbose",
|
||||
"docs": "yarn workspace @lage/docs start",
|
||||
"docs:build": "yarn workspace @lage/docs build",
|
||||
"gh-pages": "gh-pages"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@marp-team/marp-cli": "^0.20.0",
|
||||
"@types/chalk": "^2.2.0",
|
||||
"@types/cosmiconfig": "^6.0.0",
|
||||
"@types/execa": "^2.0.0",
|
||||
"@types/git-url-parse": "^9.0.0",
|
||||
"@types/ioredis": "^4.27.7",
|
||||
"@types/jest": "^27.0.1",
|
||||
"@types/node": "^12.0.0",
|
||||
"@types/npmlog": "^4.1.2",
|
||||
"@types/p-queue": "^3.2.1",
|
||||
"@types/yargs-parser": "^15.0.0",
|
||||
"beachball": "^2.16.0",
|
||||
"gh-pages": "^2.2.0",
|
||||
"jest": "^27.2.0",
|
||||
"renovate": "^23.42.2",
|
||||
"ts-jest": "^27.0.5",
|
||||
"ts-node": "^8.10.2",
|
||||
"typedoc": "^0.17.8",
|
||||
"typedoc-plugin-markdown": "^2.3.1",
|
||||
"typescript": "^4.4.4",
|
||||
"vuepress": "^1.5.3",
|
||||
"vuepress-plugin-mermaidjs": "^1.6.0"
|
||||
"lage-npm": "npm:lage@^1.5.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
# lage
|
||||
|
||||
This is the latest branch. All package published from this branch will be tagged as `lage@unstable`. When we have confirmed stability for v1.x branch, then we'll promote it to be stable.
|
||||
|
||||
Documentation is here: https://microsoft.github.io/lage/
|
||||
|
||||
## Overview
|
||||
|
||||
Your JS repo has gotten large enough that you have turned to using a tool to help you manage multiple packages inside a repository. That's great! However, you realized quickly that the tasks defined inside the workspace have to be run in package dependency order.
|
||||
|
||||
Lerna, Rush, wsrun and even pnpm will provide a simple way for you to run npm scripts to be run in a topological order. However, these tools will force you to run your tasks by script name one at a time. For example, all the `build` scripts will have to run first. Then all the `test` scripts run in the topological order.
|
||||
|
||||
This usually means that there are wasted CPU cycles in between `build` and `test`. We can achieve better pipelining the npm scripts if we had a way to say that `test` can run as soon as `build` are done for the package.
|
||||
|
||||
`lage` (Norwegian for "make", pronounced law-geh) solves this by providing a terse pipelining syntax. It has many features geared towards speeding up the task runner that we'll explore later.
|
||||
|
||||
## Quick Start
|
||||
|
||||
`lage` gives you this capability with very little configuration. First, let's install the `lage` utility. You can place this in your workspace's root `package.json` by running `yarn add`:
|
||||
|
||||
```
|
||||
yarn add -D lage
|
||||
```
|
||||
|
||||
Confirm with `yarn` that you are sure to add a package at the root level, you then place a root level script inside the `package.json` to run `lage`:
|
||||
|
||||
```
|
||||
{
|
||||
"scripts": {
|
||||
"build": "lage build",
|
||||
"test": "lage test"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Add a configuration file in the root to get started. Create this file at the root `lage.config.js`:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
pipeline: {
|
||||
build: ["^build"],
|
||||
test: ["build"],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Do not worry about the syntax for now. We will go over the configuration file in a coming section. You can now run this command:
|
||||
|
||||
```
|
||||
$ lage test
|
||||
```
|
||||
|
||||
`lage` will detect that you need to run `build` steps before `test`s are run.
|
||||
|
||||
|
||||
|
||||
# Contributing
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
||||
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
||||
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
|
||||
|
||||
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
|
||||
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
|
||||
provided by the bot. You will only need to do this once across all repos using our CLA.
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
||||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"name": "lage",
|
||||
"version": "1.5.1",
|
||||
"description": "A monorepo task runner",
|
||||
"repository": {
|
||||
"url": "https://github.com/microsoft/lage"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"bin": {
|
||||
"lage": "bin/lage.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"change": "beachball change",
|
||||
"checkchange": "beachball check",
|
||||
"decks:build": "marp -I decks --pdf -o docs/.vuepress/dist/decks",
|
||||
"docs": "vuepress dev docs --host localhost",
|
||||
"docs:build": "vuepress build docs",
|
||||
"gen-typedoc": "ts-node --transpile-only scripts/gen-typedoc.ts",
|
||||
"gh-pages": "gh-pages",
|
||||
"release": "beachball publish -y --tag unstable",
|
||||
"release:docs": "yarn gen-typedoc && yarn docs:build && yarn decks:build && yarn gh-pages -d docs/.vuepress/dist --dotfiles",
|
||||
"start": "tsc -w --preserveWatchOutput",
|
||||
"test": "jest"
|
||||
},
|
||||
"resolutions": {
|
||||
"mermaid": "8.6.4",
|
||||
"watchpack": "1.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": "^0.8.0",
|
||||
"abort-controller": "^3.0.0",
|
||||
"backfill": "^6.1.13",
|
||||
"backfill-cache": "^5.3.0",
|
||||
"backfill-config": "^6.2.0",
|
||||
"backfill-logger": "^5.1.3",
|
||||
"bullmq": "^1.50.2",
|
||||
"chalk": "^4.0.0",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"execa": "^4.0.3",
|
||||
"fast-glob": "^3.2.2",
|
||||
"git-url-parse": "^11.1.2",
|
||||
"ioredis": "^4.28.0",
|
||||
"npmlog": "^4.1.2",
|
||||
"p-graph": "^1.1.1",
|
||||
"p-limit": "^3.1.0",
|
||||
"p-profiler": "^0.2.1",
|
||||
"workspace-tools": "^0.18.2",
|
||||
"yargs-parser": "^18.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@marp-team/marp-cli": "^0.20.0",
|
||||
"@types/chalk": "^2.2.0",
|
||||
"@types/cosmiconfig": "^6.0.0",
|
||||
"@types/execa": "^2.0.0",
|
||||
"@types/git-url-parse": "^9.0.0",
|
||||
"@types/ioredis": "^4.27.7",
|
||||
"@types/jest": "^27.0.1",
|
||||
"@types/node": "^12.0.0",
|
||||
"@types/npmlog": "^4.1.2",
|
||||
"@types/p-queue": "^3.2.1",
|
||||
"@types/yargs-parser": "^15.0.0",
|
||||
"beachball": "^2.16.0",
|
||||
"gh-pages": "^2.2.0",
|
||||
"jest": "^27.2.0",
|
||||
"ts-jest": "^27.0.5",
|
||||
"ts-node": "^8.10.2",
|
||||
"typescript": "^4.4.4"
|
||||
}
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче