Skip to content

Commit e4d28dd

Browse files
committed
WIP on scripts
1 parent f41e017 commit e4d28dd

File tree

4 files changed

+186
-8
lines changed

4 files changed

+186
-8
lines changed

docker/deploy-queue.sh

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ rsync -avP ./build/sspc-queue:$VERSION.tar $REMOTE:$REMOVE_STORE
1212
echo "2. Loading Docker image on server..."
1313
ssh $REMOTE "sudo docker load -i $IMAGE_STORE/sspc-queue:$VERSION.tar"
1414

15-
echo "3. Update docker-compose.yml manually if needed, then press Enter to continue..."
16-
read -r
17-
rsync -avP ./docker-compose.yml $REMOTE:$DEPLOY_PATH/docker-compose.yml
15+
# echo "3. Update docker-compose.yml manually if needed, then press Enter to continue..."
16+
# read -r
17+
# rsync -avP ./docker-compose.yml $REMOTE:$DEPLOY_PATH/docker-compose.yml
1818

1919
echo "4. Compose up queue:$VERSION on server..."
20-
ssh $REMOTE "cd $DEPLOY_PATH && sudo docker compose down queue && sudo docker compose up queue -d"
20+
# ssh $REMOTE "cd $DEPLOY_PATH && sudo docker compose down queue && sudo docker compose up queue -d"
2121

2222
echo "5. Logging..."
23-
sleep 5
24-
ssh $REMOTE "cd $DEPLOY_PATH && sudo docker compose logs -f queue"
23+
# sleep 5
24+
# ssh $REMOTE "cd $DEPLOY_PATH && sudo docker compose logs -f queue"

docker/deploy.mjs

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
#!/usr/bin/env zx
2+
3+
import { readFile } from "fs/promises"
4+
import "zx/globals"
5+
6+
const IMAGE_STORE = "/home/cxdev"
7+
const DEPLOY_PATH = "/opt/sspc"
8+
9+
const CPU_LIMIT = "14.0"
10+
const MEMORY_LIMIT = "8g"
11+
const QUEUE_CONCURRENT_DEFAULT = 8
12+
13+
const SERVERS = [
14+
{ remote: "cx_vision", concurrent: 8 },
15+
{ remote: "cx_vision2", concurrent: 14 },
16+
]
17+
18+
const { version: PPTR_VERSION } = JSON.parse(
19+
await readFile("./packages/pptr/package.json", "utf-8"),
20+
)
21+
const { version: QUEUE_VERSION } = JSON.parse(
22+
await readFile("./packages/queue/package.json", "utf-8"),
23+
)
24+
25+
console.log(chalk.bold.cyan("\n=== SSPC Deployment Tool ===\n"))
26+
console.log(chalk.gray(`pptr version: ${PPTR_VERSION}`))
27+
console.log(chalk.gray(`queue version: ${QUEUE_VERSION}\n`))
28+
29+
// 选择要部署的应用
30+
console.log(chalk.blue("Select application(s) to deploy:"))
31+
console.log(" 1. pptr")
32+
console.log(" 2. queue")
33+
console.log(" 3. Both (pptr + queue)")
34+
35+
const appChoice = await question("Select application (default: 3): ")
36+
const appIndex = parseInt(appChoice) || 3
37+
38+
let selectedApps = []
39+
if (appIndex === 1) {
40+
selectedApps = ["pptr"]
41+
} else if (appIndex === 2) {
42+
selectedApps = ["queue"]
43+
} else if (appIndex === 3) {
44+
selectedApps = ["pptr", "queue"]
45+
} else {
46+
console.log(chalk.red("Invalid choice, exiting..."))
47+
process.exit(1)
48+
}
49+
50+
// 选择要部署的服务器
51+
console.log(chalk.blue("\nAvailable servers:"))
52+
SERVERS.forEach((server, index) => {
53+
console.log(` ${index + 1}. ${server.name} (${server.remote})`)
54+
})
55+
console.log(` ${SERVERS.length + 1}. All servers`)
56+
57+
const serverChoice = await question("Select server(s) to deploy (default: 1): ")
58+
const selectedIndex = parseInt(serverChoice) || 1
59+
60+
let selectedServers = []
61+
if (selectedIndex === SERVERS.length + 1) {
62+
selectedServers = SERVERS
63+
} else if (selectedIndex > 0 && selectedIndex <= SERVERS.length) {
64+
selectedServers = [SERVERS[selectedIndex - 1]]
65+
} else {
66+
console.log(chalk.red("Invalid choice, exiting..."))
67+
process.exit(1)
68+
}
69+
70+
console.log(
71+
chalk.green(
72+
`\nDeploying ${selectedApps.join(" + ")} to: ${selectedServers.map((s) => s.name).join(", ")}\n`,
73+
),
74+
)
75+
76+
// 部署函数
77+
async function deployApp(server, app) {
78+
const isQueue = app === "queue"
79+
const version = isQueue ? QUEUE_VERSION : PPTR_VERSION
80+
const imageName = isQueue
81+
? `sspc-queue:${version}.tar`
82+
: `sspc-pptr:${version}-bundle.tar`
83+
84+
console.log(chalk.bold.blue(`\n--- Deploying ${app} to ${server.name} ---\n`))
85+
86+
console.log(chalk.blue(`1. Copying ${app}:${version} to ${server.name}...`))
87+
await $`rsync -avP ./build/${imageName} ${server.remote}:${server.imageStore}`
88+
89+
console.log(chalk.blue(`2. Loading Docker image on ${server.name}...`))
90+
await $`ssh ${server.remote} sudo docker load -i ${server.imageStore}/${imageName}`
91+
92+
console.log(
93+
chalk.blue(`3. Compose up ${app}:${version} on ${server.name}...`),
94+
)
95+
await $`ssh ${server.remote} "cd ${server.deployPath} && sudo docker compose down ${app} && sudo docker compose up ${app} -d"`
96+
97+
console.log(chalk.blue(`4. Checking status on ${server.name}...`))
98+
await sleep(2000)
99+
await $`ssh ${server.remote} "cd ${server.deployPath} && sudo docker compose ps ${app}"`
100+
101+
console.log(
102+
chalk.green(`\n✓ ${app} deployment to ${server.name} completed!\n`),
103+
)
104+
}
105+
106+
// 部署到选中的服务器
107+
for (const server of selectedServers) {
108+
console.log(chalk.bold.magenta(`\n=== Deploying to ${server.name} ===\n`))
109+
110+
// 如果部署多个应用,先确认是否更新 docker-compose.yml
111+
if (selectedApps.length > 0) {
112+
console.log(
113+
chalk.yellow(
114+
`Update docker-compose.yml manually if needed for ${server.name}, then press Enter to continue...`,
115+
),
116+
)
117+
await question("")
118+
await $`rsync -avP ./docker-compose.yml ${server.remote}:${server.deployPath}/docker-compose.yml`
119+
}
120+
121+
// 依次部署选中的应用
122+
for (const app of selectedApps) {
123+
await deployApp(server, app)
124+
}
125+
126+
console.log(
127+
chalk.green(`\n✓✓ All deployments to ${server.name} completed!\n`),
128+
)
129+
}
130+
131+
console.log(chalk.bold.green("\n=== All deployments completed! ===\n"))
132+
133+
// 询问是否查看日志
134+
const viewLogs = await question("View logs from a server? (y/N): ")
135+
if (viewLogs.toLowerCase() === "y") {
136+
let targetServer = selectedServers[0]
137+
138+
// 如果有多个服务器,让用户选择
139+
if (selectedServers.length > 1) {
140+
console.log(chalk.blue("Select server to view logs:"))
141+
selectedServers.forEach((server, index) => {
142+
console.log(` ${index + 1}. ${server.name}`)
143+
})
144+
const serverLogChoice = await question("Select server: ")
145+
const serverLogIndex = parseInt(serverLogChoice) - 1
146+
if (serverLogIndex >= 0 && serverLogIndex < selectedServers.length) {
147+
targetServer = selectedServers[serverLogIndex]
148+
}
149+
}
150+
151+
let targetApp = selectedApps[0]
152+
153+
// 如果部署了多个应用,让用户选择
154+
if (selectedApps.length > 1) {
155+
console.log(chalk.blue("Select application to view logs:"))
156+
selectedApps.forEach((app, index) => {
157+
console.log(` ${index + 1}. ${app}`)
158+
})
159+
const appLogChoice = await question("Select application: ")
160+
const appLogIndex = parseInt(appLogChoice) - 1
161+
if (appLogIndex >= 0 && appLogIndex < selectedApps.length) {
162+
targetApp = selectedApps[appLogIndex]
163+
}
164+
}
165+
166+
console.log(chalk.blue(`Logging ${targetApp} from ${targetServer.name}...`))
167+
await $`ssh ${targetServer.remote} "cd ${targetServer.deployPath} && sudo docker compose logs -f ${targetApp}"`
168+
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"syncpack": "14.0.0-alpha.18",
1111
"typescript": "^5.8.3",
1212
"utility-types": "^3.11.0",
13-
"vitest": "^3.2.4"
13+
"vitest": "^3.2.4",
14+
"zx": "^8.8.5"
1415
},
1516
"engines": {
1617
"node": ">=22.0.0",

pnpm-lock.yaml

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)