@uipath/packager-tool-workflowcompiler 1.199.0-preview.99 → 1.199.1-preview.119
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/dist/index.js +101 -38
- package/dist/output-entry.d.ts +8 -2
- package/dist/workflow-compiler-config.d.ts +2 -0
- package/dist/workflow-compiler-tool-factory.d.ts +12 -0
- package/package.json +2 -2
- package/src/output-entry.ts +8 -2
- package/src/workflow-compiler-config.ts +4 -1
- package/src/workflow-compiler-executor.ts +102 -8
- package/src/workflow-compiler-tool-factory.ts +23 -1
package/dist/index.js
CHANGED
|
@@ -656,6 +656,30 @@ import {
|
|
|
656
656
|
translate as translate6
|
|
657
657
|
} from "@uipath/solutionpackager-tool-core";
|
|
658
658
|
|
|
659
|
+
// src/workflow-compiler-config.ts
|
|
660
|
+
var DEFAULT_WORKFLOW_COMPILER_VERSION = "26.0.198-alpha.24031";
|
|
661
|
+
var DEFAULT_DOTNET_PATH = "dotnet";
|
|
662
|
+
var workflowCompilerConfig = {
|
|
663
|
+
workflowCompilerPath: undefined,
|
|
664
|
+
workflowCompilerVersion: DEFAULT_WORKFLOW_COMPILER_VERSION,
|
|
665
|
+
dotnetPath: DEFAULT_DOTNET_PATH,
|
|
666
|
+
dotnetEnv: undefined
|
|
667
|
+
};
|
|
668
|
+
function setupWorkflowCompiler(options) {
|
|
669
|
+
if (options.compilerPath !== undefined) {
|
|
670
|
+
workflowCompilerConfig.workflowCompilerPath = options.compilerPath;
|
|
671
|
+
}
|
|
672
|
+
if (options.version !== undefined) {
|
|
673
|
+
workflowCompilerConfig.workflowCompilerVersion = options.version;
|
|
674
|
+
}
|
|
675
|
+
if (options.dotnetPath !== undefined) {
|
|
676
|
+
workflowCompilerConfig.dotnetPath = options.dotnetPath;
|
|
677
|
+
}
|
|
678
|
+
if (options.dotnetEnv !== undefined) {
|
|
679
|
+
workflowCompilerConfig.dotnetEnv = options.dotnetEnv;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
659
683
|
// ../packager-orchestrator-client/dist/index.js
|
|
660
684
|
import { I18nManager as I18nManager2 } from "@uipath/solutionpackager-tool-core";
|
|
661
685
|
import {
|
|
@@ -960,29 +984,6 @@ import {
|
|
|
960
984
|
translate as translate5
|
|
961
985
|
} from "@uipath/solutionpackager-tool-core";
|
|
962
986
|
|
|
963
|
-
// src/workflow-compiler-config.ts
|
|
964
|
-
var DEFAULT_WORKFLOW_COMPILER_VERSION = "26.0.198-alpha.24031";
|
|
965
|
-
var workflowCompilerConfig = {
|
|
966
|
-
workflowCompilerPath: undefined,
|
|
967
|
-
workflowCompilerVersion: DEFAULT_WORKFLOW_COMPILER_VERSION,
|
|
968
|
-
dotnetPath: "dotnet",
|
|
969
|
-
dotnetEnv: undefined
|
|
970
|
-
};
|
|
971
|
-
function setupWorkflowCompiler(options) {
|
|
972
|
-
if (options.compilerPath !== undefined) {
|
|
973
|
-
workflowCompilerConfig.workflowCompilerPath = options.compilerPath;
|
|
974
|
-
}
|
|
975
|
-
if (options.version !== undefined) {
|
|
976
|
-
workflowCompilerConfig.workflowCompilerVersion = options.version;
|
|
977
|
-
}
|
|
978
|
-
if (options.dotnetPath !== undefined) {
|
|
979
|
-
workflowCompilerConfig.dotnetPath = options.dotnetPath;
|
|
980
|
-
}
|
|
981
|
-
if (options.dotnetEnv !== undefined) {
|
|
982
|
-
workflowCompilerConfig.dotnetEnv = options.dotnetEnv;
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
|
|
986
987
|
// src/workflow-compiler-path-resolver.ts
|
|
987
988
|
import { execFileSync } from "node:child_process";
|
|
988
989
|
import { homedir, platform } from "node:os";
|
|
@@ -1156,6 +1157,7 @@ class WorkflowCompilerExecutor {
|
|
|
1156
1157
|
return new Promise((resolve) => {
|
|
1157
1158
|
let result = null;
|
|
1158
1159
|
const fallbackErrors = [];
|
|
1160
|
+
const analyzerFindings = [];
|
|
1159
1161
|
const childProcess = this.spawnProcess(executable, commandArgs, workflowCompilerConfig.dotnetEnv);
|
|
1160
1162
|
let stdoutEnded = false;
|
|
1161
1163
|
let stderrEnded = false;
|
|
@@ -1171,7 +1173,7 @@ class WorkflowCompilerExecutor {
|
|
|
1171
1173
|
errorCode: result.errorCode
|
|
1172
1174
|
}));
|
|
1173
1175
|
const toolResult = new ToolResult(result.errorCode, result.message, result.outputPackages);
|
|
1174
|
-
toolResult.details = getAdditionalResultDetails(result);
|
|
1176
|
+
toolResult.details = withAnalyzerFindings(getAdditionalResultDetails(result), analyzerFindings);
|
|
1175
1177
|
resolve(toolResult);
|
|
1176
1178
|
} else {
|
|
1177
1179
|
const exitCode = childProcess.exitCode ?? -1;
|
|
@@ -1201,8 +1203,8 @@ class WorkflowCompilerExecutor {
|
|
|
1201
1203
|
checkComplete();
|
|
1202
1204
|
}
|
|
1203
1205
|
};
|
|
1204
|
-
this.setupStdoutHandling(childProcess, streamCompletion, (r) => result = r);
|
|
1205
|
-
this.setupStderrHandling(childProcess, streamCompletion, fallbackErrors);
|
|
1206
|
+
this.setupStdoutHandling(childProcess, streamCompletion, (r) => result = r, analyzerFindings);
|
|
1207
|
+
this.setupStderrHandling(childProcess, streamCompletion, fallbackErrors, analyzerFindings);
|
|
1206
1208
|
this.setupProcessEventHandlers(childProcess, streamCompletion, resolve);
|
|
1207
1209
|
this.setupCancellationHandler(childProcess, cancellationToken, resolve);
|
|
1208
1210
|
});
|
|
@@ -1224,7 +1226,7 @@ class WorkflowCompilerExecutor {
|
|
|
1224
1226
|
command: fullCommand.join(" ")
|
|
1225
1227
|
}));
|
|
1226
1228
|
}
|
|
1227
|
-
setupStdoutHandling(childProcess, streamCompletion, onResult) {
|
|
1229
|
+
setupStdoutHandling(childProcess, streamCompletion, onResult, analyzerFindings) {
|
|
1228
1230
|
if (!childProcess.stdout) {
|
|
1229
1231
|
streamCompletion.markStdoutEnded();
|
|
1230
1232
|
return;
|
|
@@ -1238,24 +1240,29 @@ class WorkflowCompilerExecutor {
|
|
|
1238
1240
|
for (const line of lines) {
|
|
1239
1241
|
if (!line.trim())
|
|
1240
1242
|
continue;
|
|
1241
|
-
this.processOutputLine(line, onResult);
|
|
1243
|
+
this.processOutputLine(line, onResult, analyzerFindings);
|
|
1242
1244
|
}
|
|
1243
1245
|
});
|
|
1244
1246
|
childProcess.stdout.on("end", () => {
|
|
1245
1247
|
if (buffer.trim()) {
|
|
1246
|
-
this.processOutputLine(buffer, onResult);
|
|
1248
|
+
this.processOutputLine(buffer, onResult, analyzerFindings);
|
|
1247
1249
|
}
|
|
1248
1250
|
streamCompletion.markStdoutEnded();
|
|
1249
1251
|
});
|
|
1250
1252
|
}
|
|
1251
|
-
processOutputLine(line, onResult) {
|
|
1253
|
+
processOutputLine(line, onResult, analyzerFindings) {
|
|
1252
1254
|
const entry = this.parseOutputEntry(line);
|
|
1253
1255
|
if (!entry)
|
|
1254
1256
|
return;
|
|
1255
1257
|
if (entry.type === "Result") {
|
|
1256
1258
|
onResult(entry);
|
|
1257
1259
|
} else if (entry.type === "Log") {
|
|
1258
|
-
|
|
1260
|
+
const log = entry;
|
|
1261
|
+
const finding = toAnalyzerFinding(log);
|
|
1262
|
+
if (finding) {
|
|
1263
|
+
analyzerFindings.push(finding);
|
|
1264
|
+
}
|
|
1265
|
+
this.logMessage(log);
|
|
1259
1266
|
} else if (entry.type === "Progress") {
|
|
1260
1267
|
this.logProgress(entry);
|
|
1261
1268
|
}
|
|
@@ -1278,7 +1285,7 @@ class WorkflowCompilerExecutor {
|
|
|
1278
1285
|
const separator = percent && progress.message ? " - " : "";
|
|
1279
1286
|
this.logger.progress(`${percent}${separator}${progress.message ?? ""}`);
|
|
1280
1287
|
}
|
|
1281
|
-
setupStderrHandling(childProcess, streamCompletion, fallbackErrors) {
|
|
1288
|
+
setupStderrHandling(childProcess, streamCompletion, fallbackErrors, analyzerFindings) {
|
|
1282
1289
|
if (!childProcess.stderr) {
|
|
1283
1290
|
streamCompletion.markStderrEnded();
|
|
1284
1291
|
return;
|
|
@@ -1292,20 +1299,25 @@ class WorkflowCompilerExecutor {
|
|
|
1292
1299
|
for (const line of lines) {
|
|
1293
1300
|
if (!line.trim())
|
|
1294
1301
|
continue;
|
|
1295
|
-
this.processErrorLine(line, fallbackErrors);
|
|
1302
|
+
this.processErrorLine(line, fallbackErrors, analyzerFindings);
|
|
1296
1303
|
}
|
|
1297
1304
|
});
|
|
1298
1305
|
childProcess.stderr.on("end", () => {
|
|
1299
1306
|
if (buffer.trim()) {
|
|
1300
|
-
this.processErrorLine(buffer, fallbackErrors);
|
|
1307
|
+
this.processErrorLine(buffer, fallbackErrors, analyzerFindings);
|
|
1301
1308
|
}
|
|
1302
1309
|
streamCompletion.markStderrEnded();
|
|
1303
1310
|
});
|
|
1304
1311
|
}
|
|
1305
|
-
processErrorLine(line, fallbackErrors) {
|
|
1312
|
+
processErrorLine(line, fallbackErrors, analyzerFindings) {
|
|
1306
1313
|
const entry = this.parseOutputEntry(line);
|
|
1307
1314
|
if (entry && entry.type === "Log") {
|
|
1308
|
-
|
|
1315
|
+
const log = entry;
|
|
1316
|
+
const finding = toAnalyzerFinding(log);
|
|
1317
|
+
if (finding) {
|
|
1318
|
+
analyzerFindings.push(finding);
|
|
1319
|
+
}
|
|
1320
|
+
this.logger.error(log.message);
|
|
1309
1321
|
} else {
|
|
1310
1322
|
fallbackErrors.push(line);
|
|
1311
1323
|
this.logger.error(line);
|
|
@@ -1369,6 +1381,54 @@ function getAdditionalResultDetails(result) {
|
|
|
1369
1381
|
}
|
|
1370
1382
|
return Object.keys(details).length > 0 ? details : undefined;
|
|
1371
1383
|
}
|
|
1384
|
+
var ANALYZER_LOG_SOURCE = "Analyzer";
|
|
1385
|
+
function withAnalyzerFindings(details, findings) {
|
|
1386
|
+
const fromEnvelope = details?.findings;
|
|
1387
|
+
if (findings.length === 0 || Array.isArray(fromEnvelope) && fromEnvelope.length > 0) {
|
|
1388
|
+
return details;
|
|
1389
|
+
}
|
|
1390
|
+
return { ...details, findings };
|
|
1391
|
+
}
|
|
1392
|
+
function toAnalyzerFinding(log) {
|
|
1393
|
+
if (log.source !== ANALYZER_LOG_SOURCE) {
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1396
|
+
const message = parseAnalyzerMessage(log.data) ?? {};
|
|
1397
|
+
const activityId = message.ActivityId;
|
|
1398
|
+
const item = message.Item;
|
|
1399
|
+
return {
|
|
1400
|
+
...message,
|
|
1401
|
+
ErrorCode: message.ErrorCode ?? log.code,
|
|
1402
|
+
Description: message.Description ?? log.message,
|
|
1403
|
+
FilePath: message.FilePath ?? log.filePath,
|
|
1404
|
+
ErrorSeverity: message.ErrorSeverity ?? toErrorSeverity(log.logLevel),
|
|
1405
|
+
ActivityIdRef: activityId?.IdRef ?? log.id,
|
|
1406
|
+
AnalyzerItemName: item?.Name,
|
|
1407
|
+
AnalyzerItemType: item?.Type
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
function toErrorSeverity(logLevel) {
|
|
1411
|
+
switch (logLevel) {
|
|
1412
|
+
case "Debug":
|
|
1413
|
+
case "Trace":
|
|
1414
|
+
return "Verbose";
|
|
1415
|
+
case "Information":
|
|
1416
|
+
return "Info";
|
|
1417
|
+
default:
|
|
1418
|
+
return logLevel;
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
function parseAnalyzerMessage(data) {
|
|
1422
|
+
if (!data) {
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
try {
|
|
1426
|
+
const parsed = JSON.parse(data);
|
|
1427
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : undefined;
|
|
1428
|
+
} catch {
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1372
1432
|
|
|
1373
1433
|
// src/workflow-compiler-tool.ts
|
|
1374
1434
|
class WorkflowCompilerTool extends ProjectTool {
|
|
@@ -1637,11 +1697,14 @@ class WorkflowCompilerToolFactory {
|
|
|
1637
1697
|
ProjectTypes.WebApp
|
|
1638
1698
|
];
|
|
1639
1699
|
async createAsync(logger, fileSystem, context) {
|
|
1640
|
-
if (!this.isDotnetAvailable()) {
|
|
1700
|
+
if (!this.isPinnedByCaller() && !this.isDotnetAvailable()) {
|
|
1641
1701
|
throw new Error(translate6.t("toolWorkflowcompiler.errors.dotnetNotAvailable"));
|
|
1642
1702
|
}
|
|
1643
1703
|
return new WorkflowCompilerTool(fileSystem, logger, context);
|
|
1644
1704
|
}
|
|
1705
|
+
isPinnedByCaller() {
|
|
1706
|
+
return workflowCompilerConfig.workflowCompilerPath !== undefined && workflowCompilerConfig.dotnetPath !== DEFAULT_DOTNET_PATH;
|
|
1707
|
+
}
|
|
1645
1708
|
isDotnetAvailable() {
|
|
1646
1709
|
if (WorkflowCompilerToolFactory.cachedDotnetAvailable !== undefined) {
|
|
1647
1710
|
return WorkflowCompilerToolFactory.cachedDotnetAvailable;
|
|
@@ -1662,4 +1725,4 @@ export {
|
|
|
1662
1725
|
WorkflowCompilerToolFactory
|
|
1663
1726
|
};
|
|
1664
1727
|
|
|
1665
|
-
//# debugId=
|
|
1728
|
+
//# debugId=9E5F0B597C7A3E6E64756E2164756E21
|
package/dist/output-entry.d.ts
CHANGED
|
@@ -15,12 +15,18 @@ export interface IOutputMessage {
|
|
|
15
15
|
inputId?: string;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* Log message from workflow compiler output
|
|
18
|
+
* Log message from workflow compiler output. Analyzer findings are reported only here.
|
|
19
19
|
*/
|
|
20
20
|
export interface IOutputLog extends IOutputMessage {
|
|
21
21
|
type: OutputMessageType.Log;
|
|
22
22
|
message: string;
|
|
23
|
-
logLevel: "Information" | "Warning" | "Error";
|
|
23
|
+
logLevel: "Trace" | "Debug" | "Information" | "Warning" | "Error" | "None";
|
|
24
|
+
source?: string;
|
|
25
|
+
code?: string;
|
|
26
|
+
filePath?: string;
|
|
27
|
+
id?: string;
|
|
28
|
+
/** Serialized `AnalyzerMessage`. */
|
|
29
|
+
data?: string;
|
|
24
30
|
}
|
|
25
31
|
/**
|
|
26
32
|
* Progress update from workflow compiler output
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export declare const DEFAULT_WORKFLOW_COMPILER_VERSION = "26.0.198-alpha.24031";
|
|
2
|
+
/** The dotnet host used when no consumer pins one: whatever `dotnet` PATH resolves to. */
|
|
3
|
+
export declare const DEFAULT_DOTNET_PATH = "dotnet";
|
|
2
4
|
export declare const workflowCompilerConfig: {
|
|
3
5
|
workflowCompilerPath: string | undefined;
|
|
4
6
|
workflowCompilerVersion: string;
|
|
@@ -12,5 +12,17 @@ export declare class WorkflowCompilerToolFactory implements IProjectToolFactory
|
|
|
12
12
|
private static cachedDotnetAvailable;
|
|
13
13
|
readonly supportedTypes: readonly ProjectType[];
|
|
14
14
|
createAsync(logger: IToolLogger, fileSystem: IFileSystem, context?: ProjectOperationContext): Promise<ProjectTool>;
|
|
15
|
+
/**
|
|
16
|
+
* True when the caller has supplied both the compiler and the dotnet host to
|
|
17
|
+
* run it with — i.e. it resolved its own .NET and neither the NuGet-restore
|
|
18
|
+
* fallback nor a machine-wide install is involved.
|
|
19
|
+
*
|
|
20
|
+
* The preflight below asks PATH for an SDK. A pinned host is typically a
|
|
21
|
+
* runtime-only bundle (Studio/Robot ship the runtime, never the SDK), which
|
|
22
|
+
* cannot answer `dotnet --version` at all — that is an SDK verb. Probing it
|
|
23
|
+
* can therefore only reject a configuration that works, so a caller that has
|
|
24
|
+
* pinned both is trusted and the tool is created unconditionally.
|
|
25
|
+
*/
|
|
26
|
+
private isPinnedByCaller;
|
|
15
27
|
private isDotnetAvailable;
|
|
16
28
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/packager-tool-workflowcompiler",
|
|
3
|
-
"version": "1.199.
|
|
3
|
+
"version": "1.199.1-preview.119",
|
|
4
4
|
"description": "UiPath Workflow Compiler tool implementation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -28,5 +28,5 @@
|
|
|
28
28
|
"@uipath/solutionpackager-tool-core": "1.199.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {},
|
|
31
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "9237653cf731fb275714c8ee5aab5dc057424b42"
|
|
32
32
|
}
|
package/src/output-entry.ts
CHANGED
|
@@ -17,12 +17,18 @@ export interface IOutputMessage {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Log message from workflow compiler output
|
|
20
|
+
* Log message from workflow compiler output. Analyzer findings are reported only here.
|
|
21
21
|
*/
|
|
22
22
|
export interface IOutputLog extends IOutputMessage {
|
|
23
23
|
type: OutputMessageType.Log;
|
|
24
24
|
message: string;
|
|
25
|
-
logLevel: "Information" | "Warning" | "Error";
|
|
25
|
+
logLevel: "Trace" | "Debug" | "Information" | "Warning" | "Error" | "None";
|
|
26
|
+
source?: string;
|
|
27
|
+
code?: string;
|
|
28
|
+
filePath?: string;
|
|
29
|
+
id?: string;
|
|
30
|
+
/** Serialized `AnalyzerMessage`. */
|
|
31
|
+
data?: string;
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
/**
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
export const DEFAULT_WORKFLOW_COMPILER_VERSION = "26.0.198-alpha.24031";
|
|
2
2
|
|
|
3
|
+
/** The dotnet host used when no consumer pins one: whatever `dotnet` PATH resolves to. */
|
|
4
|
+
export const DEFAULT_DOTNET_PATH = "dotnet";
|
|
5
|
+
|
|
3
6
|
export const workflowCompilerConfig = {
|
|
4
7
|
workflowCompilerPath: undefined as string | undefined,
|
|
5
8
|
workflowCompilerVersion: DEFAULT_WORKFLOW_COMPILER_VERSION as string,
|
|
6
9
|
// The dotnet host used to launch `UiPath.WorkflowCompiler.dll`. Defaults to `dotnet` on PATH.
|
|
7
10
|
// Consumers that ship a bundled runtime (e.g. rpa-tool resolving Robot/Studio's .NET) point this
|
|
8
11
|
// at the bundled muxer so the compiler runs under that runtime instead of a machine-wide install.
|
|
9
|
-
dotnetPath:
|
|
12
|
+
dotnetPath: DEFAULT_DOTNET_PATH as string,
|
|
10
13
|
// Extra environment variables for the compiler process (e.g. DOTNET_ROOT / DOTNET_MULTILEVEL_LOOKUP).
|
|
11
14
|
// Merged over the inherited process env. Undefined means inherit the parent env unchanged.
|
|
12
15
|
dotnetEnv: undefined as Record<string, string> | undefined,
|
|
@@ -82,6 +82,7 @@ export class WorkflowCompilerExecutor {
|
|
|
82
82
|
return new Promise((resolve) => {
|
|
83
83
|
let result: IOutputResult | null = null;
|
|
84
84
|
const fallbackErrors: string[] = [];
|
|
85
|
+
const analyzerFindings: Record<string, unknown>[] = [];
|
|
85
86
|
|
|
86
87
|
const childProcess = this.spawnProcess(
|
|
87
88
|
executable,
|
|
@@ -115,7 +116,10 @@ export class WorkflowCompilerExecutor {
|
|
|
115
116
|
result.message,
|
|
116
117
|
result.outputPackages,
|
|
117
118
|
);
|
|
118
|
-
toolResult.details =
|
|
119
|
+
toolResult.details = withAnalyzerFindings(
|
|
120
|
+
getAdditionalResultDetails(result),
|
|
121
|
+
analyzerFindings,
|
|
122
|
+
);
|
|
119
123
|
resolve(toolResult);
|
|
120
124
|
} else {
|
|
121
125
|
const exitCode = childProcess.exitCode ?? -1;
|
|
@@ -163,11 +167,13 @@ export class WorkflowCompilerExecutor {
|
|
|
163
167
|
childProcess,
|
|
164
168
|
streamCompletion,
|
|
165
169
|
(r) => (result = r),
|
|
170
|
+
analyzerFindings,
|
|
166
171
|
);
|
|
167
172
|
this.setupStderrHandling(
|
|
168
173
|
childProcess,
|
|
169
174
|
streamCompletion,
|
|
170
175
|
fallbackErrors,
|
|
176
|
+
analyzerFindings,
|
|
171
177
|
);
|
|
172
178
|
this.setupProcessEventHandlers(
|
|
173
179
|
childProcess,
|
|
@@ -219,6 +225,7 @@ export class WorkflowCompilerExecutor {
|
|
|
219
225
|
childProcess: ChildProcess,
|
|
220
226
|
streamCompletion: StreamCompletion,
|
|
221
227
|
onResult: (result: IOutputResult) => void,
|
|
228
|
+
analyzerFindings: Record<string, unknown>[],
|
|
222
229
|
): void {
|
|
223
230
|
if (!childProcess.stdout) {
|
|
224
231
|
streamCompletion.markStdoutEnded();
|
|
@@ -233,13 +240,13 @@ export class WorkflowCompilerExecutor {
|
|
|
233
240
|
buffer = lines.pop()!;
|
|
234
241
|
for (const line of lines) {
|
|
235
242
|
if (!line.trim()) continue;
|
|
236
|
-
this.processOutputLine(line, onResult);
|
|
243
|
+
this.processOutputLine(line, onResult, analyzerFindings);
|
|
237
244
|
}
|
|
238
245
|
});
|
|
239
246
|
|
|
240
247
|
childProcess.stdout.on("end", () => {
|
|
241
248
|
if (buffer.trim()) {
|
|
242
|
-
this.processOutputLine(buffer, onResult);
|
|
249
|
+
this.processOutputLine(buffer, onResult, analyzerFindings);
|
|
243
250
|
}
|
|
244
251
|
streamCompletion.markStdoutEnded();
|
|
245
252
|
});
|
|
@@ -248,6 +255,7 @@ export class WorkflowCompilerExecutor {
|
|
|
248
255
|
private processOutputLine(
|
|
249
256
|
line: string,
|
|
250
257
|
onResult: (result: IOutputResult) => void,
|
|
258
|
+
analyzerFindings: Record<string, unknown>[],
|
|
251
259
|
): void {
|
|
252
260
|
const entry = this.parseOutputEntry(line);
|
|
253
261
|
if (!entry) return;
|
|
@@ -255,7 +263,12 @@ export class WorkflowCompilerExecutor {
|
|
|
255
263
|
if (entry.type === "Result") {
|
|
256
264
|
onResult(entry as IOutputResult);
|
|
257
265
|
} else if (entry.type === "Log") {
|
|
258
|
-
|
|
266
|
+
const log = entry as IOutputLog;
|
|
267
|
+
const finding = toAnalyzerFinding(log);
|
|
268
|
+
if (finding) {
|
|
269
|
+
analyzerFindings.push(finding);
|
|
270
|
+
}
|
|
271
|
+
this.logMessage(log);
|
|
259
272
|
} else if (entry.type === "Progress") {
|
|
260
273
|
this.logProgress(entry as IOutputProgress);
|
|
261
274
|
}
|
|
@@ -285,6 +298,7 @@ export class WorkflowCompilerExecutor {
|
|
|
285
298
|
childProcess: ChildProcess,
|
|
286
299
|
streamCompletion: StreamCompletion,
|
|
287
300
|
fallbackErrors: string[],
|
|
301
|
+
analyzerFindings: Record<string, unknown>[],
|
|
288
302
|
): void {
|
|
289
303
|
if (!childProcess.stderr) {
|
|
290
304
|
streamCompletion.markStderrEnded();
|
|
@@ -298,23 +312,32 @@ export class WorkflowCompilerExecutor {
|
|
|
298
312
|
buffer = lines.pop()!;
|
|
299
313
|
for (const line of lines) {
|
|
300
314
|
if (!line.trim()) continue;
|
|
301
|
-
this.processErrorLine(line, fallbackErrors);
|
|
315
|
+
this.processErrorLine(line, fallbackErrors, analyzerFindings);
|
|
302
316
|
}
|
|
303
317
|
});
|
|
304
318
|
|
|
305
319
|
childProcess.stderr.on("end", () => {
|
|
306
320
|
if (buffer.trim()) {
|
|
307
|
-
this.processErrorLine(buffer, fallbackErrors);
|
|
321
|
+
this.processErrorLine(buffer, fallbackErrors, analyzerFindings);
|
|
308
322
|
}
|
|
309
323
|
streamCompletion.markStderrEnded();
|
|
310
324
|
});
|
|
311
325
|
}
|
|
312
326
|
|
|
313
|
-
private processErrorLine(
|
|
327
|
+
private processErrorLine(
|
|
328
|
+
line: string,
|
|
329
|
+
fallbackErrors: string[],
|
|
330
|
+
analyzerFindings: Record<string, unknown>[],
|
|
331
|
+
): void {
|
|
314
332
|
const entry = this.parseOutputEntry(line);
|
|
315
333
|
|
|
316
334
|
if (entry && entry.type === "Log") {
|
|
317
|
-
|
|
335
|
+
const log = entry as IOutputLog;
|
|
336
|
+
const finding = toAnalyzerFinding(log);
|
|
337
|
+
if (finding) {
|
|
338
|
+
analyzerFindings.push(finding);
|
|
339
|
+
}
|
|
340
|
+
this.logger.error(log.message);
|
|
318
341
|
} else {
|
|
319
342
|
fallbackErrors.push(line);
|
|
320
343
|
this.logger.error(line);
|
|
@@ -434,3 +457,74 @@ function getAdditionalResultDetails(
|
|
|
434
457
|
|
|
435
458
|
return Object.keys(details).length > 0 ? details : undefined;
|
|
436
459
|
}
|
|
460
|
+
|
|
461
|
+
const ANALYZER_LOG_SOURCE = "Analyzer";
|
|
462
|
+
|
|
463
|
+
/** Only a *populated* envelope array wins — `CommandResult` defaults its lists to `[]`. */
|
|
464
|
+
function withAnalyzerFindings(
|
|
465
|
+
details: Record<string, unknown> | undefined,
|
|
466
|
+
findings: Record<string, unknown>[],
|
|
467
|
+
): Record<string, unknown> | undefined {
|
|
468
|
+
const fromEnvelope = details?.findings;
|
|
469
|
+
if (
|
|
470
|
+
findings.length === 0 ||
|
|
471
|
+
(Array.isArray(fromEnvelope) && fromEnvelope.length > 0)
|
|
472
|
+
) {
|
|
473
|
+
return details;
|
|
474
|
+
}
|
|
475
|
+
return { ...details, findings };
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/** Flattened because consumers match flat keys only; the payload omits null members. */
|
|
479
|
+
function toAnalyzerFinding(
|
|
480
|
+
log: IOutputLog,
|
|
481
|
+
): Record<string, unknown> | undefined {
|
|
482
|
+
if (log.source !== ANALYZER_LOG_SOURCE) {
|
|
483
|
+
return undefined;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const message = parseAnalyzerMessage(log.data) ?? {};
|
|
487
|
+
const activityId = message.ActivityId as { IdRef?: string } | undefined;
|
|
488
|
+
const item = message.Item as { Name?: string; Type?: string } | undefined;
|
|
489
|
+
return {
|
|
490
|
+
...message,
|
|
491
|
+
ErrorCode: message.ErrorCode ?? log.code,
|
|
492
|
+
Description: message.Description ?? log.message,
|
|
493
|
+
FilePath: message.FilePath ?? log.filePath,
|
|
494
|
+
ErrorSeverity: message.ErrorSeverity ?? toErrorSeverity(log.logLevel),
|
|
495
|
+
ActivityIdRef: activityId?.IdRef ?? log.id,
|
|
496
|
+
AnalyzerItemName: item?.Name,
|
|
497
|
+
AnalyzerItemType: item?.Type,
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/** Undo the compiler's `TraceLevel` → `LogLevel` mapping, so a consumer's lookup still matches. */
|
|
502
|
+
function toErrorSeverity(logLevel: IOutputLog["logLevel"]): string {
|
|
503
|
+
switch (logLevel) {
|
|
504
|
+
case "Debug":
|
|
505
|
+
case "Trace":
|
|
506
|
+
return "Verbose";
|
|
507
|
+
case "Information":
|
|
508
|
+
return "Info";
|
|
509
|
+
default:
|
|
510
|
+
return logLevel;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function parseAnalyzerMessage(
|
|
515
|
+
data: string | undefined,
|
|
516
|
+
): Record<string, unknown> | undefined {
|
|
517
|
+
if (!data) {
|
|
518
|
+
return undefined;
|
|
519
|
+
}
|
|
520
|
+
try {
|
|
521
|
+
const parsed: unknown = JSON.parse(data);
|
|
522
|
+
return typeof parsed === "object" &&
|
|
523
|
+
parsed !== null &&
|
|
524
|
+
!Array.isArray(parsed)
|
|
525
|
+
? (parsed as Record<string, unknown>)
|
|
526
|
+
: undefined;
|
|
527
|
+
} catch {
|
|
528
|
+
return undefined;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
@@ -9,6 +9,10 @@ import {
|
|
|
9
9
|
ProjectTypes,
|
|
10
10
|
translate,
|
|
11
11
|
} from "@uipath/solutionpackager-tool-core";
|
|
12
|
+
import {
|
|
13
|
+
DEFAULT_DOTNET_PATH,
|
|
14
|
+
workflowCompilerConfig,
|
|
15
|
+
} from "./workflow-compiler-config.js";
|
|
12
16
|
import { WorkflowCompilerTool } from "./workflow-compiler-tool.js";
|
|
13
17
|
|
|
14
18
|
/**
|
|
@@ -35,7 +39,7 @@ export class WorkflowCompilerToolFactory implements IProjectToolFactory {
|
|
|
35
39
|
fileSystem: IFileSystem,
|
|
36
40
|
context?: ProjectOperationContext,
|
|
37
41
|
): Promise<ProjectTool> {
|
|
38
|
-
if (!this.isDotnetAvailable()) {
|
|
42
|
+
if (!this.isPinnedByCaller() && !this.isDotnetAvailable()) {
|
|
39
43
|
throw new Error(
|
|
40
44
|
translate.t("toolWorkflowcompiler.errors.dotnetNotAvailable"),
|
|
41
45
|
);
|
|
@@ -43,6 +47,24 @@ export class WorkflowCompilerToolFactory implements IProjectToolFactory {
|
|
|
43
47
|
return new WorkflowCompilerTool(fileSystem, logger, context);
|
|
44
48
|
}
|
|
45
49
|
|
|
50
|
+
/**
|
|
51
|
+
* True when the caller has supplied both the compiler and the dotnet host to
|
|
52
|
+
* run it with — i.e. it resolved its own .NET and neither the NuGet-restore
|
|
53
|
+
* fallback nor a machine-wide install is involved.
|
|
54
|
+
*
|
|
55
|
+
* The preflight below asks PATH for an SDK. A pinned host is typically a
|
|
56
|
+
* runtime-only bundle (Studio/Robot ship the runtime, never the SDK), which
|
|
57
|
+
* cannot answer `dotnet --version` at all — that is an SDK verb. Probing it
|
|
58
|
+
* can therefore only reject a configuration that works, so a caller that has
|
|
59
|
+
* pinned both is trusted and the tool is created unconditionally.
|
|
60
|
+
*/
|
|
61
|
+
private isPinnedByCaller(): boolean {
|
|
62
|
+
return (
|
|
63
|
+
workflowCompilerConfig.workflowCompilerPath !== undefined &&
|
|
64
|
+
workflowCompilerConfig.dotnetPath !== DEFAULT_DOTNET_PATH
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
46
68
|
private isDotnetAvailable(): boolean {
|
|
47
69
|
if (WorkflowCompilerToolFactory.cachedDotnetAvailable !== undefined) {
|
|
48
70
|
return WorkflowCompilerToolFactory.cachedDotnetAvailable;
|