背景
在项目部署上线的过程中,正常流程是在生成环境 Git 拉取最新代码来进行更新。但是某些极端情况下,由于内网管控的封闭性,生产环境无法拉取 GitLab 端所存储的代码,此时便只能通过 SCP 和 SSH 来曲线救国了。
解决方案
借助 scp2 和 ssh2 这两个 NPM 包,实现项目代码的上传和启动。
npm i scp2 ssh2 -D
deploy.example.js
// 服务器信息
const host = '127.0.0.1';
const username = 'root';
const password = 'password';
const port = 22;
const projectName = 'example-web';
const path = `/root/web/${projectName}/`;
// 上传
async function upload () {
const client = require('scp2');
const remoteAddress = `${username}:${password}@${host}`;
return new Promise((resolve, reject) => {
client.scp(`../${projectName}`, `${remoteAddress}:${path}`, err => {
if (err) {
reject(`Fail: 1 ${err.message}`);
return;
}
resolve('upload success!');
})
});
}
// 重启
async function restart () {
var Client = require('ssh2').Client;
var conn = new Client();
return new Promise((resolve, reject) => {
conn.on('ready', function() {
console.log('Client :: ready');
conn.exec(`cd ${path};pwd;npm i;npm run restart;`, function(err, stream) {
if (err) throw err;
stream.on('close', function(code, signal) {
console.log('Stream :: close :: code: ' + code + ', signal: ' + signal);
conn.end();
resolve('restart success!');
}).on('data', function(data) {
console.log('STDOUT: ' + data);
}).stderr.on('data', function(data) {
console.log('STDERR: ' + data);
});
});
}).connect({
host,
port,
username,
password,
});
});
}
// 启动任务
;(async () => {
// 上传
const uploadResult = await upload().catch(console.error);
console.log(uploadResult);
// 重启
const restartResult = await restart().catch(console.error);
console.log(restartResult);
})();
此时已经可以在本地进行部署了。但是使用 GitLab CICD 进行部署的时候会遇到问题,就是 GitLab 容器环境中并没有 scp2 和 ssh2 这两个 NPM 包,我们可以借助 Webpack 将以上脚本打包成 Node 容器环境可直接运行的脚本。
webpack.config.deploy.example.js
const path = require('path');
module.exports = {
entry: './deploy.example.js',
mode: 'production',
output: {
filename: 'deploy.example.bin.js',
path: path.resolve(__dirname, './'),
},
target: 'node',
node: {
dgram: 'empty',
child_process: 'empty',
fs: 'empty'
}
};
package.json
{
// ...
"node": {
"http": false,
"https": false,
"net": false,
"path": false,
"stream": false,
"tls": false,
"fs": "empty"
}
}
npx webpack --config webpack.config.deploy.example.js