@ranger1/dx 0.1.52 → 0.1.54
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/commands/deploy.js +5 -1
- package/lib/vercel-deploy.js +269 -80
- package/package.json +1 -1
|
@@ -101,5 +101,9 @@ export async function handleDeploy(cli, args) {
|
|
|
101
101
|
? parseTelegramWebhookFlags(cli.args)
|
|
102
102
|
: null
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
const strictContext = process.env.DX_VERCEL_STRICT_CONTEXT != null
|
|
105
|
+
? !['0', 'false', 'no'].includes(String(process.env.DX_VERCEL_STRICT_CONTEXT).toLowerCase())
|
|
106
|
+
: true
|
|
107
|
+
|
|
108
|
+
await deployToVercel(normalizedTarget, { environment, telegramWebhook, strictContext })
|
|
105
109
|
}
|
package/lib/vercel-deploy.js
CHANGED
|
@@ -1,9 +1,41 @@
|
|
|
1
1
|
import { execSync, spawn } from 'node:child_process'
|
|
2
|
+
import { existsSync, readFileSync, rmSync } from 'node:fs'
|
|
2
3
|
import { join } from 'node:path'
|
|
3
4
|
import { envManager } from './env.js'
|
|
4
5
|
import { logger } from './logger.js'
|
|
5
6
|
|
|
6
7
|
const ALLOWED_ENVIRONMENTS = ['development', 'staging', 'production']
|
|
8
|
+
const VALID_TARGETS = ['front', 'admin', 'telegram-bot']
|
|
9
|
+
|
|
10
|
+
const TARGET_CONFIGS = {
|
|
11
|
+
front: {
|
|
12
|
+
configFile: 'vercel.front.json',
|
|
13
|
+
projectIdEnvVar: 'VERCEL_PROJECT_ID_FRONT',
|
|
14
|
+
},
|
|
15
|
+
admin: {
|
|
16
|
+
configFile: 'vercel.admin.json',
|
|
17
|
+
projectIdEnvVar: 'VERCEL_PROJECT_ID_ADMIN',
|
|
18
|
+
},
|
|
19
|
+
'telegram-bot': {
|
|
20
|
+
configFile: 'vercel.telegram-bot.json',
|
|
21
|
+
projectIdEnvVar: 'VERCEL_PROJECT_ID_TELEGRAM_BOT',
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const EXPLICIT_ENV_VARS = ['APP_ENV', 'NODE_ENV']
|
|
26
|
+
const PUBLIC_ENV_PREFIXES = ['NEXT_PUBLIC_', 'VITE_']
|
|
27
|
+
|
|
28
|
+
const APP_ENV_MAP = {
|
|
29
|
+
development: 'dev',
|
|
30
|
+
staging: 'staging',
|
|
31
|
+
production: 'prod',
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const VERCEL_PROJECT_LINK_PATH = '.vercel/project.json'
|
|
35
|
+
|
|
36
|
+
function getTargetConfig(target) {
|
|
37
|
+
return TARGET_CONFIGS[target]
|
|
38
|
+
}
|
|
7
39
|
|
|
8
40
|
function collectErrorText(err) {
|
|
9
41
|
const parts = []
|
|
@@ -22,6 +54,127 @@ function isMissingFilesError(err) {
|
|
|
22
54
|
)
|
|
23
55
|
}
|
|
24
56
|
|
|
57
|
+
function listMissingVarKeys(targetConfigs, token, orgId) {
|
|
58
|
+
const missing = []
|
|
59
|
+
|
|
60
|
+
if (!token || envManager.isPlaceholderEnvValue(token)) {
|
|
61
|
+
missing.push('VERCEL_TOKEN')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!orgId || envManager.isPlaceholderEnvValue(orgId)) {
|
|
65
|
+
missing.push('VERCEL_ORG_ID')
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
for (const config of targetConfigs) {
|
|
69
|
+
const projectId = process.env[config.projectIdEnvVar]
|
|
70
|
+
if (!projectId || envManager.isPlaceholderEnvValue(projectId)) {
|
|
71
|
+
missing.push(config.projectIdEnvVar)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return [...new Set(missing)]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function listMissingConfigs(targetConfigs, projectRoot) {
|
|
79
|
+
const missing = []
|
|
80
|
+
|
|
81
|
+
for (const config of targetConfigs) {
|
|
82
|
+
const configPath = join(projectRoot, config.configFile)
|
|
83
|
+
if (!existsSync(configPath)) {
|
|
84
|
+
missing.push(config.configFile)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return missing
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function appendTargetArgs(baseArgs, { cwd, orgId, projectId, explicitEnvArgs = [] }) {
|
|
92
|
+
const args = [...baseArgs]
|
|
93
|
+
|
|
94
|
+
if (explicitEnvArgs.length > 0) {
|
|
95
|
+
args.push(...explicitEnvArgs)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (cwd) {
|
|
99
|
+
args.push('--cwd', cwd)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (orgId) {
|
|
103
|
+
args.push('--scope', orgId)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (projectId) {
|
|
107
|
+
args.push('--project', projectId)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return args
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function collectExplicitVercelEnvEntries(sourceEnv = {}) {
|
|
114
|
+
const includeKeys = new Set(EXPLICIT_ENV_VARS)
|
|
115
|
+
|
|
116
|
+
Object.keys(sourceEnv).forEach(name => {
|
|
117
|
+
if (PUBLIC_ENV_PREFIXES.some(prefix => name.startsWith(prefix))) {
|
|
118
|
+
includeKeys.add(name)
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
return [...includeKeys]
|
|
123
|
+
.filter(name => {
|
|
124
|
+
const value = sourceEnv[name]
|
|
125
|
+
return !(
|
|
126
|
+
value === undefined ||
|
|
127
|
+
value === null ||
|
|
128
|
+
envManager.isPlaceholderEnvValue(value)
|
|
129
|
+
)
|
|
130
|
+
})
|
|
131
|
+
.sort()
|
|
132
|
+
.map(name => `${name}=${String(sourceEnv[name])}`)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function withEnvFlag(entries, flag) {
|
|
136
|
+
if (!Array.isArray(entries) || entries.length === 0) return []
|
|
137
|
+
return entries.flatMap(entry => [flag, entry])
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function maskIdentifier(value) {
|
|
141
|
+
const raw = String(value || '').trim()
|
|
142
|
+
if (raw.length <= 10) return raw || '-'
|
|
143
|
+
return `${raw.slice(0, 6)}...${raw.slice(-4)}`
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function readLinkedProjectContext(projectRoot) {
|
|
147
|
+
const path = join(projectRoot, VERCEL_PROJECT_LINK_PATH)
|
|
148
|
+
if (!existsSync(path)) {
|
|
149
|
+
return { exists: false, path, orgId: null, projectId: null, parseError: null }
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
const content = readFileSync(path, 'utf8')
|
|
154
|
+
const parsed = JSON.parse(content)
|
|
155
|
+
return {
|
|
156
|
+
exists: true,
|
|
157
|
+
path,
|
|
158
|
+
orgId: parsed?.orgId || null,
|
|
159
|
+
projectId: parsed?.projectId || null,
|
|
160
|
+
parseError: null,
|
|
161
|
+
}
|
|
162
|
+
} catch (error) {
|
|
163
|
+
return {
|
|
164
|
+
exists: true,
|
|
165
|
+
path,
|
|
166
|
+
orgId: null,
|
|
167
|
+
projectId: null,
|
|
168
|
+
parseError: error,
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function clearLinkedProjectContext(projectRoot) {
|
|
174
|
+
const path = join(projectRoot, VERCEL_PROJECT_LINK_PATH)
|
|
175
|
+
rmSync(path, { force: true })
|
|
176
|
+
}
|
|
177
|
+
|
|
25
178
|
async function runVercel(args, options = {}) {
|
|
26
179
|
const { env, cwd } = options
|
|
27
180
|
const MAX_CAPTURE = 20000
|
|
@@ -101,7 +254,12 @@ export async function deployPrebuiltWithFallback(options) {
|
|
|
101
254
|
}
|
|
102
255
|
|
|
103
256
|
export async function deployToVercel(target, options = {}) {
|
|
104
|
-
const {
|
|
257
|
+
const {
|
|
258
|
+
environment = 'staging',
|
|
259
|
+
telegramWebhook = null,
|
|
260
|
+
strictContext = true,
|
|
261
|
+
run = runVercel,
|
|
262
|
+
} = options
|
|
105
263
|
|
|
106
264
|
// 校验环境参数
|
|
107
265
|
if (!ALLOWED_ENVIRONMENTS.includes(environment)) {
|
|
@@ -111,18 +269,13 @@ export async function deployToVercel(target, options = {}) {
|
|
|
111
269
|
return
|
|
112
270
|
}
|
|
113
271
|
|
|
114
|
-
const token = process.env.VERCEL_TOKEN
|
|
115
|
-
const orgId = process.env.VERCEL_ORG_ID
|
|
116
|
-
const projectIdFront = process.env.VERCEL_PROJECT_ID_FRONT
|
|
117
|
-
const projectIdAdmin = process.env.VERCEL_PROJECT_ID_ADMIN
|
|
118
|
-
const projectIdTelegramBot = process.env.VERCEL_PROJECT_ID_TELEGRAM_BOT
|
|
119
|
-
|
|
120
272
|
const normalizedTarget = String(target || '').toLowerCase()
|
|
121
273
|
const targets = normalizedTarget === 'all' ? ['front', 'admin'] : [normalizedTarget]
|
|
274
|
+
const projectRoot = process.cwd()
|
|
122
275
|
|
|
123
276
|
// 校验目标有效性
|
|
124
277
|
for (const t of targets) {
|
|
125
|
-
if (!
|
|
278
|
+
if (!VALID_TARGETS.includes(t)) {
|
|
126
279
|
logger.error(`不支持的部署目标: ${t}`)
|
|
127
280
|
logger.info('可用目标: front, admin, telegram-bot, all')
|
|
128
281
|
process.exitCode = 1
|
|
@@ -130,47 +283,43 @@ export async function deployToVercel(target, options = {}) {
|
|
|
130
283
|
}
|
|
131
284
|
}
|
|
132
285
|
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
if (!token || envManager.isPlaceholderEnvValue(token)) {
|
|
137
|
-
missingVars.push('VERCEL_TOKEN')
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (!orgId || envManager.isPlaceholderEnvValue(orgId)) {
|
|
141
|
-
missingVars.push('VERCEL_ORG_ID')
|
|
142
|
-
}
|
|
286
|
+
const targetConfigs = targets.map(getTargetConfig)
|
|
287
|
+
const token = process.env.VERCEL_TOKEN
|
|
288
|
+
const orgId = process.env.VERCEL_ORG_ID
|
|
143
289
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
missingVars.push('VERCEL_PROJECT_ID_FRONT')
|
|
147
|
-
}
|
|
290
|
+
const missingVars = listMissingVarKeys(targetConfigs, token, orgId)
|
|
291
|
+
const missingConfigFiles = listMissingConfigs(targetConfigs, projectRoot)
|
|
148
292
|
|
|
149
|
-
if (
|
|
150
|
-
missingVars.
|
|
151
|
-
|
|
293
|
+
if (missingVars.length > 0 || missingConfigFiles.length > 0) {
|
|
294
|
+
if (missingVars.length > 0) {
|
|
295
|
+
logger.error('缺少以下 Vercel 环境变量:')
|
|
296
|
+
missingVars.forEach(v => {
|
|
297
|
+
logger.error(` - ${v}`)
|
|
298
|
+
})
|
|
299
|
+
logger.info('')
|
|
300
|
+
logger.info('请在 .env.<env>.local 中配置这些变量,例如:')
|
|
301
|
+
logger.info(' VERCEL_TOKEN=<your-vercel-token>')
|
|
302
|
+
logger.info(' VERCEL_ORG_ID=team_xxx')
|
|
303
|
+
logger.info(' VERCEL_PROJECT_ID_FRONT=prj_xxx')
|
|
304
|
+
logger.info(' VERCEL_PROJECT_ID_ADMIN=prj_xxx')
|
|
305
|
+
logger.info(' VERCEL_PROJECT_ID_TELEGRAM_BOT=prj_xxx')
|
|
306
|
+
logger.info('')
|
|
307
|
+
logger.info('获取方式:')
|
|
308
|
+
logger.info(' 1. VERCEL_TOKEN: vercel login 后查看 ~/Library/Application Support/com.vercel.cli/auth.json')
|
|
309
|
+
logger.info(' 2. PROJECT_ID: vercel project ls --scope <org> 或通过 Vercel Dashboard 获取')
|
|
310
|
+
logger.info('')
|
|
311
|
+
logger.info('提示:部署命令会显式校验 --scope 与 --project,避免环境漂移。')
|
|
312
|
+
}
|
|
152
313
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
314
|
+
if (missingConfigFiles.length > 0) {
|
|
315
|
+
logger.error('缺少以下 Vercel 配置文件:')
|
|
316
|
+
missingConfigFiles.forEach(name => {
|
|
317
|
+
logger.error(` - ${name}`)
|
|
318
|
+
})
|
|
319
|
+
logger.info('')
|
|
320
|
+
logger.info('请确认同级目录存在对应的 vercel.*.json 文件。')
|
|
321
|
+
}
|
|
156
322
|
|
|
157
|
-
// 如果有缺失变量,统一报错并退出
|
|
158
|
-
if (missingVars.length > 0) {
|
|
159
|
-
logger.error('缺少以下 Vercel 环境变量:')
|
|
160
|
-
missingVars.forEach(v => {
|
|
161
|
-
logger.error(` - ${v}`)
|
|
162
|
-
})
|
|
163
|
-
logger.info('')
|
|
164
|
-
logger.info('请在 .env.<env>.local 中配置这些变量,例如:')
|
|
165
|
-
logger.info(' VERCEL_TOKEN=<your-vercel-token>')
|
|
166
|
-
logger.info(' VERCEL_ORG_ID=team_xxx')
|
|
167
|
-
logger.info(' VERCEL_PROJECT_ID_FRONT=prj_xxx')
|
|
168
|
-
logger.info(' VERCEL_PROJECT_ID_ADMIN=prj_xxx')
|
|
169
|
-
logger.info(' VERCEL_PROJECT_ID_TELEGRAM_BOT=prj_xxx')
|
|
170
|
-
logger.info('')
|
|
171
|
-
logger.info('获取方式:')
|
|
172
|
-
logger.info(' 1. VERCEL_TOKEN: vercel login 后查看 ~/Library/Application Support/com.vercel.cli/auth.json')
|
|
173
|
-
logger.info(' 2. PROJECT_ID: vercel project ls --scope <org> 或通过 Vercel Dashboard 获取')
|
|
174
323
|
process.exitCode = 1
|
|
175
324
|
return
|
|
176
325
|
}
|
|
@@ -180,40 +329,67 @@ export async function deployToVercel(target, options = {}) {
|
|
|
180
329
|
// - 这样 dx deploy 能兼容不同 monorepo 布局(不强依赖 apps/sdk 等目录)。
|
|
181
330
|
|
|
182
331
|
// 映射环境标识:development -> dev, staging -> staging, production -> prod
|
|
183
|
-
const
|
|
184
|
-
development: 'dev',
|
|
185
|
-
staging: 'staging',
|
|
186
|
-
production: 'prod',
|
|
187
|
-
}
|
|
188
|
-
const buildEnv = envMap[environment]
|
|
332
|
+
const buildEnv = APP_ENV_MAP[environment]
|
|
189
333
|
|
|
190
334
|
for (const t of targets) {
|
|
191
|
-
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
335
|
+
const targetConfig = getTargetConfig(t)
|
|
336
|
+
const projectId = process.env[targetConfig.projectIdEnvVar]
|
|
337
|
+
const configFile = targetConfig.configFile
|
|
338
|
+
const configPath = join(projectRoot, configFile)
|
|
339
|
+
const linkedContext = readLinkedProjectContext(projectRoot)
|
|
340
|
+
|
|
341
|
+
const linkedMismatch =
|
|
342
|
+
linkedContext.exists &&
|
|
343
|
+
linkedContext.parseError == null &&
|
|
344
|
+
((linkedContext.orgId && linkedContext.orgId !== orgId) ||
|
|
345
|
+
(linkedContext.projectId && linkedContext.projectId !== projectId))
|
|
346
|
+
|
|
347
|
+
if (linkedContext.exists && linkedContext.parseError) {
|
|
348
|
+
logger.warn(
|
|
349
|
+
`检测到 ${VERCEL_PROJECT_LINK_PATH} 但解析失败: ${linkedContext.parseError.message}`,
|
|
350
|
+
)
|
|
351
|
+
if (strictContext) {
|
|
352
|
+
logger.error('strictContext 已开启,已阻止继续部署以避免回退污染')
|
|
353
|
+
process.exitCode = 1
|
|
354
|
+
return
|
|
355
|
+
}
|
|
196
356
|
}
|
|
197
357
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
358
|
+
if (linkedMismatch) {
|
|
359
|
+
logger.error('检测到 .vercel 链接冲突')
|
|
360
|
+
logger.error(` 当前目标: org=${maskIdentifier(orgId)} project=${maskIdentifier(projectId)}`)
|
|
361
|
+
logger.error(
|
|
362
|
+
` 本地链接: org=${maskIdentifier(linkedContext.orgId)} project=${maskIdentifier(linkedContext.projectId)}`,
|
|
363
|
+
)
|
|
364
|
+
if (strictContext) {
|
|
365
|
+
logger.error('strictContext 已开启,已阻止部署(请清理 .vercel 或修正环境变量)')
|
|
366
|
+
process.exitCode = 1
|
|
367
|
+
return
|
|
368
|
+
}
|
|
369
|
+
logger.warn('strictContext 已关闭,继续执行(可能存在误部署风险)')
|
|
203
370
|
}
|
|
204
371
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
372
|
+
logger.info(
|
|
373
|
+
`[deploy-context] env=${environment} target=${t} strict=${strictContext ? 1 : 0} org=${maskIdentifier(orgId)} project=${maskIdentifier(projectId)} linked=${linkedContext.exists ? 'yes' : 'no'} token=env`,
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
const explicitEnvEntries = collectExplicitVercelEnvEntries({
|
|
377
|
+
...process.env,
|
|
378
|
+
APP_ENV: buildEnv,
|
|
379
|
+
NODE_ENV: envManager.mapAppEnvToNodeEnv(environment),
|
|
380
|
+
VERCEL_ORG_ID: orgId,
|
|
381
|
+
VERCEL_PROJECT_ID: projectId,
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
const buildEnvArgs = withEnvFlag(explicitEnvEntries, '--build-env')
|
|
385
|
+
const deployEnvArgs = withEnvFlag(explicitEnvEntries, '--env')
|
|
208
386
|
|
|
209
387
|
const envVars = {
|
|
210
388
|
...process.env,
|
|
211
389
|
VERCEL_PROJECT_ID: projectId,
|
|
212
390
|
APP_ENV: buildEnv,
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (orgId) {
|
|
216
|
-
envVars.VERCEL_ORG_ID = orgId
|
|
391
|
+
NODE_ENV: envManager.mapAppEnvToNodeEnv(environment),
|
|
392
|
+
VERCEL_ORG_ID: orgId,
|
|
217
393
|
}
|
|
218
394
|
|
|
219
395
|
// 不通过 CLI args 传递 token,避免出现在错误信息/日志中
|
|
@@ -235,39 +411,52 @@ export async function deployToVercel(target, options = {}) {
|
|
|
235
411
|
}
|
|
236
412
|
|
|
237
413
|
try {
|
|
414
|
+
if (strictContext && process.env.DX_VERCEL_KEEP_LINK !== '1') {
|
|
415
|
+
clearLinkedProjectContext(projectRoot)
|
|
416
|
+
}
|
|
417
|
+
|
|
238
418
|
// 第一步:本地构建
|
|
239
419
|
logger.step(`本地构建 ${t} (${environment})`)
|
|
240
|
-
const buildArgs =
|
|
420
|
+
const buildArgs = appendTargetArgs(
|
|
421
|
+
['build', '--local-config', configPath, '--yes'],
|
|
422
|
+
{
|
|
423
|
+
cwd: projectRoot,
|
|
424
|
+
orgId,
|
|
425
|
+
projectId,
|
|
426
|
+
explicitEnvArgs: buildEnvArgs,
|
|
427
|
+
},
|
|
428
|
+
)
|
|
241
429
|
|
|
242
430
|
// staging 和 production 环境需要 --prod 标志,确保构建产物与部署环境匹配
|
|
243
431
|
if (environment === 'staging' || environment === 'production') {
|
|
244
432
|
buildArgs.push('--prod')
|
|
245
433
|
}
|
|
246
434
|
|
|
247
|
-
|
|
248
|
-
buildArgs.push('--scope', orgId)
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
await runVercel(buildArgs, { env: envVars, cwd: process.cwd() })
|
|
435
|
+
await run(buildArgs, { env: envVars, cwd: projectRoot })
|
|
252
436
|
logger.success(`${t} 本地构建成功`)
|
|
253
437
|
|
|
254
438
|
// 第二步:上传预构建产物
|
|
255
439
|
logger.step(`部署 ${t} 到 Vercel (${environment})`)
|
|
256
|
-
const baseDeployArgs =
|
|
440
|
+
const baseDeployArgs = appendTargetArgs(
|
|
441
|
+
['deploy', '--prebuilt', '--local-config', configPath, '--yes'],
|
|
442
|
+
{
|
|
443
|
+
cwd: projectRoot,
|
|
444
|
+
orgId,
|
|
445
|
+
projectId,
|
|
446
|
+
explicitEnvArgs: deployEnvArgs,
|
|
447
|
+
},
|
|
448
|
+
)
|
|
257
449
|
|
|
258
450
|
// staging 和 production 环境都添加 --prod 标志以绑定固定域名
|
|
259
451
|
if (environment === 'staging' || environment === 'production') {
|
|
260
452
|
baseDeployArgs.push('--prod')
|
|
261
453
|
}
|
|
262
454
|
|
|
263
|
-
if (orgId) {
|
|
264
|
-
baseDeployArgs.push('--scope', orgId)
|
|
265
|
-
}
|
|
266
|
-
|
|
267
455
|
const deployResult = await deployPrebuiltWithFallback({
|
|
268
456
|
baseArgs: baseDeployArgs,
|
|
269
457
|
env: envVars,
|
|
270
|
-
cwd:
|
|
458
|
+
cwd: projectRoot,
|
|
459
|
+
run,
|
|
271
460
|
})
|
|
272
461
|
|
|
273
462
|
const deployOutput = [deployResult?.result?.stdout, deployResult?.result?.stderr]
|