# 1、自动部署git项目
/*
* 快速初始化本地仓库,并且推送到远程仓库
* @Author: lxx
* @Date: 2024-11-21 15:50:32
* @Last Modified by: lxx
* @Last Modified time: 2024-11-23 10:18:55
*/
const { exec } = require("child_process");
const readline = require("readline");
const fs = require("fs");
const path = require("path");
const gitUrl = `http://192.168.xx.xx:5001`;
const gitGroup = `h5`;
let fileName = `com.line.light.frcpbd`;
let commitTx = `feat init`;
// 定义目标目录
const targetDir = path.join(__dirname, fileName);
// 创建 readline 接口用于获取用户输入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
// 定义执行 Git 命令的函数
function executeCommand(command) {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
reject(`执行命令时出错: ${error.message}`);
return;
}
resolve(stdout);
});
});
}
// 主函数
async function main() {
// 检查目标目录是否存在
if (fs.existsSync(targetDir)) {
// 改变当前工作目录
try {
process.chdir(targetDir);
console.log(`当前工作目录已更改为: ${process.cwd()}`);
try {
// 初始化 Git 仓库
console.log("初始化 Git 仓库...");
await executeCommand("git init");
// 添加远程仓库
console.log("添加远程仓库...");
const remoteUrl = `${gitUrl}/${gitGroup}/${fileName}.git`;
await executeCommand(`git remote add origin ${remoteUrl}`);
// 获取提交信息
rl.question("请输入提交信息: ", async (commitMessage) => {
try {
// 添加所有文件到暂存区
console.log("添加所有文件到暂存区...");
await executeCommand("git add .");
// 提交代码
console.log("提交代码...");
await executeCommand(
`git commit -m "${commitMessage}"`
);
// 推送到远程仓库
console.log("推送到远程仓库...");
await executeCommand("git push -u origin master");
console.log(`${fileName} 代码提交完成!`);
} catch (error) {
console.error(`提交或推送时出错: ${error}`);
} finally {
rl.close();
}
});
} catch (error) {
console.error(`初始化 Git 仓库时出错: ${error}`);
}
} catch (err) {
console.error(`无法改变工作目录: ${err}`);
}
} else {
console.error("目标目录不存在");
}
}
// 执行主函数
main();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# 2、快速复制文件夹,替换指定内容,并且执行打包命令
/*
* 快速复制文件夹,并且打包
* @Author: lxx
* @Date: 2024-09-19 14:54:49
* @Last Modified by: lxx
* @Last Modified time: 2024-11-21 15:51:13
*/
const fs = require("fs").promises;
const path = require("path");
const { spawn } = require("child_process");
/**
* 修改list即可
* @param sourceName 源model
* @param targetName 目标model
*/
const list = [
{
sourceName: "com.honyar.switch.sw3a01",
targetName: "com.tnv.switch.sw3e01",
},
// {
// sourceName: "com.honyar.switch.sw1a01",
// targetName: "com.haoyi.switch.sw1a01",
// },
];
const commandList = list.map((item) => `npm run publish ${item.targetName}`);
// 复制文件夹
async function copyFolder(src, dest) {
try {
// 创建目标文件夹
await fs.mkdir(dest, { recursive: true });
// 读取源文件夹中的文件和文件夹
const items = await fs.readdir(src);
for (const item of items) {
const srcPath = path.join(src, item);
const destPath = path.join(dest, item);
const stat = await fs.stat(srcPath);
if (stat.isDirectory()) {
// 如果是文件夹,递归调用 copyFolder
await copyFolder(srcPath, destPath);
} else {
// 如果是文件,复制文件
await fs.copyFile(srcPath, destPath);
}
}
// console.log(`复制完成: ${src} 到 ${dest}`);
} catch (error) {
console.error(`复制失败: ${error.message}`);
}
}
// 替换文件的内容
async function replaceInFile(filePath, target, replacement) {
try {
// 读取文件内容
let data = await fs.readFile(filePath, "utf8");
// 替换目标字符
const updatedData = data.replace(new RegExp(target, "g"), replacement);
// 将更新后的内容写回文件
await fs.writeFile(filePath, updatedData, "utf8");
// console.log(`成功将 "${target}" 替换为 "${replacement}"`);
} catch (error) {
console.error(`文件内容替换失败: ${error.message}`);
}
}
(async () => {
for (let i = 0; i < list.length; i++) {
const sourceName = list[i].sourceName;
const targetName = list[i].targetName;
const sourceFolder = `./projects/${sourceName}`; // 源文件夹路径
const destinationFolder = `./projects/${targetName}`; // 目标文件夹路径
const filePath = `./projects/${targetName}/project.json`; // 指定文件路径
const sourceStr = sourceName; // 要替换的字符
const newStr = targetName; // 替换成的新字符
const filePath2 = `./projects/${targetName}/package.json`; // 指定文件路径
const sourceStr2 = sourceName.replace(/\./g, "-");
const newStr2 = targetName.replace(/\./g, "-");
await copyFolder(sourceFolder, destinationFolder);
await replaceInFile(filePath, sourceStr, newStr);
await replaceInFile(filePath2, sourceStr2, newStr2);
const child = spawn(commandList[i], { shell: true });
child.stdout.on("data", (data) => {
if (data.includes("eslint fix report")) {
console.log(`${targetName} 没有error`);
}
});
child.stderr.on("data", (data) => {
console.log(`warn: ${data}`);
});
child.on("close", (code) => {
console.log(`${targetName} 打包完成,代码: ${code}`);
});
}
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# 3、前端项目自动化部署
- 所用核心库:scp2
/* eslint-disable */
// 引入scp2
var client = require('scp2');
// 下面三个插件是部署的时候控制台美化所用 可有可无
const ora = require('ora');
const chalk = require('chalk');
const spinner = ora(chalk.green('正在发布到正式服务器...'));
spinner.start();
const projectName = 'gmevue';
client.scp(
'./dist/',
{
// 本地打包文件的位置
host: '', // 服务器的IP地址
port: '22', // 服务器端口, 一般为 22
username: 'root', // 用户名
password: '', // 密码
path: '/usr/share/nginx/html/' + projectName, // 项目部署的服务器目标位置
},
(err) => {
spinner.stop();
if (!err) {
console.log(chalk.green('项目部署完毕!'));
} else {
console.log(chalk.red('发布失败!'));
console.log('err', err);
}
}
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
- 备份+部署(利用ssh2执行命令)
let Client = require('ssh2').Client;
const chalk = require('chalk');
const conn = new Client();
const ora = require('ora');
const scpClient = require('scp2');
const serverConfig = {
dev: {
id: 'dev',
name: '测试环境',
host: '', // 服务器的IP地址
port: '22', // 服务器端口, 一般为 22
username: 'root', // 用户名
password: '', // 密码
path: `/usr/share/nginx/html`, // 项目部署的服务器目标位置
},
prod: {
id: 'preview',
name: '预发布环境',
host: '', // 服务器的IP地址
port: '22', // 服务器端口, 一般为 22
username: 'root', // 用户名
password: '', // 密码
path: `/usr/share/nginx/html`, // 项目部署的服务器目标位置
}
};
const curConfig = serverConfig['dev'] // 当前配置
const fileName = `abc` // 文件夹名字
// 备份文件
function backupsFile() {
const { host, port, username, password, path } = curConfig
const cmd = `
cd ${path}\n
cp -r ${fileName} ./${fileName}_${new Date().toLocaleDateString()}
`;
conn.on('ready', function () {
conn.exec(cmd,
function (err, stream) {
console.log(chalk.green(`已备份文件 ${fileName}`));
if (err) throw err;
stream.on('close', function (code, signal) {
uploadFile()
conn.end();
})
});
})
.on('error', function (err) {
console.log(chalk.red('Fail! 服务器连接失败.\n'));
throw err;
})
.connect({
host,
port,
username,
password
});
}
// 上传文件
function uploadFile() {
const { host, port, username, password, path, name } = curConfig
const spinner = ora(
chalk.green(`正在发布到 ${name} 项目名为${fileName}...`)
);
spinner.start();
scpClient.scp(
`../dist/${fileName}`,
{
// 本地打包文件的位置
host,
port,
username,
password,
path: `${path}/${fileName}`, // 项目部署的服务器目标位置
},
(err) => {
spinner.stop();
if (!err) {
console.log(chalk.green('项目发布完毕!'));
} else {
console.log(chalk.red(`项目发布失败!`));
console.log('err', err);
}
}
);
}
/**
* @param {Boolean} isBackupsFile 是否备份文件
*/
function main(isBackupsFile = true) {
isBackupsFile ? backupsFile() : uploadFile()
}
main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# 4、两个远程仓库进行同步
const { exec } = require("child_process");
const fs = require("fs");
const path = require("path");
const https = require("https");
const gitUrl = "https://gitee.com";
const gitOrg = "you_org_name";
// 给定的目录数组,当前目录下,需要同步的目录名
const directoryArray = [
"fishtanklight",
];
// 定义执行 Git 命令的函数
function executeCommand(command) {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
reject(`执行命令时出错: ${error.message}`);
return;
}
resolve(stdout);
});
});
}
// 判断是否为git仓库
async function isGitRepo(dir) {
try {
// 方法1:检查 .git 目录是否存在
const gitDir = path.join(dir, ".git");
if (fs.existsSync(gitDir)) {
return true;
}
// 方法2:执行 git 命令检测(更准确)
const { stdout } = await executeCommand(
"git rev-parse --is-inside-work-tree",
{ cwd: dir }
);
return stdout.trim() === "true";
} catch (error) {
return false; // 不是 Git 仓库
}
}
// 主函数
async function main() {
for (const item of directoryArray) {
const targetDir = path.join(__dirname, item);
try {
process.chdir(targetDir);
console.log(`当前工作目录已更改为: ${process.cwd()}`);
await createStash(item);
const remoteUrl = `${gitUrl}/${gitOrg}/${item}.git`;
try {
// 检查远程仓库是否已存在
const remotes = await executeCommand("git remote -v");
const remoteExists = remotes.includes(`secGit\t${remoteUrl}`);
if (!remoteExists) {
console.log("添加远程仓库...", remoteUrl);
await executeCommand(`git remote add secGit ${remoteUrl}`);
}
await executeCommand("git push secGit master");
console.log(`${targetDir} 代码已同步到 secGit`);
} catch (error) {
console.error(`Git 操作出错: ${error}`);
}
} catch (err) {
console.error(`无法改变工作目录: ${err}`);
}
}
}
async function createStash(name) {
return await new Promise((resolve, reject) => {
// 目标服务器的URL和端口
const options = {
hostname: "gitee.com",
port: 443,
path: `/api/v5/orgs/${gitOrg}/repos`,
method: "POST",
headers: {
"Content-Type": "application/json", // 或者根据需要设置其他类型,如 'application/x-www-form-urlencoded'
},
};
// 要发送的数据
const postData = JSON.stringify({
name: name,
access_token: "access_token",
});
// 创建HTTPS请求
const req = https.request(options, (res) => {
console.log(`状态码: ${res.statusCode}`);
res.on("data", (d) => {
process.stdout.write(d);
});
res.on("end", () => {
resolve("end");
});
});
// 发送请求数据
req.write(postData);
// 处理请求错误
req.on("error", (e) => {
console.error(`请求遇到问题: ${e.message}`);
});
// 结束请求
req.end();
});
}
// 执行主函数
main();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128