基于nodejs的轻量自动化部署

106 阅读2分钟

前言

在传统的自动化部署通常涉及使用一些工具或流水线,如金克斯,gitlab等等,这里介绍的自动化部署将不依赖任何工具和流水线,使用node-ssh及相关nodejs包即可实现,适用于前端开发过程中的轻量自动化部署方案。

整体流程

  1. 本地打包构建
  2. 将本地打包构建后的代码压缩为zip文件
  3. 配置对应部署服务器的ip地址,用户名,密码,端口号
  4. 读取并通过配置的部署服务器的ip地址,用户名,密码,端口号进行连接
  5. 将压缩的zip文件上传至部署服务器
  6. 执行部署服务器中的部署脚本

完整代码

const path = require('path');
const archiver = require('archiver');
const fs = require('fs');
const { NodeSSH } = require('node-ssh');
const ssh = new NodeSSH();
const configs = require('./config');
const dayjs = require('dayjs');
const beforeVersion = global.process.env.version || '';
const currentVersion = dayjs().format('-YYYY-MM-DD-HH-mm');

// 用于版本回归 version='-2019-11-13-15-42' node index.js
if (beforeVersion) {
  uploadFile();
} else {
  startZip();
}

// 压缩dist目录为dist.zip
function startZip() {
  console.log('开始压缩dist目录...');
  var archive = archiver('zip', {
    zlib: { level: 5 }, // 递归扫描最多5层
  }).on('error', function (err) {
    throw err; // 压缩过程中如果有错误则抛出
  });

  var output = fs.createWriteStream(__dirname + '/dist.zip').on('close', function (err) {
    /* 压缩结束时会触发close事件,然后才能开始上传,否则会上传一个内容不全且无法使用的zip包 */
    if (err) {
      console.log('关闭archiver异常:', err);
      return;
    }
    console.log('已生成zip包');
    console.log('开始上传dist.zip至远程机器...');
    uploadFile();
  });

  archive.pipe(output);
  // 将路径对应的内容添加到zip包中/dist路径
  archive.directory(path.resolve(__dirname, '../dist'), '');
  archive.finalize();
}

// 将dist目录上传至正式环境
function uploadFile() {
  ssh
    .connect({
      host: configs.host,
      username: configs.user,
      // privateKey: configs.privateKey,
      password: configs.password,
      port: 22,
    })
    .then(function () {
      // 用于版本回归 version='-2019-11-13-15-42' node index.js
      if (beforeVersion) {
        startRemoteShell(beforeVersion);
      } else {
        // 上传网站的发布包至configs中配置的远程服务器的指定地址
        ssh
          .putFile(__dirname + '/dist.zip', '/root/xxx/dist.zip')
          .then(function (status) {
            console.log('上传文件成功');
            startRemoteShell(); // 上传成功后触发远端脚本
          })
          .catch((err) => {
            console.log('文件传输异常:', err);
            process.exit(0);
          });
      }
    })
    .catch((err) => {
      console.log('ssh连接失败:', err);
      process.exit(0);
    });
}

// 执行远端部署脚本
function startRemoteShell(beforeVersion) {
  console.log('正在解压包...');
  // 在服务器上cwd配置的路径下执行sh deploy.sh脚本来实现发布
  var v = beforeVersion || currentVersion;
  ssh.execCommand('sh deploy.sh ' + v + '', { cwd: '/root/xxx' }).then(function (result) {
    console.log('远程STDOUT输出: ' + result.stdout);
    console.log('远程STDERR输出: ' + result.stderr);
    if (!result.stderr) {
      console.log('发布成功!');
      process.exit(0);
    }
  });
}

configs.js

module.exports = {
  host: 'xxx',
  user: 'xxx',
  password: 'xxx',
  path: '',
};

deploy.sh

#!/bin/bash
# cd /usr/local/nginx/html/test

#解压新的包
unzip -o 'dist.zip'