基于electron开发轻量级自动部署工具-部署狗

部署狗

  • 适用与个人与小团队的轻量级自动部署工具
  • 基于electron+vue+element开发
  • github

技术棧

  • electron-vue

开发

$ npm install
$ npm run dev

先来一波图

项目管理

avatar

添加项目

avatar

发布进度

avatar

部署流程

avatar

安装包

windows下载

具体代码:

  • 部署代码 deploy.js (electron主进程中执行)
const path = require('path');
const node_ssh = require('node-ssh');
const zipFile = require('compressing')// 压缩zip

let SSH = new node_ssh(); // 生成ssh实例
let mainWindow = null; // 窗口实例,用于向向渲染进程通信

// 部署流程入口
const deploy = async (config, mainWindows) => {
    mainWindow = mainWindows
    await startZip(config);
    await connectSSH(config);
    await uploadZipBySSH(config)
}

//压缩代码
const startZip = async (config) => {
    return new Promise((resolve, reject) => {
        let { distPath } = config;
        let distZipPath = path.resolve(distPath, `../dist.zip`);
        mainWindow.send('deploy', '本地项目开始压缩')
        zipFile.zip.compressDir(distPath, distZipPath).then(res => {
            mainWindow.send('deploy', `本地项目压缩完成:${distZipPath}`)
            resolve()
        }).catch(err => {
            mainWindow.send('deploy', `压缩失败${err}`)
            reject()
        })
    })
}

//连接服务器
const connectSSH = async (config) => {
    return new Promise((resolve, reject) => {
        mainWindow.send('deploy', `正在连接服务器:${config.host}`)
        SSH.connect({
            host: config.host,
            username: config.username,
            password: config.password // 密码登录 方式二
        }).then(res => {
            mainWindow.send('deploy', `连接服务器成功:${config.host}`)
            resolve()
        }).catch(err => {
            mainWindow.send('deploy', `连接服务器失败:${err}`)
            reject()
        })
    })
}

//清空线上目标目录里的旧文件
const clearOldFile = async (config) => {
    mainWindow.send('deploy', `准备清空服务器部署目录${config.webDir}内的文件`)
    const commands = ['ls', 'rm -rf *'];
    await Promise.all(commands.map(async (item) => {
        return await SSH.execCommand(item, { cwd: config.webDir });
    }));
    mainWindow.send('deploy', `清空服务器目录${config.webDir}内的文件完成`)
}

//上传zip文件到服务器
const uploadZipBySSH = async (config) => {
    let distZipPath = path.resolve(config.distPath, `../dist.zip`);
    //线上目标文件清空
    await clearOldFile(config);
    try {
        await SSH.putFiles([{ local: distZipPath, remote: config.webDir + '/dist.zip' }]); //local 本地 ; remote 服务器 ;
        mainWindow.send('deploy', `上传文件到服务器成功:${config.webDir}`)
        await SSH.execCommand('unzip -o dist.zip && rm -f dist.zip', { cwd: config.webDir }); //解压
        mainWindow.send('deploy', `解压上传到服务器的文件成功`)
        await SSH.execCommand(`rm -rf ${config.webDir}/dist.zip`, { cwd: config.webDir }); //解压完删除线上压缩包
        mainWindow.send('deploy', `删除上传到服务器的文件成功`)

        //将解压后的文件夹内的所有文件移动到目标目录
        var dir = path.basename(path.join(config.distPath))
        mainWindow.send('deploy', `将${config.webDir}/${dir}/内解压的文件移动到目录${config.webDir}`)
        await SSH.execCommand(`mv - f ${config.webDir}/${dir}/*  ${config.webDir}`);
        await SSH.execCommand(`rm -rf ${config.webDir}/${dir}`); //移出后删除 dist 文件夹
        mainWindow.send('deploy', `全部完成`)
        SSH.dispose(); //断开连接
    } catch (error) {
        mainWindow.send('deploy', `文件上传到服务器失败:${error}`)
        // process.exit(); //退出流程
    }
}

export default deploy

  • 主进程进行监听与渲染进行发送的命令
// 监听前台传来的deploy命令
ipcMain.on('deploy', (e, data) => {
  deploy(data, mainWindow)
});
  • 前台部分代码
<template>
  <div id="wrapper">
    <el-row :gutter="20" class="pro-list">
      <el-col :span="12" v-for="(item, index) in dataList" :key="index">
        <el-card class="box-card">
          <ul class="prolist">
            <li>
              <span class="label">项目名称:</span>
              <span class="info">{{ item.projectName }}</span>
            </li>
            <li>
              <span class="label">服务器地址:</span>
              <span class="info">{{ item.host }}</span>
            </li>
        //    ...other
          </ul>
          <div class="btns">
            <el-button icon="el-icon-s-promotion" @click="deploy(item)" type="primary">发布</el-button>
          </div>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import { ipcRenderer } from "electron";
export default {
  name: "prolist",
  created() {
    this.getDb();
    // 接收主进程部署过程 中的 过程信息
    ipcRenderer.on("deploy", (event, arg) => {
      this.activities.unshift({
        content:arg,
        timestamp: new Date().toLocaleTimeString()
      });
    });
  },
  data() {
    return {
      dataList: [],
      activities: []
    };
  },
  methods: {

    // 部署
    deploy(config) {
    //   发送打包命令 给 主进程
      ipcRenderer.send("deploy", config);
    },
    remove(config) {
    //   删除项目
    }
  }
};
</script>

仅供大家学习参考

所有数据存在本地lowdb中,所以不用担心安全问题

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,692评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,482评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,995评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,223评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,245评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,208评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,091评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,929评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,346评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,570评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,739评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,437评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,037评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,677评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,833评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,760评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,647评论 2 354

推荐阅读更多精彩内容