@lage-run/cli 0.23.2 → 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,49 @@
2
2
  "name": "@lage-run/cli",
3
3
  "entries": [
4
4
  {
5
- "date": "Mon, 07 Oct 2024 19:33:03 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",
33
+ "version": "0.23.3",
34
+ "tag": "@lage-run/cli_v0.23.3",
35
+ "comments": {
36
+ "patch": [
37
+ {
38
+ "author": "kchau@microsoft.com",
39
+ "package": "@lage-run/cli",
40
+ "commit": "e0b1d9352f881fd802d982231471152127c65d39",
41
+ "comment": "uses the shell scripts to have a different executable name"
42
+ }
43
+ ]
44
+ }
45
+ },
46
+ {
47
+ "date": "Mon, 07 Oct 2024 19:33:13 GMT",
6
48
  "version": "0.23.2",
7
49
  "tag": "@lage-run/cli_v0.23.2",
8
50
  "comments": {
package/CHANGELOG.md CHANGED
@@ -1,12 +1,30 @@
1
1
  # Change Log - @lage-run/cli
2
2
 
3
- <!-- This log was last generated on Mon, 07 Oct 2024 19:33:03 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
+
17
+ ## 0.23.3
18
+
19
+ Tue, 08 Oct 2024 20:03:36 GMT
20
+
21
+ ### Patches
22
+
23
+ - uses the shell scripts to have a different executable name (kchau@microsoft.com)
24
+
7
25
  ## 0.23.2
8
26
 
9
- Mon, 07 Oct 2024 19:33:03 GMT
27
+ Mon, 07 Oct 2024 19:33:13 GMT
10
28
 
11
29
  ### Patches
12
30
 
@@ -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,31 +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
- lageServerBinPath,
93
- "--host",
94
- host,
95
- "--port",
96
- port,
97
- "--timeout",
98
- timeout,
99
- ...args
100
- ];
101
- logger.info(`Launching lage-server with these parameters: "${process.execPath}" ${lageServerArgs.join(" ")}`);
102
- const child = (0, _execa.default)(process.execPath, lageServerArgs, {
103
- detached: true,
104
- stdio: "ignore"
129
+ logger.info(`acquiring lock: ${lockfilePath}`);
130
+ ensurePidFile(lockfilePath);
131
+ const releaseLock = _properlockfile.default.lockSync(lockfilePath, {
132
+ stale: 1000 * 60 * 1
105
133
  });
106
- child.unref();
107
- logger.info("Server started", {
108
- 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
109
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();
110
171
  logger.info("Creating a client to connect to the background services");
111
172
  client = await tryCreateClientWithRetries(host, port, logger);
112
173
  if (!client) {
@@ -115,11 +176,15 @@ async function executeRemotely(options, command) {
115
176
  }
116
177
  logger.info(`Executing on server http://${host}:${port}`);
117
178
  const response = await executeOnServer(args, client, logger);
118
- process.stdout.write(response.stdout);
119
- process.stderr.write(response.stderr);
120
- process.exitCode = response.exitCode;
121
- if (response.exitCode === 0) {
122
- 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;
123
188
  }
124
189
  logger.info("Task execution finished");
125
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
  }
@@ -113,7 +113,6 @@ function generateCommand(target, taskArgs, config, options, binPaths) {
113
113
  } else if (target.type === "worker" && shouldRunWorkersAsService) {
114
114
  const { host , port } = (0, _parseServerOption.parseServerOption)(options.server);
115
115
  const command = [
116
- process.execPath,
117
116
  binPaths["lage"],
118
117
  "exec",
119
118
  "--server",
@@ -132,7 +131,6 @@ function generateCommand(target, taskArgs, config, options, binPaths) {
132
131
  return command;
133
132
  } else if (target.type === "worker") {
134
133
  const command = [
135
- process.execPath,
136
134
  binPaths.lage,
137
135
  "exec"
138
136
  ];
@@ -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,
@@ -10,24 +10,37 @@ Object.defineProperty(exports, "getBinPaths", {
10
10
  });
11
11
  const _path = /*#__PURE__*/ _interop_require_default(require("path"));
12
12
  const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
13
+ const _os = /*#__PURE__*/ _interop_require_default(require("os"));
13
14
  function _interop_require_default(obj) {
14
15
  return obj && obj.__esModule ? obj : {
15
16
  default: obj
16
17
  };
17
18
  }
18
- function getBinPaths() {
19
- let dir = __dirname;
20
- let packageJsonPath = "";
21
- while(dir !== "/"){
22
- packageJsonPath = _path.default.join(dir, "package.json");
23
- if (_fs.default.existsSync(packageJsonPath)) {
24
- break;
19
+ function findUp(name, dir) {
20
+ let currentDir = dir;
21
+ while(currentDir !== "/"){
22
+ const fullPath = _path.default.join(currentDir, name);
23
+ if (_fs.default.existsSync(fullPath)) {
24
+ return fullPath;
25
25
  }
26
- dir = _path.default.dirname(dir);
26
+ currentDir = _path.default.dirname(currentDir);
27
+ }
28
+ return undefined;
29
+ }
30
+ function getBinPaths() {
31
+ const bins = _os.default.platform() === "win32" ? [
32
+ "lage.cmd",
33
+ "lage-server.cmd"
34
+ ] : [
35
+ "lage",
36
+ "lage-server"
37
+ ];
38
+ const binPaths = bins.map((bin)=>findUp("node_modules/.bin/" + bin, __dirname));
39
+ if (binPaths.some((binPath)=>binPath === undefined)) {
40
+ throw new Error("Could not find bin paths for lage or lage-server");
27
41
  }
28
- const packageJson = JSON.parse(_fs.default.readFileSync(_path.default.join(dir, "package.json"), "utf8"));
29
42
  return {
30
- lage: _path.default.join(dir, packageJson.bin.lage),
31
- "lage-server": _path.default.join(dir, packageJson.bin["lage-server"])
43
+ lage: binPaths[0],
44
+ "lage-server": binPaths[1]
32
45
  };
33
46
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lage-run/cli",
3
- "version": "0.23.2",
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"