@uipath/packager-tool-workflowcompiler 1.199.0 → 1.201.0-preview.115
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/i18n/locales/en.d.ts +1 -1
- package/dist/index.js +131 -17
- package/dist/output-entry.d.ts +8 -2
- package/dist/workflow-compiler-tool.d.ts +2 -0
- package/package.json +3 -3
- package/src/output-entry.ts +8 -2
- package/src/workflow-compiler-executor.ts +102 -8
- package/src/workflow-compiler-path-resolver.ts +1 -2
- package/src/workflow-compiler-tool.ts +90 -0
|
@@ -28,7 +28,7 @@ export declare const en: {
|
|
|
28
28
|
readonly checkingNuGetCache: "[PathResolver] Checking NuGet cache: {path}";
|
|
29
29
|
readonly foundInNuGetCache: "[PathResolver] Found compiler in NuGet cache";
|
|
30
30
|
readonly notFoundStartingInstall: "[PathResolver] Compiler not found, starting dotnet restore...";
|
|
31
|
-
readonly restoringPackage:
|
|
31
|
+
readonly restoringPackage: '[PathResolver] Restoring NuGet package "{packageName}" v{version} for platform "{platform}" via dotnet restore...';
|
|
32
32
|
readonly runningDotnetRestore: "[PathResolver] Running dotnet restore...";
|
|
33
33
|
readonly restoreCompleted: "[PathResolver] dotnet restore completed";
|
|
34
34
|
readonly installCompleted: "[PathResolver] Compiler restored successfully";
|
package/dist/index.js
CHANGED
|
@@ -789,7 +789,7 @@ function addSdkUserAgentHeader(headers, userAgent) {
|
|
|
789
789
|
}
|
|
790
790
|
var package_default = {
|
|
791
791
|
name: "@uipath/packager-orchestrator-client",
|
|
792
|
-
version: "1.
|
|
792
|
+
version: "1.201.0",
|
|
793
793
|
description: "UiPath packager client for Orchestrator package-feed interaction (feed discovery + NuGet source composition)",
|
|
794
794
|
type: "module",
|
|
795
795
|
private: true,
|
|
@@ -828,7 +828,7 @@ var package_default = {
|
|
|
828
828
|
"@uipath/common": "workspace:*",
|
|
829
829
|
"@uipath/solutionpackager-tool-core": "workspace:*",
|
|
830
830
|
"@vitest/coverage-v8": "^4.1.6",
|
|
831
|
-
typescript: "^
|
|
831
|
+
typescript: "^7.0.2",
|
|
832
832
|
vitest: "^4.1.6"
|
|
833
833
|
}
|
|
834
834
|
};
|
|
@@ -992,7 +992,7 @@ import {
|
|
|
992
992
|
TemporaryStorageService as TemporaryStorageService2,
|
|
993
993
|
translate as translate3
|
|
994
994
|
} from "@uipath/solutionpackager-tool-core";
|
|
995
|
-
var NUGET_FEED_URL = "https://
|
|
995
|
+
var NUGET_FEED_URL = "https://pkgs.uipath.com/internal/index.json";
|
|
996
996
|
var WORKFLOW_COMPILER_DLL_NAME = "UiPath.WorkflowCompiler.dll";
|
|
997
997
|
var PLATFORM_PACKAGE_IDS = {
|
|
998
998
|
win32: "UiPath.WorkflowCompiler.Windows",
|
|
@@ -1157,6 +1157,7 @@ class WorkflowCompilerExecutor {
|
|
|
1157
1157
|
return new Promise((resolve) => {
|
|
1158
1158
|
let result = null;
|
|
1159
1159
|
const fallbackErrors = [];
|
|
1160
|
+
const analyzerFindings = [];
|
|
1160
1161
|
const childProcess = this.spawnProcess(executable, commandArgs, workflowCompilerConfig.dotnetEnv);
|
|
1161
1162
|
let stdoutEnded = false;
|
|
1162
1163
|
let stderrEnded = false;
|
|
@@ -1172,7 +1173,7 @@ class WorkflowCompilerExecutor {
|
|
|
1172
1173
|
errorCode: result.errorCode
|
|
1173
1174
|
}));
|
|
1174
1175
|
const toolResult = new ToolResult(result.errorCode, result.message, result.outputPackages);
|
|
1175
|
-
toolResult.details = getAdditionalResultDetails(result);
|
|
1176
|
+
toolResult.details = withAnalyzerFindings(getAdditionalResultDetails(result), analyzerFindings);
|
|
1176
1177
|
resolve(toolResult);
|
|
1177
1178
|
} else {
|
|
1178
1179
|
const exitCode = childProcess.exitCode ?? -1;
|
|
@@ -1202,8 +1203,8 @@ class WorkflowCompilerExecutor {
|
|
|
1202
1203
|
checkComplete();
|
|
1203
1204
|
}
|
|
1204
1205
|
};
|
|
1205
|
-
this.setupStdoutHandling(childProcess, streamCompletion, (r) => result = r);
|
|
1206
|
-
this.setupStderrHandling(childProcess, streamCompletion, fallbackErrors);
|
|
1206
|
+
this.setupStdoutHandling(childProcess, streamCompletion, (r) => result = r, analyzerFindings);
|
|
1207
|
+
this.setupStderrHandling(childProcess, streamCompletion, fallbackErrors, analyzerFindings);
|
|
1207
1208
|
this.setupProcessEventHandlers(childProcess, streamCompletion, resolve);
|
|
1208
1209
|
this.setupCancellationHandler(childProcess, cancellationToken, resolve);
|
|
1209
1210
|
});
|
|
@@ -1225,7 +1226,7 @@ class WorkflowCompilerExecutor {
|
|
|
1225
1226
|
command: fullCommand.join(" ")
|
|
1226
1227
|
}));
|
|
1227
1228
|
}
|
|
1228
|
-
setupStdoutHandling(childProcess, streamCompletion, onResult) {
|
|
1229
|
+
setupStdoutHandling(childProcess, streamCompletion, onResult, analyzerFindings) {
|
|
1229
1230
|
if (!childProcess.stdout) {
|
|
1230
1231
|
streamCompletion.markStdoutEnded();
|
|
1231
1232
|
return;
|
|
@@ -1239,24 +1240,29 @@ class WorkflowCompilerExecutor {
|
|
|
1239
1240
|
for (const line of lines) {
|
|
1240
1241
|
if (!line.trim())
|
|
1241
1242
|
continue;
|
|
1242
|
-
this.processOutputLine(line, onResult);
|
|
1243
|
+
this.processOutputLine(line, onResult, analyzerFindings);
|
|
1243
1244
|
}
|
|
1244
1245
|
});
|
|
1245
1246
|
childProcess.stdout.on("end", () => {
|
|
1246
1247
|
if (buffer.trim()) {
|
|
1247
|
-
this.processOutputLine(buffer, onResult);
|
|
1248
|
+
this.processOutputLine(buffer, onResult, analyzerFindings);
|
|
1248
1249
|
}
|
|
1249
1250
|
streamCompletion.markStdoutEnded();
|
|
1250
1251
|
});
|
|
1251
1252
|
}
|
|
1252
|
-
processOutputLine(line, onResult) {
|
|
1253
|
+
processOutputLine(line, onResult, analyzerFindings) {
|
|
1253
1254
|
const entry = this.parseOutputEntry(line);
|
|
1254
1255
|
if (!entry)
|
|
1255
1256
|
return;
|
|
1256
1257
|
if (entry.type === "Result") {
|
|
1257
1258
|
onResult(entry);
|
|
1258
1259
|
} else if (entry.type === "Log") {
|
|
1259
|
-
|
|
1260
|
+
const log = entry;
|
|
1261
|
+
const finding = toAnalyzerFinding(log);
|
|
1262
|
+
if (finding) {
|
|
1263
|
+
analyzerFindings.push(finding);
|
|
1264
|
+
}
|
|
1265
|
+
this.logMessage(log);
|
|
1260
1266
|
} else if (entry.type === "Progress") {
|
|
1261
1267
|
this.logProgress(entry);
|
|
1262
1268
|
}
|
|
@@ -1279,7 +1285,7 @@ class WorkflowCompilerExecutor {
|
|
|
1279
1285
|
const separator = percent && progress.message ? " - " : "";
|
|
1280
1286
|
this.logger.progress(`${percent}${separator}${progress.message ?? ""}`);
|
|
1281
1287
|
}
|
|
1282
|
-
setupStderrHandling(childProcess, streamCompletion, fallbackErrors) {
|
|
1288
|
+
setupStderrHandling(childProcess, streamCompletion, fallbackErrors, analyzerFindings) {
|
|
1283
1289
|
if (!childProcess.stderr) {
|
|
1284
1290
|
streamCompletion.markStderrEnded();
|
|
1285
1291
|
return;
|
|
@@ -1293,20 +1299,25 @@ class WorkflowCompilerExecutor {
|
|
|
1293
1299
|
for (const line of lines) {
|
|
1294
1300
|
if (!line.trim())
|
|
1295
1301
|
continue;
|
|
1296
|
-
this.processErrorLine(line, fallbackErrors);
|
|
1302
|
+
this.processErrorLine(line, fallbackErrors, analyzerFindings);
|
|
1297
1303
|
}
|
|
1298
1304
|
});
|
|
1299
1305
|
childProcess.stderr.on("end", () => {
|
|
1300
1306
|
if (buffer.trim()) {
|
|
1301
|
-
this.processErrorLine(buffer, fallbackErrors);
|
|
1307
|
+
this.processErrorLine(buffer, fallbackErrors, analyzerFindings);
|
|
1302
1308
|
}
|
|
1303
1309
|
streamCompletion.markStderrEnded();
|
|
1304
1310
|
});
|
|
1305
1311
|
}
|
|
1306
|
-
processErrorLine(line, fallbackErrors) {
|
|
1312
|
+
processErrorLine(line, fallbackErrors, analyzerFindings) {
|
|
1307
1313
|
const entry = this.parseOutputEntry(line);
|
|
1308
1314
|
if (entry && entry.type === "Log") {
|
|
1309
|
-
|
|
1315
|
+
const log = entry;
|
|
1316
|
+
const finding = toAnalyzerFinding(log);
|
|
1317
|
+
if (finding) {
|
|
1318
|
+
analyzerFindings.push(finding);
|
|
1319
|
+
}
|
|
1320
|
+
this.logger.error(log.message);
|
|
1310
1321
|
} else {
|
|
1311
1322
|
fallbackErrors.push(line);
|
|
1312
1323
|
this.logger.error(line);
|
|
@@ -1370,8 +1381,68 @@ function getAdditionalResultDetails(result) {
|
|
|
1370
1381
|
}
|
|
1371
1382
|
return Object.keys(details).length > 0 ? details : undefined;
|
|
1372
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
|
+
}
|
|
1373
1432
|
|
|
1374
1433
|
// src/workflow-compiler-tool.ts
|
|
1434
|
+
var NO_CLEANUP_SOURCE_FILES_MESSAGE = "no workflow xamls or coded source files";
|
|
1435
|
+
var CLEANUP_SOURCE_FILE_EXTENSIONS = [".xaml", ".cs", ".vb"];
|
|
1436
|
+
var CLEANUP_SOURCE_SCAN_SKIP_DIRS = new Set([
|
|
1437
|
+
".git",
|
|
1438
|
+
".local",
|
|
1439
|
+
".project",
|
|
1440
|
+
"bin",
|
|
1441
|
+
"dist",
|
|
1442
|
+
"node_modules",
|
|
1443
|
+
"obj"
|
|
1444
|
+
]);
|
|
1445
|
+
|
|
1375
1446
|
class WorkflowCompilerTool extends ProjectTool {
|
|
1376
1447
|
context;
|
|
1377
1448
|
executor;
|
|
@@ -1575,9 +1646,52 @@ class WorkflowCompilerTool extends ProjectTool {
|
|
|
1575
1646
|
args.push(`--nuget-config`, paths.userNugetConfigPath);
|
|
1576
1647
|
}
|
|
1577
1648
|
const result = await this.executor.executeAsync("remove-unused-dependencies", args, cancellationToken);
|
|
1649
|
+
if (await this.shouldRetryCleanupNoSourceFalseNegativeAsync(result, options.projectPath)) {
|
|
1650
|
+
this.logger.warn("[WorkflowCompiler] remove-unused-dependencies reported no workflow/source files even though the project contains source files; retrying once.");
|
|
1651
|
+
const retryResult = await this.executor.executeAsync("remove-unused-dependencies", args, cancellationToken);
|
|
1652
|
+
return this.toProjectCleanupResult(retryResult);
|
|
1653
|
+
}
|
|
1578
1654
|
return this.toProjectCleanupResult(result);
|
|
1579
1655
|
});
|
|
1580
1656
|
}
|
|
1657
|
+
async shouldRetryCleanupNoSourceFalseNegativeAsync(result, projectPath) {
|
|
1658
|
+
if (result.isSuccess) {
|
|
1659
|
+
return false;
|
|
1660
|
+
}
|
|
1661
|
+
const message = result.message?.toLowerCase();
|
|
1662
|
+
if (!message?.includes(NO_CLEANUP_SOURCE_FILES_MESSAGE)) {
|
|
1663
|
+
return false;
|
|
1664
|
+
}
|
|
1665
|
+
return await this.hasCleanupSourceFilesAsync(projectPath);
|
|
1666
|
+
}
|
|
1667
|
+
async hasCleanupSourceFilesAsync(projectPath) {
|
|
1668
|
+
let entries;
|
|
1669
|
+
try {
|
|
1670
|
+
entries = await this.fileSystem.readdir(projectPath);
|
|
1671
|
+
} catch {
|
|
1672
|
+
return false;
|
|
1673
|
+
}
|
|
1674
|
+
for (const entry of entries) {
|
|
1675
|
+
const lowerEntry = entry.toLowerCase();
|
|
1676
|
+
const fullPath = this.fileSystem.path.join(projectPath, entry);
|
|
1677
|
+
let stats;
|
|
1678
|
+
try {
|
|
1679
|
+
stats = await this.fileSystem.stat(fullPath);
|
|
1680
|
+
} catch {
|
|
1681
|
+
continue;
|
|
1682
|
+
}
|
|
1683
|
+
if (!stats) {
|
|
1684
|
+
continue;
|
|
1685
|
+
}
|
|
1686
|
+
if (stats.isFile() && CLEANUP_SOURCE_FILE_EXTENSIONS.some((extension) => lowerEntry.endsWith(extension))) {
|
|
1687
|
+
return true;
|
|
1688
|
+
}
|
|
1689
|
+
if (stats.isDirectory() && !CLEANUP_SOURCE_SCAN_SKIP_DIRS.has(lowerEntry) && await this.hasCleanupSourceFilesAsync(fullPath)) {
|
|
1690
|
+
return true;
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
return false;
|
|
1694
|
+
}
|
|
1581
1695
|
toProjectCleanupResult(result) {
|
|
1582
1696
|
const raw = result.details?.removeUnusedDependencies;
|
|
1583
1697
|
if (!raw) {
|
|
@@ -1666,4 +1780,4 @@ export {
|
|
|
1666
1780
|
WorkflowCompilerToolFactory
|
|
1667
1781
|
};
|
|
1668
1782
|
|
|
1669
|
-
//# debugId=
|
|
1783
|
+
//# debugId=8617FFB8E317023F64756E2164756E21
|
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
|
|
@@ -13,6 +13,8 @@ export declare class WorkflowCompilerTool extends ProjectTool {
|
|
|
13
13
|
buildAsync(options: IProjectBuildOptions, cancellationToken?: AbortSignal): Promise<ToolResult>;
|
|
14
14
|
packAsync(options: IProjectPackOptions, cancellationToken?: AbortSignal): Promise<ToolResult>;
|
|
15
15
|
cleanupAsync(options: IProjectCleanupOptions, cancellationToken?: AbortSignal): Promise<ToolResult>;
|
|
16
|
+
private shouldRetryCleanupNoSourceFalseNegativeAsync;
|
|
17
|
+
private hasCleanupSourceFilesAsync;
|
|
16
18
|
/**
|
|
17
19
|
* Convert the WorkflowCompiler's raw `remove-unused-dependencies` payload
|
|
18
20
|
* into the generic {@link ProjectCleanupInfo} the cleanup pipeline expects,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/packager-tool-workflowcompiler",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.201.0-preview.115",
|
|
4
4
|
"description": "UiPath Workflow Compiler tool implementation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"author": "",
|
|
26
26
|
"license": "ISC",
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@uipath/solutionpackager-tool-core": "1.
|
|
28
|
+
"@uipath/solutionpackager-tool-core": "1.201.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {},
|
|
31
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "f1086b73654d7728cb71f280588b3e0c77d535fc"
|
|
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
|
/**
|
|
@@ -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
|
+
}
|
|
@@ -11,8 +11,7 @@ import {
|
|
|
11
11
|
} from "@uipath/solutionpackager-tool-core";
|
|
12
12
|
import { workflowCompilerConfig } from "./workflow-compiler-config.js";
|
|
13
13
|
|
|
14
|
-
const NUGET_FEED_URL =
|
|
15
|
-
"https://uipath.pkgs.visualstudio.com/Public.Feeds/_packaging/UiPath-Internal/nuget/v3/index.json";
|
|
14
|
+
const NUGET_FEED_URL = "https://pkgs.uipath.com/internal/index.json";
|
|
16
15
|
|
|
17
16
|
const WORKFLOW_COMPILER_DLL_NAME = "UiPath.WorkflowCompiler.dll";
|
|
18
17
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { OrchestratorFeedComposer } from "@uipath/packager-orchestrator-client";
|
|
2
2
|
import {
|
|
3
|
+
type FileSystemStats,
|
|
3
4
|
type IFileSystem,
|
|
4
5
|
type IProjectBuildOptions,
|
|
5
6
|
type IProjectCleanupOptions,
|
|
@@ -25,6 +26,19 @@ import { WorkflowCompilerExecutor } from "./workflow-compiler-executor.js";
|
|
|
25
26
|
*/
|
|
26
27
|
type RawRemoveUnusedDependenciesResult = WorkflowCompilerCleanupPayload;
|
|
27
28
|
|
|
29
|
+
const NO_CLEANUP_SOURCE_FILES_MESSAGE =
|
|
30
|
+
"no workflow xamls or coded source files";
|
|
31
|
+
const CLEANUP_SOURCE_FILE_EXTENSIONS = [".xaml", ".cs", ".vb"];
|
|
32
|
+
const CLEANUP_SOURCE_SCAN_SKIP_DIRS = new Set([
|
|
33
|
+
".git",
|
|
34
|
+
".local",
|
|
35
|
+
".project",
|
|
36
|
+
"bin",
|
|
37
|
+
"dist",
|
|
38
|
+
"node_modules",
|
|
39
|
+
"obj",
|
|
40
|
+
]);
|
|
41
|
+
|
|
28
42
|
/**
|
|
29
43
|
* The two NuGet-source channels the WorkflowCompiler accepts, kept apart on
|
|
30
44
|
* purpose:
|
|
@@ -325,10 +339,86 @@ export class WorkflowCompilerTool extends ProjectTool {
|
|
|
325
339
|
args,
|
|
326
340
|
cancellationToken,
|
|
327
341
|
);
|
|
342
|
+
if (
|
|
343
|
+
await this.shouldRetryCleanupNoSourceFalseNegativeAsync(
|
|
344
|
+
result,
|
|
345
|
+
options.projectPath,
|
|
346
|
+
)
|
|
347
|
+
) {
|
|
348
|
+
this.logger.warn(
|
|
349
|
+
"[WorkflowCompiler] remove-unused-dependencies reported no workflow/source files even though the project contains source files; retrying once.",
|
|
350
|
+
);
|
|
351
|
+
const retryResult = await this.executor.executeAsync(
|
|
352
|
+
"remove-unused-dependencies",
|
|
353
|
+
args,
|
|
354
|
+
cancellationToken,
|
|
355
|
+
);
|
|
356
|
+
return this.toProjectCleanupResult(retryResult);
|
|
357
|
+
}
|
|
328
358
|
return this.toProjectCleanupResult(result);
|
|
329
359
|
});
|
|
330
360
|
}
|
|
331
361
|
|
|
362
|
+
private async shouldRetryCleanupNoSourceFalseNegativeAsync(
|
|
363
|
+
result: ToolResult,
|
|
364
|
+
projectPath: string,
|
|
365
|
+
): Promise<boolean> {
|
|
366
|
+
if (result.isSuccess) {
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const message = result.message?.toLowerCase();
|
|
371
|
+
if (!message?.includes(NO_CLEANUP_SOURCE_FILES_MESSAGE)) {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return await this.hasCleanupSourceFilesAsync(projectPath);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
private async hasCleanupSourceFilesAsync(
|
|
379
|
+
projectPath: string,
|
|
380
|
+
): Promise<boolean> {
|
|
381
|
+
let entries: string[];
|
|
382
|
+
try {
|
|
383
|
+
entries = await this.fileSystem.readdir(projectPath);
|
|
384
|
+
} catch {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
for (const entry of entries) {
|
|
389
|
+
const lowerEntry = entry.toLowerCase();
|
|
390
|
+
const fullPath = this.fileSystem.path.join(projectPath, entry);
|
|
391
|
+
let stats: FileSystemStats | null;
|
|
392
|
+
try {
|
|
393
|
+
stats = await this.fileSystem.stat(fullPath);
|
|
394
|
+
} catch {
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
if (!stats) {
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (
|
|
402
|
+
stats.isFile() &&
|
|
403
|
+
CLEANUP_SOURCE_FILE_EXTENSIONS.some((extension) =>
|
|
404
|
+
lowerEntry.endsWith(extension),
|
|
405
|
+
)
|
|
406
|
+
) {
|
|
407
|
+
return true;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (
|
|
411
|
+
stats.isDirectory() &&
|
|
412
|
+
!CLEANUP_SOURCE_SCAN_SKIP_DIRS.has(lowerEntry) &&
|
|
413
|
+
(await this.hasCleanupSourceFilesAsync(fullPath))
|
|
414
|
+
) {
|
|
415
|
+
return true;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
|
|
332
422
|
/**
|
|
333
423
|
* Convert the WorkflowCompiler's raw `remove-unused-dependencies` payload
|
|
334
424
|
* into the generic {@link ProjectCleanupInfo} the cleanup pipeline expects,
|