From cd30b53996f3af48c025999c8f6100d9459c3544 Mon Sep 17 00:00:00 2001 From: Elliot Nelson Date: Sun, 2 Feb 2025 22:55:30 -0500 Subject: [PATCH 1/6] work so far --- .../rush-http-build-cache-plugin.json | 8 + .../config/subspaces/default/pnpm-lock.yaml | 25 ++ common/scripts/auth.js | 1 + .../rush-operation-resource-plugin/README.md | 102 +++++++++ .../config/jest.config.json | 14 ++ .../config/rig.json | 18 ++ .../example.json | 25 ++ .../package.json | 32 +++ .../rush-plugin-manifest.json | 11 + .../src/RushOperationResourcePlugin.ts | 214 ++++++++++++++++++ .../src/index.ts | 7 + .../src/schemas/plugin-config.schema.json | 76 +++++++ .../tsconfig.json | 3 + rush.json | 6 + 14 files changed, 542 insertions(+) create mode 100644 common/config/rush-plugins/rush-http-build-cache-plugin.json create mode 100644 common/scripts/auth.js create mode 100644 rush-plugins/rush-operation-resource-plugin/README.md create mode 100644 rush-plugins/rush-operation-resource-plugin/config/jest.config.json create mode 100644 rush-plugins/rush-operation-resource-plugin/config/rig.json create mode 100644 rush-plugins/rush-operation-resource-plugin/example.json create mode 100644 rush-plugins/rush-operation-resource-plugin/package.json create mode 100644 rush-plugins/rush-operation-resource-plugin/rush-plugin-manifest.json create mode 100644 rush-plugins/rush-operation-resource-plugin/src/RushOperationResourcePlugin.ts create mode 100644 rush-plugins/rush-operation-resource-plugin/src/index.ts create mode 100644 rush-plugins/rush-operation-resource-plugin/src/schemas/plugin-config.schema.json create mode 100644 rush-plugins/rush-operation-resource-plugin/tsconfig.json diff --git a/common/config/rush-plugins/rush-http-build-cache-plugin.json b/common/config/rush-plugins/rush-http-build-cache-plugin.json new file mode 100644 index 00000000000..2fe17df3346 --- /dev/null +++ b/common/config/rush-plugins/rush-http-build-cache-plugin.json @@ -0,0 +1,8 @@ +{ + "url": "http://localhost:5071/cache/", + "tokenHandler": { + "exec": "node", + "args": ["common/scripts/auth.js"] + }, + "isCacheWriteAllowed": true +} diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index 19b6d2414e1..60c85836804 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -4087,6 +4087,31 @@ importers: specifier: workspace:* version: link:../../rigs/local-node-rig + ../../../rush-plugins/rush-operation-resource-plugin: + dependencies: + '@rushstack/node-core-library': + specifier: workspace:* + version: link:../../libraries/node-core-library + '@rushstack/rush-sdk': + specifier: workspace:* + version: link:../../libraries/rush-sdk + https-proxy-agent: + specifier: ~5.0.0 + version: 5.0.1 + devDependencies: + '@microsoft/rush-lib': + specifier: workspace:* + version: link:../../libraries/rush-lib + '@rushstack/heft': + specifier: workspace:* + version: link:../../apps/heft + '@rushstack/terminal': + specifier: workspace:* + version: link:../../libraries/terminal + local-node-rig: + specifier: workspace:* + version: link:../../rigs/local-node-rig + ../../../rush-plugins/rush-redis-cobuild-plugin: dependencies: '@redis/client': diff --git a/common/scripts/auth.js b/common/scripts/auth.js new file mode 100644 index 00000000000..0acdc0c31be --- /dev/null +++ b/common/scripts/auth.js @@ -0,0 +1 @@ +console.log('Basic ' + Buffer.from('rush:RushRules2!').toString('base64')); diff --git a/rush-plugins/rush-operation-resource-plugin/README.md b/rush-plugins/rush-operation-resource-plugin/README.md new file mode 100644 index 00000000000..64bd0d243e4 --- /dev/null +++ b/rush-plugins/rush-operation-resource-plugin/README.md @@ -0,0 +1,102 @@ +# @rushstack/rush-operation-resource-plugin + +A Rush plugin that enables resource constraints on specific operations. + +This plugin is designed to accomplish two goals: + + 1. Provide a generic way to restrict the total parallelism of certain operations. For example, you may generally want all "build" and "test" operations to use as many possible cores as possible, but for a + particular set of expensive projects, you only want to run up to 2 build phases at a time. Or, you may want to use up all 32 cores on a machine, but you want a maximum of 8 test processes at any given time. + + 2. Provide a generic way to model a limited pool of resources -- perhaps just 1 local simulator is available for running tests, or only 3 physical devices of a certain type that can run tests for projects with a given tag. This goal is similar to the above, but not only do we want to limit the parallelism, we want to choose a _specific resource_ from the pool for each active operation, and pass that resource to the operation for it to use. + +## Configuration + +To use the Operation Resource plugin, add it to your `rush-plugins` autoinstaller (see https://rushjs.io/pages/maintainer/using_rush_plugins/ for more information). Then, create the configuration `common/config/rush/rush-operation-resource-plugin.json`. + +### Use Case 1: Executing tests on connected Android devices + +In this use case, we have some Android devices connected via USB, and although _most_ of our test phases are simple Jest suites, a couple projects tagged `android` must run on one of these Android devices. Here's an example configuration file: + +```json +{ + "resourceConstraints": [ + { + "appliesTo": { + "phaseName": "_phase:test", + "tagName": "android" + }, + "resourcePool": { + "poolName": "android-devices", + "envVarName": "ANDROID_ID" + } + } + ], + "resourcePools": [ + { + "poolName": "android-devices", + "resources": [ + "YOGAA1BBB412", + "DROID1ABBA44" + ] + } + ] +} +``` + +Configured this way, _most_ build and test phases will run normally, but only _2_ test operations on projects tagged `android` can run at the same time. When the test scripts for these projects are launched, the environment variable `ANDROID_ID` will be set to the chosen resource. + +### Use Case 2: Expensive Builds + +In this use case, we've configured our CI/CD to run on a 32-core machine, and want to make maximum usage of it, but there are few troublesome projects that use so much RAM that if they happen to execute in parallel, they can cause intermittent issues. To work around this problem, we can assign a special tag to these projects, and allow only 1 of them to build at once. + +```json +{ + "resourceConstraints": [ + { + "appliesTo": { + "phaseName": "_phase:build", + "tagName": "expensive-build" + }, + "resourcePool": { + "poolName": "expensive-builds" + } + } + ], + "resourcePools": [ + { + "poolName": "expensive-builds", + "resourceCount": 1 + } + ] +} +``` + +Note that behind the scenes, specifying `resourceCount` instead of `resources` will simply automatically generate a list of resources (`expensive-builds-1`, etc.). In this case we don't care about exact resources, just the number of parallel builds, so we've left off the optional `envVarName` property. + +### Use Case 3: Distinguishing between Local and CI + +The plugin configuration file is a simple JSON file, and doesn't offer any run-time configuration options. To simplify the experience for local developers, ensure that your checked-in config file makes sense when building and testing locally, and then overwrite the file in your CI/CD pipeline. + +For example, you might add a line like this before running `rush` in CI/CD: + +```bash +cp common/ci/rush-operation-resource-plugin.ci.json common/config/rush/rush-operation-resource-plugin.json +``` + +## Implementation Details + +Note that this plugin does not attempt to change the way Rush calculates the build order of a given set of operations. (Rush uses the dependency tree of your monorepo's project set, and the defined phase dependencies of any phases included in the current command, to construct a relatively optimal build graph, and this plugin does not change it.) + +Instead, this plugin makes use of Rush's built-in phased operation hooks to _delay_ the start of a given task if it meets certain criteria. This approach has pros and cons: + + - One con is that this approach is not always _optimal_. A given operation may need to be delayed because it requires a resource where none is available, and it will simply wait for another operation to finish so it can start. An optimal implementation would pause this operation and run a _different_ operation, perhaps one with no resource constraints. + + - On the other hand, because we don't reorder tasks from Rush's build graph, we are guaranteed not to get into some kind of deadlock: _eventually_, the current task that is delayed will become unblocked and the other operations depending on this one will also be unblocked, no matter how many different resource pools you define. + +## Possible enhancements + +Possible future enhancements for this plugin: + + - Easier runtime configuration (for example, allowing `${ }` interpolation of env vars in resources arrays, so they could be passed from terminal or from VSCode commands). + + - Optimized build graphing (build graph changes, taking into account resource constraints, with some checking for deadlocks). diff --git a/rush-plugins/rush-operation-resource-plugin/config/jest.config.json b/rush-plugins/rush-operation-resource-plugin/config/jest.config.json new file mode 100644 index 00000000000..7cbc3ad89de --- /dev/null +++ b/rush-plugins/rush-operation-resource-plugin/config/jest.config.json @@ -0,0 +1,14 @@ +{ + "extends": "local-node-rig/profiles/default/config/jest.config.json", + "clearMocks": true, + "restoreMocks": true, + "collectCoverage": true, + "coverageThreshold": { + "global": { + "branches": 4, + "functions": 15, + "lines": 4, + "statements": 4 + } + } +} diff --git a/rush-plugins/rush-operation-resource-plugin/config/rig.json b/rush-plugins/rush-operation-resource-plugin/config/rig.json new file mode 100644 index 00000000000..bf9de6a1799 --- /dev/null +++ b/rush-plugins/rush-operation-resource-plugin/config/rig.json @@ -0,0 +1,18 @@ +{ + // The "rig.json" file directs tools to look for their config files in an external package. + // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package + "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", + + /** + * (Required) The name of the rig package to inherit from. + * It should be an NPM package name with the "-rig" suffix. + */ + "rigPackageName": "local-node-rig", + + /** + * (Optional) Selects a config profile from the rig package. The name must consist of + * lowercase alphanumeric words separated by hyphens, for example "sample-profile". + * If omitted, then the "default" profile will be used." + */ + "rigProfile": "default" +} diff --git a/rush-plugins/rush-operation-resource-plugin/example.json b/rush-plugins/rush-operation-resource-plugin/example.json new file mode 100644 index 00000000000..a802a164704 --- /dev/null +++ b/rush-plugins/rush-operation-resource-plugin/example.json @@ -0,0 +1,25 @@ +{ + "constraints": [ + { + "appliesTo": { + "phaseName": "_phase:build" + }, + "useResource": { + "poolName": "rokuDevices", + "envVarName": "ROKU_RUNNER" + } + }, + { + "appliesTo": { + "phaseName": "build", + "tagName": "donkey" + } + } + ], + "resourcePools": [ + { + "poolName": "rokuDevices", + "resources": ["AAA", "BBB"] + } + ] +} diff --git a/rush-plugins/rush-operation-resource-plugin/package.json b/rush-plugins/rush-operation-resource-plugin/package.json new file mode 100644 index 00000000000..b0d0d345d76 --- /dev/null +++ b/rush-plugins/rush-operation-resource-plugin/package.json @@ -0,0 +1,32 @@ +{ + "name": "@rushstack/rush-operation-resource-plugin", + "version": "0.0.0", + "description": "Rush plugin that enables resource constraints on specific operations", + "repository": { + "type": "git", + "url": "https://github.com/microsoft/rushstack", + "directory": "rush-plugins/rush-operation-resource-plugin" + }, + "homepage": "https://rushjs.io", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "license": "MIT", + "scripts": { + "build": "heft build --clean", + "start": "heft test-watch", + "test": "heft test", + "_phase:build": "heft run --only build -- --clean", + "_phase:test": "heft run --only test -- --clean" + }, + "dependencies": { + "@rushstack/node-core-library": "workspace:*", + "@rushstack/rush-sdk": "workspace:*", + "https-proxy-agent": "~5.0.0" + }, + "devDependencies": { + "@microsoft/rush-lib": "workspace:*", + "@rushstack/heft": "workspace:*", + "@rushstack/terminal": "workspace:*", + "local-node-rig": "workspace:*" + } +} diff --git a/rush-plugins/rush-operation-resource-plugin/rush-plugin-manifest.json b/rush-plugins/rush-operation-resource-plugin/rush-plugin-manifest.json new file mode 100644 index 00000000000..c8793b6baad --- /dev/null +++ b/rush-plugins/rush-operation-resource-plugin/rush-plugin-manifest.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-operation-resource-plugin", + "description": "Rush plugin that enables resource constraints on specific operations", + "entryPoint": "lib/index.js", + "optionsSchema": "lib/schemas/plugin-config.schema.json" + } + ] +} diff --git a/rush-plugins/rush-operation-resource-plugin/src/RushOperationResourcePlugin.ts b/rush-plugins/rush-operation-resource-plugin/src/RushOperationResourcePlugin.ts new file mode 100644 index 00000000000..d91640cedc8 --- /dev/null +++ b/rush-plugins/rush-operation-resource-plugin/src/RushOperationResourcePlugin.ts @@ -0,0 +1,214 @@ +import type { + IRushPlugin, + IPhasedCommand, + RushSession, + RushConfiguration, + ILogger, + IOperationRunnerContext, + IOperationExecutionResult, + OperationStatus, + Operation +} from '@rushstack/rush-sdk'; +import { Stopwatch } from '@rushstack/rush-sdk/lib/utilities/Stopwatch'; +import * as fs from 'fs'; + +export interface IRushOperationResourcePluginOptions { + resourceConstraints?: IResourceConstraintConfig[]; + resourcePools?: IResourcePoolConfig[]; +} + +export interface IResourceConstraintConfig { + appliesTo: { + operationName?: string; + phaseName?: string; + packageName?: string; + tagName?: string; + }; + resourcePool: { + poolName: string; + envVarName?: string; + }; +} + +export interface IResourcePoolConfig { + poolName: string; + resources?: string[]; + resourceCount?: number; +} + +export interface IResourcePool { + poolName: string; + resources: string[]; +} + +export const RESOURCE_POOL_POLL_INTERVAL_MS = 500; +export const PLUGIN_NAME: string = 'RushOperationResourcePlugin'; + +export class RushOperationResourcePlugin implements IRushPlugin { + public readonly pluginName: string = PLUGIN_NAME; + private readonly _options: IRushOperationResourcePluginOptions; + private readonly _checkedOutResources: Map; + private readonly _resourcePools: Map; + + public constructor(options: IRushOperationResourcePluginOptions) { + this._options = options; + this._checkedOutResources = new Map(); + this._resourcePools = new Map(); + } + + public apply(rushSession: RushSession, rushContext: RushConfiguration): void { + const logger: ILogger = rushSession.getLogger(this.pluginName); + + this._validateOptions(); + + rushSession.hooks.runAnyPhasedCommand.tapPromise( + this.pluginName, + async (command: IPhasedCommand): Promise => { + command.hooks.beforeExecuteOperation.tapPromise( + this.pluginName, + async ( + runnerContext: IOperationRunnerContext & IOperationExecutionResult + ): Promise => { + const constraint: IResourceConstraintConfig | undefined = this._getConstraintsForOperation( + runnerContext.operation + ); + + if (constraint) { + if (constraint.resourcePool) { + const pool: IResourcePool = this._resourcePools.get(constraint.resourcePool.poolName)!; + + // Wait to obtain a resource from the resource pool for this constraint + const resource: string = await this._obtainResource(pool, runnerContext.operation); + + // Pass this resource to the underlying operation using the specified + // environment variable + if (constraint.resourcePool.envVarName) { + const runner: any = runnerContext.operation.runner; + if (!runner.environment) { + runner.environment = {}; + } + runner.environment[constraint.resourcePool.envVarName] = resource; + } + + // Reset the stopwatch start time to account for the time spent waiting + (runnerContext.stopwatch as Stopwatch).reset().start(); + + // In "rush --debug" mode, log every time we assign a resource + logger.terminal.writeVerboseLine( + `[${this.pluginName}] ${runnerContext.operation.associatedProject?.packageName} (${runnerContext.operation.associatedPhase?.name}) Assigned ${constraint.resourcePool.envVarName}=${resource} from pool ${pool.poolName}.` + ); + } + } + + return; + } + ); + + command.hooks.afterExecuteOperation.tapPromise( + this.pluginName, + async (runnerContext: IOperationRunnerContext & IOperationExecutionResult): Promise => { + const constraint: IResourceConstraintConfig | undefined = this._getConstraintsForOperation( + runnerContext.operation + ); + + if (constraint) { + if (constraint.resourcePool) { + const pool: IResourcePool = this._resourcePools.get(constraint.resourcePool.poolName)!; + this._releaseResource(pool, runnerContext.operation); + } + } + + return; + } + ); + } + ); + } + + private async _obtainResource(pool: IResourcePool, operation: Operation): Promise { + for (;;) { + if (pool.resources.length > 0) { + const resource = pool.resources.shift()!; + this._checkedOutResources.set(operation, resource); + return resource; + } + await new Promise((resolve) => setTimeout(resolve, RESOURCE_POOL_POLL_INTERVAL_MS)); + } + } + + private _releaseResource(pool: IResourcePool, operation: Operation): void { + const resource: string | undefined = this._checkedOutResources.get(operation); + if (resource) { + pool.resources.push(resource); + } else { + throw new Error(`Internal Error: Expected operation to have a checked out device but none was found.`); + } + } + + private _getConstraintsForOperation(operation: Operation): IResourceConstraintConfig | undefined { + return this._options?.resourceConstraints?.find((constraint) => { + if (constraint.appliesTo) { + if (constraint.appliesTo.operationName && constraint.appliesTo.operationName !== operation.name) { + return false; + } + if ( + constraint.appliesTo.phaseName && + constraint.appliesTo.phaseName !== operation.associatedPhase?.name + ) { + return false; + } + if ( + constraint.appliesTo.packageName && + constraint.appliesTo.packageName !== operation.associatedProject?.packageName + ) { + return false; + } + if ( + constraint.appliesTo.tagName && + !operation.associatedProject?.tags.has(constraint.appliesTo.tagName) + ) { + return false; + } + } + return true; + }); + } + + private _validateOptions(): void { + for (const pool of this._options.resourcePools || []) { + const resources = pool.resources || this._generateResources(pool.poolName, pool.resourceCount || 0); + if (resources.length < 1) { + throw new Error( + `While initializing ${this.pluginName}, encountered resourcePool ${pool.poolName} with no defined resources.` + ); + } + if (this._resourcePools.get(pool.poolName)) { + throw new Error( + `While initializing ${this.pluginName}, encountered duplicate resourcePool ${pool.poolName}.` + ); + } + this._resourcePools.set(pool.poolName, { + poolName: pool.poolName, + resources + }); + } + + for (const constraint of this._options.resourceConstraints || []) { + if (constraint.resourcePool?.poolName && !this._resourcePools.get(constraint.resourcePool.poolName)) { + throw new Error( + `While initializing ${this.pluginName}, encountered resourceConstraint with undefined resourcePool ${constraint.resourcePool.poolName}.` + ); + } + } + } + + private _generateResources(poolName: string, number: number): string[] { + const resources: string[] = []; + for (let i = 0; i < number; i++) { + resources.push(`${poolName}-${i}`); + } + return resources; + } +} + +export default RushOperationResourcePlugin; diff --git a/rush-plugins/rush-operation-resource-plugin/src/index.ts b/rush-plugins/rush-operation-resource-plugin/src/index.ts new file mode 100644 index 00000000000..f22bbe80105 --- /dev/null +++ b/rush-plugins/rush-operation-resource-plugin/src/index.ts @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +import { RushOperationResourcePlugin } from './RushOperationResourcePlugin'; + +export default RushOperationResourcePlugin; +export type { IRushOperationResourcePluginOptions } from './RushOperationResourcePlugin'; diff --git a/rush-plugins/rush-operation-resource-plugin/src/schemas/plugin-config.schema.json b/rush-plugins/rush-operation-resource-plugin/src/schemas/plugin-config.schema.json new file mode 100644 index 00000000000..20b738121b4 --- /dev/null +++ b/rush-plugins/rush-operation-resource-plugin/src/schemas/plugin-config.schema.json @@ -0,0 +1,76 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Configuration for Rush Operation Resource Plugin", + "type": "object", + "required": ["url"], + "properties": { + "resourceConstraints": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["appliesTo", "resourcePool"], + "properties": { + "appliesTo": { + "type": "object" + }, + "resourcePool": { + "type": "object", + "additionalProperties": false, + "required": ["poolName"], + "properties": { + "poolName": { + "type": "string", + "description": "The name of the resource pool to use" + }, + "envVarName": { + "type": "string", + "description": "(Optional) Set this environment variable to the ID of the resource selected from the pool and pass it to the underlying operation" + } + } + } + } + } + }, + "resourcePools": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["poolName", "resources"], + "properties": { + "poolName": { + "type": "string", + "description": "(Required) A unique name for this pool of resources" + }, + "resources": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of named resources that belong to this pool" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["poolName", "resourceCount"], + "properties": { + "poolName": { + "type": "string", + "description": "(Required) A unique name for this pool of resources" + }, + "resourceCount": { + "type": "integer", + "description": "The number of resources available in this pool" + } + } + } + ] + } + } + } +} diff --git a/rush-plugins/rush-operation-resource-plugin/tsconfig.json b/rush-plugins/rush-operation-resource-plugin/tsconfig.json new file mode 100644 index 00000000000..dac21d04081 --- /dev/null +++ b/rush-plugins/rush-operation-resource-plugin/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "./node_modules/local-node-rig/profiles/default/tsconfig-base.json" +} diff --git a/rush.json b/rush.json index 690690c365f..4a3b25a6bcf 100644 --- a/rush.json +++ b/rush.json @@ -1255,6 +1255,12 @@ "reviewCategory": "libraries", "shouldPublish": false }, + { + "packageName": "@rushstack/rush-operation-resource-plugin", + "projectFolder": "rush-plugins/rush-operation-resource-plugin", + "reviewCategory": "libraries", + "shouldPublish": false + }, { "packageName": "@rushstack/rush-redis-cobuild-plugin", "projectFolder": "rush-plugins/rush-redis-cobuild-plugin", From 1978d80ce5d42d05c80e3b36e646aa90dc840273 Mon Sep 17 00:00:00 2001 From: Elliot Nelson Date: Mon, 3 Feb 2025 14:48:45 -0500 Subject: [PATCH 2/6] plugin-config schema --- .../src/schemas/plugin-config.schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rush-plugins/rush-operation-resource-plugin/src/schemas/plugin-config.schema.json b/rush-plugins/rush-operation-resource-plugin/src/schemas/plugin-config.schema.json index 20b738121b4..e97b41fe1d0 100644 --- a/rush-plugins/rush-operation-resource-plugin/src/schemas/plugin-config.schema.json +++ b/rush-plugins/rush-operation-resource-plugin/src/schemas/plugin-config.schema.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-04/schema#", "title": "Configuration for Rush Operation Resource Plugin", "type": "object", - "required": ["url"], + "additionalProperties": false, "properties": { "resourceConstraints": { "type": "array", From e85dfa5822a61f19184cb10610b532c58b67be02 Mon Sep 17 00:00:00 2001 From: Elliot Nelson Date: Mon, 3 Feb 2025 14:53:57 -0500 Subject: [PATCH 3/6] Remove unnecessary files --- .../config/rush-plugins/rush-http-build-cache-plugin.json | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 common/config/rush-plugins/rush-http-build-cache-plugin.json diff --git a/common/config/rush-plugins/rush-http-build-cache-plugin.json b/common/config/rush-plugins/rush-http-build-cache-plugin.json deleted file mode 100644 index 2fe17df3346..00000000000 --- a/common/config/rush-plugins/rush-http-build-cache-plugin.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "url": "http://localhost:5071/cache/", - "tokenHandler": { - "exec": "node", - "args": ["common/scripts/auth.js"] - }, - "isCacheWriteAllowed": true -} From 95d47725d543e66b7ccdb6354e690b521648075b Mon Sep 17 00:00:00 2001 From: Elliot Nelson Date: Mon, 3 Feb 2025 14:54:33 -0500 Subject: [PATCH 4/6] update README --- common/scripts/auth.js | 1 - rush-plugins/rush-operation-resource-plugin/README.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 common/scripts/auth.js diff --git a/common/scripts/auth.js b/common/scripts/auth.js deleted file mode 100644 index 0acdc0c31be..00000000000 --- a/common/scripts/auth.js +++ /dev/null @@ -1 +0,0 @@ -console.log('Basic ' + Buffer.from('rush:RushRules2!').toString('base64')); diff --git a/rush-plugins/rush-operation-resource-plugin/README.md b/rush-plugins/rush-operation-resource-plugin/README.md index 64bd0d243e4..86dc2a69902 100644 --- a/rush-plugins/rush-operation-resource-plugin/README.md +++ b/rush-plugins/rush-operation-resource-plugin/README.md @@ -11,7 +11,7 @@ This plugin is designed to accomplish two goals: ## Configuration -To use the Operation Resource plugin, add it to your `rush-plugins` autoinstaller (see https://rushjs.io/pages/maintainer/using_rush_plugins/ for more information). Then, create the configuration `common/config/rush/rush-operation-resource-plugin.json`. +To use the Operation Resource plugin, add it to your `rush-plugins` autoinstaller (see https://rushjs.io/pages/maintainer/using_rush_plugins/ for more information). Then, create the configuration file `common/config/rush-plugins/rush-operation-resource-plugin.json`. ### Use Case 1: Executing tests on connected Android devices From 5f5ff56ca5150aa2af576ccd7ad83fcaebd6796f Mon Sep 17 00:00:00 2001 From: Elliot Nelson Date: Mon, 3 Feb 2025 14:55:03 -0500 Subject: [PATCH 5/6] Remove old example --- .../example.json | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 rush-plugins/rush-operation-resource-plugin/example.json diff --git a/rush-plugins/rush-operation-resource-plugin/example.json b/rush-plugins/rush-operation-resource-plugin/example.json deleted file mode 100644 index a802a164704..00000000000 --- a/rush-plugins/rush-operation-resource-plugin/example.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "constraints": [ - { - "appliesTo": { - "phaseName": "_phase:build" - }, - "useResource": { - "poolName": "rokuDevices", - "envVarName": "ROKU_RUNNER" - } - }, - { - "appliesTo": { - "phaseName": "build", - "tagName": "donkey" - } - } - ], - "resourcePools": [ - { - "poolName": "rokuDevices", - "resources": ["AAA", "BBB"] - } - ] -} From 2481dc293b1cee7962a7a0e2a23ba4525ef0dbed Mon Sep 17 00:00:00 2001 From: Elliot Nelson Date: Mon, 3 Feb 2025 14:56:22 -0500 Subject: [PATCH 6/6] typo --- rush-plugins/rush-operation-resource-plugin/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rush-plugins/rush-operation-resource-plugin/README.md b/rush-plugins/rush-operation-resource-plugin/README.md index 86dc2a69902..235044e7468 100644 --- a/rush-plugins/rush-operation-resource-plugin/README.md +++ b/rush-plugins/rush-operation-resource-plugin/README.md @@ -4,7 +4,7 @@ A Rush plugin that enables resource constraints on specific operations. This plugin is designed to accomplish two goals: - 1. Provide a generic way to restrict the total parallelism of certain operations. For example, you may generally want all "build" and "test" operations to use as many possible cores as possible, but for a + 1. Provide a generic way to restrict the total parallelism of certain operations. For example, you may generally want all "build" and "test" operations to use as many cores as possible, but for a particular set of expensive projects, you only want to run up to 2 build phases at a time. Or, you may want to use up all 32 cores on a machine, but you want a maximum of 8 test processes at any given time. 2. Provide a generic way to model a limited pool of resources -- perhaps just 1 local simulator is available for running tests, or only 3 physical devices of a certain type that can run tests for projects with a given tag. This goal is similar to the above, but not only do we want to limit the parallelism, we want to choose a _specific resource_ from the pool for each active operation, and pass that resource to the operation for it to use.