UNPKG

4.09 kBJavaScriptView Raw
1#!/usr/bin/env node
2
3const path = require('path')
4const { spawn } = require('child_process')
5
6const {
7 error,
8 info,
9 success,
10 shell,
11} = require('./util')
12
13const deploy = async options => {
14 const {
15 // 项目信息
16 name,
17 projectDir,
18 scheme,
19 type,
20 // 目标服务器的基本信息
21 web,
22 dir,
23 user,
24 pwd,
25 // 构建打包信息
26 isNeedBuild,
27 buildScript,
28 distDir,
29 npmRegistry,
30 } = options
31
32 info('\n🚗 🚕 🚙 🚌 🚓 🚑 🚔 ✈️ 开始发车 🚗 🚕 🚙 🚌 🚓 🚑 🚔 ✈️ ')
33
34 info('\n本次部署方案为:', `${scheme}\n`)
35
36 info('\n本地项目路径:', `${projectDir}\n`)
37
38 const executeOptions = {
39 stdio: 'inherit',
40 shell: true,
41 }
42
43 const isNodeProject = type === '1'
44
45 // 处理打包
46 const build = async () => {
47 info('\n🚗 开始打包\n')
48
49 const buildOptions = [
50 path.resolve(__dirname, '../sh/build.sh'),
51 projectDir,
52 buildScript,
53 npmRegistry,
54 ]
55
56 const builder = spawn('bash', buildOptions, executeOptions)
57
58 builder.on('data', data => {
59 info(`build stdout: ${data}`)
60
61 if (data.includes('npm ERR!')) {
62 error('\n❌ npm出现未知错误,请尝试删除node_modules和package-lock.json后重装依赖\n')
63
64 process.exit(1)
65 }
66 })
67
68 builder.on('error', data => {
69 error(`\n❌ 打包失败: stderr: ${data}\n`)
70 })
71
72 builder.on('close', code => {
73 info(`build close code: ${code}`)
74
75 if (code === 0) {
76 info('\n🚗 打包成功\n')
77
78 tar()
79 } else {
80 error(`\n❌ 打包失败: close code ${code}\n`)
81 }
82 })
83 }
84
85 // 处理压缩打包
86 const tar = async () => {
87 info('\n🚗 开始压缩\n')
88
89 try {
90 const cdDir = isNodeProject ? '../' : './'
91 const sourceDir = isNodeProject ? name : distDir
92
93 await shell(`cd ${cdDir} && rm -rf ${name}.tar.gz && tar -czf ${name}.tar.gz ${sourceDir}`)
94
95 info(`\n🚗 压缩成功: ${name}.tar.gz\n`)
96
97 upload()
98 } catch (data) {
99 error(`\n❌ 压缩失败: stderr: ${data}\n`)
100
101 process.exit(1)
102 }
103 }
104
105 // 处理上传
106 const upload = () => {
107 info('\n✈️ 开始上传\n')
108
109 const tgzSrc = isNodeProject ? `../${name}.tar.gz` : `${name}.tar.gz`
110
111 const uploadOptions = [
112 path.resolve(__dirname, '../sh/upload.sh'),
113 tgzSrc,
114 web,
115 dir,
116 user,
117 pwd,
118 ]
119
120 const uploader = spawn('expect', uploadOptions, executeOptions)
121
122 uploader.on('data', data => {
123 info(`uploader stdout: ${data}`)
124 })
125
126 uploader.on('error', data => {
127 error(`❌ 上传失败: stderr: ${data}\n`)
128 })
129
130 uploader.on('close', async code => {
131 info(`uploader close code: ${code}`)
132
133 if (code === 0) {
134 info('\n✅ 上传成功\n')
135
136 execute()
137 } else {
138 error(`❌ 上传失败: close code: ${code}\n`)
139 }
140 })
141 }
142
143 // 处理部署
144 const execute = () => {
145 info('\n🛩 开始启动\n')
146
147 const script = isNodeProject ? 'execute' : 'static'
148
149 const executeParams = [
150 path.resolve(__dirname, `../sh/${script}.sh`),
151 name,
152 web,
153 dir,
154 user,
155 pwd,
156 distDir,
157 ]
158
159 const excuter = spawn('expect', executeParams, executeOptions)
160
161 excuter.on('data', data => {
162 info(`execute stdout: ${data}`)
163 })
164
165 excuter.on('error', data => {
166 error(`❌ 启动失败: stderr: ${data}\n`)
167 })
168
169 excuter.on('close', code => {
170 info(`execute close code: ${code}`)
171
172 if (code === 0) {
173 success('\n🎉 🎉 🎉 启动成功,部署完成 🍺 🍺 🍺\n')
174 } else {
175 error(`❌ 启动失败: close code: ${code}\n`)
176 }
177 })
178 }
179
180 // 本地部署流程
181 // 需要构建:build -> 打包tar -> 上传upload -> 解压untar -> 启动start
182 if (isNeedBuild) {
183 build()
184 } else {
185 // 不需要构建:打包tar -> upload -> untar -> start
186 tar()
187 }
188}
189
190module.exports = (options) => deploy(options);