@lage-run/cli 0.21.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.json CHANGED
@@ -2,7 +2,133 @@
2
2
  "name": "@lage-run/cli",
3
3
  "entries": [
4
4
  {
5
- "date": "Wed, 25 Sep 2024 20:27:33 GMT",
5
+ "date": "Wed, 02 Oct 2024 20:25:42 GMT",
6
+ "version": "0.23.0",
7
+ "tag": "@lage-run/cli_v0.23.0",
8
+ "comments": {
9
+ "minor": [
10
+ {
11
+ "author": "kchau@microsoft.com",
12
+ "package": "@lage-run/cli",
13
+ "commit": "6ecbd570669a07fa87429af5de13ec1adc58b864",
14
+ "comment": "Simulate file access for lage server"
15
+ },
16
+ {
17
+ "author": "beachball",
18
+ "package": "@lage-run/cli",
19
+ "comment": "Bump @lage-run/cache to v1.3.4",
20
+ "commit": "not available"
21
+ },
22
+ {
23
+ "author": "beachball",
24
+ "package": "@lage-run/cli",
25
+ "comment": "Bump @lage-run/config to v0.4.3",
26
+ "commit": "not available"
27
+ },
28
+ {
29
+ "author": "beachball",
30
+ "package": "@lage-run/cli",
31
+ "comment": "Bump @lage-run/globby to v14.2.0",
32
+ "commit": "not available"
33
+ },
34
+ {
35
+ "author": "beachball",
36
+ "package": "@lage-run/cli",
37
+ "comment": "Bump @lage-run/hasher to v1.6.0",
38
+ "commit": "not available"
39
+ },
40
+ {
41
+ "author": "beachball",
42
+ "package": "@lage-run/cli",
43
+ "comment": "Bump @lage-run/reporters to v1.2.11",
44
+ "commit": "not available"
45
+ },
46
+ {
47
+ "author": "beachball",
48
+ "package": "@lage-run/cli",
49
+ "comment": "Bump @lage-run/rpc to v1.2.2",
50
+ "commit": "not available"
51
+ },
52
+ {
53
+ "author": "beachball",
54
+ "package": "@lage-run/cli",
55
+ "comment": "Bump @lage-run/runners to v1.0.3",
56
+ "commit": "not available"
57
+ },
58
+ {
59
+ "author": "beachball",
60
+ "package": "@lage-run/cli",
61
+ "comment": "Bump @lage-run/scheduler to v1.3.2",
62
+ "commit": "not available"
63
+ },
64
+ {
65
+ "author": "beachball",
66
+ "package": "@lage-run/cli",
67
+ "comment": "Bump @lage-run/scheduler-types to v0.3.16",
68
+ "commit": "not available"
69
+ },
70
+ {
71
+ "author": "beachball",
72
+ "package": "@lage-run/cli",
73
+ "comment": "Bump @lage-run/target-graph to v0.9.0",
74
+ "commit": "not available"
75
+ },
76
+ {
77
+ "author": "beachball",
78
+ "package": "@lage-run/cli",
79
+ "comment": "Bump @lage-run/worker-threads-pool to v0.8.3",
80
+ "commit": "not available"
81
+ }
82
+ ]
83
+ }
84
+ },
85
+ {
86
+ "date": "Fri, 27 Sep 2024 20:03:49 GMT",
87
+ "version": "0.22.0",
88
+ "tag": "@lage-run/cli_v0.22.0",
89
+ "comments": {
90
+ "minor": [
91
+ {
92
+ "author": "kchau@microsoft.com",
93
+ "package": "@lage-run/cli",
94
+ "commit": "2919f9041f931dc6ef65017f7aedb9fef9dab66d",
95
+ "comment": "Simulate file access for lage server"
96
+ },
97
+ {
98
+ "author": "beachball",
99
+ "package": "@lage-run/cli",
100
+ "comment": "Bump @lage-run/globby to v14.1.0",
101
+ "commit": "not available"
102
+ },
103
+ {
104
+ "author": "beachball",
105
+ "package": "@lage-run/cli",
106
+ "comment": "Bump @lage-run/hasher to v1.5.0",
107
+ "commit": "not available"
108
+ },
109
+ {
110
+ "author": "beachball",
111
+ "package": "@lage-run/cli",
112
+ "comment": "Bump @lage-run/rpc to v1.2.1",
113
+ "commit": "not available"
114
+ },
115
+ {
116
+ "author": "beachball",
117
+ "package": "@lage-run/cli",
118
+ "comment": "Bump @lage-run/scheduler to v1.3.1",
119
+ "commit": "not available"
120
+ },
121
+ {
122
+ "author": "beachball",
123
+ "package": "@lage-run/cli",
124
+ "comment": "Bump @lage-run/worker-threads-pool to v0.8.2",
125
+ "commit": "not available"
126
+ }
127
+ ]
128
+ }
129
+ },
130
+ {
131
+ "date": "Wed, 25 Sep 2024 20:28:10 GMT",
6
132
  "version": "0.21.0",
7
133
  "tag": "@lage-run/cli_v0.21.0",
8
134
  "comments": {
package/CHANGELOG.md CHANGED
@@ -1,12 +1,44 @@
1
1
  # Change Log - @lage-run/cli
2
2
 
3
- <!-- This log was last generated on Wed, 25 Sep 2024 20:27:33 GMT and should not be manually modified. -->
3
+ <!-- This log was last generated on Wed, 02 Oct 2024 20:25:42 GMT and should not be manually modified. -->
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 0.23.0
8
+
9
+ Wed, 02 Oct 2024 20:25:42 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - Simulate file access for lage server (kchau@microsoft.com)
14
+ - Bump @lage-run/cache to v1.3.4
15
+ - Bump @lage-run/config to v0.4.3
16
+ - Bump @lage-run/globby to v14.2.0
17
+ - Bump @lage-run/hasher to v1.6.0
18
+ - Bump @lage-run/reporters to v1.2.11
19
+ - Bump @lage-run/rpc to v1.2.2
20
+ - Bump @lage-run/runners to v1.0.3
21
+ - Bump @lage-run/scheduler to v1.3.2
22
+ - Bump @lage-run/scheduler-types to v0.3.16
23
+ - Bump @lage-run/target-graph to v0.9.0
24
+ - Bump @lage-run/worker-threads-pool to v0.8.3
25
+
26
+ ## 0.22.0
27
+
28
+ Fri, 27 Sep 2024 20:03:49 GMT
29
+
30
+ ### Minor changes
31
+
32
+ - Simulate file access for lage server (kchau@microsoft.com)
33
+ - Bump @lage-run/globby to v14.1.0
34
+ - Bump @lage-run/hasher to v1.5.0
35
+ - Bump @lage-run/rpc to v1.2.1
36
+ - Bump @lage-run/scheduler to v1.3.1
37
+ - Bump @lage-run/worker-threads-pool to v0.8.2
38
+
7
39
  ## 0.21.0
8
40
 
9
- Wed, 25 Sep 2024 20:27:33 GMT
41
+ Wed, 25 Sep 2024 20:28:10 GMT
10
42
 
11
43
  ### Minor changes
12
44
 
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require("../lib/server.js");
@@ -1,6 +1,6 @@
1
1
  import type { Command } from "commander";
2
2
  import type { ReporterInitOptions } from "../../types/ReporterInitOptions.js";
3
- interface RunOptions extends ReporterInitOptions {
3
+ interface InfoActionOptions extends ReporterInitOptions {
4
4
  dependencies: boolean;
5
5
  dependents: boolean;
6
6
  since: string;
@@ -9,9 +9,10 @@ interface RunOptions extends ReporterInitOptions {
9
9
  cache: boolean;
10
10
  nodeArg: string;
11
11
  ignore: string[];
12
+ server: string;
12
13
  }
13
14
  /**
14
- * (UNSTABLE) The info command displays information about a target graph in a workspace.
15
+ * The info command displays information about a target graph in a workspace.
15
16
  * The generated output can be read and used by other task runners, such as BuildXL.
16
17
  *
17
18
  * Expected format:
@@ -47,5 +48,5 @@ interface RunOptions extends ReporterInitOptions {
47
48
  * ...
48
49
  * ]
49
50
  */
50
- export declare function infoAction(options: RunOptions, command: Command): Promise<void>;
51
+ export declare function infoAction(options: InfoActionOptions, command: Command): Promise<void>;
51
52
  export {};
@@ -14,9 +14,11 @@ const _config = require("@lage-run/config");
14
14
  const _workspacetools = require("workspace-tools");
15
15
  const _getFilteredPackages = require("../../filter/getFilteredPackages.js");
16
16
  const _logger = /*#__PURE__*/ _interop_require_default(require("@lage-run/logger"));
17
- const _path = /*#__PURE__*/ _interop_require_default(require("path"));
18
17
  const _targetgraph = require("@lage-run/target-graph");
18
+ const _path = /*#__PURE__*/ _interop_require_default(require("path"));
19
+ const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
19
20
  const _initializeReporters = require("../initializeReporters.js");
21
+ const _runners = require("@lage-run/runners");
20
22
  function _interop_require_default(obj) {
21
23
  return obj && obj.__esModule ? obj : {
22
24
  default: obj
@@ -28,22 +30,11 @@ async function infoAction(options, command) {
28
30
  const logger = (0, _logger.default)();
29
31
  options.logLevel = options.logLevel ?? "info";
30
32
  options.reporter = options.reporter ?? "json";
33
+ options.server = typeof options.server === "string" ? options.server : "localhost:5332";
31
34
  (0, _initializeReporters.initializeReporters)(logger, options);
32
35
  const root = (0, _workspacetools.getWorkspaceRoot)(cwd);
33
36
  const packageInfos = (0, _workspacetools.getPackageInfos)(root);
34
- const targetGraph = prepareAndCreateTargetGraph(config, logger, root, options, packageInfos, command);
35
- const scope = prepareAndGetFilteredPackages(config, logger, root, options, packageInfos);
36
- const packageTasks = processTargets(targetGraph.targets, packageInfos, config);
37
- logger.info("info", {
38
- command: command.args,
39
- scope,
40
- packageTasks: [
41
- ...packageTasks.values()
42
- ].flat()
43
- });
44
- }
45
- function prepareAndCreateTargetGraph(config, logger, root, options, packageInfos, command) {
46
- const { tasks } = (0, _filterArgsForTasks.filterArgsForTasks)(command.args);
37
+ const { tasks , taskArgs } = (0, _filterArgsForTasks.filterArgsForTasks)(command.args);
47
38
  const targetGraph = (0, _createTargetGraph.createTargetGraph)({
48
39
  logger,
49
40
  root,
@@ -58,9 +49,6 @@ function prepareAndCreateTargetGraph(config, logger, root, options, packageInfos
58
49
  tasks,
59
50
  packageInfos
60
51
  });
61
- return targetGraph;
62
- }
63
- function prepareAndGetFilteredPackages(config, logger, root, options, packageInfos) {
64
52
  const scope = (0, _getFilteredPackages.getFilteredPackages)({
65
53
  root,
66
54
  packageInfos,
@@ -72,76 +60,123 @@ function prepareAndGetFilteredPackages(config, logger, root, options, packageInf
72
60
  repoWideChanges: config.repoWideChanges,
73
61
  sinceIgnoreGlobs: options.ignore.concat(config.ignore)
74
62
  });
75
- return scope;
76
- }
77
- function processTargets(targets, packageInfos, config) {
78
- const packageTasks = new Map(); // Initialize the map with the correct type
79
- const dependenciesCache = new Map();
80
- for (const target of targets.values()){
81
- if (shouldSkipTarget(target, packageInfos)) {
82
- continue;
83
- }
84
- const packageTask = generatePackageTask(target, targets, packageInfos, dependenciesCache, config);
85
- if (packageTask) {
86
- // Check if the packageTask is defined before accessing its properties
87
- const packageName = packageTask.package;
88
- if (!packageTasks.has(packageName)) {
89
- packageTasks.set(packageName, []);
63
+ const pickerOptions = {
64
+ npmScript: {
65
+ script: require.resolve("./runners/NpmScriptRunner.js"),
66
+ options: {
67
+ nodeArg: options.nodeArg,
68
+ taskArgs,
69
+ npmCmd: config.npmClient
90
70
  }
91
- packageTasks.get(packageName).push(packageTask); // Use the non-null assertion operator to avoid type errors
71
+ },
72
+ worker: {
73
+ script: require.resolve("./runners/WorkerRunner.js"),
74
+ options: {
75
+ taskArgs
76
+ }
77
+ },
78
+ noop: {
79
+ script: require.resolve("./runners/NoOpRunner.js"),
80
+ options: {}
92
81
  }
93
- }
94
- return packageTasks;
82
+ };
83
+ const runnerPicker = new _runners.TargetRunnerPicker(pickerOptions);
84
+ const optimizedTargets = await optimizeTargetGraph(targetGraph, runnerPicker);
85
+ const binPaths = getBinPaths();
86
+ const packageTasks = optimizedTargets.map((target)=>generatePackageTask(target, taskArgs, config, options, binPaths));
87
+ logger.info("info", {
88
+ command: command.args,
89
+ scope,
90
+ packageTasks
91
+ });
95
92
  }
96
- function isTargetNoop(target, packageInfos) {
97
- return !packageInfos[target.packageName]?.scripts?.[target.task];
93
+ function getBinPaths() {
94
+ let dir = __dirname;
95
+ let packageJsonPath = "";
96
+ while(dir !== "/"){
97
+ packageJsonPath = _path.default.join(dir, "package.json");
98
+ if (_fs.default.existsSync(packageJsonPath)) {
99
+ break;
100
+ }
101
+ dir = _path.default.dirname(dir);
102
+ }
103
+ const packageJson = JSON.parse(_fs.default.readFileSync(_path.default.join(dir, "package.json"), "utf8"));
104
+ return {
105
+ lage: _path.default.join(dir, packageJson.bin.lage),
106
+ "lage-server": _path.default.join(dir, packageJson.bin["lage-server"])
107
+ };
98
108
  }
99
- function shouldSkipTarget(target, packageInfos) {
100
- return target.id === (0, _targetgraph.getStartTargetId)() || isTargetNoop(target, packageInfos);
109
+ async function optimizeTargetGraph(graph, runnerPicker) {
110
+ const targetMinimizedNodes = await (0, _targetgraph.removeNodes)([
111
+ ...graph.targets.values()
112
+ ] ?? [], async (target)=>{
113
+ if (target.type === "noop") {
114
+ return true;
115
+ }
116
+ const runner = await runnerPicker.pick(target);
117
+ if (!await runner.shouldRun(target)) {
118
+ return true;
119
+ }
120
+ return false;
121
+ });
122
+ return (0, _targetgraph.transitiveReduction)(targetMinimizedNodes);
101
123
  }
102
- function generatePackageTask(target, targets, packageInfos, dependenciesCache, config) {
103
- const command = generateCommand(target, config);
124
+ function generatePackageTask(target, taskArgs, config, options, binPaths) {
125
+ const command = generateCommand(target, taskArgs, config, options, binPaths);
104
126
  const workingDirectory = getWorkingDirectory(target);
105
- const dependenciesSet = resolveDependencies(target.dependencies, targets, packageInfos, dependenciesCache);
106
127
  const packageTask = {
107
128
  id: target.id,
108
129
  command,
109
- dependencies: [
110
- ...dependenciesSet
111
- ],
130
+ dependencies: target.dependencies,
112
131
  workingDirectory,
113
- package: target.packageName,
132
+ package: target.packageName ?? "",
114
133
  task: target.task
115
134
  };
116
135
  return packageTask;
117
136
  }
118
- function resolveDependencies(dependencies, targets, packageInfos, dependenciesCache) {
119
- const result = new Set();
120
- for (const dependency of dependencies){
121
- if (dependency === (0, _targetgraph.getStartTargetId)()) {
122
- continue;
137
+ function generateCommand(target, taskArgs, config, options, binPaths) {
138
+ if (target.type === "npmScript") {
139
+ const npmClient = config.npmClient ?? "npm";
140
+ const command = [
141
+ npmClient,
142
+ ...getNpmArgs(target.task, taskArgs)
143
+ ];
144
+ return command;
145
+ } else if (target.type === "worker" && options.server) {
146
+ const [host, port] = options.server.split(":");
147
+ const command = [
148
+ process.execPath,
149
+ binPaths["lage-server"]
150
+ ];
151
+ if (host) {
152
+ command.push("--host", host);
123
153
  }
124
- if (!dependenciesCache.has(dependency)) {
125
- const dependencyTarget = targets.get(dependency);
126
- if (isTargetNoop(dependencyTarget, packageInfos)) {
127
- dependenciesCache.set(dependency, resolveDependencies(dependencyTarget.dependencies, targets, packageInfos, dependenciesCache));
128
- } else {
129
- dependenciesCache.set(dependency, new Set([
130
- dependency
131
- ]));
132
- }
154
+ if (port) {
155
+ command.push("--port", port);
156
+ }
157
+ if (options.concurrency) {
158
+ command.push("--concurrency", options.concurrency.toString());
159
+ }
160
+ if (target.packageName) {
161
+ command.push(target.packageName);
133
162
  }
134
- dependenciesCache.get(dependency)?.forEach((dependency)=>result.add(dependency));
163
+ if (target.task) {
164
+ command.push(target.task);
165
+ }
166
+ command.push(...taskArgs);
167
+ return command;
168
+ } else if (target.type === "worker") {
169
+ const command = [
170
+ process.execPath,
171
+ binPaths.lage,
172
+ "exec"
173
+ ];
174
+ command.push(target.packageName ?? "");
175
+ command.push(target.task);
176
+ command.push(...taskArgs);
177
+ return command;
135
178
  }
136
- return result;
137
- }
138
- function generateCommand(target, config) {
139
- const npmClient = config.npmClient ?? "npm";
140
- const command = [
141
- npmClient,
142
- ...getNpmArgs(target.task, target.taskArgs)
143
- ];
144
- return command;
179
+ return [];
145
180
  }
146
181
  function getWorkingDirectory(target) {
147
182
  const cwd = process.cwd();
@@ -13,4 +13,8 @@ const _action = require("./action.js");
13
13
  const _addFilterOptions = require("../addFilterOptions.js");
14
14
  const _addLoggerOptions = require("../addLoggerOptions.js");
15
15
  const infoCommand = new _commander.Command("info");
16
- (0, _addFilterOptions.addFilterOptions)((0, _addLoggerOptions.addLoggerOptions)(infoCommand)).action(_action.infoAction);
16
+ (0, _addFilterOptions.addFilterOptions)((0, _addLoggerOptions.addLoggerOptions)(infoCommand));
17
+ infoCommand.description("Display information about a target graph in a workspace.\n" + "It is used by BuildXL to build a pip-graph");
18
+ infoCommand.option("--server [host:port]", "Run targets of type 'worker' on a background service");
19
+ infoCommand.option("--nodearg|--node-arg <nodeArg>", 'arguments to be passed to node (e.g. --nodearg="--max_old_space_size=1234 --heap-prof" - set via "NODE_OPTIONS" environment variable');
20
+ infoCommand.action(_action.infoAction);
@@ -0,0 +1 @@
1
+ export { NoOpRunner } from "@lage-run/runners";
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "NoOpRunner", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return _runners.NoOpRunner;
9
+ }
10
+ });
11
+ const _runners = require("@lage-run/runners");
@@ -0,0 +1 @@
1
+ export { NpmScriptRunner } from "@lage-run/runners";
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "NpmScriptRunner", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return _runners.NpmScriptRunner;
9
+ }
10
+ });
11
+ const _runners = require("@lage-run/runners");
@@ -0,0 +1 @@
1
+ export { WorkerRunner } from "@lage-run/runners";
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "WorkerRunner", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return _runners.WorkerRunner;
9
+ }
10
+ });
11
+ const _runners = require("@lage-run/runners");
@@ -7,7 +7,7 @@ interface CreateTargetGraphOptions {
7
7
  dependencies: boolean;
8
8
  dependents: boolean;
9
9
  since: string;
10
- scope: string[];
10
+ scope?: string[];
11
11
  ignore: string[];
12
12
  repoWideChanges: string[];
13
13
  pipeline: PipelineDefinition;
@@ -13,6 +13,7 @@ const _initializeReporters = require("../initializeReporters.js");
13
13
  const _lageService = require("./lageService.js");
14
14
  const _filterArgsForTasks = require("../run/filterArgsForTasks.js");
15
15
  const _rpc = require("@lage-run/rpc");
16
+ const _simulateFileAccess = require("./simulateFileAccess.js");
16
17
  function _interop_require_default(obj) {
17
18
  return obj && obj.__esModule ? obj : {
18
19
  default: obj
@@ -48,8 +49,12 @@ async function executeOnServer(args, client, logger) {
48
49
  task,
49
50
  taskArgs
50
51
  });
51
- logger.info(`Task ${response.packageName} #${response.task} exited with code ${response.exitCode} `);
52
+ logger.info(`Task ${response.packageName} ${response.task} exited with code ${response.exitCode} `);
52
53
  process.exitCode = response.exitCode;
54
+ if (response.exitCode === 0) {
55
+ await (0, _simulateFileAccess.simulateFileAccess)(logger, response.inputs, response.outputs);
56
+ }
57
+ logger.info("Task execution finished");
53
58
  }
54
59
  async function serverAction(options, command) {
55
60
  const { port =5332 , host ="localhost" , timeout =1 } = options;
@@ -65,12 +70,17 @@ async function serverAction(options, command) {
65
70
  } else {
66
71
  logger.info(`Starting server on http://${host}:${port}`);
67
72
  const abortController = new AbortController();
68
- const lageService = await (0, _lageService.createLageService)(process.cwd(), abortController, logger, options.concurrency);
69
- const server = await (0, _rpc.createServer)(lageService, abortController);
70
- server.addHook("onRequest", (req, res, next)=>{
71
- resetTimer(logger, timeout, abortController, server);
72
- next();
73
+ const lageService = await (0, _lageService.createLageService)({
74
+ cwd: process.cwd(),
75
+ serverControls: {
76
+ abortController,
77
+ countdownToShutdown: ()=>resetTimer(logger, timeout, abortController, server),
78
+ clearCountdown: clearTimer
79
+ },
80
+ logger,
81
+ maxWorkers: options.concurrency
73
82
  });
83
+ const server = await (0, _rpc.createServer)(lageService, abortController);
74
84
  await server.listen({
75
85
  host,
76
86
  port
@@ -86,12 +96,15 @@ async function serverAction(options, command) {
86
96
  }
87
97
  let timeoutHandle;
88
98
  function resetTimer(logger, timeout, abortController, server) {
89
- if (timeoutHandle) {
90
- clearTimeout(timeoutHandle);
91
- }
92
- timeoutHandle = setTimeout(()=>{
99
+ clearTimer();
100
+ timeoutHandle = globalThis.setTimeout(()=>{
93
101
  logger.info(`Server timed out after ${timeout} seconds`);
94
102
  abortController.abort();
95
103
  server.close();
96
104
  }, timeout * 1000);
97
105
  }
106
+ function clearTimer() {
107
+ if (timeoutHandle) {
108
+ globalThis.clearTimeout(timeoutHandle);
109
+ }
110
+ }
@@ -0,0 +1,4 @@
1
+ import type { CacheOptions } from "@lage-run/config";
2
+ import type { PackageTree } from "@lage-run/hasher";
3
+ import type { Target } from "@lage-run/target-graph";
4
+ export declare function getOutputFiles(root: string, target: Target, outputGlob: CacheOptions["outputGlob"], packageTree: PackageTree): string[];
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "getOutputFiles", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return getOutputFiles;
9
+ }
10
+ });
11
+ const _globby = require("@lage-run/globby");
12
+ const _path = /*#__PURE__*/ _interop_require_default(require("path"));
13
+ function _interop_require_default(obj) {
14
+ return obj && obj.__esModule ? obj : {
15
+ default: obj
16
+ };
17
+ }
18
+ function getOutputFiles(root, target, outputGlob, packageTree) {
19
+ const patterns = target.outputs ?? outputGlob ?? [
20
+ "**/*"
21
+ ];
22
+ const sourceControlledFiles = new Set(packageTree.getPackageFiles(target.packageName ?? "", patterns));
23
+ const outputs = (0, _globby.glob)(patterns, {
24
+ cwd: target.cwd,
25
+ gitignore: false
26
+ }).map((file)=>_path.default.relative(root, _path.default.join(target.cwd, file))).filter((file)=>!sourceControlledFiles.has(file));
27
+ return outputs;
28
+ }
@@ -1,4 +1,13 @@
1
1
  /// <reference types="node" />
2
2
  import type { Logger } from "@lage-run/logger";
3
3
  import type { ILageService } from "@lage-run/rpc";
4
- export declare function createLageService(cwd: string, abortController: AbortController, logger: Logger, maxWorkers?: number): Promise<ILageService>;
4
+ export declare function createLageService({ cwd, serverControls, logger, maxWorkers, }: {
5
+ cwd: string;
6
+ serverControls: {
7
+ abortController: AbortController;
8
+ countdownToShutdown: () => void;
9
+ clearCountdown: () => void;
10
+ };
11
+ logger: Logger;
12
+ maxWorkers?: number;
13
+ }): Promise<ILageService>;
@@ -13,6 +13,9 @@ const _targetgraph = require("@lage-run/target-graph");
13
13
  const _workspacetools = require("workspace-tools");
14
14
  const _createTargetGraph = require("../run/createTargetGraph.js");
15
15
  const _workerthreadspool = require("@lage-run/worker-threads-pool");
16
+ const _hasher = require("@lage-run/hasher");
17
+ const _getOutputFiles = require("./getOutputFiles.js");
18
+ const _globby = require("@lage-run/globby");
16
19
  function findAllTasks(pipeline) {
17
20
  const tasks = new Set();
18
21
  for (const key of Object.keys(pipeline)){
@@ -25,18 +28,15 @@ function findAllTasks(pipeline) {
25
28
  }
26
29
  return Array.from(tasks);
27
30
  }
28
- let targetGraph;
29
- let config;
31
+ let context;
30
32
  async function initializeOnce(cwd, logger) {
31
- if (!config) {
32
- config = await (0, _config.getConfig)(cwd);
33
- }
34
- if (!targetGraph) {
35
- const { pipeline } = config;
33
+ if (!context) {
34
+ const config = await (0, _config.getConfig)(cwd);
36
35
  const root = (0, _workspacetools.getWorkspaceRoot)(cwd);
36
+ const { pipeline } = config;
37
37
  const packageInfos = (0, _workspacetools.getPackageInfos)(root);
38
38
  const tasks = findAllTasks(pipeline);
39
- targetGraph = (0, _createTargetGraph.createTargetGraph)({
39
+ const targetGraph = (0, _createTargetGraph.createTargetGraph)({
40
40
  logger,
41
41
  root,
42
42
  dependencies: false,
@@ -44,28 +44,46 @@ async function initializeOnce(cwd, logger) {
44
44
  ignore: [],
45
45
  pipeline,
46
46
  repoWideChanges: config.repoWideChanges,
47
- scope: [],
47
+ scope: undefined,
48
48
  since: "",
49
49
  outputs: config.cacheOptions.outputGlob,
50
50
  tasks,
51
51
  packageInfos
52
52
  });
53
+ const dependencyMap = (0, _workspacetools.createDependencyMap)(packageInfos, {
54
+ withDevDependencies: true,
55
+ withPeerDependencies: false
56
+ });
57
+ const packageTree = new _hasher.PackageTree({
58
+ root,
59
+ packageInfos,
60
+ includeUntracked: true
61
+ });
62
+ await packageTree.initialize();
63
+ context = {
64
+ config,
65
+ targetGraph,
66
+ packageTree,
67
+ dependencyMap,
68
+ root
69
+ };
53
70
  }
54
- return {
55
- config,
56
- targetGraph
57
- };
71
+ return context;
58
72
  }
59
73
  let pool;
60
- async function createLageService(cwd, abortController, logger, maxWorkers) {
74
+ async function createLageService({ cwd , serverControls , logger , maxWorkers }) {
61
75
  logger.info(`Server started with ${maxWorkers} workers`);
62
76
  pool = new _workerthreadspool.WorkerPool({
63
77
  script: require.resolve("./singleTargetWorker.js"),
64
78
  maxWorkers
65
79
  });
66
- abortController.signal.addEventListener("abort", ()=>{
80
+ serverControls.abortController.signal.addEventListener("abort", ()=>{
67
81
  pool?.close();
68
82
  });
83
+ pool?.on("idle", ()=>{
84
+ logger.info("All workers are idle, shutting down after timeout");
85
+ serverControls.countdownToShutdown();
86
+ });
69
87
  return {
70
88
  async ping () {
71
89
  return {
@@ -73,7 +91,8 @@ async function createLageService(cwd, abortController, logger, maxWorkers) {
73
91
  };
74
92
  },
75
93
  async runTarget (request) {
76
- const { config , targetGraph } = await initializeOnce(cwd, logger);
94
+ serverControls.clearCountdown();
95
+ const { config , targetGraph , dependencyMap , packageTree , root } = await initializeOnce(cwd, logger);
77
96
  const runners = {
78
97
  npmScript: {
79
98
  script: require.resolve("../run/runners/NpmScriptRunner.js"),
@@ -94,7 +113,8 @@ async function createLageService(cwd, abortController, logger, maxWorkers) {
94
113
  options: {}
95
114
  }
96
115
  };
97
- if (!targetGraph.targets.has((0, _targetgraph.getTargetId)(request.packageName, request.task))) {
116
+ const id = (0, _targetgraph.getTargetId)(request.packageName, request.task);
117
+ if (!targetGraph.targets.has(id)) {
98
118
  logger.error(`Target not found: ${request.packageName}#${request.task}`);
99
119
  return {
100
120
  packageName: request.packageName,
@@ -102,7 +122,7 @@ async function createLageService(cwd, abortController, logger, maxWorkers) {
102
122
  exitCode: 1
103
123
  };
104
124
  }
105
- const target = targetGraph.targets.get((0, _targetgraph.getTargetId)(request.packageName, request.task));
125
+ const target = targetGraph.targets.get(id);
106
126
  const task = {
107
127
  target,
108
128
  runners
@@ -121,16 +141,32 @@ async function createLageService(cwd, abortController, logger, maxWorkers) {
121
141
  pipedStdout.unpipe(process.stdout);
122
142
  pipedStderr.unpipe(process.stderr);
123
143
  });
144
+ const globalInputs = target.environmentGlob ? (0, _globby.glob)(target.environmentGlob, {
145
+ cwd: root,
146
+ gitignore: true
147
+ }) : (0, _globby.glob)(config.cacheOptions?.environmentGlob, {
148
+ cwd: root,
149
+ gitignore: true
150
+ });
151
+ const inputs = ((0, _hasher.getInputFiles)(target, dependencyMap, packageTree) ?? []).concat(globalInputs);
124
152
  return {
125
153
  packageName: request.packageName,
126
154
  task: request.task,
127
- exitCode: 0
155
+ exitCode: 0,
156
+ hash: "",
157
+ inputs,
158
+ outputs: (0, _getOutputFiles.getOutputFiles)(root, target, config.cacheOptions?.outputGlob, packageTree),
159
+ id
128
160
  };
129
161
  } catch (e) {
130
162
  return {
131
163
  packageName: request.packageName,
132
164
  task: request.task,
133
- exitCode: 1
165
+ exitCode: 1,
166
+ hash: "",
167
+ inputs: [],
168
+ outputs: [],
169
+ id
134
170
  };
135
171
  }
136
172
  }
@@ -0,0 +1,2 @@
1
+ import type { Logger } from "@lage-run/logger";
2
+ export declare function simulateFileAccess(logger: Logger, inputs: string[], outputs: string[]): Promise<void>;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "simulateFileAccess", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return simulateFileAccess;
9
+ }
10
+ });
11
+ const _path = /*#__PURE__*/ _interop_require_default(require("path"));
12
+ const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
13
+ const _workspacetools = require("workspace-tools");
14
+ function _interop_require_default(obj) {
15
+ return obj && obj.__esModule ? obj : {
16
+ default: obj
17
+ };
18
+ }
19
+ async function simulateFileAccess(logger, inputs, outputs) {
20
+ const root = (0, _workspacetools.getWorkspaceRoot)(process.cwd());
21
+ logger.silly("Now probing and touching inputs and outputs");
22
+ // probe input files
23
+ let fd;
24
+ for (const input of inputs){
25
+ fd = _fs.default.openSync(_path.default.join(root, input), "r");
26
+ _fs.default.closeSync(fd);
27
+ }
28
+ // touch output files
29
+ const time = new Date();
30
+ for (const output of outputs){
31
+ try {
32
+ _fs.default.utimesSync(_path.default.join(root, output), time, time);
33
+ } catch (e) {
34
+ // ignore
35
+ }
36
+ }
37
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lage-run/cli",
3
- "version": "0.21.0",
3
+ "version": "0.23.0",
4
4
  "description": "Command Line Interface for Lage",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,7 +8,8 @@
8
8
  },
9
9
  "homepage": "https://microsoft.github.io/lage/",
10
10
  "bin": {
11
- "lage": "./bin/lage"
11
+ "lage": "./bin/lage.js",
12
+ "lage-server": "./bin/lage-server.js"
12
13
  },
13
14
  "license": "MIT",
14
15
  "main": "lib/index.js",
@@ -20,17 +21,18 @@
20
21
  "lint": "monorepo-scripts lint"
21
22
  },
22
23
  "dependencies": {
23
- "@lage-run/cache": "^1.3.3",
24
- "@lage-run/config": "^0.4.2",
25
- "@lage-run/hasher": "^1.4.0",
24
+ "@lage-run/cache": "^1.3.4",
25
+ "@lage-run/config": "^0.4.3",
26
+ "@lage-run/globby": "^14.2.0",
27
+ "@lage-run/hasher": "^1.6.0",
26
28
  "@lage-run/logger": "^1.3.1",
27
- "@lage-run/reporters": "^1.2.10",
28
- "@lage-run/rpc": "^1.2.0",
29
- "@lage-run/runners": "^1.0.2",
30
- "@lage-run/scheduler": "^1.3.0",
31
- "@lage-run/scheduler-types": "^0.3.15",
32
- "@lage-run/target-graph": "^0.8.10",
33
- "@lage-run/worker-threads-pool": "^0.8.1",
29
+ "@lage-run/reporters": "^1.2.11",
30
+ "@lage-run/rpc": "^1.2.2",
31
+ "@lage-run/runners": "^1.0.3",
32
+ "@lage-run/scheduler": "^1.3.2",
33
+ "@lage-run/scheduler-types": "^0.3.16",
34
+ "@lage-run/target-graph": "^0.9.0",
35
+ "@lage-run/worker-threads-pool": "^0.8.3",
34
36
  "chokidar": "3.5.3",
35
37
  "commander": "9.5.0",
36
38
  "execa": "5.1.1",
@@ -1,8 +0,0 @@
1
- import { type Logger } from "@lage-run/logger";
2
- interface ExecClientOptions {
3
- logger: Logger;
4
- server: string;
5
- args?: string[];
6
- }
7
- export declare function executeRemotely({ logger, server, args }: ExecClientOptions): Promise<void>;
8
- export {};
@@ -1,32 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "executeRemotely", {
6
- enumerable: true,
7
- get: function() {
8
- return executeRemotely;
9
- }
10
- });
11
- const _filterArgsForTasks = require("../run/filterArgsForTasks.js");
12
- async function executeRemotely({ logger , server , args }) {
13
- const task = args?.length === 1 ? args?.[0] : args?.[1];
14
- const packageName = args?.length ?? 0 > 1 ? args?.[0] : undefined;
15
- if (!task) {
16
- throw new Error("No task provided");
17
- }
18
- const { taskArgs } = (0, _filterArgsForTasks.filterArgsForTasks)(args ?? []);
19
- const rpc = (await import("@lage-run/rpc")).default;
20
- const baseUrl = server.startsWith("http") ? server : `http://${server}`;
21
- const client = rpc.createClient({
22
- baseUrl,
23
- httpVersion: baseUrl.startsWith("https") ? "2" : "1.1"
24
- });
25
- const response = await client.runTarget({
26
- packageName,
27
- task,
28
- taskArgs
29
- });
30
- logger.info(`Task ${response.packageName}#${response.task} exited with code ${response.exitCode}`);
31
- process.exitCode = response.exitCode;
32
- }