@treeseed/sdk 0.12.32 → 0.12.34
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/operations/services/railway-deploy.d.ts +2 -1
- package/dist/operations/services/railway-deploy.js +54 -24
- package/dist/operations/services/workspace-dependency-mode.d.ts +4 -0
- package/dist/operations/services/workspace-dependency-mode.js +37 -4
- package/dist/workflow/operations.js +5 -1
- package/package.json +1 -1
|
@@ -111,11 +111,12 @@ export declare function verifyRailwayManagedResources(tenantRoot: any, scope: an
|
|
|
111
111
|
checks: any[];
|
|
112
112
|
}>;
|
|
113
113
|
export declare function shouldRunRailwayPredeployBuild(env?: NodeJS.ProcessEnv): boolean;
|
|
114
|
-
export declare function deployRailwayService(tenantRoot: any, service: any, { planOnly, write, prefix, env, }?: {
|
|
114
|
+
export declare function deployRailwayService(tenantRoot: any, service: any, { planOnly, write, prefix, env, fetchImpl, }?: {
|
|
115
115
|
planOnly?: boolean;
|
|
116
116
|
write?: TreeseedBootstrapWriter;
|
|
117
117
|
prefix?: TreeseedBootstrapTaskPrefix;
|
|
118
118
|
env?: NodeJS.ProcessEnv | Record<string, string | undefined>;
|
|
119
|
+
fetchImpl?: typeof fetch;
|
|
119
120
|
}): Promise<{
|
|
120
121
|
service: any;
|
|
121
122
|
status: string;
|
|
@@ -452,7 +452,7 @@ async function waitForRailwayManagedDeploymentsSettled(tenantRoot, scope, {
|
|
|
452
452
|
} = {}) {
|
|
453
453
|
const startMs = performance.now();
|
|
454
454
|
const deadline = Date.now() + timeoutMs;
|
|
455
|
-
const projectId = services
|
|
455
|
+
const projectId = await resolveRailwayDeploymentProjectId(services, { env, fetchImpl });
|
|
456
456
|
if (!projectId) {
|
|
457
457
|
return {
|
|
458
458
|
ok: false,
|
|
@@ -571,6 +571,23 @@ async function waitForRailwayManagedDeploymentsSettled(tenantRoot, scope, {
|
|
|
571
571
|
await sleep(pollMs);
|
|
572
572
|
}
|
|
573
573
|
}
|
|
574
|
+
async function resolveRailwayDeploymentProjectId(services, { env = process.env, fetchImpl = fetch } = {}) {
|
|
575
|
+
const configuredProjectId = services.find((service) => typeof service.projectId === "string" && service.projectId.trim())?.projectId?.trim();
|
|
576
|
+
if (configuredProjectId) {
|
|
577
|
+
return configuredProjectId;
|
|
578
|
+
}
|
|
579
|
+
const projectName = services.find((service) => typeof service.projectName === "string" && service.projectName.trim())?.projectName?.trim();
|
|
580
|
+
if (!projectName) {
|
|
581
|
+
return null;
|
|
582
|
+
}
|
|
583
|
+
try {
|
|
584
|
+
const workspace = await resolveRailwayWorkspaceContext({ env, fetchImpl });
|
|
585
|
+
const projects = await listRailwayProjects({ env, workspaceId: workspace.id, fetchImpl });
|
|
586
|
+
return projects.find((project) => project.name === projectName)?.id ?? null;
|
|
587
|
+
} catch {
|
|
588
|
+
return null;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
574
591
|
async function fetchRailwayProjectDeploymentStatus({ projectId, env = process.env, fetchImpl = fetch }) {
|
|
575
592
|
const payload = await railwayGraphqlRequest({
|
|
576
593
|
query: `
|
|
@@ -1362,7 +1379,7 @@ function shouldRunRailwayPredeployBuild(env = process.env) {
|
|
|
1362
1379
|
}
|
|
1363
1380
|
return configuredEnvValue(env, "CI") !== "true";
|
|
1364
1381
|
}
|
|
1365
|
-
async function syncRailwayApiDeviceLoginVariables(service, env, write, prefix) {
|
|
1382
|
+
async function syncRailwayApiDeviceLoginVariables(service, env, write, prefix, fetchImpl = fetch) {
|
|
1366
1383
|
if (service.key !== "api") {
|
|
1367
1384
|
return null;
|
|
1368
1385
|
}
|
|
@@ -1387,22 +1404,24 @@ async function syncRailwayApiDeviceLoginVariables(service, env, write, prefix) {
|
|
|
1387
1404
|
environmentId,
|
|
1388
1405
|
serviceId,
|
|
1389
1406
|
variables,
|
|
1390
|
-
env
|
|
1407
|
+
env,
|
|
1408
|
+
fetchImpl
|
|
1391
1409
|
});
|
|
1392
1410
|
write ? write(`[${prefix.scope}][${prefix.system}][${prefix.task}][vars] Synced device login approval URL variables for ${service.serviceName ?? serviceId}.`, "stdout") : null;
|
|
1393
1411
|
return { variables: Object.keys(variables) };
|
|
1394
1412
|
}
|
|
1395
|
-
async function resolveRailwayDeployProjectContext(service, { env = process.env } = {}) {
|
|
1413
|
+
async function resolveRailwayDeployProjectContext(service, { env = process.env, fetchImpl = fetch } = {}) {
|
|
1396
1414
|
if (service.projectId) {
|
|
1397
1415
|
return service;
|
|
1398
1416
|
}
|
|
1399
|
-
const workspace = await resolveRailwayWorkspaceContext({ env });
|
|
1417
|
+
const workspace = await resolveRailwayWorkspaceContext({ env, fetchImpl });
|
|
1400
1418
|
const { project } = await ensureRailwayProject({
|
|
1401
1419
|
projectId: service.projectId,
|
|
1402
1420
|
projectName: service.projectName,
|
|
1403
1421
|
defaultEnvironmentName: service.railwayEnvironment,
|
|
1404
1422
|
env,
|
|
1405
|
-
workspace: workspace.id
|
|
1423
|
+
workspace: workspace.id,
|
|
1424
|
+
fetchImpl
|
|
1406
1425
|
});
|
|
1407
1426
|
return {
|
|
1408
1427
|
...service,
|
|
@@ -1410,7 +1429,7 @@ async function resolveRailwayDeployProjectContext(service, { env = process.env }
|
|
|
1410
1429
|
projectName: project.name ?? service.projectName
|
|
1411
1430
|
};
|
|
1412
1431
|
}
|
|
1413
|
-
async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, service, { env = process.env, writePhase = null } = {}) {
|
|
1432
|
+
async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, service, { env = process.env, writePhase = null, fetchImpl = fetch } = {}) {
|
|
1414
1433
|
const writeSyncPhase = (stage, message) => {
|
|
1415
1434
|
if (typeof writePhase === "function") {
|
|
1416
1435
|
writePhase(`sync-runtime-config:${stage}`, message);
|
|
@@ -1423,7 +1442,7 @@ async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, ser
|
|
|
1423
1442
|
return null;
|
|
1424
1443
|
}
|
|
1425
1444
|
writeSyncPhase("workspace", "Resolving Railway workspace.");
|
|
1426
|
-
const workspace = await resolveRailwayWorkspaceContext({ env });
|
|
1445
|
+
const workspace = await resolveRailwayWorkspaceContext({ env, fetchImpl });
|
|
1427
1446
|
let project = null;
|
|
1428
1447
|
if (service.projectId) {
|
|
1429
1448
|
writeSyncPhase("project", `Resolving Railway project ${service.projectName ?? service.projectId}.`);
|
|
@@ -1432,11 +1451,12 @@ async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, ser
|
|
|
1432
1451
|
projectName: service.projectName,
|
|
1433
1452
|
defaultEnvironmentName: service.railwayEnvironment,
|
|
1434
1453
|
env,
|
|
1435
|
-
workspace: workspace.id
|
|
1454
|
+
workspace: workspace.id,
|
|
1455
|
+
fetchImpl
|
|
1436
1456
|
}).then((result) => result.project);
|
|
1437
1457
|
} else {
|
|
1438
1458
|
writeSyncPhase("project", `Looking up Railway project ${service.projectName}.`);
|
|
1439
|
-
const projects = await listRailwayProjects({ env, workspaceId: workspace.id });
|
|
1459
|
+
const projects = await listRailwayProjects({ env, workspaceId: workspace.id, fetchImpl });
|
|
1440
1460
|
project = projects.find((entry) => entry.name === service.projectName) ?? null;
|
|
1441
1461
|
if (!project) {
|
|
1442
1462
|
writeSyncPhase("project", `Creating Railway project ${service.projectName}.`);
|
|
@@ -1444,7 +1464,8 @@ async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, ser
|
|
|
1444
1464
|
projectName: service.projectName,
|
|
1445
1465
|
defaultEnvironmentName: service.railwayEnvironment,
|
|
1446
1466
|
env,
|
|
1447
|
-
workspace: workspace.id
|
|
1467
|
+
workspace: workspace.id,
|
|
1468
|
+
fetchImpl
|
|
1448
1469
|
}).then((result) => result.project);
|
|
1449
1470
|
}
|
|
1450
1471
|
}
|
|
@@ -1455,7 +1476,8 @@ async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, ser
|
|
|
1455
1476
|
environment = await ensureRailwayEnvironment({
|
|
1456
1477
|
projectId: project.id,
|
|
1457
1478
|
environmentName,
|
|
1458
|
-
env
|
|
1479
|
+
env,
|
|
1480
|
+
fetchImpl
|
|
1459
1481
|
}).then((result) => result.environment);
|
|
1460
1482
|
}
|
|
1461
1483
|
let railwayService = project.services.find((entry) => entry.id === service.serviceId || entry.name === service.serviceName) ?? null;
|
|
@@ -1469,9 +1491,10 @@ async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, ser
|
|
|
1469
1491
|
imageRef: service.imageRef,
|
|
1470
1492
|
sourceRepo: service.sourceRepo,
|
|
1471
1493
|
sourceBranch: service.sourceBranch,
|
|
1472
|
-
env
|
|
1494
|
+
env,
|
|
1495
|
+
fetchImpl
|
|
1473
1496
|
}).then((result) => result.service);
|
|
1474
|
-
} else if (service.imageRef) {
|
|
1497
|
+
} else if (service.imageRef || service.sourceRepo) {
|
|
1475
1498
|
railwayService = await ensureRailwayService({
|
|
1476
1499
|
projectId: project.id,
|
|
1477
1500
|
serviceId: service.serviceId,
|
|
@@ -1480,7 +1503,8 @@ async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, ser
|
|
|
1480
1503
|
imageRef: service.imageRef,
|
|
1481
1504
|
sourceRepo: service.sourceRepo,
|
|
1482
1505
|
sourceBranch: service.sourceBranch,
|
|
1483
|
-
env
|
|
1506
|
+
env,
|
|
1507
|
+
fetchImpl
|
|
1484
1508
|
}).then((result) => result.service);
|
|
1485
1509
|
}
|
|
1486
1510
|
if (wantsInstanceConfig) {
|
|
@@ -1499,7 +1523,8 @@ async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, ser
|
|
|
1499
1523
|
restartPolicy: service.restartPolicy,
|
|
1500
1524
|
runtimeMode: service.runtimeMode,
|
|
1501
1525
|
deploymentRegion: wantsRunnerVolume ? configuredEnvValue(env, "TREESEED_RAILWAY_STATEFUL_REGION") || "us-west2" : null,
|
|
1502
|
-
env
|
|
1526
|
+
env,
|
|
1527
|
+
fetchImpl
|
|
1503
1528
|
}) : null;
|
|
1504
1529
|
writeSyncPhase("variables", "Upserting Railway runtime variables.");
|
|
1505
1530
|
await upsertRailwayVariables({
|
|
@@ -1544,7 +1569,8 @@ async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, ser
|
|
|
1544
1569
|
...configuredEnvValue(env, "TREESEED_CODEX_AUTH_JSON_B64") ? { TREESEED_CODEX_AUTH_JSON_B64: configuredEnvValue(env, "TREESEED_CODEX_AUTH_JSON_B64") } : {}
|
|
1545
1570
|
} : {}
|
|
1546
1571
|
},
|
|
1547
|
-
env
|
|
1572
|
+
env,
|
|
1573
|
+
fetchImpl
|
|
1548
1574
|
});
|
|
1549
1575
|
const volumeMountPath = service.volumeMountPath ?? service.runnerPool?.volumeMountPath ?? WORKER_RUNNER_VOLUME_MOUNT_PATH;
|
|
1550
1576
|
if (wantsRunnerVolume) {
|
|
@@ -1556,7 +1582,8 @@ async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, ser
|
|
|
1556
1582
|
serviceId: railwayService.id,
|
|
1557
1583
|
name: service.key === "operationsRunner" ? deriveRailwayOperationsRunnerVolumeName(railwayService.name, environment.name) : service.key === "capacityProviderRunner" ? deriveRailwayCapacityProviderRunnerVolumeName(railwayService.name, environment.name) : deriveRailwayWorkerRunnerVolumeName(railwayService.name, environment.name),
|
|
1558
1584
|
mountPath: volumeMountPath,
|
|
1559
|
-
env
|
|
1585
|
+
env,
|
|
1586
|
+
fetchImpl
|
|
1560
1587
|
}) : null;
|
|
1561
1588
|
if (wantsRunnerVolume) {
|
|
1562
1589
|
if (service.key === "workerRunner") {
|
|
@@ -1572,7 +1599,8 @@ async function syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, ser
|
|
|
1572
1599
|
TREESEED_WORKER_IDLE_EXIT_MS: configuredEnvValue(env, "TREESEED_WORKER_IDLE_EXIT_MS") || "60000",
|
|
1573
1600
|
...volumeConfiguration?.volume.id ? { TREESEED_RUNNER_VOLUME_ID: volumeConfiguration.volume.id } : {}
|
|
1574
1601
|
},
|
|
1575
|
-
env
|
|
1602
|
+
env,
|
|
1603
|
+
fetchImpl
|
|
1576
1604
|
});
|
|
1577
1605
|
}
|
|
1578
1606
|
}
|
|
@@ -1599,7 +1627,8 @@ async function deployRailwayService(tenantRoot, service, {
|
|
|
1599
1627
|
planOnly = false,
|
|
1600
1628
|
write,
|
|
1601
1629
|
prefix,
|
|
1602
|
-
env = process.env
|
|
1630
|
+
env = process.env,
|
|
1631
|
+
fetchImpl = fetch
|
|
1603
1632
|
} = {}) {
|
|
1604
1633
|
const timings = [];
|
|
1605
1634
|
if (planOnly) {
|
|
@@ -1618,7 +1647,7 @@ async function deployRailwayService(tenantRoot, service, {
|
|
|
1618
1647
|
}
|
|
1619
1648
|
};
|
|
1620
1649
|
}
|
|
1621
|
-
const deployService = await timedRailwayPhase(timings, "railway:resolve-context", () => resolveRailwayDeployProjectContext(service, { env }), {
|
|
1650
|
+
const deployService = await timedRailwayPhase(timings, "railway:resolve-context", () => resolveRailwayDeployProjectContext(service, { env, fetchImpl }), {
|
|
1622
1651
|
service: service.key
|
|
1623
1652
|
});
|
|
1624
1653
|
const commandEnv = buildRailwayCommandEnv({ ...process.env, ...env });
|
|
@@ -1635,7 +1664,7 @@ async function deployRailwayService(tenantRoot, service, {
|
|
|
1635
1664
|
writePhase("resolve-context", `Resolved Railway service ${deployService.serviceName ?? deployService.serviceId ?? deployService.key}.`);
|
|
1636
1665
|
writePhase("sync-runtime-config", "Syncing Railway runtime configuration.");
|
|
1637
1666
|
const runtimeConfiguration = await timedRailwayPhase(timings, "railway:sync-runtime-config", () => withRailwayPhaseTimeout(
|
|
1638
|
-
() => syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, deployService, { env: commandEnv, writePhase }),
|
|
1667
|
+
() => syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, deployService, { env: commandEnv, writePhase, fetchImpl }),
|
|
1639
1668
|
railwayPhaseTimeoutMs(commandEnv, "sync_runtime_config"),
|
|
1640
1669
|
`Railway runtime configuration sync timed out for ${deployService.serviceName ?? deployService.key}.`
|
|
1641
1670
|
), { service: deployService.key });
|
|
@@ -1650,7 +1679,7 @@ async function deployRailwayService(tenantRoot, service, {
|
|
|
1650
1679
|
};
|
|
1651
1680
|
writePhase("device-login-vars", "Syncing Railway device-login variables.");
|
|
1652
1681
|
await timedRailwayPhase(timings, "railway:device-login-vars", () => withRailwayPhaseTimeout(
|
|
1653
|
-
() => syncRailwayApiDeviceLoginVariables(cliDeployService, commandEnv, write, taskPrefix),
|
|
1682
|
+
() => syncRailwayApiDeviceLoginVariables(cliDeployService, commandEnv, write, taskPrefix, fetchImpl),
|
|
1654
1683
|
railwayPhaseTimeoutMs(commandEnv, "device_login_vars"),
|
|
1655
1684
|
`Railway device-login variable sync timed out for ${cliDeployService.serviceName ?? cliDeployService.key}.`
|
|
1656
1685
|
), {
|
|
@@ -1673,7 +1702,8 @@ async function deployRailwayService(tenantRoot, service, {
|
|
|
1673
1702
|
() => deployRailwayServiceInstance({
|
|
1674
1703
|
serviceId: cliDeployService.serviceId,
|
|
1675
1704
|
environmentId: cliDeployService.environmentId,
|
|
1676
|
-
env: commandEnv
|
|
1705
|
+
env: commandEnv,
|
|
1706
|
+
fetchImpl
|
|
1677
1707
|
}),
|
|
1678
1708
|
railwayPhaseTimeoutMs(commandEnv, "deploy"),
|
|
1679
1709
|
`Railway API deploy phase timed out for ${cliDeployService.serviceName ?? cliDeployService.key}.`
|
|
@@ -19,6 +19,7 @@ export type WorkspaceDependencyModeReport = {
|
|
|
19
19
|
}>;
|
|
20
20
|
created: string[];
|
|
21
21
|
removed: string[];
|
|
22
|
+
preserved: string[];
|
|
22
23
|
issues: string[];
|
|
23
24
|
};
|
|
24
25
|
export type DeploymentLockfileWorkspaceIssue = {
|
|
@@ -33,6 +34,7 @@ export declare function ensureLocalWorkspaceLinks(root?: any, options?: {
|
|
|
33
34
|
}): {
|
|
34
35
|
created: string[];
|
|
35
36
|
removed: never[];
|
|
37
|
+
preserved: never[];
|
|
36
38
|
mode: DependencyResolutionMode;
|
|
37
39
|
enabled: boolean;
|
|
38
40
|
root: string;
|
|
@@ -47,9 +49,11 @@ export declare function ensureLocalWorkspaceLinks(root?: any, options?: {
|
|
|
47
49
|
export declare function unlinkLocalWorkspaceLinks(root?: any, options?: {
|
|
48
50
|
mode?: WorkspaceLinksMode;
|
|
49
51
|
env?: NodeJS.ProcessEnv;
|
|
52
|
+
preserveOperatorLinks?: boolean;
|
|
50
53
|
}): {
|
|
51
54
|
enabled: boolean;
|
|
52
55
|
removed: string[];
|
|
56
|
+
preserved: string[];
|
|
53
57
|
mode: DependencyResolutionMode;
|
|
54
58
|
root: string;
|
|
55
59
|
links: Array<WorkspaceLink & {
|
|
@@ -110,6 +110,27 @@ function internalDependencyNames(packageJson, packageNames) {
|
|
|
110
110
|
}
|
|
111
111
|
return [...names].sort();
|
|
112
112
|
}
|
|
113
|
+
function operatorWorkspacePackageNames(packages) {
|
|
114
|
+
const packageByName = new Map(packages.map((pkg) => [String(pkg.name), pkg]));
|
|
115
|
+
const packageNames = new Set(packageByName.keys());
|
|
116
|
+
const roots = packages.filter((pkg) => {
|
|
117
|
+
const name = String(pkg.name ?? "");
|
|
118
|
+
if (name === "@treeseed/cli") return true;
|
|
119
|
+
return packageBinEntries(pkg.packageJson).some(([binName]) => binName === "trsd" || binName === "treeseed");
|
|
120
|
+
}).map((pkg) => String(pkg.name));
|
|
121
|
+
const closure = /* @__PURE__ */ new Set();
|
|
122
|
+
const visit = (packageName) => {
|
|
123
|
+
if (closure.has(packageName)) return;
|
|
124
|
+
const pkg = packageByName.get(packageName);
|
|
125
|
+
if (!pkg) return;
|
|
126
|
+
closure.add(packageName);
|
|
127
|
+
for (const dependencyName of internalDependencyNames(pkg.packageJson, packageNames)) {
|
|
128
|
+
visit(dependencyName);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
for (const rootName of roots) visit(rootName);
|
|
132
|
+
return closure;
|
|
133
|
+
}
|
|
113
134
|
function dependencyNames(packageJson, filter) {
|
|
114
135
|
const names = /* @__PURE__ */ new Set();
|
|
115
136
|
if (!packageJson) return names;
|
|
@@ -306,7 +327,7 @@ function ensureLocalWorkspaceLinks(root = workspaceRoot(), options = {}) {
|
|
|
306
327
|
const enabled = workspaceLinksEnabled(options.mode, options.env);
|
|
307
328
|
const links = discoverWorkspaceLinks(root);
|
|
308
329
|
const report = inspectWorkspaceDependencyMode(root, { mode: options.mode, env: options.env });
|
|
309
|
-
if (!enabled) return { ...report, enabled: false, created: [], removed: [] };
|
|
330
|
+
if (!enabled) return { ...report, enabled: false, created: [], removed: [], preserved: [] };
|
|
310
331
|
ensureGitInfoExcludes(root, links);
|
|
311
332
|
const managedLinks = readMetadata(root);
|
|
312
333
|
const created = [];
|
|
@@ -325,7 +346,8 @@ function ensureLocalWorkspaceLinks(root = workspaceRoot(), options = {}) {
|
|
|
325
346
|
return {
|
|
326
347
|
...inspectWorkspaceDependencyMode(root, { mode: options.mode, env: options.env }),
|
|
327
348
|
created,
|
|
328
|
-
removed: []
|
|
349
|
+
removed: [],
|
|
350
|
+
preserved: []
|
|
329
351
|
};
|
|
330
352
|
}
|
|
331
353
|
function unlinkLocalWorkspaceLinks(root = workspaceRoot(), options = {}) {
|
|
@@ -333,20 +355,30 @@ function unlinkLocalWorkspaceLinks(root = workspaceRoot(), options = {}) {
|
|
|
333
355
|
const links = discoverWorkspaceLinks(root);
|
|
334
356
|
const managedLinks = readMetadata(root);
|
|
335
357
|
const removed = [];
|
|
336
|
-
|
|
358
|
+
const preserved = [];
|
|
359
|
+
const packages = workspacePackages(root).filter((pkg) => typeof pkg.name === "string" && pkg.name.startsWith("@treeseed/"));
|
|
360
|
+
const packageNameByDir = new Map(packages.map((pkg) => [pathKey(pkg.dir), String(pkg.name)]));
|
|
361
|
+
const operatorPackageNames = options.preserveOperatorLinks ? operatorWorkspacePackageNames(packages) : /* @__PURE__ */ new Set();
|
|
362
|
+
if (!enabled) return { ...inspectWorkspaceDependencyMode(root, { mode: options.mode, env: options.env }), enabled: false, removed, preserved };
|
|
337
363
|
for (const link of links) {
|
|
338
364
|
const stat = safeLstat(link.linkPath);
|
|
339
365
|
if (!stat) continue;
|
|
340
366
|
const currentTarget = stat.isSymbolicLink() ? safeReadlink(link.linkPath) : null;
|
|
341
367
|
const managed = managedLinks.has(pathKey(link.linkPath)) || currentTarget === pathKey(link.targetPath);
|
|
342
368
|
if (!stat.isSymbolicLink() || !managed) continue;
|
|
369
|
+
const ownerPackageName = packageNameByDir.get(pathKey(link.ownerPath)) ?? null;
|
|
370
|
+
if (operatorPackageNames.has(link.packageName) || ownerPackageName && operatorPackageNames.has(ownerPackageName)) {
|
|
371
|
+
preserved.push(link.linkPath);
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
343
374
|
unlinkSync(link.linkPath);
|
|
344
375
|
removed.push(link.linkPath);
|
|
345
376
|
}
|
|
346
377
|
return {
|
|
347
378
|
...inspectWorkspaceDependencyMode(root, { mode: options.mode, env: options.env }),
|
|
348
379
|
removed,
|
|
349
|
-
created: []
|
|
380
|
+
created: [],
|
|
381
|
+
preserved
|
|
350
382
|
};
|
|
351
383
|
}
|
|
352
384
|
function collectDeploymentLockfileWorkspaceIssues(root = workspaceRoot()) {
|
|
@@ -425,6 +457,7 @@ function inspectWorkspaceDependencyMode(root = workspaceRoot(), options = {}) {
|
|
|
425
457
|
links: inspected,
|
|
426
458
|
created: [],
|
|
427
459
|
removed: [],
|
|
460
|
+
preserved: [],
|
|
428
461
|
issues: [
|
|
429
462
|
...inspected.filter((link) => link.exists && (!link.linked || !link.targetMatches)).map((link) => `${link.linkPath} is not linked to ${link.targetPath}.`),
|
|
430
463
|
...lockIssues
|
|
@@ -318,10 +318,13 @@ function unlinkWorkflowWorkspaceLinks(root, helpers, mode = "auto") {
|
|
|
318
318
|
if (!shouldManageWorkspaceLinks(mode, helpers.context.env)) {
|
|
319
319
|
return inspectWorkspaceDependencyMode(root, { mode: "off", env: helpers.context.env });
|
|
320
320
|
}
|
|
321
|
-
const report = unlinkLocalWorkspaceLinks(root, { mode, env: helpers.context.env });
|
|
321
|
+
const report = unlinkLocalWorkspaceLinks(root, { mode, env: helpers.context.env, preserveOperatorLinks: true });
|
|
322
322
|
if (report.removed.length > 0) {
|
|
323
323
|
helpers.write(`[workspace][unlink] Removed ${report.removed.length} local workspace package links for deployment install.`);
|
|
324
324
|
}
|
|
325
|
+
if (report.preserved.length > 0) {
|
|
326
|
+
helpers.write(`[workspace][unlink] Preserved ${report.preserved.length} operator workspace links so local trsd tooling remains available.`);
|
|
327
|
+
}
|
|
325
328
|
return report;
|
|
326
329
|
}
|
|
327
330
|
function normalizeCiMode(mode, operation) {
|
|
@@ -5652,6 +5655,7 @@ ${blockers.join("\n")}`, {
|
|
|
5652
5655
|
{ id: "production-api-guarantees", description: "Run production API release guarantees before root deploy", repoName: rootRepo.name, repoPath: rootRepo.path, branch: PRODUCTION_BRANCH, resumable: true },
|
|
5653
5656
|
{ id: "release-root", description: `Release market ${plannedRelease.rootVersion}`, repoName: rootRepo.name, repoPath: rootRepo.path, branch: STAGING_BRANCH, resumable: true },
|
|
5654
5657
|
{ id: "publish-wait", description: "Wait for production release workflows", repoName: rootRepo.name, repoPath: rootRepo.path, branch: PRODUCTION_BRANCH, resumable: true },
|
|
5658
|
+
{ id: "production-web-live-verification", description: "Run production web live verification after root deploy", repoName: rootRepo.name, repoPath: rootRepo.path, branch: PRODUCTION_BRANCH, resumable: true },
|
|
5655
5659
|
{ id: "release-back-merge", description: "Back-merge production release history into staging", repoName: rootRepo.name, repoPath: rootRepo.path, branch: STAGING_BRANCH, resumable: true },
|
|
5656
5660
|
{ id: "workspace-link", description: "Restore local workspace links after release", repoName: rootRepo.name, repoPath: rootRepo.path, branch: STAGING_BRANCH, resumable: true }
|
|
5657
5661
|
],
|