@take-out/scripts 0.0.93 → 0.0.94
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/package.json +4 -2
- package/src/build-initial.ts +76 -81
- package/src/clean.ts +21 -21
- package/src/cmd.ts +82 -0
- package/src/dev-tunnel.ts +138 -159
- package/src/ensure-port.ts +62 -70
- package/src/ensure-tunnel.ts +13 -9
- package/src/env-pull.ts +49 -47
- package/src/env-update.ts +143 -175
- package/src/exec-with-env.ts +14 -11
- package/src/helpers/args.ts +4 -4
- package/src/helpers/get-test-env.ts +5 -3
- package/src/node-version-check.ts +9 -5
- package/src/release.ts +427 -404
- package/src/sst-get-environment.ts +5 -1
- package/src/typecheck.ts +19 -16
- package/src/up.ts +355 -374
- package/src/update-changelog.ts +39 -43
- package/src/update-local-env.ts +139 -158
- package/src/wait-for-dev.ts +21 -20
package/src/ensure-port.ts
CHANGED
|
@@ -1,87 +1,79 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
* @description Ensure a port is available, exit with error if in use
|
|
5
|
-
* @args --auto-kill <prefix>
|
|
6
|
-
*/
|
|
3
|
+
import { cmd } from './cmd'
|
|
7
4
|
|
|
8
|
-
|
|
5
|
+
await cmd`ensure a port is available, exit with error if in use`
|
|
6
|
+
.args('--auto-kill string')
|
|
7
|
+
.run(async ({ args }) => {
|
|
8
|
+
const { execSync } = await import('node:child_process')
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
const port = args.rest[0]
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (!port) {
|
|
17
|
-
console.error('usage: bun tko ensure-port <port> [--auto-kill <prefix>]')
|
|
18
|
-
process.exit(1)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const portNum = Number.parseInt(port, 10)
|
|
12
|
+
if (!port) {
|
|
13
|
+
console.error('usage: bun tko ensure-port <port> [--auto-kill <prefix>]')
|
|
14
|
+
process.exit(1)
|
|
15
|
+
}
|
|
22
16
|
|
|
23
|
-
|
|
24
|
-
console.error(`invalid port: ${port}`)
|
|
25
|
-
process.exit(1)
|
|
26
|
-
}
|
|
17
|
+
const portNum = Number.parseInt(port, 10)
|
|
27
18
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const output = execSync(`lsof -i :${p} -sTCP:LISTEN -t`, {
|
|
33
|
-
encoding: 'utf-8',
|
|
34
|
-
stdio: ['pipe', 'pipe', 'ignore'],
|
|
35
|
-
}).trim()
|
|
19
|
+
if (Number.isNaN(portNum) || portNum < 1 || portNum > 65535) {
|
|
20
|
+
console.error(`invalid port: ${port}`)
|
|
21
|
+
process.exit(1)
|
|
22
|
+
}
|
|
36
23
|
|
|
37
|
-
|
|
24
|
+
function getListeningProcess(p: number): { pid?: number; command?: string } {
|
|
25
|
+
try {
|
|
26
|
+
// use -sTCP:LISTEN to only find processes LISTENING on the port (servers)
|
|
27
|
+
const output = execSync(`lsof -i :${p} -sTCP:LISTEN -t`, {
|
|
28
|
+
encoding: 'utf-8',
|
|
29
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
30
|
+
}).trim()
|
|
38
31
|
|
|
39
|
-
|
|
40
|
-
if (Number.isNaN(pid)) return {}
|
|
32
|
+
if (!output) return {}
|
|
41
33
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
encoding: 'utf-8',
|
|
45
|
-
stdio: ['pipe', 'pipe', 'ignore'],
|
|
46
|
-
}).trim()
|
|
34
|
+
const pid = Number.parseInt(output.split('\n')[0] || '', 10)
|
|
35
|
+
if (Number.isNaN(pid)) return {}
|
|
47
36
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
37
|
+
const ps = execSync(`ps -p ${pid} -o comm=`, {
|
|
38
|
+
encoding: 'utf-8',
|
|
39
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
40
|
+
}).trim()
|
|
53
41
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return false
|
|
60
|
-
}
|
|
61
|
-
}
|
|
42
|
+
return { pid, command: ps }
|
|
43
|
+
} catch {
|
|
44
|
+
return {}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
62
47
|
|
|
63
|
-
|
|
48
|
+
function killProcess(pid: number): boolean {
|
|
49
|
+
try {
|
|
50
|
+
execSync(`kill ${pid}`, { stdio: 'ignore' })
|
|
51
|
+
return true
|
|
52
|
+
} catch {
|
|
53
|
+
return false
|
|
54
|
+
}
|
|
55
|
+
}
|
|
64
56
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
57
|
+
const { pid, command } = getListeningProcess(portNum)
|
|
58
|
+
|
|
59
|
+
if (pid) {
|
|
60
|
+
if (args.autoKill && command?.startsWith(args.autoKill)) {
|
|
61
|
+
console.info(`killing ${command} (pid ${pid}) on port ${portNum}`)
|
|
62
|
+
if (killProcess(pid)) {
|
|
63
|
+
Bun.sleepSync(100)
|
|
64
|
+
const check = getListeningProcess(portNum)
|
|
65
|
+
if (!check.pid) {
|
|
66
|
+
process.exit(0)
|
|
67
|
+
}
|
|
68
|
+
console.error(`failed to free port ${portNum}`)
|
|
69
|
+
process.exit(1)
|
|
70
|
+
}
|
|
71
|
+
console.error(`failed to kill pid ${pid}`)
|
|
72
|
+
process.exit(1)
|
|
76
73
|
}
|
|
77
|
-
|
|
74
|
+
|
|
75
|
+
console.error(`port ${portNum} in use by ${command || 'unknown'} (pid ${pid})`)
|
|
76
|
+
console.error(`run: kill ${pid}`)
|
|
78
77
|
process.exit(1)
|
|
79
78
|
}
|
|
80
|
-
|
|
81
|
-
process.exit(1)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
console.error(`port ${portNum} in use by ${command || 'unknown'} (pid ${pid})`)
|
|
85
|
-
console.error(`run: kill ${pid}`)
|
|
86
|
-
process.exit(1)
|
|
87
|
-
}
|
|
79
|
+
})
|
package/src/ensure-tunnel.ts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
const netstat = spawnSync('netstat', ['-rn'], { encoding: 'utf-8' }).stdout || ''
|
|
6
|
-
const isTunnelActive = netstat.includes(`10.0.8/22`)
|
|
7
|
-
|
|
8
|
-
if (!isTunnelActive) {
|
|
9
|
-
console.error(`No tunnel active, run bun sst:tunnel:production first`)
|
|
10
|
-
process.exit(1)
|
|
11
|
-
}
|
|
3
|
+
import { cmd } from './cmd'
|
|
12
4
|
|
|
13
5
|
export function ensureEnv() {
|
|
14
6
|
// make it a module
|
|
15
7
|
}
|
|
8
|
+
|
|
9
|
+
await cmd`check if SST production tunnel is active`.run(async () => {
|
|
10
|
+
const { spawnSync } = await import('node:child_process')
|
|
11
|
+
|
|
12
|
+
const netstat = spawnSync('netstat', ['-rn'], { encoding: 'utf-8' }).stdout || ''
|
|
13
|
+
const isTunnelActive = netstat.includes(`10.0.8/22`)
|
|
14
|
+
|
|
15
|
+
if (!isTunnelActive) {
|
|
16
|
+
console.error(`No tunnel active, run bun sst:tunnel:production first`)
|
|
17
|
+
process.exit(1)
|
|
18
|
+
}
|
|
19
|
+
})
|
package/src/env-pull.ts
CHANGED
|
@@ -1,55 +1,57 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const packageJson = require(join(rootDir, 'package.json'))
|
|
19
|
-
const envVarsNeeded = packageJson.env ? Object.keys(packageJson.env) : []
|
|
20
|
-
if (!envVarsNeeded.length) {
|
|
21
|
-
console.error(
|
|
22
|
-
`❌ Error: No environment variables specified in package.json 'env' array.`
|
|
23
|
-
)
|
|
24
|
-
process.exit(1)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
const envVars = getEnvironment('WebApp')
|
|
29
|
-
|
|
30
|
-
let envFileContent = ''
|
|
31
|
-
let foundCount = 0
|
|
32
|
-
|
|
33
|
-
for (const varName of envVarsNeeded) {
|
|
34
|
-
if (envVars[varName] !== undefined) {
|
|
35
|
-
envFileContent += `${varName}=${envVars[varName]}\n`
|
|
36
|
-
foundCount++
|
|
37
|
-
} else {
|
|
38
|
-
console.warn(`⚠️ Warning: Didn't find env: ${varName}`)
|
|
39
|
-
}
|
|
3
|
+
import { cmd } from './cmd'
|
|
4
|
+
|
|
5
|
+
await cmd`pull environment variables from SST production`.run(async ({ path }) => {
|
|
6
|
+
const { existsSync, writeFileSync } = await import('node:fs')
|
|
7
|
+
const { getEnvironment } = await import('./sst-get-environment')
|
|
8
|
+
|
|
9
|
+
const rootDir = process.cwd()
|
|
10
|
+
|
|
11
|
+
const envFilePath = path.join(rootDir, '.env.production')
|
|
12
|
+
if (existsSync(envFilePath)) {
|
|
13
|
+
console.error(
|
|
14
|
+
'❌ Error: .env.production already exists. Please remove or rename it first.'
|
|
15
|
+
)
|
|
16
|
+
process.exit(1)
|
|
40
17
|
}
|
|
41
18
|
|
|
42
|
-
|
|
43
|
-
|
|
19
|
+
const packageJson = require(path.join(rootDir, 'package.json'))
|
|
20
|
+
const envVarsNeeded = packageJson.env ? Object.keys(packageJson.env) : []
|
|
21
|
+
if (!envVarsNeeded.length) {
|
|
22
|
+
console.error(
|
|
23
|
+
`❌ Error: No environment variables specified in package.json 'env' array.`
|
|
24
|
+
)
|
|
44
25
|
process.exit(1)
|
|
45
26
|
}
|
|
46
27
|
|
|
47
|
-
|
|
28
|
+
try {
|
|
29
|
+
const envVars = getEnvironment('WebApp')
|
|
30
|
+
|
|
31
|
+
let envFileContent = ''
|
|
32
|
+
let foundCount = 0
|
|
48
33
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
34
|
+
for (const varName of envVarsNeeded) {
|
|
35
|
+
if (envVars[varName] !== undefined) {
|
|
36
|
+
envFileContent += `${varName}=${envVars[varName]}\n`
|
|
37
|
+
foundCount++
|
|
38
|
+
} else {
|
|
39
|
+
console.warn(`⚠️ Warning: Didn't find env: ${varName}`)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (foundCount === 0) {
|
|
44
|
+
console.error(`❌ Error: None of the required environment variables were found.`)
|
|
45
|
+
process.exit(1)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
writeFileSync(envFilePath, envFileContent)
|
|
49
|
+
|
|
50
|
+
console.info(
|
|
51
|
+
`✅ Success! ${foundCount} environment variables written to .env.production`
|
|
52
|
+
)
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error('❌ Error fetching environment variables:', error)
|
|
55
|
+
process.exit(1)
|
|
56
|
+
}
|
|
57
|
+
})
|
package/src/env-update.ts
CHANGED
|
@@ -1,180 +1,148 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
3
|
+
import { cmd } from './cmd'
|
|
4
|
+
|
|
5
|
+
await cmd`sync environment variables from package.json to CI and server configs`.run(
|
|
6
|
+
async () => {
|
|
7
|
+
const { readFileSync, writeFileSync } = await import('node:fs')
|
|
8
|
+
|
|
9
|
+
const packageJson = JSON.parse(readFileSync('package.json', 'utf-8'))
|
|
10
|
+
const envVars = packageJson.env as Record<string, boolean | string>
|
|
11
|
+
|
|
12
|
+
if (!envVars || Array.isArray(envVars) || typeof envVars !== 'object') {
|
|
13
|
+
console.error('No environment variables found in package.json')
|
|
14
|
+
process.exit(1)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const markerStart = '🔒 start - this is generated by "bun env:update"'
|
|
18
|
+
const markerEnd = '🔒 end - this is generated by "bun env:update"'
|
|
19
|
+
|
|
20
|
+
const yamlStartMarker = `# ${markerStart}`
|
|
21
|
+
const yamlEndMarker = `# ${markerEnd}`
|
|
22
|
+
|
|
23
|
+
const jsStartMarker = `// ${markerStart}`
|
|
24
|
+
const jsEndMarker = `// ${markerEnd}`
|
|
25
|
+
|
|
26
|
+
function replaceYamlSection(
|
|
27
|
+
content: string,
|
|
28
|
+
lines: string,
|
|
29
|
+
options: { indent: string }
|
|
30
|
+
): string {
|
|
31
|
+
return content.replace(
|
|
32
|
+
new RegExp(`${yamlStartMarker}(.|\n)*?${yamlEndMarker}`, 'gm'),
|
|
33
|
+
`${yamlStartMarker}\n${lines}\n${options.indent}${yamlEndMarker}`
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function updateDeployYml() {
|
|
38
|
+
const deployYmlPath = '.github/workflows/ci.yml'
|
|
39
|
+
let deployYml = readFileSync(deployYmlPath, 'utf-8')
|
|
40
|
+
|
|
41
|
+
if (!deployYml.includes(yamlStartMarker) || !deployYml.includes(yamlEndMarker)) {
|
|
42
|
+
throw new Error(`Markers not found in ${deployYmlPath}`)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const indent = ` `
|
|
46
|
+
const envSection = Object.keys(envVars)
|
|
47
|
+
.map((key) => `${indent}${key}: \${{ secrets.${key} }}`)
|
|
48
|
+
.join('\n')
|
|
49
|
+
|
|
50
|
+
const newDeployYml = replaceYamlSection(deployYml, envSection, { indent })
|
|
51
|
+
|
|
52
|
+
writeFileSync(deployYmlPath, newDeployYml, 'utf-8')
|
|
53
|
+
console.info('✅ Updated Github workflow')
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function updateEnvServerTs() {
|
|
57
|
+
const candidates = ['src/constants/env-server.ts', 'src/server/env-server.ts']
|
|
58
|
+
let envServerPath = ''
|
|
59
|
+
let envServer = ''
|
|
60
|
+
|
|
61
|
+
for (const p of candidates) {
|
|
62
|
+
try {
|
|
63
|
+
envServer = readFileSync(p, 'utf-8')
|
|
64
|
+
envServerPath = p
|
|
65
|
+
break
|
|
66
|
+
} catch {}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!envServerPath) {
|
|
70
|
+
throw new Error(`env-server.ts not found at ${candidates.join(' or ')}`)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!envServer.includes(jsStartMarker) || !envServer.includes(jsEndMarker)) {
|
|
74
|
+
throw new Error(`Markers not found in ${envServerPath}`)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const envExports = Object.entries(envVars)
|
|
78
|
+
.map(
|
|
79
|
+
([key, value]) =>
|
|
80
|
+
`export const ${key} = ensureEnv('${key}'${typeof value === 'string' ? `, ${JSON.stringify(value)}` : ''})`
|
|
81
|
+
)
|
|
82
|
+
.join('\n')
|
|
83
|
+
|
|
84
|
+
const newEnvServer = envServer.replace(
|
|
85
|
+
new RegExp(`${jsStartMarker}(.|\n)*?${jsEndMarker}`, 'm'),
|
|
86
|
+
`${jsStartMarker}\n${envExports}\n${jsEndMarker}`
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
writeFileSync(envServerPath, newEnvServer, 'utf-8')
|
|
90
|
+
console.info('✅ Updated server env')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function updateDockerCompose() {
|
|
94
|
+
const dockerComposePath = 'src/uncloud/docker-compose.yml'
|
|
95
|
+
|
|
96
|
+
let dockerCompose = ''
|
|
97
|
+
try {
|
|
98
|
+
dockerCompose = readFileSync(dockerComposePath, 'utf-8')
|
|
99
|
+
} catch (_error) {
|
|
100
|
+
// file doesn't exist, skip
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (
|
|
105
|
+
!dockerCompose.includes(yamlStartMarker) ||
|
|
106
|
+
!dockerCompose.includes(yamlEndMarker)
|
|
107
|
+
) {
|
|
108
|
+
// no markers, skip
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// detect indent from the marker line
|
|
113
|
+
const markerMatch = dockerCompose.match(
|
|
114
|
+
new RegExp(`^(\\s*)${yamlStartMarker}`, 'm')
|
|
115
|
+
)
|
|
116
|
+
const indent = markerMatch?.[1] || ' '
|
|
117
|
+
|
|
118
|
+
// detect format: if markers are under an x- anchor block, use map syntax (KEY: val)
|
|
119
|
+
// otherwise use list syntax (- KEY=val)
|
|
120
|
+
const beforeMarker = dockerCompose.slice(
|
|
121
|
+
0,
|
|
122
|
+
dockerCompose.indexOf(yamlStartMarker)
|
|
123
|
+
)
|
|
124
|
+
const isMap = /x-[\w-]+:.*&[\w-]+/s.test(beforeMarker)
|
|
125
|
+
|
|
126
|
+
const envLines = Object.keys(envVars)
|
|
127
|
+
.map((key) =>
|
|
128
|
+
isMap ? `${indent}${key}: \${${key}:-}` : `${indent}- ${key}=\${${key}:-}`
|
|
129
|
+
)
|
|
130
|
+
.join('\n')
|
|
131
|
+
|
|
132
|
+
const newDockerCompose = replaceYamlSection(dockerCompose, envLines, { indent })
|
|
133
|
+
|
|
134
|
+
writeFileSync(dockerComposePath, newDockerCompose, 'utf-8')
|
|
135
|
+
console.info('✅ Updated docker-compose.yml')
|
|
136
|
+
}
|
|
63
137
|
|
|
64
|
-
function updateEnvServerTs() {
|
|
65
|
-
const candidates = ['src/constants/env-server.ts', 'src/server/env-server.ts']
|
|
66
|
-
let envServerPath = ''
|
|
67
|
-
let envServer = ''
|
|
68
|
-
|
|
69
|
-
for (const path of candidates) {
|
|
70
138
|
try {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (!envServer.includes(jsStartMarker) || !envServer.includes(jsEndMarker)) {
|
|
82
|
-
throw new Error(`Markers not found in ${envServerPath}`)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const envExports = Object.entries(envVars)
|
|
86
|
-
.map(
|
|
87
|
-
([key, value]) =>
|
|
88
|
-
`export const ${key} = ensureEnv('${key}'${typeof value === 'string' ? `, ${JSON.stringify(value)}` : ''})`
|
|
89
|
-
)
|
|
90
|
-
.join('\n')
|
|
91
|
-
|
|
92
|
-
const newEnvServer = envServer.replace(
|
|
93
|
-
new RegExp(`${jsStartMarker}(.|\n)*?${jsEndMarker}`, 'm'),
|
|
94
|
-
`${jsStartMarker}\n${envExports}\n${jsEndMarker}`
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
writeFileSync(envServerPath, newEnvServer, 'utf-8')
|
|
98
|
-
console.info('✅ Updated server env')
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// function updateDockerfile() {
|
|
102
|
-
// const dockerfilePath = 'Dockerfile'
|
|
103
|
-
|
|
104
|
-
// let dockerfile = ''
|
|
105
|
-
// try {
|
|
106
|
-
// dockerfile = readFileSync(dockerfilePath, 'utf-8')
|
|
107
|
-
// } catch (_error) {
|
|
108
|
-
// throw new Error(`File ${dockerfilePath} not found`)
|
|
109
|
-
// }
|
|
110
|
-
|
|
111
|
-
// if (!dockerfile.includes(yamlStartMarker) || !dockerfile.includes(yamlEndMarker)) {
|
|
112
|
-
// throw new Error(`Markers not found in ${dockerfilePath}`)
|
|
113
|
-
// }
|
|
114
|
-
|
|
115
|
-
// const dockerArgs = Object.keys(envVars)
|
|
116
|
-
// .map((env) => `ARG ${env}`)
|
|
117
|
-
// .join('\n')
|
|
118
|
-
|
|
119
|
-
// const newDockerfile = dockerfile.replace(
|
|
120
|
-
// new RegExp(`${yamlStartMarker}(.|\n)*?${yamlEndMarker}`, 'm'),
|
|
121
|
-
// `${yamlStartMarker}\n${dockerArgs}\n${yamlEndMarker}`
|
|
122
|
-
// )
|
|
123
|
-
|
|
124
|
-
// writeFileSync(dockerfilePath, newDockerfile, 'utf-8')
|
|
125
|
-
// console.info('✅ Updated Dockerfile')
|
|
126
|
-
// }
|
|
127
|
-
|
|
128
|
-
function updateDockerCompose() {
|
|
129
|
-
const dockerComposePath = 'src/uncloud/docker-compose.yml'
|
|
130
|
-
|
|
131
|
-
let dockerCompose = ''
|
|
132
|
-
try {
|
|
133
|
-
dockerCompose = readFileSync(dockerComposePath, 'utf-8')
|
|
134
|
-
} catch (_error) {
|
|
135
|
-
// file doesn't exist, skip
|
|
136
|
-
return
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (
|
|
140
|
-
!dockerCompose.includes(yamlStartMarker) ||
|
|
141
|
-
!dockerCompose.includes(yamlEndMarker)
|
|
142
|
-
) {
|
|
143
|
-
// no markers, skip
|
|
144
|
-
return
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// detect indent from the marker line
|
|
148
|
-
const markerMatch = dockerCompose.match(new RegExp(`^(\\s*)${yamlStartMarker}`, 'm'))
|
|
149
|
-
const indent = markerMatch?.[1] || ' '
|
|
150
|
-
|
|
151
|
-
// detect format: if markers are under an x- anchor block, use map syntax (KEY: val)
|
|
152
|
-
// otherwise use list syntax (- KEY=val)
|
|
153
|
-
const beforeMarker = dockerCompose.slice(0, dockerCompose.indexOf(yamlStartMarker))
|
|
154
|
-
const isMap = /x-[\w-]+:.*&[\w-]+/s.test(beforeMarker)
|
|
155
|
-
|
|
156
|
-
const envLines = Object.keys(envVars)
|
|
157
|
-
.map((key) =>
|
|
158
|
-
isMap ? `${indent}${key}: \${${key}:-}` : `${indent}- ${key}=\${${key}:-}`
|
|
159
|
-
)
|
|
160
|
-
.join('\n')
|
|
161
|
-
|
|
162
|
-
const newDockerCompose = replaceYamlSection(dockerCompose, envLines, { indent })
|
|
163
|
-
|
|
164
|
-
writeFileSync(dockerComposePath, newDockerCompose, 'utf-8')
|
|
165
|
-
console.info('✅ Updated docker-compose.yml')
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
async function updateAll() {
|
|
169
|
-
try {
|
|
170
|
-
updateDeployYml()
|
|
171
|
-
updateEnvServerTs()
|
|
172
|
-
updateDockerCompose()
|
|
173
|
-
console.info('✅ All files updated successfully')
|
|
174
|
-
} catch (error: any) {
|
|
175
|
-
console.error('❌ Update failed:', error.message)
|
|
176
|
-
process.exit(1)
|
|
139
|
+
updateDeployYml()
|
|
140
|
+
updateEnvServerTs()
|
|
141
|
+
updateDockerCompose()
|
|
142
|
+
console.info('✅ All files updated successfully')
|
|
143
|
+
} catch (error: any) {
|
|
144
|
+
console.error('❌ Update failed:', error.message)
|
|
145
|
+
process.exit(1)
|
|
146
|
+
}
|
|
177
147
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
await updateAll()
|
|
148
|
+
)
|
package/src/exec-with-env.ts
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
import { spawnSync } from 'node:child_process'
|
|
4
|
-
|
|
5
3
|
import { ensureExists } from '@take-out/helpers'
|
|
6
|
-
|
|
4
|
+
|
|
5
|
+
import { cmd } from './cmd'
|
|
7
6
|
|
|
8
7
|
export async function execWithEnvironment(
|
|
9
8
|
environment: 'development' | 'production',
|
|
10
9
|
command: string
|
|
11
10
|
) {
|
|
11
|
+
const { spawnSync } = await import('node:child_process')
|
|
12
|
+
const { loadEnv } = await import('./helpers/env-load')
|
|
13
|
+
|
|
12
14
|
const { USE_LOCAL_SERVER } = process.env
|
|
13
15
|
|
|
14
16
|
let envFileEnv: Record<string, string>
|
|
15
17
|
|
|
16
18
|
if (process.env.REMOTE) {
|
|
17
|
-
await import('
|
|
19
|
+
await import('./ensure-tunnel')
|
|
18
20
|
const { getEnvironment } = await import('./sst-get-environment')
|
|
19
21
|
envFileEnv = getEnvironment(process.env.REMOTE)
|
|
20
22
|
ensureExists(envFileEnv)
|
|
@@ -36,9 +38,6 @@ export async function execWithEnvironment(
|
|
|
36
38
|
ONE_SERVER_URL: devEnv?.ONE_SERVER_URL,
|
|
37
39
|
// vite reads from .env.production for us unless defined into process.env
|
|
38
40
|
VITE_PUBLIC_ZERO_SERVER: 'https://start.chat',
|
|
39
|
-
// actually we need to use prod better auth but allow localhost trusted origin, may need other env though
|
|
40
|
-
// BETTER_AUTH_SECRET: devEnv?.BETTER_AUTH_SECRET,
|
|
41
|
-
// BETTER_AUTH_URL: devEnv?.BETTER_AUTH_URL,
|
|
42
41
|
}),
|
|
43
42
|
} as any as Record<string, string>
|
|
44
43
|
|
|
@@ -50,9 +49,13 @@ export async function execWithEnvironment(
|
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
if (import.meta.main) {
|
|
53
|
-
|
|
54
|
-
(
|
|
55
|
-
|
|
52
|
+
await cmd`execute command with environment variables loaded from local or remote`.run(
|
|
53
|
+
async () => {
|
|
54
|
+
const result = await execWithEnvironment(
|
|
55
|
+
(process.env.NODE_ENV as 'development' | 'production') || 'development',
|
|
56
|
+
process.argv.slice(3).join(' ')
|
|
57
|
+
)
|
|
58
|
+
process.exit(result.status ?? 1)
|
|
59
|
+
}
|
|
56
60
|
)
|
|
57
|
-
process.exit(result.status ?? 1)
|
|
58
61
|
}
|