@uipath/packager-tool-workflowcompiler 1.197.0 → 1.198.0-preview.80
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.d.ts +1 -0
- package/dist/index.js +112 -30
- package/dist/workflow-cleanup-details.d.ts +1 -0
- package/dist/workflow-compiler-tool.d.ts +30 -2
- package/package.json +3 -3
- package/src/index.ts +10 -0
- package/src/workflow-cleanup-details.ts +4 -0
- package/src/workflow-compiler-executor.ts +20 -13
- package/src/workflow-compiler-tool.ts +212 -18
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import "./i18n/index.js";
|
|
2
2
|
export { WorkflowCompilerToolFactory } from "./workflow-compiler-tool-factory.js";
|
|
3
3
|
export { setupWorkflowCompiler } from "./workflow-compiler-config.js";
|
|
4
|
+
export type { CleanedWorkflowDetail, WorkflowCleanupDetails, } from "./workflow-cleanup-details.js";
|
package/dist/index.js
CHANGED
|
@@ -850,17 +850,8 @@ function feedsEndpoint(orchestratorUrl) {
|
|
|
850
850
|
end--;
|
|
851
851
|
}
|
|
852
852
|
const trimmed = orchestratorUrl.slice(0, end);
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
}
|
|
856
|
-
return hasPathSegments(trimmed) ? `${trimmed}/orchestrator_${FEEDS_PATH}` : `${trimmed}${FEEDS_PATH}`;
|
|
857
|
-
}
|
|
858
|
-
function hasPathSegments(url) {
|
|
859
|
-
const [error, parsed] = catchError(() => new URL(url));
|
|
860
|
-
if (error) {
|
|
861
|
-
return true;
|
|
862
|
-
}
|
|
863
|
-
return parsed.pathname !== "/" && parsed.pathname !== "";
|
|
853
|
+
const base = /\/orchestrator_$/i.test(trimmed) ? trimmed : `${trimmed}/orchestrator_`;
|
|
854
|
+
return `${base}${FEEDS_PATH}`;
|
|
864
855
|
}
|
|
865
856
|
async function describeFailure(response) {
|
|
866
857
|
const text = await response.text().catch(() => "");
|
|
@@ -957,7 +948,8 @@ function toTenantFeedSource(feed, accessToken) {
|
|
|
957
948
|
// src/workflow-compiler-tool.ts
|
|
958
949
|
import {
|
|
959
950
|
LogLevel,
|
|
960
|
-
ProjectTool
|
|
951
|
+
ProjectTool,
|
|
952
|
+
toProjectCleanupInfo
|
|
961
953
|
} from "@uipath/solutionpackager-tool-core";
|
|
962
954
|
|
|
963
955
|
// src/workflow-compiler-executor.ts
|
|
@@ -1381,20 +1373,24 @@ class WorkflowCompilerTool extends ProjectTool {
|
|
|
1381
1373
|
this.context = context;
|
|
1382
1374
|
this.executor = new WorkflowCompilerExecutor(logger, fileSystem);
|
|
1383
1375
|
}
|
|
1384
|
-
async
|
|
1376
|
+
async withFeedPaths(options, run) {
|
|
1377
|
+
const userNugetConfigPath = options.nuGetSourcesConfigPath;
|
|
1385
1378
|
const connection = this.context?.connection;
|
|
1386
|
-
if (
|
|
1387
|
-
return run(
|
|
1379
|
+
if (!connection) {
|
|
1380
|
+
return run({ userNugetConfigPath });
|
|
1388
1381
|
}
|
|
1389
1382
|
const composed = await new OrchestratorFeedComposer(this.fileSystem, this.logger).composeAsync({ connection });
|
|
1390
1383
|
try {
|
|
1391
|
-
return await run(
|
|
1384
|
+
return await run({
|
|
1385
|
+
orchestratorFeedsJsonPath: composed.configPath,
|
|
1386
|
+
userNugetConfigPath
|
|
1387
|
+
});
|
|
1392
1388
|
} finally {
|
|
1393
1389
|
await composed.dispose();
|
|
1394
1390
|
}
|
|
1395
1391
|
}
|
|
1396
1392
|
async restoreAsync(options, cancellationToken) {
|
|
1397
|
-
return this.
|
|
1393
|
+
return this.withFeedPaths(options, (paths) => {
|
|
1398
1394
|
const args = [
|
|
1399
1395
|
`-p`,
|
|
1400
1396
|
options.projectPath,
|
|
@@ -1407,14 +1403,17 @@ class WorkflowCompilerTool extends ProjectTool {
|
|
|
1407
1403
|
`--exclude-configured-sources`,
|
|
1408
1404
|
`${options.excludeConfiguredSources}`
|
|
1409
1405
|
];
|
|
1410
|
-
if (
|
|
1411
|
-
args.push(`--nuget-config-file`,
|
|
1406
|
+
if (paths.orchestratorFeedsJsonPath) {
|
|
1407
|
+
args.push(`--nuget-config-file`, paths.orchestratorFeedsJsonPath);
|
|
1408
|
+
}
|
|
1409
|
+
if (paths.userNugetConfigPath) {
|
|
1410
|
+
args.push(`--nuget-config`, paths.userNugetConfigPath);
|
|
1412
1411
|
}
|
|
1413
1412
|
return this.executor.executeAsync("restore", args, cancellationToken);
|
|
1414
1413
|
});
|
|
1415
1414
|
}
|
|
1416
1415
|
async validateAsync(options, cancellationToken) {
|
|
1417
|
-
return this.
|
|
1416
|
+
return this.withFeedPaths(options, (paths) => {
|
|
1418
1417
|
const args = [
|
|
1419
1418
|
`-p`,
|
|
1420
1419
|
options.projectPath,
|
|
@@ -1441,14 +1440,17 @@ class WorkflowCompilerTool extends ProjectTool {
|
|
|
1441
1440
|
if (options.policyFileType) {
|
|
1442
1441
|
args.push(`--policy-file-type`, `${options.policyFileType}`);
|
|
1443
1442
|
}
|
|
1444
|
-
if (
|
|
1445
|
-
args.push(`--nuget-config-file`,
|
|
1443
|
+
if (paths.orchestratorFeedsJsonPath) {
|
|
1444
|
+
args.push(`--nuget-config-file`, paths.orchestratorFeedsJsonPath);
|
|
1445
|
+
}
|
|
1446
|
+
if (paths.userNugetConfigPath) {
|
|
1447
|
+
args.push(`--nuget-config`, paths.userNugetConfigPath);
|
|
1446
1448
|
}
|
|
1447
1449
|
return this.executor.executeAsync("validate", args, cancellationToken);
|
|
1448
1450
|
});
|
|
1449
1451
|
}
|
|
1450
1452
|
async buildAsync(options, cancellationToken) {
|
|
1451
|
-
return this.
|
|
1453
|
+
return this.withFeedPaths(options, (paths) => {
|
|
1452
1454
|
const args = [
|
|
1453
1455
|
`-p`,
|
|
1454
1456
|
options.projectPath,
|
|
@@ -1478,14 +1480,17 @@ class WorkflowCompilerTool extends ProjectTool {
|
|
|
1478
1480
|
const outputType = this.mapOutputType(options.outputType);
|
|
1479
1481
|
args.push(`--output-type`, outputType);
|
|
1480
1482
|
}
|
|
1481
|
-
if (
|
|
1482
|
-
args.push(`--nuget-config-file`,
|
|
1483
|
+
if (paths.orchestratorFeedsJsonPath) {
|
|
1484
|
+
args.push(`--nuget-config-file`, paths.orchestratorFeedsJsonPath);
|
|
1485
|
+
}
|
|
1486
|
+
if (paths.userNugetConfigPath) {
|
|
1487
|
+
args.push(`--nuget-config`, paths.userNugetConfigPath);
|
|
1483
1488
|
}
|
|
1484
1489
|
return this.executor.executeAsync("build", args, cancellationToken);
|
|
1485
1490
|
});
|
|
1486
1491
|
}
|
|
1487
1492
|
async packAsync(options, cancellationToken) {
|
|
1488
|
-
return this.
|
|
1493
|
+
return this.withFeedPaths(options, async (paths) => {
|
|
1489
1494
|
const args = [
|
|
1490
1495
|
`-p`,
|
|
1491
1496
|
options.projectPath,
|
|
@@ -1528,15 +1533,92 @@ class WorkflowCompilerTool extends ProjectTool {
|
|
|
1528
1533
|
const outputType = this.mapOutputType(options.outputType);
|
|
1529
1534
|
args.push(`--output-type`, outputType);
|
|
1530
1535
|
}
|
|
1531
|
-
if (
|
|
1532
|
-
args.push(`--nuget-config-file`,
|
|
1536
|
+
if (paths.orchestratorFeedsJsonPath) {
|
|
1537
|
+
args.push(`--nuget-config-file`, paths.orchestratorFeedsJsonPath);
|
|
1533
1538
|
}
|
|
1534
|
-
|
|
1539
|
+
if (paths.userNugetConfigPath) {
|
|
1540
|
+
args.push(`--nuget-config`, paths.userNugetConfigPath);
|
|
1541
|
+
}
|
|
1542
|
+
const result = await this.executor.executeAsync("build", args, cancellationToken);
|
|
1543
|
+
return this.recoverPackagePathsAsync(result, options.outputPath);
|
|
1535
1544
|
});
|
|
1536
1545
|
}
|
|
1546
|
+
async cleanupAsync(options, cancellationToken) {
|
|
1547
|
+
return this.withFeedPaths(options, async (paths) => {
|
|
1548
|
+
const args = [
|
|
1549
|
+
`-p`,
|
|
1550
|
+
options.projectPath,
|
|
1551
|
+
`--log-level`,
|
|
1552
|
+
String(options.logLevel ?? LogLevel.Info),
|
|
1553
|
+
`--format-logs`,
|
|
1554
|
+
`true`,
|
|
1555
|
+
`--exclude-configured-sources`,
|
|
1556
|
+
`${options.excludeConfiguredSources}`
|
|
1557
|
+
];
|
|
1558
|
+
if (options.dryRun) {
|
|
1559
|
+
args.push(`--dry-run`);
|
|
1560
|
+
}
|
|
1561
|
+
if (options.skipImports) {
|
|
1562
|
+
args.push(`--skip-imports`);
|
|
1563
|
+
}
|
|
1564
|
+
if (paths.orchestratorFeedsJsonPath) {
|
|
1565
|
+
args.push(`--nuget-config-file`, paths.orchestratorFeedsJsonPath);
|
|
1566
|
+
}
|
|
1567
|
+
if (paths.userNugetConfigPath) {
|
|
1568
|
+
args.push(`--nuget-config`, paths.userNugetConfigPath);
|
|
1569
|
+
}
|
|
1570
|
+
const result = await this.executor.executeAsync("remove-unused-dependencies", args, cancellationToken);
|
|
1571
|
+
return this.toProjectCleanupResult(result);
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1574
|
+
toProjectCleanupResult(result) {
|
|
1575
|
+
const raw = result.details?.removeUnusedDependencies;
|
|
1576
|
+
if (!raw) {
|
|
1577
|
+
return result;
|
|
1578
|
+
}
|
|
1579
|
+
const details = { ...result.details };
|
|
1580
|
+
delete details.removeUnusedDependencies;
|
|
1581
|
+
details.projectCleanup = toProjectCleanupInfo(raw);
|
|
1582
|
+
result.details = details;
|
|
1583
|
+
return result;
|
|
1584
|
+
}
|
|
1537
1585
|
mapOutputType(outputType) {
|
|
1538
1586
|
return outputType === "WebApp" ? "Process" : outputType;
|
|
1539
1587
|
}
|
|
1588
|
+
async recoverPackagePathsAsync(result, outputPath) {
|
|
1589
|
+
if (!result.isSuccess) {
|
|
1590
|
+
return result;
|
|
1591
|
+
}
|
|
1592
|
+
const alreadyHasNupkgPaths = result.packages.length > 0 && result.packages.every((p) => p.toLowerCase().endsWith(".nupkg"));
|
|
1593
|
+
if (alreadyHasNupkgPaths) {
|
|
1594
|
+
return result;
|
|
1595
|
+
}
|
|
1596
|
+
const recovered = await this.findNupkgFilesAsync(outputPath);
|
|
1597
|
+
if (recovered.length > 0) {
|
|
1598
|
+
this.logger.warn(`[WorkflowCompiler] pack result did not include .nupkg paths; recovered ${recovered.length} package(s) by scanning the output folder (UV-15007 workaround).`);
|
|
1599
|
+
result.packages = recovered;
|
|
1600
|
+
}
|
|
1601
|
+
return result;
|
|
1602
|
+
}
|
|
1603
|
+
async findNupkgFilesAsync(dir) {
|
|
1604
|
+
const results = [];
|
|
1605
|
+
let entries;
|
|
1606
|
+
try {
|
|
1607
|
+
entries = await this.fileSystem.readdir(dir);
|
|
1608
|
+
} catch {
|
|
1609
|
+
return results;
|
|
1610
|
+
}
|
|
1611
|
+
for (const entry of entries) {
|
|
1612
|
+
const fullPath = this.fileSystem.path.join(dir, entry);
|
|
1613
|
+
const stats = await this.fileSystem.stat(fullPath);
|
|
1614
|
+
if (stats?.isDirectory()) {
|
|
1615
|
+
results.push(...await this.findNupkgFilesAsync(fullPath));
|
|
1616
|
+
} else if (entry.toLowerCase().endsWith(".nupkg")) {
|
|
1617
|
+
results.push(fullPath);
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
return results;
|
|
1621
|
+
}
|
|
1540
1622
|
}
|
|
1541
1623
|
|
|
1542
1624
|
// src/workflow-compiler-tool-factory.ts
|
|
@@ -1574,4 +1656,4 @@ export {
|
|
|
1574
1656
|
WorkflowCompilerToolFactory
|
|
1575
1657
|
};
|
|
1576
1658
|
|
|
1577
|
-
//# debugId=
|
|
1659
|
+
//# debugId=34D4B1BF483A641664756E2164756E21
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { CleanedWorkflowDetail, WorkflowCleanupDetails, } from "@uipath/solutionpackager-tool-core";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type IFileSystem, type IProjectBuildOptions, type IProjectPackOptions, type IProjectRestoreOptions, type IProjectValidateOptions, type IToolLogger, type ProjectOperationContext, ProjectTool, type ToolResult } from "@uipath/solutionpackager-tool-core";
|
|
1
|
+
import { type IFileSystem, type IProjectBuildOptions, type IProjectCleanupOptions, type IProjectPackOptions, type IProjectRestoreOptions, type IProjectValidateOptions, type IToolLogger, type ProjectOperationContext, ProjectTool, type ToolResult } from "@uipath/solutionpackager-tool-core";
|
|
2
2
|
/**
|
|
3
3
|
* Workflow compiler tool implementation.
|
|
4
4
|
* Builds commands and delegates execution to WorkflowCompilerExecutor.
|
|
@@ -7,13 +7,41 @@ export declare class WorkflowCompilerTool extends ProjectTool {
|
|
|
7
7
|
private readonly context?;
|
|
8
8
|
private readonly executor;
|
|
9
9
|
constructor(fileSystem: IFileSystem, logger: IToolLogger, context?: ProjectOperationContext | undefined);
|
|
10
|
-
private
|
|
10
|
+
private withFeedPaths;
|
|
11
11
|
restoreAsync(options: IProjectRestoreOptions, cancellationToken?: AbortSignal): Promise<ToolResult>;
|
|
12
12
|
validateAsync(options: IProjectValidateOptions, cancellationToken?: AbortSignal): Promise<ToolResult>;
|
|
13
13
|
buildAsync(options: IProjectBuildOptions, cancellationToken?: AbortSignal): Promise<ToolResult>;
|
|
14
14
|
packAsync(options: IProjectPackOptions, cancellationToken?: AbortSignal): Promise<ToolResult>;
|
|
15
|
+
cleanupAsync(options: IProjectCleanupOptions, cancellationToken?: AbortSignal): Promise<ToolResult>;
|
|
16
|
+
/**
|
|
17
|
+
* Convert the WorkflowCompiler's raw `remove-unused-dependencies` payload
|
|
18
|
+
* into the generic {@link ProjectCleanupInfo} the cleanup pipeline expects,
|
|
19
|
+
* exposed under the generic `details.projectCleanup` key. The
|
|
20
|
+
* workflow-specific bits (per-file removed namespaces) are preserved under
|
|
21
|
+
* `toolDetails` with this tool's own type; callers that only want the general
|
|
22
|
+
* result ignore it. Leaves the result untouched when the tool reported no
|
|
23
|
+
* cleanup payload (e.g. a failure, or an older compiler build).
|
|
24
|
+
*/
|
|
25
|
+
private toProjectCleanupResult;
|
|
15
26
|
/**
|
|
16
27
|
* Maps output type for workflow compiler.
|
|
17
28
|
*/
|
|
18
29
|
private mapOutputType;
|
|
30
|
+
/**
|
|
31
|
+
* WORKAROUND (UV-15007): older WorkflowCompiler builds report the staging
|
|
32
|
+
* content folder in their pack result instead of the produced `.nupkg` path,
|
|
33
|
+
* so downstream consumers (package signing, solution compression) cannot rely
|
|
34
|
+
* on `packages`. When the result does not already carry `.nupkg` paths, recover
|
|
35
|
+
* them by scanning the output folder.
|
|
36
|
+
*
|
|
37
|
+
* Remove this fallback after UV-15007 lands and the bundled WorkflowCompiler
|
|
38
|
+
* surfaces the produced `.nupkg` path in its result
|
|
39
|
+
* (see scripts/Download-WorkflowCompiler.ps1).
|
|
40
|
+
*/
|
|
41
|
+
private recoverPackagePathsAsync;
|
|
42
|
+
/**
|
|
43
|
+
* Recursively collect `.nupkg` files under `dir` (cross-platform). Returns an
|
|
44
|
+
* empty list if the folder cannot be read.
|
|
45
|
+
*/
|
|
46
|
+
private findNupkgFilesAsync;
|
|
19
47
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/packager-tool-workflowcompiler",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.198.0-preview.80",
|
|
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.198.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {},
|
|
31
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "9b2c3c0f21a256d2f38dd28bc97e72e6f7b10a9c"
|
|
32
32
|
}
|
package/src/index.ts
CHANGED
|
@@ -16,3 +16,13 @@ export { WorkflowCompilerToolFactory } from "./workflow-compiler-tool-factory.js
|
|
|
16
16
|
// ============================================================================
|
|
17
17
|
|
|
18
18
|
export { setupWorkflowCompiler } from "./workflow-compiler-config.js";
|
|
19
|
+
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Tool-specific cleanup detail. Surfaced via `ProjectCleanupInfo.toolDetails`;
|
|
22
|
+
// only consumers that want WorkflowCompiler specifics import these types.
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
export type {
|
|
26
|
+
CleanedWorkflowDetail,
|
|
27
|
+
WorkflowCleanupDetails,
|
|
28
|
+
} from "./workflow-cleanup-details.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
1
|
+
import { type ChildProcess, spawn } from "node:child_process";
|
|
2
2
|
import {
|
|
3
3
|
type IFileSystem,
|
|
4
4
|
type IToolLogger,
|
|
@@ -17,6 +17,13 @@ import {
|
|
|
17
17
|
WorkflowCompilerPathResolver,
|
|
18
18
|
} from "./workflow-compiler-path-resolver.js";
|
|
19
19
|
|
|
20
|
+
/** Signals when each child-process stream has finished. */
|
|
21
|
+
interface StreamCompletion {
|
|
22
|
+
markStdoutEnded(): void;
|
|
23
|
+
markStderrEnded(): void;
|
|
24
|
+
markProcessExited(): void;
|
|
25
|
+
}
|
|
26
|
+
|
|
20
27
|
function camelCaseKeys(obj: unknown): unknown {
|
|
21
28
|
if (Array.isArray(obj)) {
|
|
22
29
|
return obj.map(camelCaseKeys);
|
|
@@ -195,8 +202,8 @@ export class WorkflowCompilerExecutor {
|
|
|
195
202
|
}
|
|
196
203
|
|
|
197
204
|
private setupStdoutHandling(
|
|
198
|
-
childProcess:
|
|
199
|
-
streamCompletion:
|
|
205
|
+
childProcess: ChildProcess,
|
|
206
|
+
streamCompletion: StreamCompletion,
|
|
200
207
|
onResult: (result: IOutputResult) => void,
|
|
201
208
|
): void {
|
|
202
209
|
if (!childProcess.stdout) {
|
|
@@ -261,8 +268,8 @@ export class WorkflowCompilerExecutor {
|
|
|
261
268
|
}
|
|
262
269
|
|
|
263
270
|
private setupStderrHandling(
|
|
264
|
-
childProcess:
|
|
265
|
-
streamCompletion:
|
|
271
|
+
childProcess: ChildProcess,
|
|
272
|
+
streamCompletion: StreamCompletion,
|
|
266
273
|
fallbackErrors: string[],
|
|
267
274
|
): void {
|
|
268
275
|
if (!childProcess.stderr) {
|
|
@@ -301,8 +308,8 @@ export class WorkflowCompilerExecutor {
|
|
|
301
308
|
}
|
|
302
309
|
|
|
303
310
|
private setupProcessEventHandlers(
|
|
304
|
-
childProcess:
|
|
305
|
-
streamCompletion:
|
|
311
|
+
childProcess: ChildProcess,
|
|
312
|
+
streamCompletion: StreamCompletion,
|
|
306
313
|
resolve: (value: ToolResult) => void,
|
|
307
314
|
): void {
|
|
308
315
|
childProcess.on("exit", () => streamCompletion.markProcessExited());
|
|
@@ -326,7 +333,7 @@ export class WorkflowCompilerExecutor {
|
|
|
326
333
|
}
|
|
327
334
|
|
|
328
335
|
private setupCancellationHandler(
|
|
329
|
-
childProcess:
|
|
336
|
+
childProcess: ChildProcess,
|
|
330
337
|
cancellationToken: AbortSignal | undefined,
|
|
331
338
|
resolve: (value: ToolResult) => void,
|
|
332
339
|
): void {
|
|
@@ -354,7 +361,7 @@ export class WorkflowCompilerExecutor {
|
|
|
354
361
|
const parsed = JSON.parse(line);
|
|
355
362
|
|
|
356
363
|
// Convert PascalCase to camelCase
|
|
357
|
-
const camelCased = camelCaseKeys(parsed) as Record<string,
|
|
364
|
+
const camelCased = camelCaseKeys(parsed) as Record<string, unknown>;
|
|
358
365
|
|
|
359
366
|
// Convert numeric error codes to strings
|
|
360
367
|
if (camelCased.errorCode !== undefined) {
|
|
@@ -367,12 +374,12 @@ export class WorkflowCompilerExecutor {
|
|
|
367
374
|
|
|
368
375
|
// Extract paths from OutputPackages array of objects
|
|
369
376
|
if (camelCased.outputPackages) {
|
|
370
|
-
camelCased.outputPackages =
|
|
371
|
-
|
|
372
|
-
);
|
|
377
|
+
camelCased.outputPackages = (
|
|
378
|
+
camelCased.outputPackages as Array<{ path?: string }>
|
|
379
|
+
).map((pkg) => pkg.path || pkg);
|
|
373
380
|
}
|
|
374
381
|
|
|
375
|
-
return camelCased as IOutputMessage;
|
|
382
|
+
return camelCased as unknown as IOutputMessage;
|
|
376
383
|
} catch {
|
|
377
384
|
// Not JSON, return null
|
|
378
385
|
return null;
|
|
@@ -2,6 +2,7 @@ import { OrchestratorFeedComposer } from "@uipath/packager-orchestrator-client";
|
|
|
2
2
|
import {
|
|
3
3
|
type IFileSystem,
|
|
4
4
|
type IProjectBuildOptions,
|
|
5
|
+
type IProjectCleanupOptions,
|
|
5
6
|
type IProjectOptions,
|
|
6
7
|
type IProjectPackOptions,
|
|
7
8
|
type IProjectRestoreOptions,
|
|
@@ -11,9 +12,33 @@ import {
|
|
|
11
12
|
type ProjectOperationContext,
|
|
12
13
|
ProjectTool,
|
|
13
14
|
type ToolResult,
|
|
15
|
+
toProjectCleanupInfo,
|
|
16
|
+
type WorkflowCompilerCleanupPayload,
|
|
14
17
|
} from "@uipath/solutionpackager-tool-core";
|
|
15
18
|
import { WorkflowCompilerExecutor } from "./workflow-compiler-executor.js";
|
|
16
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Raw `remove-unused-dependencies` payload the WorkflowCompiler emits on
|
|
22
|
+
* `details.removeUnusedDependencies` (PascalCase on the wire, camelCased by the
|
|
23
|
+
* executor). Owned by this tool; mapped to the generic {@link ProjectCleanupInfo}
|
|
24
|
+
* before it leaves `cleanupAsync` so nothing downstream depends on this shape.
|
|
25
|
+
*/
|
|
26
|
+
type RawRemoveUnusedDependenciesResult = WorkflowCompilerCleanupPayload;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The two NuGet-source channels the WorkflowCompiler accepts, kept apart on
|
|
30
|
+
* purpose:
|
|
31
|
+
* - `orchestratorFeedsJsonPath` — Orchestrator tenant feeds composed internally into a
|
|
32
|
+
* JSON file, passed on the hidden `--nuget-config-file` option. Never
|
|
33
|
+
* user-supplied.
|
|
34
|
+
* - `userNugetConfigPath` — the user's own NuGet.config (XML), passed verbatim on
|
|
35
|
+
* `--nuget-config`.
|
|
36
|
+
*/
|
|
37
|
+
interface FeedPaths {
|
|
38
|
+
orchestratorFeedsJsonPath?: string;
|
|
39
|
+
userNugetConfigPath?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
17
42
|
/**
|
|
18
43
|
* Workflow compiler tool implementation.
|
|
19
44
|
* Builds commands and delegates execution to WorkflowCompilerExecutor.
|
|
@@ -30,20 +55,28 @@ export class WorkflowCompilerTool extends ProjectTool {
|
|
|
30
55
|
this.executor = new WorkflowCompilerExecutor(logger, fileSystem);
|
|
31
56
|
}
|
|
32
57
|
|
|
33
|
-
private async
|
|
58
|
+
private async withFeedPaths(
|
|
34
59
|
options: IProjectOptions,
|
|
35
|
-
run: (
|
|
60
|
+
run: (paths: FeedPaths) => Promise<ToolResult>,
|
|
36
61
|
): Promise<ToolResult> {
|
|
62
|
+
// The user's own NuGet.config (XML) always rides the --nuget-config
|
|
63
|
+
// channel; it is never mixed into the internal feeds file.
|
|
64
|
+
const userNugetConfigPath = options.nuGetSourcesConfigPath;
|
|
37
65
|
const connection = this.context?.connection;
|
|
38
|
-
if (
|
|
39
|
-
return run(
|
|
66
|
+
if (!connection) {
|
|
67
|
+
return run({ userNugetConfigPath });
|
|
40
68
|
}
|
|
69
|
+
// Orchestrator tenant feeds are composed into a JSON file that only ever
|
|
70
|
+
// goes on the hidden --nuget-config-file option.
|
|
41
71
|
const composed = await new OrchestratorFeedComposer(
|
|
42
72
|
this.fileSystem,
|
|
43
73
|
this.logger,
|
|
44
74
|
).composeAsync({ connection });
|
|
45
75
|
try {
|
|
46
|
-
return await run(
|
|
76
|
+
return await run({
|
|
77
|
+
orchestratorFeedsJsonPath: composed.configPath,
|
|
78
|
+
userNugetConfigPath,
|
|
79
|
+
});
|
|
47
80
|
} finally {
|
|
48
81
|
await composed.dispose();
|
|
49
82
|
}
|
|
@@ -53,7 +86,7 @@ export class WorkflowCompilerTool extends ProjectTool {
|
|
|
53
86
|
options: IProjectRestoreOptions,
|
|
54
87
|
cancellationToken?: AbortSignal,
|
|
55
88
|
): Promise<ToolResult> {
|
|
56
|
-
return this.
|
|
89
|
+
return this.withFeedPaths(options, (paths) => {
|
|
57
90
|
const args = [
|
|
58
91
|
`-p`,
|
|
59
92
|
options.projectPath,
|
|
@@ -67,8 +100,14 @@ export class WorkflowCompilerTool extends ProjectTool {
|
|
|
67
100
|
`${options.excludeConfiguredSources}`,
|
|
68
101
|
];
|
|
69
102
|
|
|
70
|
-
if (
|
|
71
|
-
args.push(
|
|
103
|
+
if (paths.orchestratorFeedsJsonPath) {
|
|
104
|
+
args.push(
|
|
105
|
+
`--nuget-config-file`,
|
|
106
|
+
paths.orchestratorFeedsJsonPath,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
if (paths.userNugetConfigPath) {
|
|
110
|
+
args.push(`--nuget-config`, paths.userNugetConfigPath);
|
|
72
111
|
}
|
|
73
112
|
|
|
74
113
|
return this.executor.executeAsync(
|
|
@@ -83,7 +122,7 @@ export class WorkflowCompilerTool extends ProjectTool {
|
|
|
83
122
|
options: IProjectValidateOptions,
|
|
84
123
|
cancellationToken?: AbortSignal,
|
|
85
124
|
): Promise<ToolResult> {
|
|
86
|
-
return this.
|
|
125
|
+
return this.withFeedPaths(options, (paths) => {
|
|
87
126
|
const args = [
|
|
88
127
|
`-p`,
|
|
89
128
|
options.projectPath,
|
|
@@ -111,8 +150,14 @@ export class WorkflowCompilerTool extends ProjectTool {
|
|
|
111
150
|
if (options.policyFileType) {
|
|
112
151
|
args.push(`--policy-file-type`, `${options.policyFileType}`);
|
|
113
152
|
}
|
|
114
|
-
if (
|
|
115
|
-
args.push(
|
|
153
|
+
if (paths.orchestratorFeedsJsonPath) {
|
|
154
|
+
args.push(
|
|
155
|
+
`--nuget-config-file`,
|
|
156
|
+
paths.orchestratorFeedsJsonPath,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
if (paths.userNugetConfigPath) {
|
|
160
|
+
args.push(`--nuget-config`, paths.userNugetConfigPath);
|
|
116
161
|
}
|
|
117
162
|
|
|
118
163
|
return this.executor.executeAsync(
|
|
@@ -127,7 +172,7 @@ export class WorkflowCompilerTool extends ProjectTool {
|
|
|
127
172
|
options: IProjectBuildOptions,
|
|
128
173
|
cancellationToken?: AbortSignal,
|
|
129
174
|
): Promise<ToolResult> {
|
|
130
|
-
return this.
|
|
175
|
+
return this.withFeedPaths(options, (paths) => {
|
|
131
176
|
const args = [
|
|
132
177
|
`-p`,
|
|
133
178
|
options.projectPath,
|
|
@@ -158,8 +203,14 @@ export class WorkflowCompilerTool extends ProjectTool {
|
|
|
158
203
|
const outputType = this.mapOutputType(options.outputType);
|
|
159
204
|
args.push(`--output-type`, outputType);
|
|
160
205
|
}
|
|
161
|
-
if (
|
|
162
|
-
args.push(
|
|
206
|
+
if (paths.orchestratorFeedsJsonPath) {
|
|
207
|
+
args.push(
|
|
208
|
+
`--nuget-config-file`,
|
|
209
|
+
paths.orchestratorFeedsJsonPath,
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
if (paths.userNugetConfigPath) {
|
|
213
|
+
args.push(`--nuget-config`, paths.userNugetConfigPath);
|
|
163
214
|
}
|
|
164
215
|
|
|
165
216
|
return this.executor.executeAsync("build", args, cancellationToken);
|
|
@@ -170,7 +221,7 @@ export class WorkflowCompilerTool extends ProjectTool {
|
|
|
170
221
|
options: IProjectPackOptions,
|
|
171
222
|
cancellationToken?: AbortSignal,
|
|
172
223
|
): Promise<ToolResult> {
|
|
173
|
-
return this.
|
|
224
|
+
return this.withFeedPaths(options, async (paths) => {
|
|
174
225
|
const args: string[] = [
|
|
175
226
|
`-p`,
|
|
176
227
|
options.projectPath,
|
|
@@ -214,18 +265,161 @@ export class WorkflowCompilerTool extends ProjectTool {
|
|
|
214
265
|
const outputType = this.mapOutputType(options.outputType);
|
|
215
266
|
args.push(`--output-type`, outputType);
|
|
216
267
|
}
|
|
217
|
-
if (
|
|
218
|
-
args.push(
|
|
268
|
+
if (paths.orchestratorFeedsJsonPath) {
|
|
269
|
+
args.push(
|
|
270
|
+
`--nuget-config-file`,
|
|
271
|
+
paths.orchestratorFeedsJsonPath,
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
if (paths.userNugetConfigPath) {
|
|
275
|
+
args.push(`--nuget-config`, paths.userNugetConfigPath);
|
|
219
276
|
}
|
|
220
277
|
|
|
221
|
-
|
|
278
|
+
const result = await this.executor.executeAsync(
|
|
279
|
+
"build",
|
|
280
|
+
args,
|
|
281
|
+
cancellationToken,
|
|
282
|
+
);
|
|
283
|
+
return this.recoverPackagePathsAsync(result, options.outputPath);
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async cleanupAsync(
|
|
288
|
+
options: IProjectCleanupOptions,
|
|
289
|
+
cancellationToken?: AbortSignal,
|
|
290
|
+
): Promise<ToolResult> {
|
|
291
|
+
return this.withFeedPaths(options, async (paths) => {
|
|
292
|
+
const args = [
|
|
293
|
+
`-p`,
|
|
294
|
+
options.projectPath,
|
|
295
|
+
`--log-level`,
|
|
296
|
+
String(options.logLevel ?? LogLevel.Info),
|
|
297
|
+
`--format-logs`,
|
|
298
|
+
`true`,
|
|
299
|
+
`--exclude-configured-sources`,
|
|
300
|
+
`${options.excludeConfiguredSources}`,
|
|
301
|
+
];
|
|
302
|
+
|
|
303
|
+
// --dry-run and --skip-imports are boolean switches on the compiler CLI:
|
|
304
|
+
// present means true, absent means false. They take no value — passing
|
|
305
|
+
// one (`--dry-run false`) leaves a stray token and still enables the flag.
|
|
306
|
+
if (options.dryRun) {
|
|
307
|
+
args.push(`--dry-run`);
|
|
308
|
+
}
|
|
309
|
+
if (options.skipImports) {
|
|
310
|
+
args.push(`--skip-imports`);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (paths.orchestratorFeedsJsonPath) {
|
|
314
|
+
args.push(
|
|
315
|
+
`--nuget-config-file`,
|
|
316
|
+
paths.orchestratorFeedsJsonPath,
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
if (paths.userNugetConfigPath) {
|
|
320
|
+
args.push(`--nuget-config`, paths.userNugetConfigPath);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const result = await this.executor.executeAsync(
|
|
324
|
+
"remove-unused-dependencies",
|
|
325
|
+
args,
|
|
326
|
+
cancellationToken,
|
|
327
|
+
);
|
|
328
|
+
return this.toProjectCleanupResult(result);
|
|
222
329
|
});
|
|
223
330
|
}
|
|
224
331
|
|
|
332
|
+
/**
|
|
333
|
+
* Convert the WorkflowCompiler's raw `remove-unused-dependencies` payload
|
|
334
|
+
* into the generic {@link ProjectCleanupInfo} the cleanup pipeline expects,
|
|
335
|
+
* exposed under the generic `details.projectCleanup` key. The
|
|
336
|
+
* workflow-specific bits (per-file removed namespaces) are preserved under
|
|
337
|
+
* `toolDetails` with this tool's own type; callers that only want the general
|
|
338
|
+
* result ignore it. Leaves the result untouched when the tool reported no
|
|
339
|
+
* cleanup payload (e.g. a failure, or an older compiler build).
|
|
340
|
+
*/
|
|
341
|
+
private toProjectCleanupResult(result: ToolResult): ToolResult {
|
|
342
|
+
const raw = result.details?.removeUnusedDependencies as
|
|
343
|
+
| RawRemoveUnusedDependenciesResult
|
|
344
|
+
| undefined;
|
|
345
|
+
if (!raw) {
|
|
346
|
+
return result;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Re-key the wire-named payload under the generic `projectCleanup` so
|
|
350
|
+
// nothing downstream sees this tool's domain naming.
|
|
351
|
+
const details = { ...result.details };
|
|
352
|
+
delete details.removeUnusedDependencies;
|
|
353
|
+
details.projectCleanup = toProjectCleanupInfo(raw);
|
|
354
|
+
result.details = details;
|
|
355
|
+
return result;
|
|
356
|
+
}
|
|
357
|
+
|
|
225
358
|
/**
|
|
226
359
|
* Maps output type for workflow compiler.
|
|
227
360
|
*/
|
|
228
361
|
private mapOutputType(outputType: string): string {
|
|
229
362
|
return outputType === "WebApp" ? "Process" : outputType;
|
|
230
363
|
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* WORKAROUND (UV-15007): older WorkflowCompiler builds report the staging
|
|
367
|
+
* content folder in their pack result instead of the produced `.nupkg` path,
|
|
368
|
+
* so downstream consumers (package signing, solution compression) cannot rely
|
|
369
|
+
* on `packages`. When the result does not already carry `.nupkg` paths, recover
|
|
370
|
+
* them by scanning the output folder.
|
|
371
|
+
*
|
|
372
|
+
* Remove this fallback after UV-15007 lands and the bundled WorkflowCompiler
|
|
373
|
+
* surfaces the produced `.nupkg` path in its result
|
|
374
|
+
* (see scripts/Download-WorkflowCompiler.ps1).
|
|
375
|
+
*/
|
|
376
|
+
private async recoverPackagePathsAsync(
|
|
377
|
+
result: ToolResult,
|
|
378
|
+
outputPath: string,
|
|
379
|
+
): Promise<ToolResult> {
|
|
380
|
+
if (!result.isSuccess) {
|
|
381
|
+
return result;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const alreadyHasNupkgPaths =
|
|
385
|
+
result.packages.length > 0 &&
|
|
386
|
+
result.packages.every((p) => p.toLowerCase().endsWith(".nupkg"));
|
|
387
|
+
if (alreadyHasNupkgPaths) {
|
|
388
|
+
return result;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const recovered = await this.findNupkgFilesAsync(outputPath);
|
|
392
|
+
if (recovered.length > 0) {
|
|
393
|
+
this.logger.warn(
|
|
394
|
+
`[WorkflowCompiler] pack result did not include .nupkg paths; recovered ${recovered.length} package(s) by scanning the output folder (UV-15007 workaround).`,
|
|
395
|
+
);
|
|
396
|
+
result.packages = recovered;
|
|
397
|
+
}
|
|
398
|
+
return result;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Recursively collect `.nupkg` files under `dir` (cross-platform). Returns an
|
|
403
|
+
* empty list if the folder cannot be read.
|
|
404
|
+
*/
|
|
405
|
+
private async findNupkgFilesAsync(dir: string): Promise<string[]> {
|
|
406
|
+
const results: string[] = [];
|
|
407
|
+
let entries: string[];
|
|
408
|
+
try {
|
|
409
|
+
entries = await this.fileSystem.readdir(dir);
|
|
410
|
+
} catch {
|
|
411
|
+
return results;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
for (const entry of entries) {
|
|
415
|
+
const fullPath = this.fileSystem.path.join(dir, entry);
|
|
416
|
+
const stats = await this.fileSystem.stat(fullPath);
|
|
417
|
+
if (stats?.isDirectory()) {
|
|
418
|
+
results.push(...(await this.findNupkgFilesAsync(fullPath)));
|
|
419
|
+
} else if (entry.toLowerCase().endsWith(".nupkg")) {
|
|
420
|
+
results.push(fullPath);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return results;
|
|
424
|
+
}
|
|
231
425
|
}
|