@ranger1/dx 0.1.56 → 0.1.58
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/vercel-deploy.js +77 -18
- package/package.json +1 -1
package/lib/vercel-deploy.js
CHANGED
|
@@ -11,17 +11,25 @@ const TARGET_CONFIGS = {
|
|
|
11
11
|
front: {
|
|
12
12
|
configFile: 'vercel.front.json',
|
|
13
13
|
projectIdEnvVar: 'VERCEL_PROJECT_ID_FRONT',
|
|
14
|
+
deployCwd: 'apps/front',
|
|
15
|
+
deployMode: 'prebuilt',
|
|
16
|
+
prebuiltCwd: '.',
|
|
14
17
|
},
|
|
15
18
|
admin: {
|
|
16
19
|
configFile: 'vercel.admin.json',
|
|
17
20
|
projectIdEnvVar: 'VERCEL_PROJECT_ID_ADMIN',
|
|
21
|
+
deployCwd: 'apps/admin-front',
|
|
22
|
+
deployMode: 'prebuilt',
|
|
18
23
|
},
|
|
19
24
|
'telegram-bot': {
|
|
20
25
|
configFile: 'vercel.telegram-bot.json',
|
|
21
26
|
projectIdEnvVar: 'VERCEL_PROJECT_ID_TELEGRAM_BOT',
|
|
27
|
+
deployMode: 'prebuilt',
|
|
22
28
|
},
|
|
23
29
|
}
|
|
24
30
|
|
|
31
|
+
const ALLOWED_DEPLOY_MODES = ['prebuilt']
|
|
32
|
+
|
|
25
33
|
const APP_ENV_MAP = {
|
|
26
34
|
development: 'dev',
|
|
27
35
|
staging: 'staging',
|
|
@@ -51,6 +59,14 @@ function isMissingFilesError(err) {
|
|
|
51
59
|
)
|
|
52
60
|
}
|
|
53
61
|
|
|
62
|
+
function isNextPrebuiltMissingPathError(err) {
|
|
63
|
+
const text = collectErrorText(err)
|
|
64
|
+
return (
|
|
65
|
+
text.includes('ENOENT') &&
|
|
66
|
+
(text.includes('next-server.js') || text.includes('/node_modules/.pnpm/'))
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
54
70
|
function listMissingVarKeys(targetConfigs, token, orgId) {
|
|
55
71
|
const missing = []
|
|
56
72
|
|
|
@@ -85,13 +101,9 @@ function listMissingConfigs(targetConfigs, projectRoot) {
|
|
|
85
101
|
return missing
|
|
86
102
|
}
|
|
87
103
|
|
|
88
|
-
function appendTargetArgs(baseArgs, {
|
|
104
|
+
function appendTargetArgs(baseArgs, { orgId }) {
|
|
89
105
|
const args = [...baseArgs]
|
|
90
106
|
|
|
91
|
-
if (cwd) {
|
|
92
|
-
args.push('--cwd', cwd)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
107
|
if (orgId) {
|
|
96
108
|
args.push('--scope', orgId)
|
|
97
109
|
}
|
|
@@ -99,14 +111,33 @@ function appendTargetArgs(baseArgs, { cwd, orgId }) {
|
|
|
99
111
|
return args
|
|
100
112
|
}
|
|
101
113
|
|
|
114
|
+
export function resolveTargetRunCwd(projectRoot, targetConfig) {
|
|
115
|
+
if (!targetConfig?.deployCwd) return projectRoot
|
|
116
|
+
return join(projectRoot, targetConfig.deployCwd)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function resolveTargetDeployMode(targetConfig) {
|
|
120
|
+
if (!targetConfig?.deployMode) return 'prebuilt'
|
|
121
|
+
return targetConfig.deployMode
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function isSupportedDeployMode(mode) {
|
|
125
|
+
return ALLOWED_DEPLOY_MODES.includes(mode)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function resolveTargetPrebuiltCwd(projectRoot, targetConfig, runCwd) {
|
|
129
|
+
if (!targetConfig?.prebuiltCwd) return runCwd
|
|
130
|
+
return join(projectRoot, targetConfig.prebuiltCwd)
|
|
131
|
+
}
|
|
132
|
+
|
|
102
133
|
function maskIdentifier(value) {
|
|
103
134
|
const raw = String(value || '').trim()
|
|
104
135
|
if (raw.length <= 10) return raw || '-'
|
|
105
136
|
return `${raw.slice(0, 6)}...${raw.slice(-4)}`
|
|
106
137
|
}
|
|
107
138
|
|
|
108
|
-
function readLinkedProjectContext(
|
|
109
|
-
const path = join(
|
|
139
|
+
function readLinkedProjectContext(contextRoot) {
|
|
140
|
+
const path = join(contextRoot, VERCEL_PROJECT_LINK_PATH)
|
|
110
141
|
if (!existsSync(path)) {
|
|
111
142
|
return { exists: false, path, orgId: null, projectId: null, parseError: null }
|
|
112
143
|
}
|
|
@@ -132,8 +163,8 @@ function readLinkedProjectContext(projectRoot) {
|
|
|
132
163
|
}
|
|
133
164
|
}
|
|
134
165
|
|
|
135
|
-
function clearLinkedProjectContext(
|
|
136
|
-
const path = join(
|
|
166
|
+
function clearLinkedProjectContext(contextRoot) {
|
|
167
|
+
const path = join(contextRoot, VERCEL_PROJECT_LINK_PATH)
|
|
137
168
|
rmSync(path, { force: true })
|
|
138
169
|
}
|
|
139
170
|
|
|
@@ -191,7 +222,7 @@ export async function deployPrebuiltWithFallback(options) {
|
|
|
191
222
|
run = runVercel,
|
|
192
223
|
cleanupArchiveParts = () => {
|
|
193
224
|
try {
|
|
194
|
-
execSync('rm -f .vercel/source.tgz.part*', { stdio: 'ignore' })
|
|
225
|
+
execSync('rm -f .vercel/source.tgz.part*', { stdio: 'ignore', cwd: cwd || process.cwd() })
|
|
195
226
|
} catch {
|
|
196
227
|
// ignore
|
|
197
228
|
}
|
|
@@ -298,7 +329,32 @@ export async function deployToVercel(target, options = {}) {
|
|
|
298
329
|
const projectId = process.env[targetConfig.projectIdEnvVar]
|
|
299
330
|
const configFile = targetConfig.configFile
|
|
300
331
|
const configPath = join(projectRoot, configFile)
|
|
301
|
-
const
|
|
332
|
+
const runCwd = resolveTargetRunCwd(projectRoot, targetConfig)
|
|
333
|
+
const deployMode = resolveTargetDeployMode(targetConfig)
|
|
334
|
+
const prebuiltCwd = resolveTargetPrebuiltCwd(projectRoot, targetConfig, runCwd)
|
|
335
|
+
|
|
336
|
+
if (!existsSync(runCwd)) {
|
|
337
|
+
logger.error(`部署目录不存在: target=${t} deployCwd=${targetConfig.deployCwd || '.'} resolved=${runCwd}`)
|
|
338
|
+
process.exitCode = 1
|
|
339
|
+
return
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (!isSupportedDeployMode(deployMode)) {
|
|
343
|
+
logger.error(`不支持的部署模式: target=${t} mode=${deployMode}`)
|
|
344
|
+
logger.info(`可用部署模式: ${ALLOWED_DEPLOY_MODES.join(', ')}`)
|
|
345
|
+
process.exitCode = 1
|
|
346
|
+
return
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (!existsSync(prebuiltCwd)) {
|
|
350
|
+
logger.error(
|
|
351
|
+
`预构建部署目录不存在: target=${t} prebuiltCwd=${targetConfig.prebuiltCwd || targetConfig.deployCwd || '.'} resolved=${prebuiltCwd}`,
|
|
352
|
+
)
|
|
353
|
+
process.exitCode = 1
|
|
354
|
+
return
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const linkedContext = readLinkedProjectContext(prebuiltCwd)
|
|
302
358
|
|
|
303
359
|
const linkedMismatch =
|
|
304
360
|
linkedContext.exists &&
|
|
@@ -332,7 +388,7 @@ export async function deployToVercel(target, options = {}) {
|
|
|
332
388
|
}
|
|
333
389
|
|
|
334
390
|
logger.info(
|
|
335
|
-
`[deploy-context] env=${environment} target=${t} strict=${strictContext ? 1 : 0} org=${maskIdentifier(orgId)} project=${maskIdentifier(projectId)} linked=${linkedContext.exists ? 'yes' : 'no'} token=env`,
|
|
391
|
+
`[deploy-context] env=${environment} target=${t} mode=${deployMode} runCwd=${runCwd} prebuiltCwd=${prebuiltCwd} strict=${strictContext ? 1 : 0} org=${maskIdentifier(orgId)} project=${maskIdentifier(projectId)} linked=${linkedContext.exists ? 'yes' : 'no'} token=env`,
|
|
336
392
|
)
|
|
337
393
|
|
|
338
394
|
const envVars = {
|
|
@@ -363,7 +419,7 @@ export async function deployToVercel(target, options = {}) {
|
|
|
363
419
|
|
|
364
420
|
try {
|
|
365
421
|
if (strictContext && process.env.DX_VERCEL_KEEP_LINK !== '1') {
|
|
366
|
-
clearLinkedProjectContext(
|
|
422
|
+
clearLinkedProjectContext(prebuiltCwd)
|
|
367
423
|
}
|
|
368
424
|
|
|
369
425
|
// 第一步:本地构建
|
|
@@ -371,7 +427,6 @@ export async function deployToVercel(target, options = {}) {
|
|
|
371
427
|
const buildArgs = appendTargetArgs(
|
|
372
428
|
['build', '--local-config', configPath, '--yes'],
|
|
373
429
|
{
|
|
374
|
-
cwd: projectRoot,
|
|
375
430
|
orgId,
|
|
376
431
|
},
|
|
377
432
|
)
|
|
@@ -381,15 +436,14 @@ export async function deployToVercel(target, options = {}) {
|
|
|
381
436
|
buildArgs.push('--prod')
|
|
382
437
|
}
|
|
383
438
|
|
|
384
|
-
await run(buildArgs, { env: envVars, cwd:
|
|
439
|
+
await run(buildArgs, { env: envVars, cwd: runCwd })
|
|
385
440
|
logger.success(`${t} 本地构建成功`)
|
|
386
441
|
|
|
387
|
-
// 第二步:上传预构建产物
|
|
388
442
|
logger.step(`部署 ${t} 到 Vercel (${environment})`)
|
|
443
|
+
|
|
389
444
|
const baseDeployArgs = appendTargetArgs(
|
|
390
445
|
['deploy', '--prebuilt', '--local-config', configPath, '--yes'],
|
|
391
446
|
{
|
|
392
|
-
cwd: projectRoot,
|
|
393
447
|
orgId,
|
|
394
448
|
},
|
|
395
449
|
)
|
|
@@ -402,7 +456,7 @@ export async function deployToVercel(target, options = {}) {
|
|
|
402
456
|
const deployResult = await deployPrebuiltWithFallback({
|
|
403
457
|
baseArgs: baseDeployArgs,
|
|
404
458
|
env: envVars,
|
|
405
|
-
cwd:
|
|
459
|
+
cwd: prebuiltCwd,
|
|
406
460
|
run,
|
|
407
461
|
})
|
|
408
462
|
|
|
@@ -423,6 +477,11 @@ export async function deployToVercel(target, options = {}) {
|
|
|
423
477
|
logger.success(`${t} 部署成功`)
|
|
424
478
|
}
|
|
425
479
|
} catch (error) {
|
|
480
|
+
if (deployMode === 'prebuilt' && isNextPrebuiltMissingPathError(error)) {
|
|
481
|
+
logger.error(
|
|
482
|
+
'高优先级提示:检测到 Next.js 预构建产物缺失(next-server.js/node_modules/.pnpm)。请检查 front prebuiltCwd 与构建产物路径是否一致。',
|
|
483
|
+
)
|
|
484
|
+
}
|
|
426
485
|
const message = error?.message || String(error)
|
|
427
486
|
logger.error(`${t} 构建或部署失败: ${message}`)
|
|
428
487
|
process.exitCode = 1
|