文档章节

实现项目发布自动化

S
 Sinxc
发布于 2017/08/13 14:45
字数 1464
阅读 14
收藏 0

背景:公司开发项目发布系统

需求:    

        1.实现本地文件或者git/svn上的文件上传(ftp)到服务器
        2.错误实时返回到前台
        3.文件备份回滚

简单分析场景:
    1.下载到本地时,如果本地存在,则会报错,故需要在下载之前删除本地文件夹
        判断存在?执行删除
        或者直接删除,捕获错误忽略(try)
    2.只有在上一步成功过后才可以读取文件夹,所以需不需要判断文件夹存在情况呢?
        还是判断一下吧!可能有直接输入文件夹上传,没有 下载 一步
    3.读取文件列表 (此为同步进行) 成功失败后执行响应操作
    4.以上成功。连接ftp。
    5.以上成功。首先创建一个备份'_back'的文件夹,作为项目名称 也就是 name_back
    6.以上成功。上传文件。适时返回进度,在上传完成(未出错)
    7.以上成功。将项目名称改为 name_getTime() 。此处可能出错,因为文件可能不存在,捕获错误,忽略。
    8.以上成功。讲上传的项目 name_back 重命名为 name
    9.关闭连接,完成。
    10. 回滚。需要传入 服务器端的 项目地址 以及 版本识别符

说明:
    1.所有的失败(错误)均需要处理,防止服务崩溃
    2.所有输入的文件夹路径前后不能有 '/'
    3.对于有ftp连接的需要在失败或者错误或者结束业务的时候关闭 避免超时报错,服务器崩溃
    4.针对回滚,考虑往数据库中存入数据,结合 uuid 识别项目
技术:nodejs + node-ftp

实现:
    1.下载远程代码
        通过命令node调取命令行实现下载(svn命令行需要安装subversion)
        依赖 child_process 实现命令行调取 exec = require('child_process').exec 
        异步执行,需要结合 promise 返回状态

        参数说明:    
            cmd 执行的命令行 (我执行多条命令的时候出错,然后没有去找解决的办法,妈的没有时间)
            {} 配置项。设置下载的超时时间,以及下载的buffer(小了可能报错)
            cb 回调处理
        exec(cmd, {
            encoding: 'utf8',
            timeout: 0,
            maxBuffer: 10000 * 1024, // 默认 200 * 1024
            killSignal: 'SIGTERM'
        }, function(err, stdout, stderr) {
            if (err) {
                console.log('下载文件%s出错%s',cmd,err)
            } else {
                cb()               
            }
        });

    2.读取本地文件(如果本地文件夹上传直接读取)

        //递归读取文件 
        //参数 path 读取的文件夹 相对路径是相对当前的服务(server index)路径,绝对路径带盘符
        function readFile(path) {
              files = fs.readdirSync(path); //需要用到同步读取
             files.forEach(walk);

              function walk(file) {
                states = fs.statSync(path + '/' + file);
                if (states.isDirectory()) {
                      readFile(path + '/' + file);
                } else {
                      _fileList.push(path + '/' + file);
                }
              }
        }
         try {
            readFile(path);
               resolve(fileList) //读取文件夹是同步api
          } catch (err) {
            reject(err)
          }


    3.实现ftp的远程连接
        需要依赖 node-ftp (npm install)
        Client = require('ftp')

        var ftp_client = new Client()
        ftp_client.on('ready', function() {
            console.log('ftp连接建立成功');
            //成功的执行
            cb(file_client)
        });
        ftp_client.on('error', function(err) {
            console.log('ftp连接建立失败',error);
            //失败的回调
            cb(err)
            return;
        });

   

    4.根据文件列表,远程创建(调用nodejs的api好像不能远程创建,他只能创建在该服务运行的电脑)
        使用ftp-node 的api
        参数:     ftp_client  ftp的实例
                fileList 文件列表
                serverPath 服务器端的相对目录
        还需要参数就是文件列表
        准备操作:通过文件列表,获得所有的文件夹路径;路径数组进行去重.
            hash快速去重:
                function uniqArray(arr) {
                    var hash = {},
                          len = arr.length,
                         result = [];

                    for (var i = 0; i < len; i++) {
                          if (!hash[arr[i]]) {
                            hash[arr[i]] = true;
                            result.push(arr[i]);
                          }
                    }
                    return result;
                }

        创建文件夹:

            var pre = new Promise(function(resolve, reject) {
                  // 建立相应的文件夹
                  async.each(fileList, function(item, cb) {
                    var _path = serverPath + "/" + item;
                    ftp_client.mkdir(_path, true, function(err) { //参数 true 表示已有文件夹不报错
                          if (err) {
                            console.log('创建文件夹%s出错%s', _path, err)
                            reject(err)
                         } else {
                               ++file_num;
                            if (file_len == file_num) { //这一步很重要!!! 分别是文件的总数量,和当前数量
                                 resolve()
                            }
                          }
                    });
                })
            })

    5.上传文件
        参数:     ftp_client  ftp的实例
                fileList 文件列表
                serverPath 服务器端的相对目录
        上传:
            var pre = new Promise(function(resolve, reject) {
                  async.each(fileList, function(item, cb) {
                    ftp_client.put(item, serverPath + "/" + item, function(err) {
                          if (err) {
                            console.log('上传文件%s出错:%s', item, err)
                               reject(err)
                          } else {
                                ++file_num;
                            if (file_len == file_num) { //同上,很重要
                                  resolve(ftp_client)
                            }
                          }
                    })
                  })
            })

    6.回滚实现
        很抱歉,暂时没有找到copy到指定文件夹的快捷方法
        暂时使用的是重命名,感觉挺快的。

        参数:
            /**
             * file_client
             * from 备份文件夹名称
             * to 项目文件夹名称
             */
        1.调用方法建立连接
        2.参照文件夹操作


配合的文件夹操作:
    依赖 fs 系统
    1.删除本地文件夹

        function deleteFloderLocal(path) {
            var files = [];
               if (fs.existsSync(path)) {
                files = fs.readdirSync(path)
                files.forEach(function(file, index) {
                    var curPath = path + "/" + file;
                    if (fs.statSync(curPath).isDirectory()) {
                        deleteFloderLocal(curPath);
                    } else {
                        fs.unlinkSync(curPath);
                    }
                });
                fs.rmdirSync(path);
            }
        }
        //判断本地文件夹是否存在
        function fsExistsSync(path) {
            try {
                fs.accessSync(path, fs.F_OK);
            } catch (e) {
                console.log(e)
                return false;
            }
            return true;
        }

    2.删除服务器端文件夹

        function deleteFloderServer(path, ftp_client) {
            var pre = new Promise(function(resolve, reject) {
                ftp_client.rmdir(path, true, function(err) { 
                    if (err) {
                        console.log('删除目录失败:', err);
                    };
                    resolve();
                    console.log('删除目录' + path + "成功!")
                })
            })
            return pre
        }

        说明:    1.rmdir true 参数说明文件夹非空时仍可以移除
                2.所有的不要含有中文,我再操作的时候含有中文报错了

    3.备份文件夹
        说白了就是重命名,很显然只能保留一个,此处的备份是考虑到上传文件可能破坏,以后回滚
        远程的,不要跟我讲node api
        function copyFloderServer(path,lab, ftp_client) {
            console.log('备份文件开始...')
            ftp_client.rename(path, path + lab, function(err) {
                if (err) {
                    console.log('备份目录失败:', err);
                    return
                };
                console.log('文件备份/恢复完成!')
            })
        }

说明:这个是临时接手node的一个需求,从0到0.1的新手还是有很多事情要做,很多地方考虑不周,敬请指出,感谢。

© 著作权归作者所有

上一篇: 页面离线缓存
下一篇: 页面离线缓存
S
粉丝 0
博文 2
码字总数 2184
作品 0
南京
私信 提问
自动化代码发布工具--Flamingo-deployment

Flamingo -基于Ansible的自动化代码发布工具 目的: 通过Ansible实现统一的代码发布方式,思路基于Capistrano Flamingo对Ansistrano进行了二次修改和整理以实现根据不同的语言环境,主机组(应...

匿名
2016/03/15
1K
0
Linux内核测试工具--CrackerJack

Crackerjack Project 是由中日韩三方共同参加开发,该项目主要目的是为Linux内核提供自动化的回归测试功能,以帮助提高内核开发质量等,项目包括一个完整的内核自动化测试框架,以实现自动化...

匿名
2009/08/19
1K
0
python递归实现Easyui combotree树

原文链接:http://www.huangdc.com/43 自动化发布系统在选择文件时,使用jQuery EasyUI 创建页面 树形菜单(Tree) 及 后端python 递归实现Easyui combotree 树。这里主要分享2点: 1、linux 中...

dchuang
2014/11/19
661
0
基于Jenkins 实现php项目的自动化测试、自动打包和自动部署

本篇博文宅鸟将在上篇: 基于Jenkins 搭建持续集成环境 的基础上,继续介绍Jenkins结合php项目实现自动化测试和自动部署。废话不再多说,直接上干活。 宅鸟所使用的server为Ubuntu 要实现在j...

birdinroom
2018/06/28
0
0
【MPD上海站】“构建自动化运维体系”专场火热报名中!

时间 5月20日上午9:00-12:00 所属会场 测试管理/运维发布 讲师及介绍 梁定安 腾讯SNG自动化运维平台技术总监 毕业于四川大学,曾服务于IBM,现任腾讯社交网络运营部社交平台业务运维组组长、...

msup
2017/05/12
12
0

没有更多内容

加载失败,请刷新页面

加载更多

SpringBoot中 集成 redisTemplate 对 Redis 的操作(二)

SpringBoot中 集成 redisTemplate 对 Redis 的操作(二) List 类型的操作 1、 向列表左侧添加数据 Long leftPush = redisTemplate.opsForList().leftPush("name", name); 2、 向列表右......

TcWong
今天
5
0
排序––快速排序(二)

根据排序––快速排序(一)的描述,现准备写一个快速排序的主体框架: 1、首先需要设置一个枢轴元素即setPivot(int i); 2、然后需要与枢轴元素进行比较即int comparePivot(int j); 3、最后...

FAT_mt
昨天
4
0
mysql概览

学习知识,首先要有一个总体的认识。以下为mysql概览 1-架构图 2-Detail csdn |简书 | 头条 | SegmentFault 思否 | 掘金 | 开源中国 |

程序员深夜写bug
昨天
10
0
golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web

micro web micro 功能非常强大,本文将详细阐述micro web 命令行的功能 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go-micro环境, golang微服务框架...

非正式解决方案
昨天
8
0
前端——使用base64编码在页面嵌入图片

因为页面中插入一个图片都要写明图片的路径——相对路径或者绝对路径。而除了具体的网站图片的图片地址,如果是在自己电脑文件夹里的图片,当我们的HTML文件在别人电脑上打开的时候图片则由于...

被毒打的程序猿
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部