openxiangda 1.0.239 → 1.0.241
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 +286 -4
- package/lib/delivery-v2-executor.js +4 -0
- package/lib/release-plan.js +9 -0
- package/package.json +1 -1
package/lib/cli.js
CHANGED
|
@@ -7292,6 +7292,11 @@ async function runAppReleaseCommand(
|
|
|
7292
7292
|
environmentControl: appReleaseEnvironmentControl(flags),
|
|
7293
7293
|
}
|
|
7294
7294
|
);
|
|
7295
|
+
const finalizedDataViews = await finalizeDeferredDataViewResources(
|
|
7296
|
+
config,
|
|
7297
|
+
target,
|
|
7298
|
+
readCommaSeparatedFlag(flags, 'finalize-data-views')
|
|
7299
|
+
);
|
|
7295
7300
|
const bindingVerification =
|
|
7296
7301
|
await verifyFinalizedBackendBindingContracts(
|
|
7297
7302
|
config,
|
|
@@ -7336,6 +7341,9 @@ async function runAppReleaseCommand(
|
|
|
7336
7341
|
prepared,
|
|
7337
7342
|
verified,
|
|
7338
7343
|
activated,
|
|
7344
|
+
...(finalizedDataViews
|
|
7345
|
+
? { finalizedDataViews }
|
|
7346
|
+
: {}),
|
|
7339
7347
|
...(bindingVerification ? { bindingVerification } : {}),
|
|
7340
7348
|
...(healthWait ? { healthWait } : {}),
|
|
7341
7349
|
...(stateReconcileWarning ? { stateReconcileWarning } : {}),
|
|
@@ -14380,9 +14388,16 @@ async function resource(args) {
|
|
|
14380
14388
|
manifest.scopeGrantSources || []
|
|
14381
14389
|
)
|
|
14382
14390
|
: [];
|
|
14391
|
+
const dataViewFormCodes = stagedChangeId
|
|
14392
|
+
? resolveDataViewSourceFormCodes(
|
|
14393
|
+
manifest.dataViews || [],
|
|
14394
|
+
target.bound
|
|
14395
|
+
)
|
|
14396
|
+
: [];
|
|
14383
14397
|
const stagedContractFormCodes = unique([
|
|
14384
14398
|
...workflowFormCodes,
|
|
14385
14399
|
...scopeGrantSourceFormCodes,
|
|
14400
|
+
...dataViewFormCodes,
|
|
14386
14401
|
]).sort();
|
|
14387
14402
|
if (
|
|
14388
14403
|
stagedContractFormCodes.length > 0 &&
|
|
@@ -14509,6 +14524,20 @@ async function resource(args) {
|
|
|
14509
14524
|
const publishLease = await telemetry.runPhase('lease', async () =>
|
|
14510
14525
|
resolvePublishLeaseForWrite(config, target, flags)
|
|
14511
14526
|
);
|
|
14527
|
+
const deliveryV2BackendManifestIntent =
|
|
14528
|
+
resolveDeliveryV2BackendManifestReplacementIntent({
|
|
14529
|
+
flags,
|
|
14530
|
+
typeFilters,
|
|
14531
|
+
codeFilters,
|
|
14532
|
+
manifest,
|
|
14533
|
+
});
|
|
14534
|
+
const publishLeaseFlags = deliveryV2BackendManifestIntent
|
|
14535
|
+
? {
|
|
14536
|
+
...flags,
|
|
14537
|
+
reason: deliveryV2BackendManifestIntent.reason,
|
|
14538
|
+
'replace-reason': deliveryV2BackendManifestIntent.reason,
|
|
14539
|
+
}
|
|
14540
|
+
: flags;
|
|
14512
14541
|
const changeBaselinePreflight = await telemetry.runPhase(
|
|
14513
14542
|
'preflight',
|
|
14514
14543
|
{
|
|
@@ -14538,10 +14567,12 @@ async function resource(args) {
|
|
|
14538
14567
|
pruneCandidates,
|
|
14539
14568
|
publishLeaseId: publishLease?.leaseId,
|
|
14540
14569
|
publishLease,
|
|
14541
|
-
publishLeaseFlags
|
|
14570
|
+
publishLeaseFlags,
|
|
14542
14571
|
scopedFiles,
|
|
14543
14572
|
baseRef: flags.since || 'HEAD',
|
|
14544
|
-
replaceManifest:
|
|
14573
|
+
replaceManifest:
|
|
14574
|
+
Boolean(flags['replace-manifest']) ||
|
|
14575
|
+
Boolean(deliveryV2BackendManifestIntent),
|
|
14545
14576
|
changeId:
|
|
14546
14577
|
flags.change || getStoredChangeBaseline(target)?.changeId || null,
|
|
14547
14578
|
stagedFormBindingOverlays,
|
|
@@ -14557,6 +14588,10 @@ async function resource(args) {
|
|
|
14557
14588
|
Boolean(typeFilters?.has('workflows')),
|
|
14558
14589
|
})
|
|
14559
14590
|
);
|
|
14591
|
+
if (deliveryV2BackendManifestIntent) {
|
|
14592
|
+
result.deliveryV2BackendManifestReplacement =
|
|
14593
|
+
deliveryV2BackendManifestIntent;
|
|
14594
|
+
}
|
|
14560
14595
|
if (changeBaselinePreflight) {
|
|
14561
14596
|
result.changeBaselinePreflight = changeBaselinePreflight;
|
|
14562
14597
|
}
|
|
@@ -23789,6 +23824,10 @@ async function findExistingScopeResource(config, target, segment, code) {
|
|
|
23789
23824
|
}
|
|
23790
23825
|
|
|
23791
23826
|
async function publishDataViewResources(config, target, dataViews, result, options = {}) {
|
|
23827
|
+
const stagedFormBindingOverlays =
|
|
23828
|
+
options.stagedFormBindingOverlays instanceof Map
|
|
23829
|
+
? options.stagedFormBindingOverlays
|
|
23830
|
+
: new Map();
|
|
23792
23831
|
for (const dataViewItem of dataViews) {
|
|
23793
23832
|
if (shouldSkipNoopResource(options, 'dataView', dataViewItem.code)) {
|
|
23794
23833
|
recordNoopResource(result, 'dataView', dataViewItem.code, options);
|
|
@@ -23796,6 +23835,18 @@ async function publishDataViewResources(config, target, dataViews, result, optio
|
|
|
23796
23835
|
}
|
|
23797
23836
|
const existing = await findExistingDataView(config, target, dataViewItem.code);
|
|
23798
23837
|
const body = normalizeDataViewManifest(target.bound, dataViewItem);
|
|
23838
|
+
const stagedFormReleases = options.finalizeDeferredDataViews
|
|
23839
|
+
? []
|
|
23840
|
+
: stagedDataViewFormReleaseDependencies(
|
|
23841
|
+
body,
|
|
23842
|
+
stagedFormBindingOverlays
|
|
23843
|
+
);
|
|
23844
|
+
if (stagedFormReleases.length > 0) {
|
|
23845
|
+
body.stagedFormReleases = stagedFormReleases;
|
|
23846
|
+
}
|
|
23847
|
+
if (options.finalizeDeferredDataViews) {
|
|
23848
|
+
body.finalizeDeferred = true;
|
|
23849
|
+
}
|
|
23799
23850
|
const data = existing
|
|
23800
23851
|
? await requestWithAuth(
|
|
23801
23852
|
config,
|
|
@@ -23819,10 +23870,26 @@ async function publishDataViewResources(config, target, dataViews, result, optio
|
|
|
23819
23870
|
result.published.push({
|
|
23820
23871
|
kind: 'dataView',
|
|
23821
23872
|
code: dataViewItem.code,
|
|
23822
|
-
action:
|
|
23873
|
+
action: options.finalizeDeferredDataViews
|
|
23874
|
+
? data?.status === 'active'
|
|
23875
|
+
? 'finalize'
|
|
23876
|
+
: 'noop'
|
|
23877
|
+
: existing
|
|
23878
|
+
? 'update'
|
|
23879
|
+
: 'create',
|
|
23823
23880
|
id: data?.id,
|
|
23881
|
+
status: data?.status || null,
|
|
23882
|
+
...(stagedFormReleases.length > 0
|
|
23883
|
+
? {
|
|
23884
|
+
activation: 'deferred-until-form-activation',
|
|
23885
|
+
stagedFormReleaseCount: stagedFormReleases.length,
|
|
23886
|
+
}
|
|
23887
|
+
: {}),
|
|
23824
23888
|
});
|
|
23825
|
-
if (
|
|
23889
|
+
if (
|
|
23890
|
+
!options.finalizeDeferredDataViews &&
|
|
23891
|
+
Array.isArray(body.permissionGroups)
|
|
23892
|
+
) {
|
|
23826
23893
|
await publishDataViewPermissionGroups(config, target, dataViewItem.code, body.permissionGroups);
|
|
23827
23894
|
result.published.push({
|
|
23828
23895
|
kind: 'dataViewPermissionGroup',
|
|
@@ -23833,6 +23900,128 @@ async function publishDataViewResources(config, target, dataViews, result, optio
|
|
|
23833
23900
|
}
|
|
23834
23901
|
}
|
|
23835
23902
|
|
|
23903
|
+
function stagedDataViewFormReleaseDependencies(
|
|
23904
|
+
body,
|
|
23905
|
+
stagedFormBindingOverlays = new Map()
|
|
23906
|
+
) {
|
|
23907
|
+
const overlaysByFormUuid = new Map(
|
|
23908
|
+
Array.from(stagedFormBindingOverlays.values())
|
|
23909
|
+
.map(overlay => [String(overlay?.formUuid || '').trim(), overlay])
|
|
23910
|
+
.filter(([formUuid]) => Boolean(formUuid))
|
|
23911
|
+
);
|
|
23912
|
+
const sources = [
|
|
23913
|
+
body?.definition?.base,
|
|
23914
|
+
...(body?.definition?.joins || []),
|
|
23915
|
+
].filter(Boolean);
|
|
23916
|
+
const dependencies = new Map();
|
|
23917
|
+
for (const source of sources) {
|
|
23918
|
+
const formUuid = String(source?.formUuid || '').trim();
|
|
23919
|
+
const staged = overlaysByFormUuid.get(formUuid);
|
|
23920
|
+
if (!staged) continue;
|
|
23921
|
+
dependencies.set(formUuid, {
|
|
23922
|
+
formUuid,
|
|
23923
|
+
releaseId: staged.releaseId,
|
|
23924
|
+
contentHash: staged.contentHash,
|
|
23925
|
+
baseRevision: staged.baseRevision,
|
|
23926
|
+
parentReleaseId: staged.parentReleaseId,
|
|
23927
|
+
});
|
|
23928
|
+
}
|
|
23929
|
+
return Array.from(dependencies.values()).sort((left, right) =>
|
|
23930
|
+
left.formUuid.localeCompare(right.formUuid)
|
|
23931
|
+
);
|
|
23932
|
+
}
|
|
23933
|
+
|
|
23934
|
+
function resolveDataViewSourceFormCodes(dataViews, bound) {
|
|
23935
|
+
const codeByFormUuid = new Map(
|
|
23936
|
+
Object.entries(bound.resources?.forms || {})
|
|
23937
|
+
.map(([formCode, resource]) => [
|
|
23938
|
+
String(resource?.formUuid || '').trim(),
|
|
23939
|
+
formCode,
|
|
23940
|
+
])
|
|
23941
|
+
.filter(([formUuid]) => Boolean(formUuid))
|
|
23942
|
+
);
|
|
23943
|
+
const formCodes = [];
|
|
23944
|
+
for (const dataView of dataViews || []) {
|
|
23945
|
+
const definition =
|
|
23946
|
+
dataView?.definition !== undefined
|
|
23947
|
+
? dataView.definition
|
|
23948
|
+
: dataView;
|
|
23949
|
+
const sources = [
|
|
23950
|
+
definition?.base,
|
|
23951
|
+
...(definition?.joins || []),
|
|
23952
|
+
].filter(Boolean);
|
|
23953
|
+
for (const source of sources) {
|
|
23954
|
+
const formCode = String(
|
|
23955
|
+
source?.formCode ||
|
|
23956
|
+
source?.form ||
|
|
23957
|
+
(source?.kind === 'form' ? source?.code : '') ||
|
|
23958
|
+
codeByFormUuid.get(String(source?.formUuid || '').trim()) ||
|
|
23959
|
+
''
|
|
23960
|
+
).trim();
|
|
23961
|
+
if (formCode) formCodes.push(formCode);
|
|
23962
|
+
}
|
|
23963
|
+
}
|
|
23964
|
+
return unique(formCodes).sort();
|
|
23965
|
+
}
|
|
23966
|
+
|
|
23967
|
+
async function finalizeDeferredDataViewResources(
|
|
23968
|
+
config,
|
|
23969
|
+
target,
|
|
23970
|
+
codes
|
|
23971
|
+
) {
|
|
23972
|
+
if (!Array.isArray(codes) || codes.length === 0) return null;
|
|
23973
|
+
const selectors = codes.map(code => ({
|
|
23974
|
+
key: 'dataViews',
|
|
23975
|
+
code,
|
|
23976
|
+
raw: code,
|
|
23977
|
+
}));
|
|
23978
|
+
const manifest = loadWorkspaceResources({
|
|
23979
|
+
typeFilters: new Set(['dataViews']),
|
|
23980
|
+
codeFilters: selectors,
|
|
23981
|
+
});
|
|
23982
|
+
if ((manifest.unmatchedResourceCodeFilters || []).length > 0) {
|
|
23983
|
+
fail(
|
|
23984
|
+
`DATA_VIEW_FINALIZE_SOURCE_MISSING: App finalize 找不到数据视图源码: ${manifest.unmatchedResourceCodeFilters.join(', ')}`
|
|
23985
|
+
);
|
|
23986
|
+
}
|
|
23987
|
+
const result = {
|
|
23988
|
+
appType: target.appType,
|
|
23989
|
+
profile: target.profileName,
|
|
23990
|
+
published: [],
|
|
23991
|
+
warnings: [],
|
|
23992
|
+
};
|
|
23993
|
+
await publishDataViewResources(
|
|
23994
|
+
config,
|
|
23995
|
+
target,
|
|
23996
|
+
manifest.dataViews || [],
|
|
23997
|
+
result,
|
|
23998
|
+
{
|
|
23999
|
+
skipNoop: false,
|
|
24000
|
+
finalizeDeferredDataViews: true,
|
|
24001
|
+
}
|
|
24002
|
+
);
|
|
24003
|
+
const notActive = result.published.filter(
|
|
24004
|
+
item => item.kind === 'dataView' && item.status !== 'active'
|
|
24005
|
+
);
|
|
24006
|
+
if (notActive.length > 0) {
|
|
24007
|
+
fail(
|
|
24008
|
+
`DATA_VIEW_FINALIZE_INCOMPLETE: ${notActive
|
|
24009
|
+
.map(item => `${item.code}:${item.status || 'unknown'}`)
|
|
24010
|
+
.join(', ')}`
|
|
24011
|
+
);
|
|
24012
|
+
}
|
|
24013
|
+
return {
|
|
24014
|
+
requested: codes,
|
|
24015
|
+
finalized: result.published
|
|
24016
|
+
.filter(item => item.kind === 'dataView')
|
|
24017
|
+
.map(item => ({
|
|
24018
|
+
code: item.code,
|
|
24019
|
+
id: item.id || null,
|
|
24020
|
+
status: item.status,
|
|
24021
|
+
})),
|
|
24022
|
+
};
|
|
24023
|
+
}
|
|
24024
|
+
|
|
23836
24025
|
async function publishStorageConfigResources(config, target, storageConfigs, result, options = {}) {
|
|
23837
24026
|
for (const storageItem of storageConfigs) {
|
|
23838
24027
|
const code = storageItem.code || storageItem.resourceCode;
|
|
@@ -28096,6 +28285,86 @@ function shouldReplaceResourceManifestItem(item, resourceKey, code, options = {}
|
|
|
28096
28285
|
return options.replaceManifest === true;
|
|
28097
28286
|
}
|
|
28098
28287
|
|
|
28288
|
+
function resolveDeliveryV2BackendManifestReplacementIntent({
|
|
28289
|
+
flags = {},
|
|
28290
|
+
typeFilters = null,
|
|
28291
|
+
codeFilters = null,
|
|
28292
|
+
manifest = {},
|
|
28293
|
+
deliveryContext = activeDeliveryV2Context,
|
|
28294
|
+
} = {}) {
|
|
28295
|
+
if (!deliveryContext || !flags['stage-only']) return null;
|
|
28296
|
+
const selectedTypes = Array.from(typeFilters || []);
|
|
28297
|
+
if (
|
|
28298
|
+
selectedTypes.length === 0 ||
|
|
28299
|
+
selectedTypes.some(
|
|
28300
|
+
type => !['functions', 'automations'].includes(type)
|
|
28301
|
+
)
|
|
28302
|
+
) {
|
|
28303
|
+
return null;
|
|
28304
|
+
}
|
|
28305
|
+
if (!Array.isArray(codeFilters) || codeFilters.length === 0) {
|
|
28306
|
+
const error = new Error(
|
|
28307
|
+
'DELIVERY_BACKEND_SCOPE_MISMATCH: Delivery V2 Backend stage 缺少冻结的精确 selector'
|
|
28308
|
+
);
|
|
28309
|
+
error.code = 'DELIVERY_BACKEND_SCOPE_MISMATCH';
|
|
28310
|
+
error.retryable = false;
|
|
28311
|
+
throw error;
|
|
28312
|
+
}
|
|
28313
|
+
const expectedSelectors = unique([
|
|
28314
|
+
...(deliveryContext.targets?.functions || []).map(
|
|
28315
|
+
code => `Function:${String(code)}`
|
|
28316
|
+
),
|
|
28317
|
+
...(deliveryContext.targets?.automations || []).map(
|
|
28318
|
+
code => `Automation:${String(code)}`
|
|
28319
|
+
),
|
|
28320
|
+
]).sort();
|
|
28321
|
+
const actualSelectors = unique([
|
|
28322
|
+
...(manifest.functions || []).map(
|
|
28323
|
+
item => `Function:${getResourceItemCode(item)}`
|
|
28324
|
+
),
|
|
28325
|
+
...(manifest.automations || []).map(
|
|
28326
|
+
item => `Automation:${getResourceItemCode(item)}`
|
|
28327
|
+
),
|
|
28328
|
+
])
|
|
28329
|
+
.filter(selector => !selector.endsWith(':'))
|
|
28330
|
+
.sort();
|
|
28331
|
+
if (
|
|
28332
|
+
expectedSelectors.length === 0 ||
|
|
28333
|
+
JSON.stringify(actualSelectors) !== JSON.stringify(expectedSelectors)
|
|
28334
|
+
) {
|
|
28335
|
+
const error = new Error(
|
|
28336
|
+
`DELIVERY_BACKEND_SCOPE_MISMATCH: Delivery V2 Backend stage 与 ReleaseRun 冻结范围不一致;expected=[${expectedSelectors.join(
|
|
28337
|
+
','
|
|
28338
|
+
)}] actual=[${actualSelectors.join(',')}]`
|
|
28339
|
+
);
|
|
28340
|
+
error.code = 'DELIVERY_BACKEND_SCOPE_MISMATCH';
|
|
28341
|
+
error.retryable = false;
|
|
28342
|
+
error.expectedSelectors = expectedSelectors;
|
|
28343
|
+
error.actualSelectors = actualSelectors;
|
|
28344
|
+
throw error;
|
|
28345
|
+
}
|
|
28346
|
+
const runId = String(deliveryContext.runId || '').trim();
|
|
28347
|
+
const packageDigest = String(deliveryContext.packageDigest || '').trim();
|
|
28348
|
+
if (!runId || !/^[a-f0-9]{64}$/.test(packageDigest)) {
|
|
28349
|
+
const error = new Error(
|
|
28350
|
+
'DELIVERY_CONTROL_INVALID: Delivery V2 Backend stage 缺少 ReleaseRun/packageDigest 权威上下文'
|
|
28351
|
+
);
|
|
28352
|
+
error.code = 'DELIVERY_CONTROL_INVALID';
|
|
28353
|
+
error.retryable = false;
|
|
28354
|
+
throw error;
|
|
28355
|
+
}
|
|
28356
|
+
return {
|
|
28357
|
+
mode: 'manifest_replacement',
|
|
28358
|
+
authority: 'delivery_v2_sealed_package',
|
|
28359
|
+
runId,
|
|
28360
|
+
packageDigest,
|
|
28361
|
+
selectors: actualSelectors,
|
|
28362
|
+
reason:
|
|
28363
|
+
`Delivery V2 ReleaseRun ${runId} sealed package ${packageDigest} ` +
|
|
28364
|
+
'authoritative backend manifest and binding contract replacement',
|
|
28365
|
+
};
|
|
28366
|
+
}
|
|
28367
|
+
|
|
28099
28368
|
function buildAutomationSourcePatchSources(existingDefinition, desiredDefinition) {
|
|
28100
28369
|
const existing = existingDefinition || {};
|
|
28101
28370
|
const desired = desiredDefinition || {};
|
|
@@ -29431,6 +29700,16 @@ function readStringFlag(flags, key) {
|
|
|
29431
29700
|
return String(value).trim();
|
|
29432
29701
|
}
|
|
29433
29702
|
|
|
29703
|
+
function readCommaSeparatedFlag(flags, key) {
|
|
29704
|
+
const value = readStringFlag(flags, key);
|
|
29705
|
+
return unique(
|
|
29706
|
+
value
|
|
29707
|
+
.split(',')
|
|
29708
|
+
.map(item => item.trim())
|
|
29709
|
+
.filter(Boolean)
|
|
29710
|
+
).sort();
|
|
29711
|
+
}
|
|
29712
|
+
|
|
29434
29713
|
function normalizeWorkspacePublishOptions(flags) {
|
|
29435
29714
|
const targetForm = readStringFlag(flags, 'form');
|
|
29436
29715
|
const targetPage = readStringFlag(flags, 'page');
|
|
@@ -29812,5 +30091,8 @@ module.exports = {
|
|
|
29812
30091
|
buildScopeGrantSourceSyncDecision,
|
|
29813
30092
|
main,
|
|
29814
30093
|
resolveReleaseCommandScopedFiles,
|
|
30094
|
+
resolveDeliveryV2BackendManifestReplacementIntent,
|
|
30095
|
+
resolveDataViewSourceFormCodes,
|
|
29815
30096
|
satisfiedFormCodesFromContext,
|
|
30097
|
+
stagedDataViewFormReleaseDependencies,
|
|
29816
30098
|
};
|
|
@@ -882,6 +882,10 @@ function compactStepResult(stepId, result, context = {}) {
|
|
|
882
882
|
if (bindingContracts) {
|
|
883
883
|
compact.backendBindingContracts = bindingContracts;
|
|
884
884
|
}
|
|
885
|
+
if (result.deliveryV2BackendManifestReplacement) {
|
|
886
|
+
compact.backendManifestReplacement =
|
|
887
|
+
result.deliveryV2BackendManifestReplacement;
|
|
888
|
+
}
|
|
885
889
|
}
|
|
886
890
|
return compact;
|
|
887
891
|
}
|
package/lib/release-plan.js
CHANGED
|
@@ -327,6 +327,9 @@ function buildWorkspaceReleaseSteps(
|
|
|
327
327
|
const stagesFormRelease =
|
|
328
328
|
runtimeMode === 'react-spa' &&
|
|
329
329
|
(targets.forms.length > 0 || formPermissionGroups.length > 0);
|
|
330
|
+
const deferredDataViewCodes = stagesFormRelease
|
|
331
|
+
? uniqueSorted(targets.resourceSelectors?.dataViews || [])
|
|
332
|
+
: [];
|
|
330
333
|
const directConfigurationSteps =
|
|
331
334
|
buildDirectConfigurationReleaseSteps(
|
|
332
335
|
targets,
|
|
@@ -437,6 +440,12 @@ function buildWorkspaceReleaseSteps(
|
|
|
437
440
|
`.openxiangda/releases/${changeId || 'change'}/staged-resources.json`,
|
|
438
441
|
]
|
|
439
442
|
: []),
|
|
443
|
+
...(deferredDataViewCodes.length > 0
|
|
444
|
+
? [
|
|
445
|
+
'--finalize-data-views',
|
|
446
|
+
deferredDataViewCodes.join(','),
|
|
447
|
+
]
|
|
448
|
+
: []),
|
|
440
449
|
'--wait',
|
|
441
450
|
],
|
|
442
451
|
profileArg,
|