feat(core): add pre and post run apis (#29636)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> There is no specific API for running things before and after tasks run. ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> This PR adds an API akin to npm's `preinstall` and `postinstall`. Plugins can now specify `preTasksExecution` and `postTasksExecution` functions which run before and after Nx runs tasks respectively. ```ts import type { PreTasksExecutionContext, PostTasksExecutionContext } from '@nx/devkit'; interface PluginOptions { field: any; } export function preTasksExecution(options: PluginOptions, context: PreTasksExecutionContext) { console.log('prerun') } export function postTasksExecution(options: PluginOptions, context: PostTasksExecutionContext) { console.log('postrun', context.taskResults) } ``` ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
f02a88a72c
commit
4a9508b368
@ -2,4 +2,4 @@
|
||||
|
||||
Ƭ **NxPlugin**: [`NxPluginV2`](../../devkit/documents/NxPluginV2)
|
||||
|
||||
A plugin for Nx
|
||||
A plugin which enhances the behavior of Nx
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
Ƭ **NxPluginV2**\<`TOptions`\>: `Object`
|
||||
|
||||
A plugin for Nx which creates nodes and dependencies for the [ProjectGraph](../../devkit/documents/ProjectGraph)
|
||||
A plugin which enhances the behavior of Nx
|
||||
|
||||
#### Type parameters
|
||||
|
||||
@ -19,3 +19,5 @@ A plugin for Nx which creates nodes and dependencies for the [ProjectGraph](../.
|
||||
| `createNodes?` | [`CreateNodes`](../../devkit/documents/CreateNodes)\<`TOptions`\> | Provides a file pattern and function that retrieves configuration info from those files. e.g. { '**/\*.csproj': buildProjectsFromCsProjFile } **`Deprecated`\*\* Use createNodesV2 instead. In Nx 21 support for calling createNodes with a single file for the first argument will be removed. |
|
||||
| `createNodesV2?` | [`CreateNodesV2`](../../devkit/documents/CreateNodesV2)\<`TOptions`\> | Provides a file pattern and function that retrieves configuration info from those files. e.g. { '\*_/_.csproj': buildProjectsFromCsProjFiles } In Nx 21 createNodes will be replaced with this property. In Nx 22, this property will be removed. |
|
||||
| `name` | `string` | - |
|
||||
| `postTasksExecution?` | [`PostTasksExecution`](../../devkit/documents/PostTasksExecution)\<`TOptions`\> | Provides a function to run after the Nx runs tasks |
|
||||
| `preTasksExecution?` | [`PreTasksExecution`](../../devkit/documents/PreTasksExecution)\<`TOptions`\> | Provides a function to run before the Nx runs tasks |
|
||||
|
||||
24
docs/generated/devkit/PostTasksExecution.md
Normal file
24
docs/generated/devkit/PostTasksExecution.md
Normal file
@ -0,0 +1,24 @@
|
||||
# Type alias: PostTasksExecution\<TOptions\>
|
||||
|
||||
Ƭ **PostTasksExecution**\<`TOptions`\>: (`options`: `TOptions` \| `undefined`, `context`: [`PostTasksExecutionContext`](../../devkit/documents/PostTasksExecutionContext)) => `void` \| `Promise`\<`void`\>
|
||||
|
||||
#### Type parameters
|
||||
|
||||
| Name | Type |
|
||||
| :--------- | :-------- |
|
||||
| `TOptions` | `unknown` |
|
||||
|
||||
#### Type declaration
|
||||
|
||||
▸ (`options`, `context`): `void` \| `Promise`\<`void`\>
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Type |
|
||||
| :-------- | :------------------------------------------------------------------------------ |
|
||||
| `options` | `TOptions` \| `undefined` |
|
||||
| `context` | [`PostTasksExecutionContext`](../../devkit/documents/PostTasksExecutionContext) |
|
||||
|
||||
##### Returns
|
||||
|
||||
`void` \| `Promise`\<`void`\>
|
||||
11
docs/generated/devkit/PostTasksExecutionContext.md
Normal file
11
docs/generated/devkit/PostTasksExecutionContext.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Type alias: PostTasksExecutionContext
|
||||
|
||||
Ƭ **PostTasksExecutionContext**: `Object`
|
||||
|
||||
#### Type declaration
|
||||
|
||||
| Name | Type |
|
||||
| :-------------------- | :------------------------------------------------------------------ |
|
||||
| `nxJsonConfiguration` | [`NxJsonConfiguration`](../../devkit/documents/NxJsonConfiguration) |
|
||||
| `taskResults` | [`TaskResults`](../../devkit/documents/TaskResults) |
|
||||
| `workspaceRoot` | `string` |
|
||||
24
docs/generated/devkit/PreTasksExecution.md
Normal file
24
docs/generated/devkit/PreTasksExecution.md
Normal file
@ -0,0 +1,24 @@
|
||||
# Type alias: PreTasksExecution\<TOptions\>
|
||||
|
||||
Ƭ **PreTasksExecution**\<`TOptions`\>: (`options`: `TOptions` \| `undefined`, `context`: [`PreTasksExecutionContext`](../../devkit/documents/PreTasksExecutionContext)) => `void` \| `Promise`\<`void`\>
|
||||
|
||||
#### Type parameters
|
||||
|
||||
| Name | Type |
|
||||
| :--------- | :-------- |
|
||||
| `TOptions` | `unknown` |
|
||||
|
||||
#### Type declaration
|
||||
|
||||
▸ (`options`, `context`): `void` \| `Promise`\<`void`\>
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Type |
|
||||
| :-------- | :---------------------------------------------------------------------------- |
|
||||
| `options` | `TOptions` \| `undefined` |
|
||||
| `context` | [`PreTasksExecutionContext`](../../devkit/documents/PreTasksExecutionContext) |
|
||||
|
||||
##### Returns
|
||||
|
||||
`void` \| `Promise`\<`void`\>
|
||||
10
docs/generated/devkit/PreTasksExecutionContext.md
Normal file
10
docs/generated/devkit/PreTasksExecutionContext.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Type alias: PreTasksExecutionContext
|
||||
|
||||
Ƭ **PreTasksExecutionContext**: `Object`
|
||||
|
||||
#### Type declaration
|
||||
|
||||
| Name | Type |
|
||||
| :-------------------- | :------------------------------------------------------------------ |
|
||||
| `nxJsonConfiguration` | [`NxJsonConfiguration`](../../devkit/documents/NxJsonConfiguration) |
|
||||
| `workspaceRoot` | `string` |
|
||||
@ -59,6 +59,7 @@ It only uses language primitives and immutable objects
|
||||
- [Task](../../devkit/documents/Task)
|
||||
- [TaskGraph](../../devkit/documents/TaskGraph)
|
||||
- [TaskHasher](../../devkit/documents/TaskHasher)
|
||||
- [TaskResult](../../devkit/documents/TaskResult)
|
||||
- [Tree](../../devkit/documents/Tree)
|
||||
- [Workspace](../../devkit/documents/Workspace)
|
||||
|
||||
@ -86,6 +87,10 @@ It only uses language primitives and immutable objects
|
||||
- [NxPluginV2](../../devkit/documents/NxPluginV2)
|
||||
- [PackageManager](../../devkit/documents/PackageManager)
|
||||
- [PluginConfiguration](../../devkit/documents/PluginConfiguration)
|
||||
- [PostTasksExecution](../../devkit/documents/PostTasksExecution)
|
||||
- [PostTasksExecutionContext](../../devkit/documents/PostTasksExecutionContext)
|
||||
- [PreTasksExecution](../../devkit/documents/PreTasksExecution)
|
||||
- [PreTasksExecutionContext](../../devkit/documents/PreTasksExecutionContext)
|
||||
- [ProjectType](../../devkit/documents/ProjectType)
|
||||
- [ProjectsMetadata](../../devkit/documents/ProjectsMetadata)
|
||||
- [PromiseExecutor](../../devkit/documents/PromiseExecutor)
|
||||
@ -94,6 +99,7 @@ It only uses language primitives and immutable objects
|
||||
- [StringChange](../../devkit/documents/StringChange)
|
||||
- [TargetDefaults](../../devkit/documents/TargetDefaults)
|
||||
- [TaskGraphExecutor](../../devkit/documents/TaskGraphExecutor)
|
||||
- [TaskResults](../../devkit/documents/TaskResults)
|
||||
- [ToJSOptions](../../devkit/documents/ToJSOptions)
|
||||
- [WorkspaceJsonConfiguration](../../devkit/documents/WorkspaceJsonConfiguration)
|
||||
|
||||
|
||||
36
docs/generated/devkit/TaskResult.md
Normal file
36
docs/generated/devkit/TaskResult.md
Normal file
@ -0,0 +1,36 @@
|
||||
# Interface: TaskResult
|
||||
|
||||
The result of a completed [Task](../../devkit/documents/Task)
|
||||
|
||||
## Table of contents
|
||||
|
||||
### Properties
|
||||
|
||||
- [code](../../devkit/documents/TaskResult#code): number
|
||||
- [status](../../devkit/documents/TaskResult#status): TaskStatus
|
||||
- [task](../../devkit/documents/TaskResult#task): Task
|
||||
- [terminalOutput](../../devkit/documents/TaskResult#terminaloutput): string
|
||||
|
||||
## Properties
|
||||
|
||||
### code
|
||||
|
||||
• **code**: `number`
|
||||
|
||||
---
|
||||
|
||||
### status
|
||||
|
||||
• **status**: `TaskStatus`
|
||||
|
||||
---
|
||||
|
||||
### task
|
||||
|
||||
• **task**: [`Task`](../../devkit/documents/Task)
|
||||
|
||||
---
|
||||
|
||||
### terminalOutput
|
||||
|
||||
• `Optional` **terminalOutput**: `string`
|
||||
5
docs/generated/devkit/TaskResults.md
Normal file
5
docs/generated/devkit/TaskResults.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Type alias: TaskResults
|
||||
|
||||
Ƭ **TaskResults**: `Record`\<`string`, [`TaskResult`](../../devkit/documents/TaskResult)\>
|
||||
|
||||
A map of [TaskResult](../../devkit/documents/TaskResult) keyed by the ID of the completed [Task](../../devkit/documents/Task)s
|
||||
@ -59,6 +59,7 @@ It only uses language primitives and immutable objects
|
||||
- [Task](../../devkit/documents/Task)
|
||||
- [TaskGraph](../../devkit/documents/TaskGraph)
|
||||
- [TaskHasher](../../devkit/documents/TaskHasher)
|
||||
- [TaskResult](../../devkit/documents/TaskResult)
|
||||
- [Tree](../../devkit/documents/Tree)
|
||||
- [Workspace](../../devkit/documents/Workspace)
|
||||
|
||||
@ -86,6 +87,10 @@ It only uses language primitives and immutable objects
|
||||
- [NxPluginV2](../../devkit/documents/NxPluginV2)
|
||||
- [PackageManager](../../devkit/documents/PackageManager)
|
||||
- [PluginConfiguration](../../devkit/documents/PluginConfiguration)
|
||||
- [PostTasksExecution](../../devkit/documents/PostTasksExecution)
|
||||
- [PostTasksExecutionContext](../../devkit/documents/PostTasksExecutionContext)
|
||||
- [PreTasksExecution](../../devkit/documents/PreTasksExecution)
|
||||
- [PreTasksExecutionContext](../../devkit/documents/PreTasksExecutionContext)
|
||||
- [ProjectType](../../devkit/documents/ProjectType)
|
||||
- [ProjectsMetadata](../../devkit/documents/ProjectsMetadata)
|
||||
- [PromiseExecutor](../../devkit/documents/PromiseExecutor)
|
||||
@ -94,6 +99,7 @@ It only uses language primitives and immutable objects
|
||||
- [StringChange](../../devkit/documents/StringChange)
|
||||
- [TargetDefaults](../../devkit/documents/TargetDefaults)
|
||||
- [TaskGraphExecutor](../../devkit/documents/TaskGraphExecutor)
|
||||
- [TaskResults](../../devkit/documents/TaskResults)
|
||||
- [ToJSOptions](../../devkit/documents/ToJSOptions)
|
||||
- [WorkspaceJsonConfiguration](../../devkit/documents/WorkspaceJsonConfiguration)
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ import {
|
||||
describe('Jest', () => {
|
||||
beforeAll(() => {
|
||||
newProject({ name: uniq('proj-jest'), packages: ['@nx/js', '@nx/node'] });
|
||||
process.env.NX_E2E_VERBOSE_LOGGING = 'true';
|
||||
});
|
||||
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
@ -29,7 +29,7 @@ describe('Convert Nx Executor', () => {
|
||||
|
||||
const registry = new schema.CoreSchemaRegistry();
|
||||
registry.addPostTransform(schema.transforms.addUndefinedDefaults);
|
||||
const testArchitectHost = new TestingArchitectHost();
|
||||
const testArchitectHost = new TestingArchitectHost(fs.tempDir, fs.tempDir);
|
||||
testArchitectHost.workspaceRoot = fs.tempDir;
|
||||
const architect = new Architect(testArchitectHost, registry);
|
||||
|
||||
|
||||
@ -26,6 +26,11 @@ import {
|
||||
import { deepMergeJson } from './config/deep-merge-json';
|
||||
import { filterReleaseGroups } from './config/filter-release-groups';
|
||||
import { printConfigAndExit } from './utils/print-config';
|
||||
import { workspaceRoot } from '../../utils/workspace-root';
|
||||
import {
|
||||
runPostTasksExecution,
|
||||
runPreTasksExecution,
|
||||
} from '../../project-graph/plugins/tasks-execution-hooks';
|
||||
|
||||
export interface PublishProjectsResult {
|
||||
[projectName: string]: {
|
||||
@ -249,6 +254,10 @@ async function runPublishOnProjects(
|
||||
].join('\n')}\n`
|
||||
);
|
||||
}
|
||||
await runPreTasksExecution({
|
||||
workspaceRoot,
|
||||
nxJsonConfiguration: nxJson,
|
||||
});
|
||||
|
||||
/**
|
||||
* Run the relevant nx-release-publish executor on each of the selected projects.
|
||||
@ -276,6 +285,11 @@ async function runPublishOnProjects(
|
||||
code: taskData.code,
|
||||
};
|
||||
}
|
||||
await runPostTasksExecution({
|
||||
taskResults: commandResults,
|
||||
workspaceRoot,
|
||||
nxJsonConfiguration: nxJson,
|
||||
});
|
||||
|
||||
return publishProjectsResult;
|
||||
}
|
||||
|
||||
@ -78,6 +78,16 @@ import {
|
||||
type HandleFlushSyncGeneratorChangesToDiskMessage,
|
||||
} from '../message-types/flush-sync-generator-changes-to-disk';
|
||||
import { DelayedSpinner } from '../../utils/delayed-spinner';
|
||||
import {
|
||||
PostTasksExecutionContext,
|
||||
PreTasksExecutionContext,
|
||||
} from '../../project-graph/plugins/public-api';
|
||||
import {
|
||||
HandlePostTasksExecutionMessage,
|
||||
HandlePreTasksExecutionMessage,
|
||||
POST_TASKS_EXECUTION,
|
||||
PRE_TASKS_EXECUTION,
|
||||
} from '../message-types/run-tasks-execution-hooks';
|
||||
|
||||
const DAEMON_ENV_SETTINGS = {
|
||||
NX_PROJECT_GLOB_CACHE: 'false',
|
||||
@ -435,6 +445,26 @@ export class DaemonClient {
|
||||
return this.sendToDaemonViaQueue(message);
|
||||
}
|
||||
|
||||
async runPreTasksExecution(
|
||||
context: PreTasksExecutionContext
|
||||
): Promise<NodeJS.ProcessEnv[]> {
|
||||
const message: HandlePreTasksExecutionMessage = {
|
||||
type: PRE_TASKS_EXECUTION,
|
||||
context,
|
||||
};
|
||||
return this.sendToDaemonViaQueue(message);
|
||||
}
|
||||
|
||||
async runPostTasksExecution(
|
||||
context: PostTasksExecutionContext
|
||||
): Promise<void> {
|
||||
const message: HandlePostTasksExecutionMessage = {
|
||||
type: POST_TASKS_EXECUTION,
|
||||
context,
|
||||
};
|
||||
return this.sendToDaemonViaQueue(message);
|
||||
}
|
||||
|
||||
async isServerAvailable(): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
try {
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
import type {
|
||||
PostTasksExecutionContext,
|
||||
PreTasksExecutionContext,
|
||||
} from '../../project-graph/plugins';
|
||||
|
||||
export const PRE_TASKS_EXECUTION = 'PRE_TASKS_EXECUTION' as const;
|
||||
export const POST_TASKS_EXECUTION = 'POST_TASKS_EXECUTION' as const;
|
||||
|
||||
export type HandlePreTasksExecutionMessage = {
|
||||
type: typeof PRE_TASKS_EXECUTION;
|
||||
context: PreTasksExecutionContext;
|
||||
};
|
||||
export type HandlePostTasksExecutionMessage = {
|
||||
type: typeof POST_TASKS_EXECUTION;
|
||||
context: PostTasksExecutionContext;
|
||||
};
|
||||
|
||||
export function isHandlePreTasksExecutionMessage(
|
||||
message: unknown
|
||||
): message is HandlePreTasksExecutionMessage {
|
||||
return (
|
||||
typeof message === 'object' &&
|
||||
message !== null &&
|
||||
'type' in message &&
|
||||
message['type'] === PRE_TASKS_EXECUTION
|
||||
);
|
||||
}
|
||||
|
||||
export function isHandlePostTasksExecutionMessage(
|
||||
message: unknown
|
||||
): message is HandlePostTasksExecutionMessage {
|
||||
return (
|
||||
typeof message === 'object' &&
|
||||
message !== null &&
|
||||
'type' in message &&
|
||||
message['type'] === POST_TASKS_EXECUTION
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
import type {
|
||||
PostTasksExecutionContext,
|
||||
PreTasksExecutionContext,
|
||||
} from '../../project-graph/plugins/public-api';
|
||||
import {
|
||||
runPostTasksExecution,
|
||||
runPreTasksExecution,
|
||||
} from '../../project-graph/plugins/tasks-execution-hooks';
|
||||
|
||||
export async function handleRunPreTasksExecution(
|
||||
context: PreTasksExecutionContext
|
||||
) {
|
||||
try {
|
||||
const envs = await runPreTasksExecution(context);
|
||||
return {
|
||||
response: JSON.stringify(envs),
|
||||
description: 'handleRunPreTasksExecution',
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
error: e,
|
||||
description: `Error when running preTasksExecution.`,
|
||||
};
|
||||
}
|
||||
}
|
||||
export async function handleRunPostTasksExecution(
|
||||
context: PostTasksExecutionContext
|
||||
) {
|
||||
try {
|
||||
await runPostTasksExecution(context);
|
||||
return {
|
||||
response: 'true',
|
||||
description: 'handleRunPostTasksExecution',
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
error: e,
|
||||
description: `Error when running postTasksExecution.`,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -110,6 +110,16 @@ import {
|
||||
isHandleFlushSyncGeneratorChangesToDiskMessage,
|
||||
} from '../message-types/flush-sync-generator-changes-to-disk';
|
||||
import { handleFlushSyncGeneratorChangesToDisk } from './handle-flush-sync-generator-changes-to-disk';
|
||||
import {
|
||||
isHandlePostTasksExecutionMessage,
|
||||
isHandlePreTasksExecutionMessage,
|
||||
POST_TASKS_EXECUTION,
|
||||
PRE_TASKS_EXECUTION,
|
||||
} from '../message-types/run-tasks-execution-hooks';
|
||||
import {
|
||||
handleRunPostTasksExecution,
|
||||
handleRunPreTasksExecution,
|
||||
} from './handle-tasks-execution-hooks';
|
||||
|
||||
let performanceObserver: PerformanceObserver | undefined;
|
||||
let workspaceWatcherError: Error | undefined;
|
||||
@ -281,6 +291,14 @@ async function handleMessage(socket, data: string) {
|
||||
payload.deletedFiles
|
||||
)
|
||||
);
|
||||
} else if (isHandlePreTasksExecutionMessage(payload)) {
|
||||
await handleResult(socket, PRE_TASKS_EXECUTION, () =>
|
||||
handleRunPreTasksExecution(payload.context)
|
||||
);
|
||||
} else if (isHandlePostTasksExecutionMessage(payload)) {
|
||||
await handleResult(socket, POST_TASKS_EXECUTION, () =>
|
||||
handleRunPostTasksExecution(payload.context)
|
||||
);
|
||||
} else {
|
||||
await respondWithErrorAndExit(
|
||||
socket,
|
||||
|
||||
@ -57,6 +57,10 @@ export type {
|
||||
CreateMetadata,
|
||||
CreateMetadataContext,
|
||||
ProjectsMetadata,
|
||||
PreTasksExecution,
|
||||
PreTasksExecutionContext,
|
||||
PostTasksExecution,
|
||||
PostTasksExecutionContext,
|
||||
} from './project-graph/plugins';
|
||||
|
||||
export { AggregateCreateNodesError } from './project-graph/error-types';
|
||||
@ -64,10 +68,15 @@ export { AggregateCreateNodesError } from './project-graph/error-types';
|
||||
export { createNodesFromFiles } from './project-graph/plugins';
|
||||
|
||||
/**
|
||||
* @category Workspace
|
||||
* @category Tasks
|
||||
*/
|
||||
export type { Task, TaskGraph } from './config/task-graph';
|
||||
|
||||
/**
|
||||
* @category Tasks
|
||||
*/
|
||||
export type { TaskResult, TaskResults } from './tasks-runner/life-cycle';
|
||||
|
||||
/**
|
||||
* @category Workspace
|
||||
*/
|
||||
|
||||
@ -13,6 +13,7 @@ import {
|
||||
cleanupPluginTSTranspiler,
|
||||
pluginTranspilerIsRegistered,
|
||||
} from './transpiler';
|
||||
import { isIsolationEnabled } from './isolation/enabled';
|
||||
|
||||
/**
|
||||
* Stuff for specified NX Plugins.
|
||||
@ -97,23 +98,6 @@ export function cleanupPlugins() {
|
||||
* Stuff for generic loading
|
||||
*/
|
||||
|
||||
function isIsolationEnabled() {
|
||||
// Explicitly enabled, regardless of further conditions
|
||||
if (process.env.NX_ISOLATE_PLUGINS === 'true') {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
// Explicitly disabled
|
||||
process.env.NX_ISOLATE_PLUGINS === 'false' ||
|
||||
// Isolation is disabled on WASM builds currently.
|
||||
IS_WASM
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
// Default value
|
||||
return true;
|
||||
}
|
||||
|
||||
const loadingMethod = isIsolationEnabled()
|
||||
? loadNxPluginInIsolation
|
||||
: loadNxPlugin;
|
||||
|
||||
18
packages/nx/src/project-graph/plugins/isolation/enabled.ts
Normal file
18
packages/nx/src/project-graph/plugins/isolation/enabled.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { IS_WASM } from '../../../native';
|
||||
|
||||
export function isIsolationEnabled() {
|
||||
// Explicitly enabled, regardless of further conditions
|
||||
if (process.env.NX_ISOLATE_PLUGINS === 'true') {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
// Explicitly disabled
|
||||
process.env.NX_ISOLATE_PLUGINS === 'false' ||
|
||||
// Isolation is disabled on WASM builds currently.
|
||||
IS_WASM
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
// Default value
|
||||
return true;
|
||||
}
|
||||
@ -1,13 +1,15 @@
|
||||
import { ProjectGraph } from '../../../config/project-graph';
|
||||
import { PluginConfiguration } from '../../../config/nx-json';
|
||||
import {
|
||||
import type { ProjectGraph } from '../../../config/project-graph';
|
||||
import type { PluginConfiguration } from '../../../config/nx-json';
|
||||
import type {
|
||||
CreateDependenciesContext,
|
||||
CreateMetadataContext,
|
||||
CreateNodesContextV2,
|
||||
PreTasksExecutionContext,
|
||||
PostTasksExecutionContext,
|
||||
} from '../public-api';
|
||||
import type { LoadedNxPlugin } from '../loaded-nx-plugin';
|
||||
import { Serializable } from 'child_process';
|
||||
import { Socket } from 'net';
|
||||
import type { Serializable } from 'child_process';
|
||||
import type { Socket } from 'net';
|
||||
|
||||
export interface PluginWorkerLoadMessage {
|
||||
type: 'load';
|
||||
@ -31,6 +33,8 @@ export interface PluginWorkerLoadResult {
|
||||
hasCreateDependencies: boolean;
|
||||
hasProcessProjectGraph: boolean;
|
||||
hasCreateMetadata: boolean;
|
||||
hasPreTasksExecution: boolean;
|
||||
hasPostTasksExecution: boolean;
|
||||
success: true;
|
||||
}
|
||||
| {
|
||||
@ -110,17 +114,66 @@ export interface PluginCreateMetadataResult {
|
||||
};
|
||||
}
|
||||
|
||||
export interface PluginWorkerPreTasksExecutionMessage {
|
||||
type: 'preTasksExecution';
|
||||
payload: {
|
||||
tx: string;
|
||||
context: PreTasksExecutionContext;
|
||||
};
|
||||
}
|
||||
|
||||
export interface PluginWorkerPreTasksExecutionMessageResult {
|
||||
type: 'preTasksExecutionResult';
|
||||
payload:
|
||||
| {
|
||||
tx: string;
|
||||
success: true;
|
||||
mutations: NodeJS.ProcessEnv;
|
||||
}
|
||||
| {
|
||||
success: false;
|
||||
error: Error;
|
||||
tx: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface PluginWorkerPostTasksExecutionMessage {
|
||||
type: 'postTasksExecution';
|
||||
payload: {
|
||||
tx: string;
|
||||
context: PostTasksExecutionContext;
|
||||
};
|
||||
}
|
||||
|
||||
export interface PluginWorkerPostTasksExecutionMessageResult {
|
||||
type: 'postTasksExecutionResult';
|
||||
payload:
|
||||
| {
|
||||
tx: string;
|
||||
success: true;
|
||||
}
|
||||
| {
|
||||
success: false;
|
||||
error: Error;
|
||||
tx: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type PluginWorkerMessage =
|
||||
| PluginWorkerLoadMessage
|
||||
| PluginWorkerCreateNodesMessage
|
||||
| PluginCreateDependenciesMessage
|
||||
| PluginCreateMetadataMessage;
|
||||
| PluginCreateMetadataMessage
|
||||
| PluginWorkerPreTasksExecutionMessage
|
||||
| PluginWorkerPostTasksExecutionMessage;
|
||||
|
||||
export type PluginWorkerResult =
|
||||
| PluginWorkerLoadResult
|
||||
| PluginWorkerCreateNodesResult
|
||||
| PluginCreateDependenciesResult
|
||||
| PluginCreateMetadataResult;
|
||||
| PluginCreateMetadataResult
|
||||
| PluginWorkerPreTasksExecutionMessageResult
|
||||
| PluginWorkerPostTasksExecutionMessageResult;
|
||||
|
||||
export function isPluginWorkerMessage(
|
||||
message: Serializable
|
||||
@ -133,9 +186,11 @@ export function isPluginWorkerMessage(
|
||||
'load',
|
||||
'createNodes',
|
||||
'createDependencies',
|
||||
'processProjectGraph',
|
||||
'createMetadata',
|
||||
'processProjectGraph',
|
||||
'shutdown',
|
||||
'preTasksExecution',
|
||||
'postTasksExecution',
|
||||
].includes(message.type)
|
||||
);
|
||||
}
|
||||
@ -153,6 +208,8 @@ export function isPluginWorkerResult(
|
||||
'createDependenciesResult',
|
||||
'processProjectGraphResult',
|
||||
'createMetadataResult',
|
||||
'preTasksExecutionResult',
|
||||
'postTasksExecutionResult',
|
||||
].includes(message.type)
|
||||
);
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ const MAX_MESSAGE_WAIT =
|
||||
|
||||
interface PendingPromise {
|
||||
promise: Promise<unknown>;
|
||||
resolver: (result: any) => void;
|
||||
resolver: (result?: any) => void;
|
||||
rejector: (err: any) => void;
|
||||
}
|
||||
|
||||
@ -217,6 +217,46 @@ function createWorkerHandler(
|
||||
);
|
||||
}
|
||||
: undefined,
|
||||
preTasksExecution: result.hasPreTasksExecution
|
||||
? (context) => {
|
||||
const tx =
|
||||
pluginName + worker.pid + ':preTasksExecution:' + txId++;
|
||||
return registerPendingPromise(
|
||||
tx,
|
||||
pending,
|
||||
() => {
|
||||
sendMessageOverSocket(socket, {
|
||||
type: 'preTasksExecution',
|
||||
payload: { tx, context },
|
||||
});
|
||||
},
|
||||
{
|
||||
plugin: pluginName,
|
||||
operation: 'preTasksExecution',
|
||||
}
|
||||
);
|
||||
}
|
||||
: undefined,
|
||||
postTasksExecution: result.hasPostTasksExecution
|
||||
? (context) => {
|
||||
const tx =
|
||||
pluginName + worker.pid + ':postTasksExecution:' + txId++;
|
||||
return registerPendingPromise(
|
||||
tx,
|
||||
pending,
|
||||
() => {
|
||||
sendMessageOverSocket(socket, {
|
||||
type: 'postTasksExecution',
|
||||
payload: { tx, context },
|
||||
});
|
||||
},
|
||||
{
|
||||
plugin: pluginName,
|
||||
operation: 'postTasksExecution',
|
||||
}
|
||||
);
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
} else if (result.success === false) {
|
||||
onloadError(result.error);
|
||||
@ -246,6 +286,22 @@ function createWorkerHandler(
|
||||
rejector(result.error);
|
||||
}
|
||||
},
|
||||
preTasksExecutionResult: ({ tx, ...result }) => {
|
||||
const { resolver, rejector } = pending.get(tx);
|
||||
if (result.success) {
|
||||
resolver(result.mutations);
|
||||
} else if (result.success === false) {
|
||||
rejector(result.error);
|
||||
}
|
||||
},
|
||||
postTasksExecutionResult: ({ tx, ...result }) => {
|
||||
const { resolver, rejector } = pending.get(tx);
|
||||
if (result.success) {
|
||||
resolver();
|
||||
} else if (result.success === false) {
|
||||
rejector(result.error);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { consumeMessage, isPluginWorkerMessage } from './messaging';
|
||||
import { createSerializableError } from '../../../utils/serializable-error';
|
||||
import { consumeMessagesFromSocket } from '../../../utils/consume-messages-from-socket';
|
||||
import type { LoadedNxPlugin } from '../loaded-nx-plugin';
|
||||
|
||||
import { createServer } from 'net';
|
||||
import { unlinkSync } from 'fs';
|
||||
@ -12,7 +13,7 @@ if (process.env.NX_PERF_LOGGING === 'true') {
|
||||
global.NX_GRAPH_CREATION = true;
|
||||
global.NX_PLUGIN_WORKER = true;
|
||||
let connected = false;
|
||||
let plugin;
|
||||
let plugin: LoadedNxPlugin;
|
||||
|
||||
const socketPath = process.argv[2];
|
||||
|
||||
@ -75,6 +76,10 @@ const server = createServer((socket) => {
|
||||
!!plugin.processProjectGraph,
|
||||
hasCreateMetadata:
|
||||
'createMetadata' in plugin && !!plugin.createMetadata,
|
||||
hasPreTasksExecution:
|
||||
'preTasksExecution' in plugin && !!plugin.preTasksExecution,
|
||||
hasPostTasksExecution:
|
||||
'postTasksExecution' in plugin && !!plugin.postTasksExecution,
|
||||
success: true,
|
||||
},
|
||||
};
|
||||
@ -142,6 +147,42 @@ const server = createServer((socket) => {
|
||||
};
|
||||
}
|
||||
},
|
||||
preTasksExecution: async ({ tx, context }) => {
|
||||
try {
|
||||
const mutations = await plugin.preTasksExecution?.(context);
|
||||
return {
|
||||
type: 'preTasksExecutionResult',
|
||||
payload: { success: true, tx, mutations },
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
type: 'preTasksExecutionResult',
|
||||
payload: {
|
||||
success: false,
|
||||
error: createSerializableError(e),
|
||||
tx,
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
postTasksExecution: async ({ tx, context }) => {
|
||||
try {
|
||||
await plugin.postTasksExecution?.(context);
|
||||
return {
|
||||
type: 'postTasksExecutionResult',
|
||||
payload: { success: true, tx },
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
type: 'postTasksExecutionResult',
|
||||
payload: {
|
||||
success: false,
|
||||
error: createSerializableError(e),
|
||||
tx,
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
@ -18,7 +18,10 @@ async function importPluginModule(pluginPath: string): Promise<NxPlugin> {
|
||||
m.default &&
|
||||
('createNodes' in m.default ||
|
||||
'createNodesV2' in m.default ||
|
||||
'createDependencies' in m.default)
|
||||
'createDependencies' in m.default ||
|
||||
'createMetadata' in m.default ||
|
||||
'preTasksExecution' in m.default ||
|
||||
'postTasksExecution' in m.default)
|
||||
) {
|
||||
return m.default;
|
||||
}
|
||||
|
||||
@ -11,9 +11,13 @@ import type {
|
||||
CreateNodesContextV2,
|
||||
CreateNodesResult,
|
||||
NxPluginV2,
|
||||
PostTasksExecutionContext,
|
||||
PreTasksExecutionContext,
|
||||
ProjectsMetadata,
|
||||
} from './public-api';
|
||||
import { createNodesFromFiles } from './utils';
|
||||
import { isIsolationEnabled } from './isolation/enabled';
|
||||
import { isDaemonEnabled } from '../../daemon/client/client';
|
||||
|
||||
export class LoadedNxPlugin {
|
||||
readonly name: string;
|
||||
@ -35,6 +39,12 @@ export class LoadedNxPlugin {
|
||||
graph: ProjectGraph,
|
||||
context: CreateMetadataContext
|
||||
) => Promise<ProjectsMetadata>;
|
||||
readonly preTasksExecution?: (
|
||||
context: PreTasksExecutionContext
|
||||
) => Promise<NodeJS.ProcessEnv>;
|
||||
readonly postTasksExecution?: (
|
||||
context: PostTasksExecutionContext
|
||||
) => Promise<void>;
|
||||
|
||||
readonly options?: unknown;
|
||||
readonly include?: string[];
|
||||
@ -107,10 +117,37 @@ export class LoadedNxPlugin {
|
||||
this.createMetadata = async (graph, context) =>
|
||||
plugin.createMetadata(graph, this.options, context);
|
||||
}
|
||||
|
||||
if (plugin.preTasksExecution) {
|
||||
this.preTasksExecution = async (context: PreTasksExecutionContext) => {
|
||||
const updates = {};
|
||||
let revokeFn: () => void;
|
||||
if (isIsolationEnabled() || isDaemonEnabled()) {
|
||||
const { proxy, revoke } = Proxy.revocable<NodeJS.ProcessEnv>(
|
||||
process.env,
|
||||
{
|
||||
set: (target, key: string, value) => {
|
||||
target[key] = value;
|
||||
updates[key] = value;
|
||||
return true;
|
||||
},
|
||||
}
|
||||
);
|
||||
process.env = proxy;
|
||||
revokeFn = revoke;
|
||||
}
|
||||
await plugin.preTasksExecution(this.options, context);
|
||||
|
||||
if (revokeFn) {
|
||||
revokeFn();
|
||||
}
|
||||
return updates;
|
||||
};
|
||||
|
||||
if (plugin.postTasksExecution) {
|
||||
this.postTasksExecution = async (context: PostTasksExecutionContext) =>
|
||||
plugin.postTasksExecution(this.options, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type CreateNodesResultWithContext = CreateNodesResult & {
|
||||
file: string;
|
||||
pluginName: string;
|
||||
};
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
// This file represents the public API for plugins which live in nx.json's plugins array.
|
||||
// For methods to interact with plugins from within Nx, see `./internal-api.ts`.
|
||||
|
||||
import {
|
||||
import type {
|
||||
FileMap,
|
||||
ProjectGraph,
|
||||
ProjectGraphExternalNode,
|
||||
} from '../../config/project-graph';
|
||||
|
||||
import { ProjectConfiguration } from '../../config/workspace-json-project-json';
|
||||
import type { ProjectConfiguration } from '../../config/workspace-json-project-json';
|
||||
|
||||
import { NxJsonConfiguration } from '../../config/nx-json';
|
||||
import { RawProjectGraphDependency } from '../project-graph-builder';
|
||||
import type { NxJsonConfiguration } from '../../config/nx-json';
|
||||
import type { RawProjectGraphDependency } from '../project-graph-builder';
|
||||
import type { TaskResults } from '../../tasks-runner/life-cycle';
|
||||
|
||||
/**
|
||||
* Context for {@link CreateNodesFunction}
|
||||
@ -146,7 +147,7 @@ export type CreateMetadata<T = unknown> = (
|
||||
) => ProjectsMetadata | Promise<ProjectsMetadata>;
|
||||
|
||||
/**
|
||||
* A plugin for Nx which creates nodes and dependencies for the {@link ProjectGraph}
|
||||
* A plugin which enhances the behavior of Nx
|
||||
*/
|
||||
export type NxPluginV2<TOptions = unknown> = {
|
||||
name: string;
|
||||
@ -176,9 +177,37 @@ export type NxPluginV2<TOptions = unknown> = {
|
||||
* Provides a function to create metadata for the {@link ProjectGraph}
|
||||
*/
|
||||
createMetadata?: CreateMetadata<TOptions>;
|
||||
|
||||
/**
|
||||
* Provides a function to run before the Nx runs tasks
|
||||
*/
|
||||
preTasksExecution?: PreTasksExecution<TOptions>;
|
||||
|
||||
/**
|
||||
* Provides a function to run after the Nx runs tasks
|
||||
*/
|
||||
postTasksExecution?: PostTasksExecution<TOptions>;
|
||||
};
|
||||
|
||||
export type PreTasksExecutionContext = {
|
||||
readonly workspaceRoot: string;
|
||||
readonly nxJsonConfiguration: NxJsonConfiguration;
|
||||
};
|
||||
export type PostTasksExecutionContext = {
|
||||
readonly workspaceRoot: string;
|
||||
readonly nxJsonConfiguration: NxJsonConfiguration;
|
||||
readonly taskResults: TaskResults;
|
||||
};
|
||||
|
||||
export type PreTasksExecution<TOptions = unknown> = (
|
||||
options: TOptions | undefined,
|
||||
context: PreTasksExecutionContext
|
||||
) => void | Promise<void>;
|
||||
export type PostTasksExecution<TOptions = unknown> = (
|
||||
options: TOptions | undefined,
|
||||
context: PostTasksExecutionContext
|
||||
) => void | Promise<void>;
|
||||
/**
|
||||
* A plugin for Nx
|
||||
* A plugin which enhances the behavior of Nx
|
||||
*/
|
||||
export type NxPlugin = NxPluginV2;
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
import type {
|
||||
PostTasksExecutionContext,
|
||||
PreTasksExecutionContext,
|
||||
} from './public-api';
|
||||
import { getPlugins } from './get-plugins';
|
||||
import { isOnDaemon } from '../../daemon/is-on-daemon';
|
||||
import { daemonClient, isDaemonEnabled } from '../../daemon/client/client';
|
||||
|
||||
export async function runPreTasksExecution(
|
||||
pluginContext: PreTasksExecutionContext
|
||||
) {
|
||||
if (isOnDaemon() || !isDaemonEnabled()) {
|
||||
performance.mark(`preTasksExecution:start`);
|
||||
const plugins = await getPlugins(pluginContext.workspaceRoot);
|
||||
const envs = await Promise.all(
|
||||
plugins
|
||||
.filter((p) => p.preTasksExecution)
|
||||
.map(async (plugin) => {
|
||||
performance.mark(`${plugin.name}:preTasksExecution:start`);
|
||||
try {
|
||||
return await plugin.preTasksExecution(pluginContext);
|
||||
} finally {
|
||||
performance.mark(`${plugin.name}:preTasksExecution:end`);
|
||||
performance.measure(
|
||||
`${plugin.name}:preTasksExecution`,
|
||||
`${plugin.name}:preTasksExecution:start`,
|
||||
`${plugin.name}:preTasksExecution:end`
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
if (!isDaemonEnabled()) {
|
||||
applyProcessEnvs(envs);
|
||||
}
|
||||
performance.mark(`preTasksExecution:end`);
|
||||
performance.measure(
|
||||
`preTasksExecution`,
|
||||
`preTasksExecution:start`,
|
||||
`preTasksExecution:end`
|
||||
);
|
||||
return envs;
|
||||
} else {
|
||||
const envs = await daemonClient.runPreTasksExecution(pluginContext);
|
||||
applyProcessEnvs(envs);
|
||||
}
|
||||
}
|
||||
|
||||
function applyProcessEnvs(envs: NodeJS.ProcessEnv[]) {
|
||||
for (const env of envs) {
|
||||
for (const key in env) {
|
||||
process.env[key] = env[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function runPostTasksExecution(
|
||||
context: PostTasksExecutionContext
|
||||
) {
|
||||
if (isOnDaemon() || !isDaemonEnabled()) {
|
||||
performance.mark(`postTasksExecution:start`);
|
||||
const plugins = await getPlugins();
|
||||
await Promise.all(
|
||||
plugins
|
||||
.filter((p) => p.postTasksExecution)
|
||||
.map(async (plugin) => {
|
||||
performance.mark(`${plugin.name}:postTasksExecution:start`);
|
||||
try {
|
||||
await plugin.postTasksExecution(context);
|
||||
} finally {
|
||||
performance.mark(`${plugin.name}:postTasksExecution:end`);
|
||||
performance.measure(
|
||||
`${plugin.name}:postTasksExecution`,
|
||||
`${plugin.name}:postTasksExecution:start`,
|
||||
`${plugin.name}:postTasksExecution:end`
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
performance.mark(`postTasksExecution:end`);
|
||||
performance.measure(
|
||||
`postTasksExecution`,
|
||||
`postTasksExecution:start`,
|
||||
`postTasksExecution:end`
|
||||
);
|
||||
} else {
|
||||
await daemonClient.runPostTasksExecution(context);
|
||||
}
|
||||
}
|
||||
@ -97,7 +97,7 @@ export async function retrieveProjectConfigurationsWithAngularProjects(
|
||||
pluginsToLoad.push(join(__dirname, '../../adapter/angular-json'));
|
||||
}
|
||||
|
||||
const plugins = await getPlugins();
|
||||
const plugins = await getPlugins(workspaceRoot);
|
||||
|
||||
const res = await retrieveProjectConfigurations(
|
||||
plugins,
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
import { TaskStatus } from './tasks-runner';
|
||||
import { Task } from '../config/task-graph';
|
||||
|
||||
/**
|
||||
* The result of a completed {@link Task}
|
||||
*/
|
||||
export interface TaskResult {
|
||||
task: Task;
|
||||
status: TaskStatus;
|
||||
@ -8,6 +11,11 @@ export interface TaskResult {
|
||||
terminalOutput?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A map of {@link TaskResult} keyed by the ID of the completed {@link Task}s
|
||||
*/
|
||||
export type TaskResults = Record<string, TaskResult>;
|
||||
|
||||
export interface TaskMetadata {
|
||||
groupId: number;
|
||||
}
|
||||
|
||||
@ -34,7 +34,12 @@ import {
|
||||
} from '../utils/sync-generators';
|
||||
import { workspaceRoot } from '../utils/workspace-root';
|
||||
import { createTaskGraph } from './create-task-graph';
|
||||
import { CompositeLifeCycle, LifeCycle, TaskResult } from './life-cycle';
|
||||
import {
|
||||
CompositeLifeCycle,
|
||||
LifeCycle,
|
||||
TaskResult,
|
||||
TaskResults,
|
||||
} from './life-cycle';
|
||||
import { createRunManyDynamicOutputRenderer } from './life-cycles/dynamic-run-many-terminal-output-life-cycle';
|
||||
import { createRunOneDynamicOutputRenderer } from './life-cycles/dynamic-run-one-terminal-output-life-cycle';
|
||||
import { StaticRunManyTerminalOutputLifeCycle } from './life-cycles/static-run-many-terminal-output-life-cycle';
|
||||
@ -55,6 +60,10 @@ import { shouldStreamOutput } from './utils';
|
||||
import chalk = require('chalk');
|
||||
import type { Observable } from 'rxjs';
|
||||
import { printPowerpackLicense } from '../utils/powerpack';
|
||||
import {
|
||||
runPostTasksExecution,
|
||||
runPreTasksExecution,
|
||||
} from '../project-graph/plugins/tasks-execution-hooks';
|
||||
|
||||
async function getTerminalOutputLifeCycle(
|
||||
initiatingProject: string,
|
||||
@ -177,23 +186,42 @@ export async function runCommand(
|
||||
const status = await handleErrors(
|
||||
process.env.NX_VERBOSE_LOGGING === 'true',
|
||||
async () => {
|
||||
await runPreTasksExecution({
|
||||
workspaceRoot,
|
||||
nxJsonConfiguration: nxJson,
|
||||
});
|
||||
|
||||
const taskResults = await runCommandForTasks(
|
||||
projectsToRun,
|
||||
currentProjectGraph,
|
||||
{ nxJson },
|
||||
nxArgs,
|
||||
{
|
||||
...nxArgs,
|
||||
skipNxCache:
|
||||
nxArgs.skipNxCache ||
|
||||
process.env.NX_SKIP_NX_CACHE === 'true' ||
|
||||
process.env.NX_DISABLE_NX_CACHE === 'true',
|
||||
},
|
||||
overrides,
|
||||
initiatingProject,
|
||||
extraTargetDependencies,
|
||||
extraOptions
|
||||
);
|
||||
|
||||
return Object.values(taskResults).some(
|
||||
const result = Object.values(taskResults).some(
|
||||
(taskResult) =>
|
||||
taskResult.status === 'failure' || taskResult.status === 'skipped'
|
||||
)
|
||||
? 1
|
||||
: 0;
|
||||
|
||||
await runPostTasksExecution({
|
||||
taskResults,
|
||||
workspaceRoot,
|
||||
nxJsonConfiguration: nxJson,
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
);
|
||||
|
||||
@ -209,7 +237,7 @@ export async function runCommandForTasks(
|
||||
initiatingProject: string | null,
|
||||
extraTargetDependencies: Record<string, (TargetDependencyConfig | string)[]>,
|
||||
extraOptions: { excludeTaskDependencies: boolean; loadDotEnvFiles: boolean }
|
||||
): Promise<{ [id: string]: TaskResult }> {
|
||||
): Promise<TaskResults> {
|
||||
const projectNames = projectsToRun.map((t) => t.name);
|
||||
|
||||
const { projectGraph, taskGraph } = await ensureWorkspaceIsInSyncAndGetGraphs(
|
||||
|
||||
@ -230,7 +230,6 @@ export class TaskOrchestrator {
|
||||
task: Task;
|
||||
status: 'local-cache' | 'local-cache-kept-existing' | 'remote-cache';
|
||||
}> {
|
||||
task.startTime = Date.now();
|
||||
const cachedResult = await this.cache.get(task);
|
||||
if (!cachedResult || cachedResult.code !== 0) return null;
|
||||
|
||||
@ -241,7 +240,6 @@ export class TaskOrchestrator {
|
||||
if (shouldCopyOutputsFromCache) {
|
||||
await this.cache.copyFilesFromCache(task.hash, cachedResult, outputs);
|
||||
}
|
||||
task.endTime = Date.now();
|
||||
const status = cachedResult.remote
|
||||
? 'remote-cache'
|
||||
: shouldCopyOutputsFromCache
|
||||
@ -545,6 +543,10 @@ export class TaskOrchestrator {
|
||||
|
||||
// region Lifecycle
|
||||
private async preRunSteps(tasks: Task[], metadata: TaskMetadata) {
|
||||
const now = Date.now();
|
||||
for (const task of tasks) {
|
||||
task.startTime = now;
|
||||
}
|
||||
await this.options.lifeCycle.startTasks(tasks, metadata);
|
||||
}
|
||||
|
||||
@ -558,7 +560,9 @@ export class TaskOrchestrator {
|
||||
doNotSkipCache: boolean,
|
||||
{ groupId }: { groupId: number }
|
||||
) {
|
||||
const now = Date.now();
|
||||
for (const task of tasks) {
|
||||
task.endTime = now;
|
||||
await this.recordOutputsHash(task);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user