openxiangda-devkit-core 2.71.4 → 2.71.6
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/application-services.d.ts +322 -32
- package/dist/application-services.d.ts.map +1 -1
- package/dist/application-services.js +53 -19
- package/dist/application-services.js.map +1 -1
- package/dist/control-plane-client.d.ts +1 -0
- package/dist/control-plane-client.d.ts.map +1 -1
- package/dist/control-plane-client.js +14 -0
- package/dist/control-plane-client.js.map +1 -1
- package/dist/deployment-prerequisites.d.ts +2 -1
- package/dist/deployment-prerequisites.d.ts.map +1 -1
- package/dist/deployment-prerequisites.js +15 -3
- package/dist/deployment-prerequisites.js.map +1 -1
- package/dist/deployment.d.ts +3 -1
- package/dist/deployment.d.ts.map +1 -1
- package/dist/deployment.js +18 -12
- package/dist/deployment.js.map +1 -1
- package/dist/developer-operations.d.ts +72 -4
- package/dist/developer-operations.d.ts.map +1 -1
- package/dist/developer-operations.js +4 -1
- package/dist/developer-operations.js.map +1 -1
- package/dist/development-lifecycle.d.ts +109 -8
- package/dist/development-lifecycle.d.ts.map +1 -1
- package/dist/development-lifecycle.js +35 -6
- package/dist/development-lifecycle.js.map +1 -1
- package/package.json +2 -2
|
@@ -1147,8 +1147,8 @@ export class OpenXiangdaApplicationServices {
|
|
|
1147
1147
|
if (diagnostics.length > 0) {
|
|
1148
1148
|
return this.result("deployment.plan", workspace.context.workspace, undefined, diagnostics);
|
|
1149
1149
|
}
|
|
1150
|
-
const source = await operationStage('source', '
|
|
1151
|
-
const lifecycle = developmentLifecycle(workspace.root, this.appSpecContractIndex(workspace, true));
|
|
1150
|
+
const source = await operationStage('source', '核对远端主线与源码(网络不可达时保留本地来源)', () => publishedDeliverySource(workspace.root));
|
|
1151
|
+
const lifecycle = developmentLifecycle(workspace.root, this.appSpecContractIndex(workspace, true), undefined, input.appSpecChangeId, 'warning-first');
|
|
1152
1152
|
if (!lifecycle.readyForTest)
|
|
1153
1153
|
return this.result('deployment.plan', workspace.context.workspace, { lifecycle: summarizeLifecycle(lifecycle) }, lifecycle.diagnostics);
|
|
1154
1154
|
const sources = compileApplicationSources(workspace.config, this.toolchainVersion);
|
|
@@ -1158,6 +1158,7 @@ export class OpenXiangdaApplicationServices {
|
|
|
1158
1158
|
return this.result("deployment.plan", workspace.context.workspace, {
|
|
1159
1159
|
runtimeCapacity,
|
|
1160
1160
|
workflowActivation,
|
|
1161
|
+
lifecycle: summarizeLifecycle(lifecycle),
|
|
1161
1162
|
environment: input.environment,
|
|
1162
1163
|
appCode: workspace.config.app.code,
|
|
1163
1164
|
sealed: false,
|
|
@@ -1168,7 +1169,7 @@ export class OpenXiangdaApplicationServices {
|
|
|
1168
1169
|
backendRoot: workspace.config.backend.root,
|
|
1169
1170
|
configDigest: sources.config.digest,
|
|
1170
1171
|
contractDigest: sources.contracts.digest,
|
|
1171
|
-
}, workflowActivation);
|
|
1172
|
+
}, [...workflowActivation, ...lifecycle.diagnostics]);
|
|
1172
1173
|
}
|
|
1173
1174
|
async deploy(input) {
|
|
1174
1175
|
const workspace = await this.workspace(input.root);
|
|
@@ -1181,14 +1182,18 @@ export class OpenXiangdaApplicationServices {
|
|
|
1181
1182
|
this.diagnostic("DEPLOY_PREPRODUCTION_ONLY", "Native 2.0 只允许直接部署到预发环境", String(input.environment), "使用 openxiangda deploy;生产环境必须显式复用成功的测试 DeploymentRun"),
|
|
1182
1183
|
]);
|
|
1183
1184
|
}
|
|
1184
|
-
const source = await operationStage('source', '
|
|
1185
|
+
const source = await operationStage('source', '核对远端主线与源码(网络不可达时保留本地来源)', () => publishedDeliverySource(workspace.root));
|
|
1185
1186
|
const client = await this.client(workspace.root);
|
|
1186
1187
|
const capabilities = await client.capabilities();
|
|
1188
|
+
let prerequisiteWarnings = [];
|
|
1187
1189
|
if (capabilities.features?.['application.deployment-prerequisites']?.status === 'available') {
|
|
1188
|
-
await operationStage('prerequisites', '
|
|
1190
|
+
const prerequisites = await operationStage('prerequisites', '检查内核、源码托管与镜像仓库(源码异常转为警告)', async () => {
|
|
1189
1191
|
const backend = backendRuntimeRequired(workspace.config);
|
|
1190
|
-
|
|
1192
|
+
const report = await client.deploymentPrerequisites(workspace.config.app.code, backend);
|
|
1193
|
+
const warnings = assertDeploymentPrerequisites(report, workspace.config.app.code, backend);
|
|
1194
|
+
return { report, warnings };
|
|
1191
1195
|
});
|
|
1196
|
+
prerequisiteWarnings = prerequisites.warnings;
|
|
1192
1197
|
}
|
|
1193
1198
|
const sources = compileApplicationSources(workspace.config, this.toolchainVersion);
|
|
1194
1199
|
await operationStage('target-preflight', '目标平台只读预检', () => this.validateTargetConfigurationCompatibility(workspace, input.environment, compileLocalConfiguration(workspace.config, this.toolchainVersion)));
|
|
@@ -1204,8 +1209,8 @@ export class OpenXiangdaApplicationServices {
|
|
|
1204
1209
|
const generated = await this.generate({ root: workspace.root, check: true });
|
|
1205
1210
|
if (!generated.ok)
|
|
1206
1211
|
return { ...generated, operation: 'deploy' };
|
|
1207
|
-
const lifecycle = await operationStage('development-records', '
|
|
1208
|
-
const lifecycle = developmentLifecycle(workspace.root, this.appSpecContractIndex(workspace, true));
|
|
1212
|
+
const lifecycle = await operationStage('development-records', '读取需求、架构与测试验收计划(缺口转为警告)', async () => {
|
|
1213
|
+
const lifecycle = developmentLifecycle(workspace.root, this.appSpecContractIndex(workspace, true), undefined, input.appSpecChangeId, 'warning-first');
|
|
1209
1214
|
return { ...lifecycle, ok: lifecycle.readyForTest };
|
|
1210
1215
|
});
|
|
1211
1216
|
if (!lifecycle.readyForTest)
|
|
@@ -1253,8 +1258,13 @@ export class OpenXiangdaApplicationServices {
|
|
|
1253
1258
|
idempotencyKey: input.idempotencyKey ||
|
|
1254
1259
|
`deploy:${built.data.package.digest}:${input.environment}${input.deploymentStrategy === 'maintenance-replace' ? ':maintenance-replace' : ''}`,
|
|
1255
1260
|
...(input.requestId ? { requestId: input.requestId } : {}),
|
|
1261
|
+
...(input.approvalLink ? { approvalLink: true } : {}),
|
|
1256
1262
|
});
|
|
1257
|
-
return this.result("deploy", workspace.context.workspace, deployment,
|
|
1263
|
+
return this.result("deploy", workspace.context.workspace, deployment, [
|
|
1264
|
+
...workflowActivation,
|
|
1265
|
+
...prerequisiteWarnings,
|
|
1266
|
+
...lifecycle.diagnostics,
|
|
1267
|
+
], [
|
|
1258
1268
|
{
|
|
1259
1269
|
code: "status",
|
|
1260
1270
|
label: "查看部署状态",
|
|
@@ -1447,7 +1457,7 @@ export class OpenXiangdaApplicationServices {
|
|
|
1447
1457
|
if (!appVersionId)
|
|
1448
1458
|
throw new Error("DEPLOYMENT_APP_VERSION_NOT_AVAILABLE");
|
|
1449
1459
|
const diagnostics = await this.productionPromotionDiagnostics(workspace, client, source, appVersionId);
|
|
1450
|
-
if (diagnostics.
|
|
1460
|
+
if (diagnostics.some(item => item.severity === 'error')) {
|
|
1451
1461
|
return this.result("deploy", workspace.context.workspace, undefined, diagnostics);
|
|
1452
1462
|
}
|
|
1453
1463
|
const deployment = await operationStage('submit', '提交生产晋级', () => client.promote({
|
|
@@ -1456,7 +1466,7 @@ export class OpenXiangdaApplicationServices {
|
|
|
1456
1466
|
environmentKind: environment,
|
|
1457
1467
|
idempotencyKey: `promote:${source.packageDigest}:${environment}`,
|
|
1458
1468
|
}));
|
|
1459
|
-
return this.
|
|
1469
|
+
return this.result("deploy", workspace.context.workspace, deployment, diagnostics, [
|
|
1460
1470
|
{ code: "status", label: "查看生产部署状态", command: `openxiangda status ${deployment.id}` },
|
|
1461
1471
|
]);
|
|
1462
1472
|
}
|
|
@@ -1476,12 +1486,21 @@ export class OpenXiangdaApplicationServices {
|
|
|
1476
1486
|
assertProductionPromotionPreflight(version, {
|
|
1477
1487
|
appCode: workspace.config.app.code, sourceDeploymentId: source.id, appVersionId, packageDigest: source.packageDigest,
|
|
1478
1488
|
});
|
|
1479
|
-
|
|
1489
|
+
let testedLifecycle;
|
|
1490
|
+
try {
|
|
1491
|
+
testedLifecycle = lifecycleAtCommit(workspace.root, version.source.commit, this.appSpecContractIndex(workspace, true));
|
|
1492
|
+
}
|
|
1493
|
+
catch (error) {
|
|
1494
|
+
// 生产晋级使用已封存的 packageDigest;当前机器无法读取来源仓库时仅提示,
|
|
1495
|
+
// 不把本地 Git、VPN 或远端仓库可达性误判成制品不可发布。
|
|
1496
|
+
diagnostics.push(this.advisoryDiagnostic(this.diagnostic('APPSPEC_TESTED_SOURCE_UNAVAILABLE', '无法从测试版本来源读取 AppSpec 验收计划;仍可按不可变测试制品晋级', 'appspec', '网络恢复后补齐验收记录;本次以测试 DeploymentRun 和 packageDigest 为准', { message: error instanceof Error ? error.message : String(error) })));
|
|
1497
|
+
testedLifecycle = { changeId: null, acceptanceIds: [], design: { diagnostics: [] } };
|
|
1498
|
+
}
|
|
1480
1499
|
if (!testedLifecycle.changeId || !testedLifecycle.acceptanceIds.length) {
|
|
1481
|
-
diagnostics.push(this.diagnostic('APPSPEC_TESTED_PLAN_REQUIRED', '
|
|
1500
|
+
diagnostics.push(this.advisoryDiagnostic(this.diagnostic('APPSPEC_TESTED_PLAN_REQUIRED', '指定测试版本缺少可追溯的需求与验收计划;仍可继续生产晋级,请在后续补齐记录', 'appspec', '补齐真实记录并在下一次发布前复核;本次仅作为发布风险提示')));
|
|
1482
1501
|
}
|
|
1483
1502
|
// 原测试提交中的设计基线也必须有效,当前主线的补写不能补签旧版本。
|
|
1484
|
-
diagnostics.push(...testedLifecycle.design.diagnostics);
|
|
1503
|
+
diagnostics.push(...this.advisoryDiagnostics(testedLifecycle.design.diagnostics));
|
|
1485
1504
|
const acceptance = await operationStage('business-acceptance', '核对原测试版本的业务验收报告', async () => {
|
|
1486
1505
|
const result = verifyBusinessAcceptance(workspace.root, source, testedLifecycle);
|
|
1487
1506
|
if (result.ok)
|
|
@@ -1492,13 +1511,13 @@ export class OpenXiangdaApplicationServices {
|
|
|
1492
1511
|
});
|
|
1493
1512
|
return result;
|
|
1494
1513
|
});
|
|
1495
|
-
diagnostics.push(...acceptance.diagnostics);
|
|
1514
|
+
diagnostics.push(...this.advisoryDiagnostics(acceptance.diagnostics));
|
|
1496
1515
|
}
|
|
1497
1516
|
catch (error) {
|
|
1498
1517
|
return [this.configurationCompatibilityDiagnostic(error)];
|
|
1499
1518
|
}
|
|
1500
1519
|
if (workspace.context.workspace.dirty || version.source.dirty) {
|
|
1501
|
-
diagnostics.push(this.diagnostic("PRODUCTION_SOURCE_DIRTY", "
|
|
1520
|
+
diagnostics.push(this.advisoryDiagnostic(this.diagnostic("PRODUCTION_SOURCE_DIRTY", "测试版本或当前工作区存在未提交变更;本次仍复用已封存测试制品晋级", "git", "后续发布前补齐来源快照;当前制品仍按不可变 packageDigest 晋级")));
|
|
1502
1521
|
}
|
|
1503
1522
|
const repository = git(workspace.root, ["config", "--get", "remote.origin.url"]);
|
|
1504
1523
|
const currentRepository = this.repositoryIdentity(repository);
|
|
@@ -1506,9 +1525,9 @@ export class OpenXiangdaApplicationServices {
|
|
|
1506
1525
|
if (!currentRepository ||
|
|
1507
1526
|
!sourceRepository ||
|
|
1508
1527
|
currentRepository !== sourceRepository) {
|
|
1509
|
-
diagnostics.push(this.diagnostic("PRODUCTION_SOURCE_REPOSITORY_MISMATCH", "当前工作区仓库与 AppVersion
|
|
1528
|
+
diagnostics.push(this.advisoryDiagnostic(this.diagnostic("PRODUCTION_SOURCE_REPOSITORY_MISMATCH", "当前工作区仓库与 AppVersion 来源仓库不一致;仓库归属仅作溯源提示", "git.remote.origin.url", "确认 packageDigest 和测试 DeploymentRun 后继续;如需完整溯源再补充仓库信息", { current: repository || null, source: version.source.repository })));
|
|
1510
1529
|
}
|
|
1511
|
-
if (diagnostics.
|
|
1530
|
+
if (diagnostics.some(item => item.severity === 'error'))
|
|
1512
1531
|
return diagnostics;
|
|
1513
1532
|
try {
|
|
1514
1533
|
await operationStage('promotion-source', '核对测试制品的主线来源', () => publishedDeliverySource(workspace.root, version.source.commit));
|
|
@@ -1516,7 +1535,7 @@ export class OpenXiangdaApplicationServices {
|
|
|
1516
1535
|
catch (error) {
|
|
1517
1536
|
if (!(error instanceof DeliverySourceError))
|
|
1518
1537
|
throw error;
|
|
1519
|
-
diagnostics.push(this.diagnostic(error.code, error.message, 'git', String(error.data.remediation), error.data));
|
|
1538
|
+
diagnostics.push(this.advisoryDiagnostic(this.diagnostic(error.code, error.message, 'git', String(error.data.remediation), error.data)));
|
|
1520
1539
|
}
|
|
1521
1540
|
return diagnostics;
|
|
1522
1541
|
}
|
|
@@ -2080,6 +2099,21 @@ export class OpenXiangdaApplicationServices {
|
|
|
2080
2099
|
...(details ? { details } : {}),
|
|
2081
2100
|
};
|
|
2082
2101
|
}
|
|
2102
|
+
advisoryDiagnostic(diagnostic) {
|
|
2103
|
+
return {
|
|
2104
|
+
...diagnostic,
|
|
2105
|
+
severity: diagnostic.severity === 'error' ? 'warning' : diagnostic.severity,
|
|
2106
|
+
retryable: true,
|
|
2107
|
+
details: {
|
|
2108
|
+
...diagnostic.details,
|
|
2109
|
+
gateClass: 'advisory',
|
|
2110
|
+
affects: ['release-readiness'],
|
|
2111
|
+
},
|
|
2112
|
+
};
|
|
2113
|
+
}
|
|
2114
|
+
advisoryDiagnostics(diagnostics) {
|
|
2115
|
+
return diagnostics.map(diagnostic => this.advisoryDiagnostic(diagnostic));
|
|
2116
|
+
}
|
|
2083
2117
|
connectedDevelopmentFailure(error, workspaceRoot) {
|
|
2084
2118
|
const rawCode = String(error?.code ||
|
|
2085
2119
|
(error instanceof Error ? error.message.split(":", 1)[0] : "") ||
|