openxiangda 1.0.180 → 1.0.182

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') {
@@ -269,6 +339,7 @@ module.exports = {
269
339
  buildCandidateBundle,
270
340
  canonicalJson,
271
341
  normalizeEnvironmentKind,
342
+ normalizeManagedReleaseSourceRevision,
272
343
  normalizeTargetName,
273
344
  hasStateResourceMappings,
274
345
  readCandidate,
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,
@@ -1557,9 +1558,12 @@ async function publishWorkspaceRelease(config, target, flags = {}) {
1557
1558
  execution: null,
1558
1559
  };
1559
1560
  }
1560
- const plannedSourceRevision = prepareReleaseSourceRevision({
1561
- cwd: process.cwd(),
1562
- });
1561
+ const plannedSourceRevision = normalizeManagedReleaseSourceRevision(
1562
+ target,
1563
+ prepareReleaseSourceRevision({
1564
+ cwd: process.cwd(),
1565
+ })
1566
+ );
1563
1567
  const existing = readReleaseExecution(changeId, deploymentId);
1564
1568
  if (
1565
1569
  existing &&
@@ -2313,16 +2317,11 @@ async function createApplicationCandidate(config, target, flags, positional) {
2313
2317
  if (!changeId) {
2314
2318
  fail('用法: openxiangda release candidate --change <id>');
2315
2319
  }
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
- }
2320
+ const sourceRevision = normalizeManagedReleaseSourceRevision(
2321
+ target,
2322
+ prepareReleaseSourceRevision({ cwd: process.cwd() }),
2323
+ { errorCode: 'CANDIDATE_REPOSITORY_MISMATCH' }
2324
+ );
2326
2325
  const plan = buildWorkspaceReleasePlan({
2327
2326
  changed: true,
2328
2327
  since: flags.since,
@@ -4917,9 +4916,13 @@ async function ensureChangeBaseline(
4917
4916
  }
4918
4917
  const activeLease = getUsableStoredPublishLease(target);
4919
4918
  const sourceBase = resolveChangeSourceBase(changeId, flags);
4920
- const releaseSourceRevision = prepareReleaseSourceRevision({
4921
- cwd: process.cwd(),
4922
- });
4919
+ const releaseSourceRevision = normalizeManagedReleaseSourceRevision(
4920
+ target,
4921
+ prepareReleaseSourceRevision({
4922
+ cwd: process.cwd(),
4923
+ }),
4924
+ { errorCode: 'RELEASE_SOURCE_REPOSITORY_MISMATCH' }
4925
+ );
4923
4926
 
4924
4927
  const data = await requestWithAuth(
4925
4928
  config,
@@ -16614,7 +16617,11 @@ async function ensureOwnedImmutableReleasePublishContext(
16614
16617
  `${releaseKind} 只接受与本地冻结基线匹配的 stored lease;外部 opaque lease 不能用于原子发布`
16615
16618
  );
16616
16619
  }
16617
- const sourceRevision = clonePlainJson(baseline.sourceBase || {});
16620
+ const sourceRevision = normalizeManagedReleaseSourceRevision(
16621
+ target,
16622
+ baseline.releaseSourceRevision || {},
16623
+ { errorCode: 'RELEASE_SOURCE_REPOSITORY_MISMATCH' }
16624
+ );
16618
16625
  const sourceRepositoryId = String(
16619
16626
  sourceRevision.repositoryId || sourceRevision.repo || ''
16620
16627
  ).trim();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "1.0.180",
3
+ "version": "1.0.182",
4
4
  "description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
5
5
  "private": false,
6
6
  "bin": {
@@ -172,8 +172,7 @@
172
172
  "tsx": "^4.20.0",
173
173
  "typescript": "^5.7.0",
174
174
  "undici": "^6.27.0",
175
- "vite": "^6.0.0",
176
- "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
175
+ "vite": "^6.0.0"
177
176
  },
178
177
  "peerDependencies": {
179
178
  "react": ">=18 <20",
@@ -190,7 +189,8 @@
190
189
  "react": "18.3.1",
191
190
  "react-dom": "18.3.1",
192
191
  "tsup": "^8.3.0",
193
- "vitest": "^4.1.7"
192
+ "vitest": "^4.1.7",
193
+ "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
194
194
  },
195
195
  "engines": {
196
196
  "node": ">=18"