openxiangda 1.0.181 → 1.0.183

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.
@@ -45,6 +45,76 @@ function cloneJsonValue(value) {
45
45
  : JSON.parse(JSON.stringify(value));
46
46
  }
47
47
 
48
+ function normalizeIdentityList(values) {
49
+ return Array.from(
50
+ new Set(
51
+ values
52
+ .map(value => String(value || '').trim().toLowerCase())
53
+ .filter(value => /^sha256:[0-9a-f]{64}$/.test(value))
54
+ )
55
+ ).sort();
56
+ }
57
+
58
+ function normalizeManagedReleaseSourceRevision(
59
+ target,
60
+ sourceRevision,
61
+ options = {}
62
+ ) {
63
+ const logicalApp = target?.logicalApp || target?.state?.logicalApp;
64
+ const expectedRepositoryId = String(
65
+ logicalApp?.sourceRepositoryId || ''
66
+ )
67
+ .trim()
68
+ .toLowerCase();
69
+ if (!expectedRepositoryId) return cloneJsonValue(sourceRevision);
70
+ const revision =
71
+ sourceRevision &&
72
+ typeof sourceRevision === 'object' &&
73
+ !Array.isArray(sourceRevision)
74
+ ? cloneJsonValue(sourceRevision)
75
+ : {};
76
+ const repositoryAliases = normalizeIdentityList([
77
+ revision.repo,
78
+ revision.repositoryId,
79
+ ...(Array.isArray(revision.repoAliases) ? revision.repoAliases : []),
80
+ ]);
81
+ if (!repositoryAliases.includes(expectedRepositoryId)) {
82
+ const code =
83
+ String(options.errorCode || '').trim() ||
84
+ 'MANAGED_SOURCE_REPOSITORY_MISMATCH';
85
+ const error = new Error(
86
+ `${code}: 当前 Git 仓库与 logical app 权威仓库不一致`
87
+ );
88
+ error.code = code;
89
+ error.details = {
90
+ expectedRepositoryId,
91
+ repositoryAliases,
92
+ };
93
+ throw error;
94
+ }
95
+ const {
96
+ capturedAt: _capturedAt,
97
+ worktreeRoot: _worktreeRoot,
98
+ ...stableRevision
99
+ } = revision;
100
+ return {
101
+ ...stableRevision,
102
+ repo: expectedRepositoryId,
103
+ repositoryId: expectedRepositoryId,
104
+ repoAliases: normalizeIdentityList([
105
+ expectedRepositoryId,
106
+ ...repositoryAliases,
107
+ ]),
108
+ ...(Array.isArray(revision.remoteUrlHashAliases)
109
+ ? {
110
+ remoteUrlHashAliases: normalizeIdentityList(
111
+ revision.remoteUrlHashAliases
112
+ ),
113
+ }
114
+ : {}),
115
+ };
116
+ }
117
+
48
118
  function hasStateResourceMappings(value) {
49
119
  if (Array.isArray(value)) return value.length > 0;
50
120
  if (!value || typeof value !== 'object') {
@@ -264,11 +334,27 @@ function releaseExecutionPath(changeId, deploymentId, cwd = process.cwd()) {
264
334
  : path.join(base, 'execution.json');
265
335
  }
266
336
 
337
+ function withManagedReleaseForwardedFlags(stepId, args = [], flags = {}) {
338
+ const forwarded = [...args];
339
+ if (stepId !== 'backend-stage' || !flags['adopt-online-baseline']) {
340
+ return forwarded;
341
+ }
342
+ forwarded.push('--adopt-online-baseline');
343
+ const reason = String(
344
+ flags['adoption-reason'] || flags.reason || ''
345
+ ).trim();
346
+ if (reason) {
347
+ forwarded.push('--adoption-reason', reason);
348
+ }
349
+ return forwarded;
350
+ }
351
+
267
352
  module.exports = {
268
353
  bindEnvironmentTarget,
269
354
  buildCandidateBundle,
270
355
  canonicalJson,
271
356
  normalizeEnvironmentKind,
357
+ normalizeManagedReleaseSourceRevision,
272
358
  normalizeTargetName,
273
359
  hasStateResourceMappings,
274
360
  readCandidate,
@@ -278,5 +364,6 @@ module.exports = {
278
364
  resolveEnvironmentTarget,
279
365
  saveCandidate,
280
366
  sha256Canonical,
367
+ withManagedReleaseForwardedFlags,
281
368
  writePrivateJsonAtomic,
282
369
  };
package/lib/cli.js CHANGED
@@ -131,6 +131,7 @@ const {
131
131
  bindEnvironmentTarget,
132
132
  buildCandidateBundle,
133
133
  normalizeEnvironmentKind,
134
+ normalizeManagedReleaseSourceRevision,
134
135
  readCandidate,
135
136
  readJsonInput,
136
137
  releaseExecutionPath,
@@ -138,6 +139,7 @@ const {
138
139
  resolveEnvironmentTarget,
139
140
  saveCandidate,
140
141
  sha256Canonical,
142
+ withManagedReleaseForwardedFlags,
141
143
  } = require('./application-environments');
142
144
  const { startDeveloperCenter } = require('./developer-center');
143
145
  const {
@@ -1432,6 +1434,11 @@ function decorateEnvironmentReleaseSteps(steps, target, flags = {}) {
1432
1434
  if (!target.environmentId || !target.targetName) return steps;
1433
1435
  const deploymentId = readStringFlag(flags, 'deployment-id');
1434
1436
  for (const step of steps) {
1437
+ step.args = withManagedReleaseForwardedFlags(
1438
+ step.id,
1439
+ step.args,
1440
+ flags
1441
+ );
1435
1442
  step.args.push('--environment', target.targetName);
1436
1443
  if (deploymentId) step.args.push('--deployment-id', deploymentId);
1437
1444
  if (step.id === 'app-finalize') {
@@ -1557,9 +1564,12 @@ async function publishWorkspaceRelease(config, target, flags = {}) {
1557
1564
  execution: null,
1558
1565
  };
1559
1566
  }
1560
- const plannedSourceRevision = prepareReleaseSourceRevision({
1561
- cwd: process.cwd(),
1562
- });
1567
+ const plannedSourceRevision = normalizeManagedReleaseSourceRevision(
1568
+ target,
1569
+ prepareReleaseSourceRevision({
1570
+ cwd: process.cwd(),
1571
+ })
1572
+ );
1563
1573
  const existing = readReleaseExecution(changeId, deploymentId);
1564
1574
  if (
1565
1575
  existing &&
@@ -2313,16 +2323,11 @@ async function createApplicationCandidate(config, target, flags, positional) {
2313
2323
  if (!changeId) {
2314
2324
  fail('用法: openxiangda release candidate --change <id>');
2315
2325
  }
2316
- prepareReleaseSourceRevision({ cwd: process.cwd() });
2317
- const sourceRevision = readGitSourceBase(process.cwd(), 'HEAD');
2318
- if (
2319
- logicalApp.sourceRepositoryId !==
2320
- (sourceRevision.repositoryId || sourceRevision.repo)
2321
- ) {
2322
- fail(
2323
- 'CANDIDATE_REPOSITORY_MISMATCH: 当前 Git 仓库与 logical app 权威仓库不一致'
2324
- );
2325
- }
2326
+ const sourceRevision = normalizeManagedReleaseSourceRevision(
2327
+ target,
2328
+ prepareReleaseSourceRevision({ cwd: process.cwd() }),
2329
+ { errorCode: 'CANDIDATE_REPOSITORY_MISMATCH' }
2330
+ );
2326
2331
  const plan = buildWorkspaceReleasePlan({
2327
2332
  changed: true,
2328
2333
  since: flags.since,
@@ -4917,9 +4922,13 @@ async function ensureChangeBaseline(
4917
4922
  }
4918
4923
  const activeLease = getUsableStoredPublishLease(target);
4919
4924
  const sourceBase = resolveChangeSourceBase(changeId, flags);
4920
- const releaseSourceRevision = prepareReleaseSourceRevision({
4921
- cwd: process.cwd(),
4922
- });
4925
+ const releaseSourceRevision = normalizeManagedReleaseSourceRevision(
4926
+ target,
4927
+ prepareReleaseSourceRevision({
4928
+ cwd: process.cwd(),
4929
+ }),
4930
+ { errorCode: 'RELEASE_SOURCE_REPOSITORY_MISMATCH' }
4931
+ );
4923
4932
 
4924
4933
  const data = await requestWithAuth(
4925
4934
  config,
@@ -16614,7 +16623,11 @@ async function ensureOwnedImmutableReleasePublishContext(
16614
16623
  `${releaseKind} 只接受与本地冻结基线匹配的 stored lease;外部 opaque lease 不能用于原子发布`
16615
16624
  );
16616
16625
  }
16617
- const sourceRevision = clonePlainJson(baseline.sourceBase || {});
16626
+ const sourceRevision = normalizeManagedReleaseSourceRevision(
16627
+ target,
16628
+ baseline.releaseSourceRevision || {},
16629
+ { errorCode: 'RELEASE_SOURCE_REPOSITORY_MISMATCH' }
16630
+ );
16618
16631
  const sourceRepositoryId = String(
16619
16632
  sourceRevision.repositoryId || sourceRevision.repo || ''
16620
16633
  ).trim();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "1.0.181",
3
+ "version": "1.0.183",
4
4
  "description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
5
5
  "private": false,
6
6
  "bin": {