From 76d4c2d2e0380826eb4f043ca9d983a156f5194d Mon Sep 17 00:00:00 2001 From: Elizabeth Craig Date: Sat, 24 Jan 2026 01:41:37 -0800 Subject: [PATCH] Doc updates --- ...-3149882c-234c-4f98-acf7-65bab0d9b84c.json | 11 ++ ...-593b47e4-a1fd-4e48-b20d-f4f4c4e8b407.json | 39 ++++ docs/docs/guides/pipeline.md | 181 +++++++++++++++--- docs/docs/guides/priority.md | 10 +- docs/docs/reference/cli.md | 116 +++++++---- docs/docs/reference/config.md | 18 +- packages/cache/README.md | 29 +-- packages/cli/src/commands/options.ts | 10 +- packages/cli/src/commands/run/index.ts | 8 +- packages/config/CHANGELOG.md | 5 + packages/config/src/types/ConfigOptions.ts | 26 ++- packages/globby/README.md | 1 + packages/lage/CHANGELOG.md | 4 + packages/runners/src/WorkerRunner.ts | 6 +- packages/target-graph/src/types/Target.ts | 16 +- 15 files changed, 362 insertions(+), 118 deletions(-) create mode 100644 change/change-3149882c-234c-4f98-acf7-65bab0d9b84c.json create mode 100644 change/change-593b47e4-a1fd-4e48-b20d-f4f4c4e8b407.json create mode 100644 packages/globby/README.md diff --git a/change/change-3149882c-234c-4f98-acf7-65bab0d9b84c.json b/change/change-3149882c-234c-4f98-acf7-65bab0d9b84c.json new file mode 100644 index 000000000..5037e5b36 --- /dev/null +++ b/change/change-3149882c-234c-4f98-acf7-65bab0d9b84c.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "type": "patch", + "comment": "Update docs", + "packageName": "@lage-run/cache", + "email": "elcraig@microsoft.com", + "dependentChangeType": "patch" + } + ] +} \ No newline at end of file diff --git a/change/change-593b47e4-a1fd-4e48-b20d-f4f4c4e8b407.json b/change/change-593b47e4-a1fd-4e48-b20d-f4f4c4e8b407.json new file mode 100644 index 000000000..f4938e5ee --- /dev/null +++ b/change/change-593b47e4-a1fd-4e48-b20d-f4f4c4e8b407.json @@ -0,0 +1,39 @@ +{ + "changes": [ + { + "type": "patch", + "comment": "Update docs", + "packageName": "@lage-run/cli", + "email": "elcraig@microsoft.com", + "dependentChangeType": "patch" + }, + { + "type": "patch", + "comment": "Update docs", + "packageName": "@lage-run/config", + "email": "elcraig@microsoft.com", + "dependentChangeType": "patch" + }, + { + "type": "patch", + "comment": "Update docs", + "packageName": "@lage-run/globby", + "email": "elcraig@microsoft.com", + "dependentChangeType": "patch" + }, + { + "type": "patch", + "comment": "Update docs", + "packageName": "@lage-run/runners", + "email": "elcraig@microsoft.com", + "dependentChangeType": "patch" + }, + { + "type": "patch", + "comment": "Update docs", + "packageName": "@lage-run/target-graph", + "email": "elcraig@microsoft.com", + "dependentChangeType": "patch" + } + ] +} \ No newline at end of file diff --git a/docs/docs/guides/pipeline.md b/docs/docs/guides/pipeline.md index b376101aa..6d972a1c9 100644 --- a/docs/docs/guides/pipeline.md +++ b/docs/docs/guides/pipeline.md @@ -8,18 +8,18 @@ In this step, you'll learn about how to influence how `lage` schedules which "ta ## What is a `lage` pipeline? -In the traditional monorepo task runners, 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. +In the traditional monorepo task runners, 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 twofold: +`lage` gives developers a way to specify these relationships **explicitly**. The advantage here is twofold: -- Incoming new developers can look at `lage.config.js` and understand how tasks are related. - `lage` can use this explicit declaration to perform an optimized build based on the abundant availability of multi-core processors. +- Incoming developers can look at `lage.config.js` and understand how tasks are related. ## 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`: +To define the task dependency graph, use the `pipeline` key in `lage.config.js`. For example, this is the default generated configuration when you run `npx lage init`: ```js title="/lage.config.js" module.exports = { @@ -31,54 +31,177 @@ module.exports = { }; ``` -### Task dependency format +Each key is a **task name**, and each value is an array of **task dependencies** (or an [advanced configuration](#advanced-pipeline-configuration) object). -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. A task can depend on multiple other tasks. This may be more relevant in a more complex monorepo. +Usually, a task name corresponds to a `scripts` entry in package-level `package.json` files: e.g. `build`, `test`, `lint`. If the script name doesn't exist for a particular package, it's skipped. (There are also [advanced task types](#advanced-task-types).) -### Topological dependency +A task can depend on zero or more other tasks. The special characters `^`, `^^`, and `#` are used to indicate dependency types (see below for details). -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 + +A task with no dependencies will start whenever a worker is available. Unless a [priority](./priority) is specified, there's no guarantee of ordering by package or relative to other tasks. -```json -{ - "pipeline": { - "build": ["^build"] +```js +module.exports = { + pipeline: { + lint: [] } -} +}; ``` -### Empty dependency list +### Same-package dependency + +A dependency name with **no special characters** means depend on this task from the _same package_ only. There's no direct guarantee about the ordering of packages. + +In the example below, `lage test` will ensure each package's `build` task completes before running its `test` task. (Since `build` has no dependencies in this example, each package's `build`+`test` sequence could run in any order relative to the other packages.) + +```js +module.exports = { + pipeline: { + build: [], + test: ["build"] + } +}; +``` + +### `^` Direct topological dependency -The `lint` task above has NO dependencies. This means that it can start whenever it can! +`^task` means the task has a package-topological dependency: it must run in topological order based on the package dependency graph. -```json -{ - "pipeline": { - "lint": [] +For the example below, suppose package `foo` depends on package `bar`. `lage build` guarantees that `bar`'s `build` task will complete before `foo`'s `build` task starts. + +```js +module.exports = { + pipeline: { + build: ["^build"] + } +}; +``` + +### `^^` Transitive topological dependency + +`^^task` means the task must be run in topological order for all nested dependencies of the current package. + +Note that the task will **NOT** be run for the current package unless you also include that variant in the dependencies list: e.g. `["^^task", "task"]`. + +In the example below, suppose package `foo` depends on `bar` which depends on `baz`, and _only_ `foo` has a `bundle` task. `lage bundle` will run the following: + +1. `baz`'s `transpile` task +2. `bar`'s `transpile` task +3. `foo`'s `bundle` task (but NOT its `transpile` task if present) + +```js +module.exports = { + pipeline: { + bundle: ["^^transpile"], + transpile: [] } -} +}; ``` -### Tasks that are in the `pipeline` but not in SOME `package.json` +To run `foo`'s `transpile` task, the configuration would need to be updated with `bundle: ["^^transpile", "transpile"]`. -Sometimes tasks declared in the `pipeline` are not present in all packages' `package.json` files. `lage` will automatically ignore those. No problem! +If `bar` or `baz` also had a `bundle` task, note that the configuration above provides no guarantee of `bundle` task ordering. If that order _did_ matter, you'd need to use `bundle: ["^bundle", "^^transpile"]`. ### Specific package tasks Sometimes a specific package may depend on a task from another specific package. This can occur especially in repos that are just coming off of lerna or rush where the tasks are traditionally run in separate phases. Sometimes assumptions were made that cannot be expressed in the simple task pipeline configuration as seen above. These dependencies can be specified in the pipeline config as follows. -In this example, we illustrate a `build` script of `foo` package depends on the `test` script of `bar`. The syntax is `[package]#[task]`. +In this example, a `build` script of `foo` package depends on the `test` script of `bar`. The syntax is `package#task`. -```json -// foo build depends on the output of bar build. -{ - "pipeline": { - "test": ["build"], +```js +module.exports = { + pipeline: { + test: ["build"], + // foo build depends on the output of bar test "foo#build": ["bar#test"] } -} +}; ``` This seems like it goes against `test: ["build"]`, but it does not. Since `test` scripts does not have a topological dependency, they can theoretically be triggered whenever that package's `build` script has finished! The general guidance is to get rid of these specific package-task to package-task dependencies in the pipeline as quickly as possible so the builds can be optimized better. + +## Advanced pipeline configuration + +Optionally, you can use an object for advanced pipeline task target configuration, such as priority, weight, inputs and outputs for caching, worker count limits, custom conditions, and custom worker configuration. + +See the [`TargetConfig` source](https://github.com/microsoft/lage/blob/master/packages/target-graph/src/types/TargetConfig.ts) for full details. There are also some examples in [lage's own config](https://github.com/microsoft/lage/blob/master/lage.config.js). + +```js +/** @type {import("lage").ConfigOptions} */ +const config = { + pipeline: { + build: { + type: "npmScript", // this is the default + dependsOn: ["^build"], // replaces the dependency array syntax + priority: 1, + weight: 10, + outputs: ["dist/**", "lib/**"], + inputs: ["src/**", "package.json", "tsconfig.json"] + } + } +}; +module.exports = config; +``` + +## Advanced task types + +For most tasks, the default type of `"npmScript"` is sufficient. However, there are some other types available. There are also options for each type. + +### npm script tasks + +By default, tasks have `type: "npmScript"`, meaning they correspond to a script in `package.json` for at least one package. + +Usually, the only reason you'd need to explicitly specify this type is + +```js +/** @type {import("lage").ConfigOptions} */ +const config = { + pipeline: { + // "transpile" is a worker task for most packages + transpile: { + type: "worker" + // ... see below for an example of worker options + }, + // For package foo, change "transpile" back to a normal npmScript task + "foo#transpile": { + type: "npmScript" + }, + // For package bar, run a different npm script instead of "transpile" + "bar#transpile": { + type: "npmScript", + options: { + script: "build" + } + } + } +}; +module.exports = config; +``` + +### No-op tasks + +A task can be configured with `type: "noop"` to indicate that it does not correspond to any actual script in the package's `package.json` file. This is useful for grouping other tasks together, or is one way to disable a task for a specific package. + +This example (modified from lage's own configuration) defines a `build` "meta-task" that depends the `transpile` and `types` tasks which correspond , but does not correspond to any actual script in the packages. + +```js +/** @type {import("lage").ConfigOptions} */ +const config = { + pipeline: { + transpile: [], + types: ["^types"], + build: { + type: "noop", + dependsOn: ["transpile", "types"] + } + } +}; +module.exports = config; +``` + +### Worker tasks + +There are also some examples in the [cookbook section](../cookbook/make-jest-fast) and [lage's own config](https://github.com/microsoft/lage/blob/master/lage.config.js). diff --git a/docs/docs/guides/priority.md b/docs/docs/guides/priority.md index da91be713..e03d92e9e 100644 --- a/docs/docs/guides/priority.md +++ b/docs/docs/guides/priority.md @@ -6,7 +6,9 @@ title: Priorities In a large monorepo, you'll need to do some [profiling](./profile.md) to understand bottlenecks. Sometimes, the package tasks are not scheduled in the order that will produce the most optimized run times. -## v2 styled configuration for priority +Lage provides the following options to customize the task priority. The higher the priority number, the higher the priority. These numbers are relative to each other. Any task that is not listed in the priorities array is not prioritized. + +## Configuration As of `lage` v2, you can now configure the priority inside the target pipeline configuration: @@ -23,9 +25,9 @@ module.exports = { }; ``` -## Legacy (v1 + v2) way of configuring priority +## Legacy (v1 + v2) configuration -To manually pick a package task to be higher priority, simply add a [`priorities` configuration](../reference/config.md) in the `lage.config.js`: +To manually pick a package task to be higher priority, simply add a [`priorities` configuration](../reference/config.md) in `lage.config.js`: ```js module.exports = { @@ -38,5 +40,3 @@ module.exports = { ] }; ``` - -The higher the priority number, the higher the priority. These numbers are relative to each other. Any task that is not listed in the priorities array is not prioritized. diff --git a/docs/docs/reference/cli.md b/docs/docs/reference/cli.md index 7a99d599e..e48c41924 100644 --- a/docs/docs/reference/cli.md +++ b/docs/docs/reference/cli.md @@ -18,24 +18,46 @@ Usage: `lage [run] [command2...commandN] [options] run commands` ### Options +**[Logging options](#logging-options)** also apply. + +#### Filtering options + +These can optionally be set with environment variables `LAGE_FILTER_*` (e.g. `LAGE_FILTER_SCOPE`). + +``` +--scope scopes the run to a subset of packages (by default, includes the dependencies and dependents as well) +--no-deps|--no-dependents disables running any dependents of the scoped packages (env: LAGE_FILTER_NO_DEPS) +--include-dependencies adds the scoped packages dependencies as the "entry points" for the target graph run + |--dependencies (env: LAGE_FILTER_INCLUDE_DEPENDENCIES) +--to runs up to a package (shorthand for --scope= --no-dependents) +--since only runs packages that have changed since the given commit, tag, or branch +--ignore ignores files when calculating the scope with `--since` in addition to the files specified in lage.config.js +--grouped groups the logs (default: false) +``` + +#### Worker options + +These can optionally be set with environment variables `LAGE_POOL_*` (e.g. `LAGE_POOL_CONCURRENCY`). + +``` +-c|--concurrency max jobs to run at a time +--max-workers-per-task set max worker per task, e.g. --max-workers-per-task build=2 test=4 +``` + +#### Other options + +These can optionally be set with environment variables `LAGE_RUN_*` (e.g. `LAGE_RUN_NODE_ARG`). + ``` - --reporter reporter (default: "npmLog") - --log-level log level (choices: "info", "warn", "error", "verbose", "silly") - --verbose verbose output - -c, --concurrency concurrency (default: os.cpus() - 1) - --scope scopes the run to a subset of packages (by default, includes the dependencies and dependents as well) - --no-dependents|--no-deps disables running any dependents of the scoped packages - --dependencies|--include-dependencies adds the scoped packages dependencies as the "entry points" for the target graph run - --since only runs packages that have changed since the given commit, tag, or branch - --to runs up to a package (shorthand for --scope= --no-dependents) - --grouped groups the logs (default: false) - --no-cache disables the cache - --reset-cache resets the cache, filling it after a run - --skip-local-cache skips caching locally - --profile [profile] writes a run profile into a file that can be processed by Chromium devtool - --nodearg arguments to be passed to node (e.g. --nodearg="--max_old_space_size=1234 --heap-prof" - set via "NODE_OPTIONS" environment variable) - --continue continues the run even on error - -h, --help display help for command +-n|--node-arg node arguments for workers and child processes (like NODE_OPTIONS) as a single string + (e.g. --nodearg="--max_old_space_size=1234 --heap-prof") +--no-cache disables the cache (env: LAGE_RUN_CACHE) +--reset-cache resets the cache, filling it after a run +--skip-local-cache skips caching locally (defaults to true in CI environments) +--profile [profile] writes a run profile into a file that can be processed by Chromium devtool +--continue continues the run even on error +--allow-no-target-runs succeed even if no targets match the given name +--watch runs in watch mode ``` ### Examples @@ -62,6 +84,10 @@ Scoped to packages that have changed in the current branch against a target merg lage build test lint --since origin/master +#### Providing node.js arguments for each command + + lage build test lint --nodearg=--max_old_space_size=1234 --nodearg=--heap-prof + #### Continue running even after encountering an error for one of the targets lage build test lint --continue @@ -84,6 +110,14 @@ Choosing a different reporter while logging (e.g. nice outputs for Azure DevOps) lage build test lint --reporter=azureDevops +Or combine multiple reporters (e.g. Azure DepOps with VerboseFileLog) + + lage build test lint --reporter azureDevops --reporter vfl --log-file /my/verbose/log.file + +Ignoring files when calculating the scope with --since in addition to files specified in lage.config: + + lage build test lint --since origin/master --ignore "package.json" "yarn.lock" "**/.azure-pipelines/**" + --- ## Cache Command @@ -96,13 +130,11 @@ lage build --no-cache ### Options +[Logging options](#logging-options) also apply. + ``` - --reporter reporter (default: "npmLog") - --log-level log level (choices: "info", "warn", "error", "verbose", "silly") - --verbose verbose output - --prune Prunes cache older than certain number of - --clear Clears the cache locally - -h, --help display help for command +--prune Prunes cache older than certain number of +--clear Clears the cache locally ``` ### Examples @@ -121,39 +153,51 @@ lage cache --clear --- -## Global Options +## Common options -These are options that apply to all commands. +### Logging options -### Verbosity, Log Levels, and Grouping +Logging options apply to most commands, and can optionally be set with environment variables `LAGE_LOGGER_*` (e.g. `LAGE_LOGGER_REPORTER`). -`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. +``` +--reporter reporter (choices: "default", "json", "azureDevops", "npmLog", "verboseFileLog", "vfl") +--log-level log level (choices: "info", "warn", "error", "verbose", "silly") +--log-file when used with --reporter vfl, writes verbose, ungrouped logs to the specified file +--progress show progress (default: true locally, false in CI) +--verbose verbose output (default: false) +--grouped groups the logs by package+task (default: false) +--indented enabled indentation of the JSON output (default: false) +``` + +#### Verbosity + +`lage` by default will hide the output from successful tasks. If you want to see all output as it's generated, use `--verbose`: ``` lage build --verbose ``` -#### Log Levels - -You can control the log level instead of using "--verbose" argument. You can display `warn` messages and above (`error`) in the following example: +You can also control the log level more specifically with `--log-level `. This example will show `warn` messages and above (`error`): ``` lage build --log-level warn ``` -Valid values here are `silly`, `verbose`, `info`, `warn`, `error`. If `error` is passed to `--log-level`, you'll receive the least amount of information. The default is `info`. +Valid values are `silly`, `verbose`, `info`, `warn`, `error`. If `error` is passed to `--log-level`, you'll receive the least amount of information. The default is `info`. + +#### Grouping -#### Grouped logs +By default, `lage` will interweave all the `stdout` and `stderr` from all active targets as they are running. -`lage` will interweave all the `stdout` and `stderr` from all active targets as they are running. This may become a mess, so `lage` can group output messages together. These messages will only be displayed when the target is completed: +Use the `--grouped` This may become a mess, so `lage` can group output messages together. These messages will only be displayed when the target is completed: ``` lage build --verbose --grouped ``` -### Reporter +#### Reporter -`lage` comes with various kinds of reporters. Reporters take the logged messages of the target runs, format them, and display them. The default one can group messages, and there are ones that would work well with various Continuous Integration systems like Azure DevOps. +`lage` comes with various reporters which take the logged messages of the target runs, format them, and display them. You can pick the reporter by passing the `--reporter` flag: @@ -163,7 +207,7 @@ lage build --reporter json Available built-in reporters are: `default`, `azureDevops`, `fancy`, `json`, `npmLog`, `verboseFileLog` (or `vfl`), and `profile`. By default the log messages are formatted with the `default` reporter. The `profile` reporter is typically activated with the `--profile` option. -#### Custom Reporters +#### Custom reporters You can also create and use your own custom reporters. Define them in your `lage.config.js`: diff --git a/docs/docs/reference/config.md b/docs/docs/reference/config.md index 5b02367c8..75f1e4e66 100644 --- a/docs/docs/reference/config.md +++ b/docs/docs/reference/config.md @@ -4,24 +4,30 @@ 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 at the workspace root and place all your configurations there: +Create a `lage.config.js` file at the workspace root and place all your configuration there. + +A short example: ```js title="/lage.config.js" -module.exports = { +/** @type {import("lage").ConfigOptions} */ +const config = { pipeline: { build: ["^build"], test: ["build"] } }; +module.exports = config; ``` -### A Complete Tour of the Config +### Available properties + +See the source for [`ConfigOptions`](https://github.com/microsoft/lage/blob/master/packages/config/src/types/ConfigOptions.ts) and its sibling files for the complete list of available options. -:::tip +Some options can also be set with [CLI options or environment variables](./cli). -Roll over the various properties to tour the different configs +### Example -::: +This example demonstrates many of the available options, including some advanced cases. Your config probably doesn't need to be this complicated, at least starting out. ```js twoslash title="/lage.config.js" /// diff --git a/packages/cache/README.md b/packages/cache/README.md index 4fda1b8fb..bae3d2cc7 100644 --- a/packages/cache/README.md +++ b/packages/cache/README.md @@ -2,16 +2,18 @@ This package provides: -1. `Cache` interface -2. a default cache provider that uses `backfill` +1. `CacheProvider` interface +2. a default cache provider that uses [`backfill`](https://www.npmjs.com/package/backfill) ## Usage +The following example shows standalone cache usage. If you're using the `lage` CLI, provider creation is handled internally (though you can customize `cacheOptions` in `lage.config.js`). + ```ts -import { BackfillCacheProvider, RemoteFallbackCacheProvider, TargetHasher } from "@lage-run/cache"; +import { BackfillCacheProvider, RemoteFallbackCacheProvider, TargetHasher, type CacheOptions } from "@lage-run/cache"; import { getWorkspaceManagerRoot } from "workspace-tools"; -const cacheOptions = { +const cacheOptions: CacheOptions = { internalCacheFolder: ".cache", outputGlob: ["dist/**", "lib/**"] } @@ -33,10 +35,13 @@ const remoteFallbackCacheProviderOptions = { cacheStorageOptions: { provider: "azure-blob", options: { - connectionString: "asdfasdfasdfafds"; // Providing an un-authenitcated Blob Service Endpoint will force use of Azure EnvironmentCredential + // This connection string can optionally contain credentials. + // If no credentials are present, see credentialName below. + connectionString: "asdfasdfasdfafds"; container: "container"; maxSize?: 150; - credentialName?: "environment-credential" // Default value or ignored if connectionString carries credentials + // If connectionString doesn't have credentials, specify a supported credential type + credentialName?: "environment" } }, ...cacheOptions @@ -71,16 +76,14 @@ if (target.cache && !skipCaching) { await cacheProvider.put(hash, target); ``` -## Differentiating Cache - -To specifically differentiate the hash generated for the cache, between different steps the parameter `cacheKey` can be used. The parameter will be a part of the hash generation for the cache, and generated hash can be altered by modifying the parameter. +## Differentiating cache -### Usage +`CacheOptions.cacheKey` is included in the hash and can be used to differentiate the hash generated for the cache between different steps, or to invalidate the cache. -Add the parameter in your `lage.config.js` as follows +Example of usage in `lage.config.js`: -```ts -{ +```js +module.exports = { cacheOptions: { cacheKey: "some cache key"; } diff --git a/packages/cli/src/commands/options.ts b/packages/cli/src/commands/options.ts index e693ebc85..4a13abb02 100644 --- a/packages/cli/src/commands/options.ts +++ b/packages/cli/src/commands/options.ts @@ -20,7 +20,7 @@ const options: Options = { logger: { reporter: new Option("--reporter ", `log reporter (built-in choices: ${logBuiltInReporterNames.join(", ")})`), grouped: new Option("--grouped", "groups the logs").default(false), - progress: new Option("--progress").conflicts(["reporter", "grouped", "verbose"]).default(!isCI), + progress: new Option("--progress", "show progress").conflicts(["reporter", "grouped", "verbose"]).default(!isCI), logLevel: new Option("--log-level ", "log level").choices(["info", "warn", "error", "verbose", "silly"]).conflicts("verbose"), logFile: new Option("--log-file ", "when used with --reporter vfl, writes verbose, ungrouped logs to the specified file"), verbose: new Option("--verbose", "verbose output").default(false), @@ -30,14 +30,14 @@ const options: Options = { concurrency: new Option("-c|--concurrency ", "max jobs to run at a time").argParser((v) => parseInt(v)), continue: new Option("--continue", "continue running even after encountering an error for one of the targets"), maxWorkersPerTask: new Option( - "--max-workers-per-task ", + "--max-workers-per-task ", "set max worker per task, e.g. --max-workers-per-task build=2 test=4" ).default([]), }, runner: { nodeArg: new Option( "-n|--node-arg ", - 'node arguments as a string to be passed into node like a NODE_OPTIONS setting, (e.g. --nodearg="--max_old_space_size=1234 --heap-prof")' + 'node arguments for workers and child processes (like NODE_OPTIONS) as a single string (e.g. --node-arg="--max_old_space_size=1234 --heap-prof")' ), }, run: { @@ -46,7 +46,7 @@ const options: Options = { skipLocalCache: new Option("--skip-local-cache", "skips caching locally (defaults to true in CI environments)").default(isCI), profile: new Option("--profile [profile]", "writes a run profile into a file that can be processed by Chromium devtool"), continue: new Option("--continue", "continues the run even on error"), - allowNoTargetRuns: new Option("--allow-no-target-runs"), + allowNoTargetRuns: new Option("--allow-no-target-runs", "succeed even if no targets match the given name"), watch: new Option("--watch", "runs in watch mode"), }, server: { @@ -74,7 +74,7 @@ const options: Options = { affected: { outputFormat: new Option( "--output-format ", - `Generate a report about what packages are affected by the current change (defaults to human readable format) ` + + `Generate a report about what packages are affected by the current change (defaults to human readable format). ` + `"graph" will generate a GraphViz .dot file format` ), }, diff --git a/packages/cli/src/commands/run/index.ts b/packages/cli/src/commands/run/index.ts index 1a0465145..a6b2e656c 100644 --- a/packages/cli/src/commands/run/index.ts +++ b/packages/cli/src/commands/run/index.ts @@ -21,13 +21,13 @@ Runs a set of commands in a target graph. The targets are defined by packages an Examples ======== - + ### Basic case, running "build", "test", and "lint" against all packages $ lage build test lint ### Concurrency - + $ lage build test lint --concurrency=4 ### Filtering by certain packages @@ -68,11 +68,11 @@ Show logs as grouped by each target: Choosing a different reporter while logging (e.g. nice outputs for Azure DevOps): - $ lage build test lint --reporter=azureDevOps + $ lage build test lint --reporter=azureDevops Or combine multiple reporters (e.g. Azure DepOps with VerboseFileLog) - $ lage build test lint --reporter azureDevOps --reporter vfl --log-file /my/verbose/log.file + $ lage build test lint --reporter azureDevops --reporter vfl --log-file /my/verbose/log.file Ignoring files when calculating the scope with --since in addition to files specified in lage.config: diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index b52920c41..f1f3f8abf 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -24,10 +24,15 @@ Tue, 21 Oct 2025 23:42:35 GMT Thu, 25 Sep 2025 18:00:51 GMT +**Potential breaking change**: For the `"azure-blob"` cache storage provider (`CacheOptions.cacheStorageConfig.provider` or `BACKFILL_CACHE_PROVIDER`), usage of [`DefaultAzureCredential`](https://learn.microsoft.com/en-us/azure/developer/javascript/sdk/authentication/credential-chains#use-defaultazurecredential-for-flexibility) has been removed. + +If your `connectionString` in `cacheOptions.cacheStorageConfig.options` or `BACKFILL_CACHE_PROVIDER_OPTIONS` supplies a token or your credentials are provided as [environment variables](https://learn.microsoft.com/en-us/javascript/api/%40azure/identity/environmentcredential?view=azure-node-latest), nothing changes. Otherwise, you'll need to add a `credentialName` option (one of the type names formerly handled by the default credential, e.g. `'azure-cli'`) or a full `credential` object. `credentialName` can be added to the options object (either config file or env) or specified separately via `AZURE_IDENTITY_CREDENTIAL_NAME`. More advanced scenarios (such as chaining) with a `credential` object are only supported in code. + ### Minor changes - Enhance CredentialCache to support multiple Azure credential types and allow configuration of credentialName in cache options (brunoru@microsoft.com) + ## 0.5.0 Mon, 01 Sep 2025 08:10:36 GMT diff --git a/packages/config/src/types/ConfigOptions.ts b/packages/config/src/types/ConfigOptions.ts index 31188ca3e..bd7b65f7a 100644 --- a/packages/config/src/types/ConfigOptions.ts +++ b/packages/config/src/types/ConfigOptions.ts @@ -8,18 +8,26 @@ export type NpmClient = "npm" | "yarn" | "pnpm"; export interface ConfigOptions { /** - * Defines the task pipeline, prefix with "^" character to denote a direct topological dependency, - * prefix with ^^ to denote a transitive topological dependency. + * Defines the task pipeline (task names, dependencies, and optional custom target configuration). + * + * Dependency syntax: + * - No prefix for dependencies on tasks for the same package. + * - Prefix with `^` to denote a direct package-topological dependency. (e.g. `^build` means run the `build` task + * in topological order by package.) + * - Prefix with `^^` to denote a transitive package-topological dependency. (e.g. `^^transpile` means run the `transpile` task for nested dependencies, but *not* for the current package.) + * - Use `packageName#taskName` to denote a dependency on a specific package's task: in the example below, + * package `foo`'s `build` task depends on package `bar`'s `bundle` task. * * Example: * - * ``` + * ```js * { * build: ["^build"], * test: ["build"], - * lint: [] + * lint: [], * bundle: ["^^transpile"], * transpile: [], + * "foo#build": ["bar#bundle"] * } * ``` */ @@ -28,16 +36,16 @@ export interface ConfigOptions { /** Backfill cache options */ cacheOptions: CacheOptions; - /** Which files to ignore when calculating scopes with --since */ + /** Which files to ignore when calculating scopes with `--since` */ ignore: string[]; - /** disables --since flag when any of this list of files changed */ + /** Disable the `--since` flag when any of these files changed */ repoWideChanges: string[]; /** Which NPM Client to use when running npm lifecycle scripts */ npmClient: NpmClient; - /** 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 */ + /** Optional package task priorities, to make the scheduler give higher priority to tasks on the critical path */ priorities: Priority[]; /** @@ -52,9 +60,9 @@ export interface ConfigOptions { runners: TargetRunnerPickerOptions; /** - * Maximum worker idle memory, this would cause workers to restart if they exceed this limit. This is useful to prevent memory leaks. + * Maximum worker idle memory in bytes. If exceeded, the worker will be restarted. This is useful to mitigate memory leaks. */ - workerIdleMemoryLimit: number; // in bytes + workerIdleMemoryLimit: number; /** * Maximum number of concurrent tasks to run diff --git a/packages/globby/README.md b/packages/globby/README.md new file mode 100644 index 000000000..e2c7beb25 --- /dev/null +++ b/packages/globby/README.md @@ -0,0 +1 @@ +CommonJS wrapper of [`globby`](https://www.npmjs.com/package/globby) with caching support and all dependencies bundled. diff --git a/packages/lage/CHANGELOG.md b/packages/lage/CHANGELOG.md index be7904533..adf4f7cd2 100644 --- a/packages/lage/CHANGELOG.md +++ b/packages/lage/CHANGELOG.md @@ -59,6 +59,10 @@ Fri, 10 Oct 2025 07:48:07 GMT Thu, 25 Sep 2025 18:00:51 GMT +**Potential breaking change**: For the `"azure-blob"` cache storage provider (`cacheOptions.cacheStorageConfig.provider` or `BACKFILL_CACHE_PROVIDER`), usage of [`DefaultAzureCredential`](https://learn.microsoft.com/en-us/azure/developer/javascript/sdk/authentication/credential-chains#use-defaultazurecredential-for-flexibility) has been removed. + +If your `connectionString` in `cacheOptions.cacheStorageConfig.options` or `BACKFILL_CACHE_PROVIDER_OPTIONS` supplies a token or your credentials are provided as [environment variables](https://learn.microsoft.com/en-us/javascript/api/%40azure/identity/environmentcredential?view=azure-node-latest), nothing changes. Otherwise, you'll need to add a `credentialName` option (one of the type names formerly handled by the default credential, e.g. `'azure-cli'`) or a full `credential` object. `credentialName` can be added to the options object (either config file or env) or specified separately via `AZURE_IDENTITY_CREDENTIAL_NAME`. More advanced scenarios (such as chaining) with a `credential` object are only supported in `lage.config.js`. + ### Minor changes - `@lage-run/cache` diff --git a/packages/runners/src/WorkerRunner.ts b/packages/runners/src/WorkerRunner.ts index 1700728b2..9eb6af691 100644 --- a/packages/runners/src/WorkerRunner.ts +++ b/packages/runners/src/WorkerRunner.ts @@ -7,11 +7,9 @@ export interface WorkerRunnerOptions { } /** - * Creates a workerpool per target task definition of "type: worker" + * Creates a worker pool per target task definition of "type: worker", to be run with `@lage-run/worker-threads-pool`. * - * Target options are fed into `workerpool`, so target can customize the pool: - * - * https://www.npmjs.com/package/workerpool + * The worker script should export a function, which receives an object with target info. * * Example: * diff --git a/packages/target-graph/src/types/Target.ts b/packages/target-graph/src/types/Target.ts index dabb1355c..d672f0f6d 100644 --- a/packages/target-graph/src/types/Target.ts +++ b/packages/target-graph/src/types/Target.ts @@ -20,7 +20,8 @@ export interface Target { task: string; /** - * Type of the target. If not specified, it will default to "npmScript". Determines the runner for the target. + * Type of the target. Determines the runner for the target. + * @default "npmScript" */ type?: string; @@ -45,22 +46,23 @@ export interface Target { dependents: string[]; /** - * Any custom priority for the target. A priority of >0 will always be prioritized over the default targets in queue + * Priority of the target. A priority of >0 will always be prioritized over the default targets in queue. */ priority?: number; /** - * Outputs of this target (for cache purposes) + * Inputs for this target. This is used to determine the hash key for caching */ - outputs?: string[]; + inputs?: string[]; /** - * Inputs for this target (for cache purposes) + * Outputs of this target. This is used to determine the files to be stored for caching */ - inputs?: string[]; + outputs?: string[]; /** * Whether to cache this target + * @default true */ cache?: boolean; @@ -84,7 +86,7 @@ export interface Target { weight?: number; /** - * Run options for the Target + * Run options for the Target Runner. (e.g. `{ env: ...process.env, colors: true, ... }`) */ options?: Record;