@lage-run/cli 0.23.3 → 0.23.4

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,34 @@
2
2
  "name": "@lage-run/cli",
3
3
  "entries": [
4
4
  {
5
- "date": "Tue, 08 Oct 2024 20:03:26 GMT",
5
+ "date": "Wed, 09 Oct 2024 17:20:17 GMT",
6
+ "version": "0.23.4",
7
+ "tag": "@lage-run/cli_v0.23.4",
8
+ "comments": {
9
+ "patch": [
10
+ {
11
+ "author": "kchau@microsoft.com",
12
+ "package": "@lage-run/cli",
13
+ "commit": "41964958d510982762eaa7a496cad7bbb560bcc5",
14
+ "comment": "fixing up the lage integrate with buildxl to utilize lage-server"
15
+ },
16
+ {
17
+ "author": "beachball",
18
+ "package": "@lage-run/cli",
19
+ "comment": "Bump @lage-run/scheduler to v1.3.3",
20
+ "commit": "not available"
21
+ },
22
+ {
23
+ "author": "beachball",
24
+ "package": "@lage-run/cli",
25
+ "comment": "Bump @lage-run/worker-threads-pool to v0.8.4",
26
+ "commit": "not available"
27
+ }
28
+ ]
29
+ }
30
+ },
31
+ {
32
+ "date": "Tue, 08 Oct 2024 20:03:36 GMT",
6
33
  "version": "0.23.3",
7
34
  "tag": "@lage-run/cli_v0.23.3",
8
35
  "comments": {
package/CHANGELOG.md CHANGED
@@ -1,12 +1,22 @@
1
1
  # Change Log - @lage-run/cli
2
2
 
3
- <!-- This log was last generated on Tue, 08 Oct 2024 20:03:26 GMT and should not be manually modified. -->
3
+ <!-- This log was last generated on Wed, 09 Oct 2024 17:20:17 GMT and should not be manually modified. -->
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 0.23.4
8
+
9
+ Wed, 09 Oct 2024 17:20:17 GMT
10
+
11
+ ### Patches
12
+
13
+ - fixing up the lage integrate with buildxl to utilize lage-server (kchau@microsoft.com)
14
+ - Bump @lage-run/scheduler to v1.3.3
15
+ - Bump @lage-run/worker-threads-pool to v0.8.4
16
+
7
17
  ## 0.23.3
8
18
 
9
- Tue, 08 Oct 2024 20:03:26 GMT
19
+ Tue, 08 Oct 2024 20:03:36 GMT
10
20
 
11
21
  ### Patches
12
22
 
@@ -19,6 +19,7 @@ function _interop_require_default(obj) {
19
19
  }
20
20
  async function execAction(options, command) {
21
21
  const logger = (0, _logger.default)();
22
+ options.cwd = options.cwd ?? process.cwd();
22
23
  options.logLevel = options.logLevel ?? "info";
23
24
  options.reporter = options.reporter ?? "json";
24
25
  (0, _initializeReporters.initializeReporters)(logger, options);
@@ -1,5 +1,6 @@
1
1
  import type { ReporterInitOptions } from "../../types/ReporterInitOptions.js";
2
2
  interface ExecRemotelyOptions extends ReporterInitOptions {
3
+ cwd?: string;
3
4
  server?: string | boolean;
4
5
  timeout?: number;
5
6
  }
@@ -16,6 +16,10 @@ const _simulateFileAccess = require("./simulateFileAccess.js");
16
16
  const _execa = /*#__PURE__*/ _interop_require_default(require("execa"));
17
17
  const _getBinPaths = require("../../getBinPaths.js");
18
18
  const _parseServerOption = require("../parseServerOption.js");
19
+ const _properlockfile = /*#__PURE__*/ _interop_require_default(require("proper-lockfile"));
20
+ const _path = /*#__PURE__*/ _interop_require_default(require("path"));
21
+ const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
22
+ const _workspacetools = require("workspace-tools");
19
23
  function _interop_require_default(obj) {
20
24
  return obj && obj.__esModule ? obj : {
21
25
  default: obj
@@ -64,13 +68,47 @@ async function executeOnServer(args, client, logger) {
64
68
  throw new Error("No task provided");
65
69
  }
66
70
  const { taskArgs } = (0, _filterArgsForTasks.filterArgsForTasks)(args ?? []);
67
- const response = await client.runTarget({
68
- packageName,
69
- task,
70
- taskArgs
71
- });
72
- logger.info(`Task ${response.packageName} ${response.task} exited with code ${response.exitCode} `);
73
- return response;
71
+ try {
72
+ const response = await client.runTarget({
73
+ packageName,
74
+ task,
75
+ taskArgs
76
+ });
77
+ logger.info(`Task ${response.packageName} ${response.task} exited with code ${response.exitCode} `);
78
+ return response;
79
+ } catch (error) {
80
+ if (error instanceof _rpc.ConnectError) {
81
+ logger.error("Error connecting to server", {
82
+ error
83
+ });
84
+ } else {
85
+ logger.error("Error running task", {
86
+ error
87
+ });
88
+ }
89
+ }
90
+ }
91
+ function isAlive(pid) {
92
+ try {
93
+ return process.kill(pid, 0);
94
+ } catch {
95
+ return false;
96
+ }
97
+ }
98
+ function ensurePidFile(lockfilePath) {
99
+ if (!_fs.default.existsSync(_path.default.dirname(lockfilePath))) {
100
+ _fs.default.mkdirSync(_path.default.dirname(lockfilePath), {
101
+ recursive: true
102
+ });
103
+ }
104
+ if (!_fs.default.existsSync(lockfilePath)) {
105
+ try {
106
+ const fd = _fs.default.openSync(lockfilePath, "w");
107
+ _fs.default.closeSync(fd);
108
+ } catch {
109
+ // ignore
110
+ }
111
+ }
74
112
  }
75
113
  async function executeRemotely(options, command) {
76
114
  // launch a 'lage-server.js' process, detached if it is not already running
@@ -82,30 +120,54 @@ async function executeRemotely(options, command) {
82
120
  options.logLevel = options.logLevel ?? "info";
83
121
  options.reporter = options.reporter ?? "json";
84
122
  (0, _initializeReporters.initializeReporters)(logger, options);
123
+ const root = (0, _workspacetools.getWorkspaceRoot)(options.cwd ?? process.cwd());
124
+ const lockfilePath = _path.default.join(root, `node_modules/.cache/lage/.lage-server-${host}-${port}.pid`);
85
125
  let client = await tryCreateClient(host, port);
86
126
  const args = command.args;
87
127
  if (!client) {
88
128
  logger.info(`Starting server on http://${host}:${port}`);
89
- const binPaths = (0, _getBinPaths.getBinPaths)();
90
- const lageServerBinPath = binPaths["lage-server"];
91
- const lageServerArgs = [
92
- "--host",
93
- host,
94
- "--port",
95
- port,
96
- "--timeout",
97
- timeout,
98
- ...args
99
- ];
100
- logger.info(`Launching lage-server with these parameters: ${lageServerArgs.join(" ")}`);
101
- const child = (0, _execa.default)(lageServerBinPath, lageServerArgs, {
102
- detached: true,
103
- stdio: "ignore"
129
+ logger.info(`acquiring lock: ${lockfilePath}`);
130
+ ensurePidFile(lockfilePath);
131
+ const releaseLock = _properlockfile.default.lockSync(lockfilePath, {
132
+ stale: 1000 * 60 * 1
104
133
  });
105
- child.unref();
106
- logger.info("Server started", {
107
- pid: child.pid
134
+ const pid = parseInt(_fs.default.readFileSync(lockfilePath, "utf-8"));
135
+ const isServerRunning = pid && isAlive(pid);
136
+ logger.info("Checking if server is already running", {
137
+ pid,
138
+ isServerRunning
108
139
  });
140
+ if (pid && isServerRunning) {
141
+ logger.info("Server already running", {
142
+ pid
143
+ });
144
+ } else {
145
+ const binPaths = (0, _getBinPaths.getBinPaths)();
146
+ const lageServerBinPath = binPaths["lage-server"];
147
+ const lageServerArgs = [
148
+ "--host",
149
+ host,
150
+ "--port",
151
+ port,
152
+ "--timeout",
153
+ timeout,
154
+ ...args
155
+ ];
156
+ logger.info(`Launching lage-server with these parameters: ${lageServerArgs.join(" ")}`);
157
+ const child = (0, _execa.default)(lageServerBinPath, lageServerArgs, {
158
+ cwd: root,
159
+ detached: true,
160
+ stdio: "ignore"
161
+ });
162
+ if (child && child.pid) {
163
+ _fs.default.writeFileSync(lockfilePath, child.pid.toString());
164
+ }
165
+ child.unref();
166
+ logger.info("Server started", {
167
+ pid: child.pid
168
+ });
169
+ }
170
+ releaseLock();
109
171
  logger.info("Creating a client to connect to the background services");
110
172
  client = await tryCreateClientWithRetries(host, port, logger);
111
173
  if (!client) {
@@ -114,11 +176,15 @@ async function executeRemotely(options, command) {
114
176
  }
115
177
  logger.info(`Executing on server http://${host}:${port}`);
116
178
  const response = await executeOnServer(args, client, logger);
117
- process.stdout.write(response.stdout);
118
- process.stderr.write(response.stderr);
119
- process.exitCode = response.exitCode;
120
- if (response.exitCode === 0) {
121
- await (0, _simulateFileAccess.simulateFileAccess)(logger, response.inputs, response.outputs);
179
+ if (response) {
180
+ process.stdout.write(response.stdout);
181
+ process.stderr.write(response.stderr);
182
+ process.exitCode = response.exitCode;
183
+ if (response.exitCode === 0) {
184
+ await (0, _simulateFileAccess.simulateFileAccess)(logger, response.inputs, response.outputs);
185
+ }
186
+ } else {
187
+ process.exitCode = 1;
122
188
  }
123
189
  logger.info("Task execution finished");
124
190
  }
@@ -76,7 +76,7 @@ async function infoAction(options, command) {
76
76
  async function optimizeTargetGraph(graph, runnerPicker) {
77
77
  const targetMinimizedNodes = await (0, _targetgraph.removeNodes)([
78
78
  ...graph.targets.values()
79
- ] ?? [], async (target)=>{
79
+ ], async (target)=>{
80
80
  if (target.type === "noop") {
81
81
  return true;
82
82
  }
@@ -30,9 +30,18 @@ function findAllTasks(pipeline) {
30
30
  }
31
31
  return Array.from(tasks);
32
32
  }
33
- let context;
34
- async function initializeOnce(cwd, logger) {
35
- if (!context) {
33
+ let initializedPromise;
34
+ /**
35
+ * Initializes the lageService: the extra "initializePromise" ensures only one initialization is done at a time across threads
36
+ * @param cwd
37
+ * @param logger
38
+ * @returns
39
+ */ async function initialize(cwd, logger) {
40
+ if (initializedPromise) {
41
+ return await initializedPromise;
42
+ }
43
+ async function createInitializedPromise() {
44
+ logger.info("Initializing context");
36
45
  const config = await (0, _config.getConfig)(cwd);
37
46
  const root = (0, _workspacetools.getWorkspaceRoot)(cwd);
38
47
  const { pipeline } = config;
@@ -61,8 +70,9 @@ async function initializeOnce(cwd, logger) {
61
70
  packageInfos,
62
71
  includeUntracked: true
63
72
  });
73
+ logger.info("Initializing Package Tree");
64
74
  await packageTree.initialize();
65
- context = {
75
+ return {
66
76
  config,
67
77
  targetGraph,
68
78
  packageTree,
@@ -70,7 +80,8 @@ async function initializeOnce(cwd, logger) {
70
80
  root
71
81
  };
72
82
  }
73
- return context;
83
+ initializedPromise = createInitializedPromise();
84
+ return await initializedPromise;
74
85
  }
75
86
  let pool;
76
87
  async function createLageService({ cwd , serverControls , logger , maxWorkers }) {
@@ -94,18 +105,21 @@ async function createLageService({ cwd , serverControls , logger , maxWorkers }
94
105
  },
95
106
  async runTarget (request) {
96
107
  serverControls.clearCountdown();
108
+ const { config , targetGraph , dependencyMap , packageTree , root } = await initialize(cwd, logger);
97
109
  logger.info("Running target", request);
98
- const { config , targetGraph , dependencyMap , packageTree , root } = await initializeOnce(cwd, logger);
99
110
  const runners = (0, _runnerPickerOptions.runnerPickerOptions)(request.nodeOptions, config.npmClient, request.taskArgs);
100
111
  const id = (0, _targetgraph.getTargetId)(request.packageName, request.task);
101
112
  if (!targetGraph.targets.has(id)) {
102
- logger.error(`Target not found: ${request.packageName}#${request.task}`);
113
+ logger.info(`Target not found: ${request.packageName}#${request.task}`);
103
114
  return {
104
115
  packageName: request.packageName,
105
116
  task: request.task,
106
117
  exitCode: 1
107
118
  };
108
119
  }
120
+ logger.info("Target found", {
121
+ id
122
+ });
109
123
  const target = targetGraph.targets.get(id);
110
124
  const task = {
111
125
  target,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lage-run/cli",
3
- "version": "0.23.3",
3
+ "version": "0.23.4",
4
4
  "description": "Command Line Interface for Lage",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,19 +29,21 @@
29
29
  "@lage-run/reporters": "^1.2.11",
30
30
  "@lage-run/rpc": "^1.2.3",
31
31
  "@lage-run/runners": "^1.0.3",
32
- "@lage-run/scheduler": "^1.3.2",
32
+ "@lage-run/scheduler": "^1.3.3",
33
33
  "@lage-run/scheduler-types": "^0.3.16",
34
34
  "@lage-run/target-graph": "^0.9.0",
35
- "@lage-run/worker-threads-pool": "^0.8.3",
35
+ "@lage-run/worker-threads-pool": "^0.8.4",
36
36
  "chokidar": "3.5.3",
37
37
  "commander": "9.5.0",
38
38
  "execa": "5.1.1",
39
39
  "fast-glob": "3.3.2",
40
+ "proper-lockfile": "^4.1.2",
40
41
  "workspace-tools": "0.36.4"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@lage-run/monorepo-fixture": "*",
44
- "@lage-run/monorepo-scripts": "*"
45
+ "@lage-run/monorepo-scripts": "*",
46
+ "@types/proper-lockfile": "^4.1.4"
45
47
  },
46
48
  "publishConfig": {
47
49
  "access": "public"