openxiangda 1.0.241 → 1.0.243
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/lib/cli.js +378 -30
- package/package.json +1 -1
package/lib/cli.js
CHANGED
|
@@ -3698,6 +3698,29 @@ function deploymentQueueDetails(error) {
|
|
|
3698
3698
|
return value;
|
|
3699
3699
|
}
|
|
3700
3700
|
|
|
3701
|
+
function deploymentQueueWaitDecision(statusInput) {
|
|
3702
|
+
const status = String(statusInput || '').trim().toLowerCase();
|
|
3703
|
+
return {
|
|
3704
|
+
status,
|
|
3705
|
+
wait: status === 'running',
|
|
3706
|
+
evidencePending: status === 'deployed',
|
|
3707
|
+
};
|
|
3708
|
+
}
|
|
3709
|
+
|
|
3710
|
+
function deploymentEvidencePendingError(deployment = {}) {
|
|
3711
|
+
const deploymentId = String(deployment.deploymentId || deployment.id || '').trim();
|
|
3712
|
+
const error = new Error(
|
|
3713
|
+
`APP_DEPLOYMENT_EVIDENCE_PENDING: 目标环境部署 ${deploymentId || '-'} 已完成激活,当前为 deployed,待提交测试证据;请先执行 openxiangda release test --deployment ${deploymentId || '<id>'} --evidence-json <JSON|file>`
|
|
3714
|
+
);
|
|
3715
|
+
error.code = 'APP_DEPLOYMENT_EVIDENCE_PENDING';
|
|
3716
|
+
error.data = {
|
|
3717
|
+
deploymentId: deploymentId || null,
|
|
3718
|
+
status: 'deployed',
|
|
3719
|
+
nextAction: 'release test',
|
|
3720
|
+
};
|
|
3721
|
+
return error;
|
|
3722
|
+
}
|
|
3723
|
+
|
|
3701
3724
|
async function createApplicationDeploymentWhenAvailable(
|
|
3702
3725
|
config,
|
|
3703
3726
|
target,
|
|
@@ -3718,9 +3741,17 @@ async function createApplicationDeploymentWhenAvailable(
|
|
|
3718
3741
|
);
|
|
3719
3742
|
} catch (error) {
|
|
3720
3743
|
const queue = deploymentQueueDetails(error);
|
|
3721
|
-
if (!queue
|
|
3744
|
+
if (!queue) throw error;
|
|
3722
3745
|
const deploymentId = String(queue.deploymentId || '').trim();
|
|
3723
3746
|
if (!deploymentId) throw error;
|
|
3747
|
+
const queuedState = deploymentQueueWaitDecision(queue.status);
|
|
3748
|
+
if (queuedState.evidencePending) {
|
|
3749
|
+
throw deploymentEvidencePendingError({
|
|
3750
|
+
...queue,
|
|
3751
|
+
deploymentId,
|
|
3752
|
+
});
|
|
3753
|
+
}
|
|
3754
|
+
if (Date.now() >= deadline || waitSeconds === 0) throw error;
|
|
3724
3755
|
const delaySeconds = Math.min(
|
|
3725
3756
|
Math.max(Number(queue.retryAfterSeconds || 5), 1),
|
|
3726
3757
|
30
|
|
@@ -3742,7 +3773,14 @@ async function createApplicationDeploymentWhenAvailable(
|
|
|
3742
3773
|
} catch {
|
|
3743
3774
|
break;
|
|
3744
3775
|
}
|
|
3745
|
-
|
|
3776
|
+
const activeState = deploymentQueueWaitDecision(active?.status);
|
|
3777
|
+
if (activeState.evidencePending) {
|
|
3778
|
+
throw deploymentEvidencePendingError({
|
|
3779
|
+
...active,
|
|
3780
|
+
deploymentId,
|
|
3781
|
+
});
|
|
3782
|
+
}
|
|
3783
|
+
if (!activeState.wait) break;
|
|
3746
3784
|
}
|
|
3747
3785
|
if (Date.now() >= deadline) {
|
|
3748
3786
|
fail(
|
|
@@ -3990,6 +4028,281 @@ async function readManagedDeployment(
|
|
|
3990
4028
|
return deployment;
|
|
3991
4029
|
}
|
|
3992
4030
|
|
|
4031
|
+
function inspectSucceededPreproductionDeployment(
|
|
4032
|
+
deployment,
|
|
4033
|
+
context,
|
|
4034
|
+
now = Date.now()
|
|
4035
|
+
) {
|
|
4036
|
+
const candidate = context?.candidate || {};
|
|
4037
|
+
const target = context?.target || {};
|
|
4038
|
+
const currentAppReleaseId = String(
|
|
4039
|
+
context?.currentAppReleaseId || ''
|
|
4040
|
+
).trim();
|
|
4041
|
+
const evidence = deployment?.evidenceSummary;
|
|
4042
|
+
const reasons = [];
|
|
4043
|
+
if (deployment?.status !== 'succeeded') {
|
|
4044
|
+
reasons.push('status_not_succeeded');
|
|
4045
|
+
}
|
|
4046
|
+
if (deployment?.kind !== 'deploy') {
|
|
4047
|
+
reasons.push('kind_not_preproduction_deploy');
|
|
4048
|
+
}
|
|
4049
|
+
if (deployment?.candidateId !== candidate.id) {
|
|
4050
|
+
reasons.push('candidate_mismatch');
|
|
4051
|
+
}
|
|
4052
|
+
if (deployment?.targetEnvironmentId !== target.environmentId) {
|
|
4053
|
+
reasons.push('target_environment_mismatch');
|
|
4054
|
+
}
|
|
4055
|
+
if (!currentAppReleaseId) reasons.push('current_app_release_missing');
|
|
4056
|
+
if (deployment?.targetAppReleaseId !== currentAppReleaseId) {
|
|
4057
|
+
reasons.push('active_app_release_mismatch');
|
|
4058
|
+
}
|
|
4059
|
+
if (!deployment?.evidenceHash) reasons.push('evidence_hash_missing');
|
|
4060
|
+
if (!evidence || typeof evidence !== 'object' || Array.isArray(evidence)) {
|
|
4061
|
+
reasons.push('evidence_summary_missing');
|
|
4062
|
+
} else {
|
|
4063
|
+
if (sha256Canonical(evidence) !== deployment.evidenceHash) {
|
|
4064
|
+
reasons.push('evidence_hash_mismatch');
|
|
4065
|
+
}
|
|
4066
|
+
if (evidence.outcome !== 'passed') reasons.push('evidence_not_passed');
|
|
4067
|
+
if (evidence.deploymentId !== deployment.id) {
|
|
4068
|
+
reasons.push('evidence_deployment_mismatch');
|
|
4069
|
+
}
|
|
4070
|
+
if (evidence.candidateId !== candidate.id) {
|
|
4071
|
+
reasons.push('evidence_candidate_mismatch');
|
|
4072
|
+
}
|
|
4073
|
+
if (evidence.candidateHash !== candidate.candidateHash) {
|
|
4074
|
+
reasons.push('evidence_candidate_hash_mismatch');
|
|
4075
|
+
}
|
|
4076
|
+
if ((evidence.testPlanHash || null) !== (candidate.testPlanHash || null)) {
|
|
4077
|
+
reasons.push('evidence_test_plan_hash_mismatch');
|
|
4078
|
+
}
|
|
4079
|
+
if (evidence.environmentId !== target.environmentId) {
|
|
4080
|
+
reasons.push('evidence_environment_mismatch');
|
|
4081
|
+
}
|
|
4082
|
+
if (evidence.environmentKind !== 'preproduction') {
|
|
4083
|
+
reasons.push('evidence_environment_kind_mismatch');
|
|
4084
|
+
}
|
|
4085
|
+
if (evidence.appType !== target.appType) {
|
|
4086
|
+
reasons.push('evidence_app_type_mismatch');
|
|
4087
|
+
}
|
|
4088
|
+
if (evidence.appReleaseId !== deployment.targetAppReleaseId) {
|
|
4089
|
+
reasons.push('evidence_app_release_mismatch');
|
|
4090
|
+
}
|
|
4091
|
+
const validUntil = Date.parse(evidence.validUntil || '');
|
|
4092
|
+
if (!Number.isFinite(validUntil) || validUntil <= now) {
|
|
4093
|
+
reasons.push('evidence_expired');
|
|
4094
|
+
}
|
|
4095
|
+
}
|
|
4096
|
+
return { accepted: reasons.length === 0, reasons };
|
|
4097
|
+
}
|
|
4098
|
+
|
|
4099
|
+
function selectSucceededPreproductionDeployment(
|
|
4100
|
+
deployments,
|
|
4101
|
+
context,
|
|
4102
|
+
now = Date.now()
|
|
4103
|
+
) {
|
|
4104
|
+
const ordered = [...(deployments || [])].sort((left, right) => {
|
|
4105
|
+
const rightCreated =
|
|
4106
|
+
Date.parse(right?.createdAt || right?.finishedAt || '') || 0;
|
|
4107
|
+
const leftCreated =
|
|
4108
|
+
Date.parse(left?.createdAt || left?.finishedAt || '') || 0;
|
|
4109
|
+
return rightCreated - leftCreated;
|
|
4110
|
+
});
|
|
4111
|
+
for (const deployment of ordered) {
|
|
4112
|
+
const validation = inspectSucceededPreproductionDeployment(
|
|
4113
|
+
deployment,
|
|
4114
|
+
context,
|
|
4115
|
+
now
|
|
4116
|
+
);
|
|
4117
|
+
if (validation.accepted) return deployment;
|
|
4118
|
+
}
|
|
4119
|
+
return null;
|
|
4120
|
+
}
|
|
4121
|
+
|
|
4122
|
+
function managedPreproductionEvidenceLineage(
|
|
4123
|
+
deployment,
|
|
4124
|
+
candidate,
|
|
4125
|
+
target
|
|
4126
|
+
) {
|
|
4127
|
+
return {
|
|
4128
|
+
deploymentId: deployment.id,
|
|
4129
|
+
candidateId: candidate.id,
|
|
4130
|
+
candidateHash: candidate.candidateHash,
|
|
4131
|
+
testPlanHash: candidate.testPlanHash || null,
|
|
4132
|
+
environmentId: target.environmentId,
|
|
4133
|
+
environmentKind: target.environmentKind,
|
|
4134
|
+
appType: target.appType,
|
|
4135
|
+
appReleaseId: deployment.targetAppReleaseId,
|
|
4136
|
+
evidenceHash: deployment.evidenceHash || null,
|
|
4137
|
+
};
|
|
4138
|
+
}
|
|
4139
|
+
|
|
4140
|
+
function recoveredPreproductionShipPatch(
|
|
4141
|
+
resolution,
|
|
4142
|
+
candidate,
|
|
4143
|
+
target,
|
|
4144
|
+
recoveredAt = new Date().toISOString()
|
|
4145
|
+
) {
|
|
4146
|
+
const deployment = resolution.deployment;
|
|
4147
|
+
return {
|
|
4148
|
+
status: 'awaiting_production_confirmation',
|
|
4149
|
+
preproductionDeploymentId: deployment.id,
|
|
4150
|
+
preproductionAppReleaseId: deployment.targetAppReleaseId,
|
|
4151
|
+
preproductionStatus: deployment.status,
|
|
4152
|
+
preproductionEvidenceHash: deployment.evidenceHash,
|
|
4153
|
+
preproductionEvidenceLineage: managedPreproductionEvidenceLineage(
|
|
4154
|
+
deployment,
|
|
4155
|
+
candidate,
|
|
4156
|
+
target
|
|
4157
|
+
),
|
|
4158
|
+
preproductionRecovery: {
|
|
4159
|
+
status: 'recovered_from_candidate_history',
|
|
4160
|
+
replacedDeploymentId: resolution.replacedDeploymentId,
|
|
4161
|
+
replacedDeploymentStatus: resolution.replacedDeploymentStatus,
|
|
4162
|
+
selectedDeploymentId: deployment.id,
|
|
4163
|
+
recoveredAt,
|
|
4164
|
+
},
|
|
4165
|
+
failure: null,
|
|
4166
|
+
};
|
|
4167
|
+
}
|
|
4168
|
+
|
|
4169
|
+
async function resolvePreproductionDeploymentForAcceptance(
|
|
4170
|
+
config,
|
|
4171
|
+
target,
|
|
4172
|
+
logicalAppCode,
|
|
4173
|
+
originalDeploymentId,
|
|
4174
|
+
candidate
|
|
4175
|
+
) {
|
|
4176
|
+
await assertRemoteCandidateMatches(
|
|
4177
|
+
config,
|
|
4178
|
+
target,
|
|
4179
|
+
logicalAppCode,
|
|
4180
|
+
candidate
|
|
4181
|
+
);
|
|
4182
|
+
const status = await requestWithAuth(
|
|
4183
|
+
config,
|
|
4184
|
+
target.profileName,
|
|
4185
|
+
environmentSetApiPath(logicalAppCode, '/status')
|
|
4186
|
+
);
|
|
4187
|
+
const targetStatus = (status?.environments || []).find(
|
|
4188
|
+
environment =>
|
|
4189
|
+
environment?.id === target.environmentId &&
|
|
4190
|
+
environment?.kind === 'preproduction' &&
|
|
4191
|
+
environment?.appType === target.appType
|
|
4192
|
+
);
|
|
4193
|
+
const currentAppReleaseId = String(
|
|
4194
|
+
targetStatus?.heads?.appReleaseId || ''
|
|
4195
|
+
).trim();
|
|
4196
|
+
if (!targetStatus || !currentAppReleaseId) {
|
|
4197
|
+
fail(
|
|
4198
|
+
`PREPRODUCTION_ACTIVE_HEAD_REQUIRED: 预发环境 ${target.environmentId} 缺少可验证的当前 AppRelease head`
|
|
4199
|
+
);
|
|
4200
|
+
}
|
|
4201
|
+
|
|
4202
|
+
let originalDeployment = null;
|
|
4203
|
+
let originalReadError = null;
|
|
4204
|
+
try {
|
|
4205
|
+
originalDeployment = await readManagedDeployment(
|
|
4206
|
+
config,
|
|
4207
|
+
target,
|
|
4208
|
+
logicalAppCode,
|
|
4209
|
+
originalDeploymentId,
|
|
4210
|
+
{ full: true }
|
|
4211
|
+
);
|
|
4212
|
+
} catch (error) {
|
|
4213
|
+
originalReadError = error;
|
|
4214
|
+
}
|
|
4215
|
+
const context = { candidate, target, currentAppReleaseId };
|
|
4216
|
+
if (originalDeployment?.status === 'deployed') {
|
|
4217
|
+
const identityMatches =
|
|
4218
|
+
originalDeployment.kind === 'deploy' &&
|
|
4219
|
+
originalDeployment.candidateId === candidate.id &&
|
|
4220
|
+
originalDeployment.targetEnvironmentId === target.environmentId &&
|
|
4221
|
+
originalDeployment.targetAppReleaseId === currentAppReleaseId;
|
|
4222
|
+
if (identityMatches) {
|
|
4223
|
+
return {
|
|
4224
|
+
deployment: originalDeployment,
|
|
4225
|
+
recovered: false,
|
|
4226
|
+
currentAppReleaseId,
|
|
4227
|
+
};
|
|
4228
|
+
}
|
|
4229
|
+
}
|
|
4230
|
+
if (originalDeployment?.status === 'succeeded') {
|
|
4231
|
+
const validation = inspectSucceededPreproductionDeployment(
|
|
4232
|
+
originalDeployment,
|
|
4233
|
+
context
|
|
4234
|
+
);
|
|
4235
|
+
if (validation.accepted) {
|
|
4236
|
+
return {
|
|
4237
|
+
deployment: originalDeployment,
|
|
4238
|
+
recovered: false,
|
|
4239
|
+
currentAppReleaseId,
|
|
4240
|
+
};
|
|
4241
|
+
}
|
|
4242
|
+
}
|
|
4243
|
+
|
|
4244
|
+
const history = await requestWithAuth(
|
|
4245
|
+
config,
|
|
4246
|
+
target.profileName,
|
|
4247
|
+
`${applicationDeploymentApiPath(logicalAppCode)}?limit=200`
|
|
4248
|
+
);
|
|
4249
|
+
const summaries = (Array.isArray(history) ? history : [])
|
|
4250
|
+
.filter(
|
|
4251
|
+
deployment =>
|
|
4252
|
+
deployment?.id !== originalDeploymentId &&
|
|
4253
|
+
deployment?.status === 'succeeded' &&
|
|
4254
|
+
deployment?.kind === 'deploy' &&
|
|
4255
|
+
deployment?.candidateId === candidate.id &&
|
|
4256
|
+
deployment?.targetEnvironmentId === target.environmentId &&
|
|
4257
|
+
deployment?.targetAppReleaseId === currentAppReleaseId
|
|
4258
|
+
)
|
|
4259
|
+
.sort((left, right) => {
|
|
4260
|
+
const rightCreated = Date.parse(right?.createdAt || '') || 0;
|
|
4261
|
+
const leftCreated = Date.parse(left?.createdAt || '') || 0;
|
|
4262
|
+
return rightCreated - leftCreated;
|
|
4263
|
+
});
|
|
4264
|
+
const details = [];
|
|
4265
|
+
for (const summary of summaries) {
|
|
4266
|
+
const detail = await requestWithAuth(
|
|
4267
|
+
config,
|
|
4268
|
+
target.profileName,
|
|
4269
|
+
`${applicationDeploymentApiPath(
|
|
4270
|
+
logicalAppCode,
|
|
4271
|
+
summary.id
|
|
4272
|
+
)}?full=true`
|
|
4273
|
+
);
|
|
4274
|
+
details.push(detail);
|
|
4275
|
+
}
|
|
4276
|
+
const replacement = selectSucceededPreproductionDeployment(
|
|
4277
|
+
details,
|
|
4278
|
+
context
|
|
4279
|
+
);
|
|
4280
|
+
if (!replacement) {
|
|
4281
|
+
const originalStatus = originalDeployment?.status || 'unreadable';
|
|
4282
|
+
const error = new Error(
|
|
4283
|
+
`PREPRODUCTION_NOT_READY_FOR_ACCEPTANCE: 预发 deployment ${originalDeploymentId} 当前状态为 ${originalStatus},且未找到同 candidate、同环境、当前 AppRelease 和有效测试证据完全一致的 succeeded replacement`
|
|
4284
|
+
);
|
|
4285
|
+
error.code = 'PREPRODUCTION_NOT_READY_FOR_ACCEPTANCE';
|
|
4286
|
+
error.data = {
|
|
4287
|
+
originalDeploymentId,
|
|
4288
|
+
originalStatus,
|
|
4289
|
+
originalReadErrorCode: originalReadError?.code || null,
|
|
4290
|
+
candidateId: candidate.id,
|
|
4291
|
+
targetEnvironmentId: target.environmentId,
|
|
4292
|
+
currentAppReleaseId,
|
|
4293
|
+
};
|
|
4294
|
+
throw error;
|
|
4295
|
+
}
|
|
4296
|
+
rememberTargetDeployment(target, replacement);
|
|
4297
|
+
return {
|
|
4298
|
+
deployment: replacement,
|
|
4299
|
+
recovered: true,
|
|
4300
|
+
replacedDeploymentId: originalDeploymentId,
|
|
4301
|
+
replacedDeploymentStatus: originalDeployment?.status || 'unreadable',
|
|
4302
|
+
currentAppReleaseId,
|
|
4303
|
+
};
|
|
4304
|
+
}
|
|
4305
|
+
|
|
3993
4306
|
async function completeManagedDeployment(
|
|
3994
4307
|
config,
|
|
3995
4308
|
target,
|
|
@@ -4004,11 +4317,40 @@ async function completeManagedDeployment(
|
|
|
4004
4317
|
evidence: deployment.evidenceSummary || evidenceInput || null,
|
|
4005
4318
|
};
|
|
4006
4319
|
}
|
|
4007
|
-
if (deployment.status
|
|
4320
|
+
if (!['deployed', 'failed'].includes(deployment.status)) {
|
|
4008
4321
|
fail(
|
|
4009
4322
|
`DEPLOYMENT_NOT_READY_FOR_COMPLETION: deployment ${deployment.id} 当前状态为 ${deployment.status}`
|
|
4010
4323
|
);
|
|
4011
4324
|
}
|
|
4325
|
+
const reconciled = await requestWithAuth(
|
|
4326
|
+
config,
|
|
4327
|
+
target.profileName,
|
|
4328
|
+
applicationDeploymentApiPath(
|
|
4329
|
+
logicalAppCode,
|
|
4330
|
+
deployment.id,
|
|
4331
|
+
'reconcile'
|
|
4332
|
+
),
|
|
4333
|
+
{
|
|
4334
|
+
method: 'POST',
|
|
4335
|
+
body: {
|
|
4336
|
+
reason: 'bind final active AppRelease lineage before test evidence',
|
|
4337
|
+
},
|
|
4338
|
+
}
|
|
4339
|
+
);
|
|
4340
|
+
if (reconciled.status === 'succeeded') {
|
|
4341
|
+
rememberTargetDeployment(target, reconciled);
|
|
4342
|
+
return {
|
|
4343
|
+
deployment: reconciled,
|
|
4344
|
+
evidence: reconciled.evidenceSummary || evidenceInput || null,
|
|
4345
|
+
};
|
|
4346
|
+
}
|
|
4347
|
+
if (reconciled.status !== 'deployed') {
|
|
4348
|
+
fail(
|
|
4349
|
+
`DEPLOYMENT_RECONCILIATION_NOT_CONFIRMED: deployment ${deployment.id} 恢复后状态为 ${reconciled.status}`
|
|
4350
|
+
);
|
|
4351
|
+
}
|
|
4352
|
+
deployment = reconciled;
|
|
4353
|
+
rememberTargetDeployment(target, deployment);
|
|
4012
4354
|
const evidence = buildBoundDeploymentEvidence(
|
|
4013
4355
|
evidenceInput,
|
|
4014
4356
|
target,
|
|
@@ -4273,21 +4615,25 @@ async function runApplicationShipCommand(
|
|
|
4273
4615
|
);
|
|
4274
4616
|
const candidate = readCandidate(existingShip.candidateId);
|
|
4275
4617
|
assertLocalCandidate(candidate);
|
|
4276
|
-
|
|
4618
|
+
const preproductionResolution = await resolvePreproductionDeploymentForAcceptance(
|
|
4277
4619
|
config,
|
|
4278
4620
|
preproduction,
|
|
4279
4621
|
logicalApp.code,
|
|
4280
4622
|
existingShip.preproductionDeploymentId,
|
|
4281
|
-
|
|
4623
|
+
candidate
|
|
4282
4624
|
);
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4625
|
+
let preproductionDeployment = preproductionResolution.deployment;
|
|
4626
|
+
if (preproductionResolution.recovered) {
|
|
4627
|
+
writeManagedShip(
|
|
4628
|
+
changeId,
|
|
4629
|
+
recoveredPreproductionShipPatch(
|
|
4630
|
+
preproductionResolution,
|
|
4631
|
+
candidate,
|
|
4632
|
+
preproduction
|
|
4633
|
+
)
|
|
4634
|
+
);
|
|
4635
|
+
warn(
|
|
4636
|
+
`预发验收已从同 candidate 的成功部署恢复: ${preproductionResolution.replacedDeploymentId} -> ${preproductionDeployment.id}`
|
|
4291
4637
|
);
|
|
4292
4638
|
}
|
|
4293
4639
|
|
|
@@ -4360,6 +4706,15 @@ async function runApplicationShipCommand(
|
|
|
4360
4706
|
const promotionStartedAt = new Date().toISOString();
|
|
4361
4707
|
writeManagedShip(changeId, {
|
|
4362
4708
|
status: 'confirmed_for_production',
|
|
4709
|
+
preproductionDeploymentId: preproductionDeployment.id,
|
|
4710
|
+
preproductionAppReleaseId: preproductionDeployment.targetAppReleaseId,
|
|
4711
|
+
preproductionStatus: preproductionDeployment.status,
|
|
4712
|
+
preproductionEvidenceHash: preproductionDeployment.evidenceHash,
|
|
4713
|
+
preproductionEvidenceLineage: managedPreproductionEvidenceLineage(
|
|
4714
|
+
preproductionDeployment,
|
|
4715
|
+
candidate,
|
|
4716
|
+
preproduction
|
|
4717
|
+
),
|
|
4363
4718
|
productionConfirmation: {
|
|
4364
4719
|
status: 'confirmed',
|
|
4365
4720
|
confirmedAt,
|
|
@@ -4627,26 +4982,14 @@ async function runApplicationEnvironmentReleaseCommand(
|
|
|
4627
4982
|
const candidate = deployment.candidateId
|
|
4628
4983
|
? readCandidate(deployment.candidateId)
|
|
4629
4984
|
: null;
|
|
4630
|
-
|
|
4631
|
-
|
|
4985
|
+
return await completeManagedDeployment(
|
|
4986
|
+
config,
|
|
4632
4987
|
target,
|
|
4988
|
+
logicalApp.code,
|
|
4633
4989
|
deployment,
|
|
4634
|
-
candidate
|
|
4635
|
-
|
|
4636
|
-
const completed = await requestWithAuth(
|
|
4637
|
-
config,
|
|
4638
|
-
target.profileName,
|
|
4639
|
-
applicationDeploymentApiPath(logicalApp.code, deploymentId, 'complete'),
|
|
4640
|
-
{
|
|
4641
|
-
method: 'POST',
|
|
4642
|
-
body: {
|
|
4643
|
-
evidenceSummary: evidence,
|
|
4644
|
-
evidenceHash: sha256Canonical(evidence),
|
|
4645
|
-
},
|
|
4646
|
-
}
|
|
4990
|
+
candidate,
|
|
4991
|
+
readJsonInput(flags['evidence-json'], 'evidence-json')
|
|
4647
4992
|
);
|
|
4648
|
-
rememberTargetDeployment(target, completed);
|
|
4649
|
-
return { deployment: completed, evidence };
|
|
4650
4993
|
}
|
|
4651
4994
|
|
|
4652
4995
|
if (subcommand === 'rollback') {
|
|
@@ -30089,8 +30432,13 @@ function buildWorkspacePublishEnv(
|
|
|
30089
30432
|
module.exports = {
|
|
30090
30433
|
buildResourceManifestSddTargets,
|
|
30091
30434
|
buildScopeGrantSourceSyncDecision,
|
|
30435
|
+
deploymentEvidencePendingError,
|
|
30436
|
+
deploymentQueueWaitDecision,
|
|
30437
|
+
inspectSucceededPreproductionDeployment,
|
|
30092
30438
|
main,
|
|
30439
|
+
recoveredPreproductionShipPatch,
|
|
30093
30440
|
resolveReleaseCommandScopedFiles,
|
|
30441
|
+
selectSucceededPreproductionDeployment,
|
|
30094
30442
|
resolveDeliveryV2BackendManifestReplacementIntent,
|
|
30095
30443
|
resolveDataViewSourceFormCodes,
|
|
30096
30444
|
satisfiedFormCodesFromContext,
|