checkcode.js 5.77 KB
/**
 * 采集数据
 * 
 * @class Check
 * @author shenzm<zhimin.shen@yoho.cn>
 * @date 2016/10/12
 */
'use strict';

const fs = require('fs');
const sh = require('shelljs');
const moment = require('moment');
const path = require('path');
const config = require('../../config/config');
const mail = require('../models/mail');
const ws = require('../../lib/ws');
const {
    Checklist,
    Checklogs
} = require('../models');

class Check {
    constructor(projectname, gitlab, branch) {
        this.projectname = projectname;
        this.gitlab = gitlab;
        this.branch = branch;
        this.buildTime = new Date().getTime().toString();
        this.mailOptions = {
            from: 'automan@yoho.cn',
            to: 'webtech@yoho.cn',
            subject: `${projectname}:${branch} 代码检查一览 ` + moment().format('YYYY-MM-DD HH:mm:ss')
        };
        this.id = `${projectname}_${branch}_${this.buildTime}`;

        Checklist.insertLog(this.id, projectname, branch, this.buildTime, "starting");
    }

    get buildPath() {
        return path.join(config.buildDir, this.projectname, this.buildTime, this.projectname);
    }

    get rootPath() {
        return path.join(config.buildDir, this.projectname, this.buildTime);
    }
    /**
     * do some folder check
     */
    _prebuild() {
        if (!sh.test('-e', config.buildDir)) {
            sh.mkdir('-p', config.buildDir);
        }

        if (!sh.test('-e', this.rootPath)) {
            sh.mkdir('-p', this.rootPath);
        }
        this.logFile = path.join(this.rootPath, 'check.log');
        sh.touch(this.logFile);
    }

    _cloneCode(branch) {
        var self = this;
        this._log('cloning_code');
        this._state('cloning_code');
        let clone_script = `git clone --depth 1 -b ${branch} ${this.gitlab} `;
        this._log(`>>>>>>>>> ${clone_script} >>>>>>>>>>>`);

        return new Promise((reslove, reject) => {
            sh.cd(self.rootPath);

            let child = sh.exec(clone_script, {
                silent: self.silent,
                async: true
            });

            child.stdout.pipe(fs.createWriteStream(self.logFile, {
                flags: 'a'
            }));

            child.stderr.pipe(fs.createWriteStream(self.logFile, {
                flags: 'a'
            }));

            child.on('close', (code) => {
                if (code == 0) {
                    self._log('clone code success');
                    reslove();
                } else {
                    reject(new Error(`clone code fail`));
                }
            });
        });
    }

    _installdep() {
        var self = this;
        this._log('>>>>>>>> install dependencies >>>>>>>');
        this._state('install dependencies');
        return new Promise((resolve, reject) => {
            sh.cd(self.buildPath);

            var child = sh.exec('npm i --production=false', {
                silent: self.silent,
                async: true
            });

            child.stdout.pipe(fs.createWriteStream(self.logFile, {
                flags: 'a'
            }));
            child.stderr.pipe(fs.createWriteStream(self.logFile, {
                flags: 'a'
            }));

            child.on('close', (code) => {
                if (code == 0) {
                    self._log('install dependencies success');
                } else {
                    self._log('install dependencies with error,rebuild please');
                }
                resolve();
            });
        })
    }

    _checkScript() {
        var self = this;
        this._log(`>>>>>>>>> check code >>>>>>>>>>>`);
        this._state('check code');
        return new Promise((reslove, reject) => {
            sh.cd(self.buildPath);

            var child = sh.exec('npm run lint-all -s', {
                silent: self.silent,
                async: true
            });

            var dataText = '';
            child.stdout.on('data', (chunk) => {
                dataText += chunk.toString();
            });

            child.stdout.on("end", function () {
                self.mailOptions.html = `<pre style='font-family: Menlo,Monaco,Consolas,"Courier New",monospace;'>${dataText}</pre>`;
                mail.sendMail(self.mailOptions, function(err, info){
                    if(err){
                        self._log(error);
                    } else {
                        self._log('mail sent: ' + info.response);
                    }
                });
                self._state('success');
                Checklogs.insertLog(self.id, dataText);
            });

            child.stderr.pipe(fs.createWriteStream(self.logFile, {
                flags: 'a'
            }));

            child.on('close', (code) => {
                if (code == 0) {
                    reslove();
                } else {
                    reject(new Error(`${self.projectname} build code fail`));
                }
            });
        });
    }

    async check() {
        let self = this;

        this._prebuild();

        this.startTime = (new Date()).getTime();
        return this._cloneCode(this.branch).then(() => {
            return self._installdep();
        }).then(() => {
            return self._checkScript();
        }).then(() => {
            let diff = (new Date()).getTime() - self.startTime;
            let costTime = moment.duration(diff, 'ms').humanize();
            self._log(`\n\n========== check success. cost: ${costTime} =======================`);
        }).catch((e) => {
            console.error(e);
            self._log('fail');
            self._state('fail');
        });
    }

    _state(state) {
        ws.broadcast(`/check/state`, {
            id: this.id,
            state: state
        });
        Checklist.updateState(this.id, state);
    }

    _log(msg) {
        console.log(msg);
    }
}

module.exports = Check;