pgy-deploy
Version:
使用ssh2与scp2实现代码发布
211 lines (199 loc) • 6.23 kB
JavaScript
const chalk = require('chalk');
const Client = require('ssh2').Client;
var fs = require('fs');
const blue = chalk.blue;
const success = chalk.green;
const error = chalk.bold.red;
const warning = chalk.keyword('orange');
const ProgressBar = require('progress');
const bar = new ProgressBar('执行时间:elapsed 秒 :bar :percent (:hint)', { total: 40, complete: "*" });
let showProg = null;
let progHint = "";
let stapValue = 0;
module.exports = function (server) {
try {
console.log("开始执行【" + server.serverNmae + "】配置");
progHint = "开始建立连接";
showProg = setInterval(function () {
bar.tick(stapValue, {
hint: progHint
});
stapValue = 0;
}, 500);
if (!verifyConfig(server)) {
return;
}
const conn = new Client();
const connect = connectConfig(server);
// return;
conn.on('ready', function () {
// 前置命令执行
const preCmd = server.preCmd || "";
stapValue = 5;
progHint = "执行前置命令";
executeOrder(conn, preCmd, function () {
console.log(blue("\n前置命令执行完成"));
stapValue = 5;
progHint = "";
// 后置命令执行
const rearCmd = server.rearCmd || "";
const finish = function () {
progHint = "开始执行后置命令";
stapValue = 5;
executeOrder(conn, rearCmd, async function () {
await bar.tick(20);
console.log(blue("\n后置命令执行完成"));
await clearInterval(showProg);
progHint = "完成";
stapValue = 5;
conn.end();
console.log("项目发布结束");
});
};
if (fs.existsSync(server.localPath)) {
//文件上传
progHint = "上传文件中";
uploadFiles(server, finish);
} else {
console.log(warning("\n不存在上传文件"));
finish();
}
});
}).on('end', function () {
// console.log('退出');
}).connect(connect);
return;
} catch (error) {
clearInterval(showProg);
throw error;
}
};
// 执行命令
function executeOrder(conn, order, callBack) {
let newOrder = order;
if (order instanceof Array) {
newOrder = order.join("\n ");
}
conn.exec(newOrder, function (
err,
stream
) {
if (err) throw err;
stream.on('close', function (code, signal) {
callBack();
}).on('data', function (data) {
const str = data.toString();
if (str.indexOf("Error")) {
console.log(data.toString());
}
callBack();
return;
}).stderr.on('data', function (data) {
const str = data.toString();
if (str.indexOf("Error")) {
console.log(data.toString());
}
callBack();
return;
});
});
return;
}
// 上传发布文件
function uploadFiles(server, rearCmd) {
const scpClient = require('scp2');
const connect = connectConfig(server);
scpClient.scp(
server.localPath,
{
...connect,
path: server.serverPath
},
function (err) {
progHint = "";
if (err) {
console.log(error('\n文件上传失败'));
clearInterval(showProg);
throw err;
} else {
stapValue = 20;
console.log(
blue(
'\n文件上传成功'
)
);
rearCmd();
}
}
);
return;
}
// 参数校验
function verifyConfig(data) {
console.log();
// 错误统计
let errorNum = 0;
let errorArr = [];
// 校验参数
function paramVerify(key, str, isFile) {
if (key in data && (data[key].length > 0 || typeof data[key] == "number")) {
if (isFile) {
return fs.existsSync(data[key]);
} else {
return true;
}
}
errorNum++;
errorArr.push(str);
return false;
}
// 范围校验
function inInterior(key, arr, str) {
if (arr.indexOf(data[key]) != -1) {
return true;
}
errorNum++;
errorArr.push(str);
return;
}
paramVerify("host", "未设置ip地址");
paramVerify("port", "未设置端口号");
paramVerify("username", "未设置用户名");
inInterior("loginWay", [0, 1], "loginWay参数只能设置为0或1");
switch (data.loginWay) {
case 0:
paramVerify("password", "未设置登陆密码");
break;
case 1:
paramVerify("privateKeyPath", "证书检查失败", true);
break;
default:
paramVerify("password", "未设置登陆密码");
break;
}
if (errorNum > 0) {
console.log(error(errorArr.join("\n")));
return false;
}
return true;
}
// 处理连接参数
function connectConfig(server) {
const config = {
host: server.host,
port: server.port,
username: server.username,
};
switch (server.loginWay) {
case 0:
config.password = server.password;
break;
case 1:
config.privateKey = fs.readFileSync(server.privateKeyPath);
break;
default:
config.password = server.password;
break;
}
return config;
}