projects.js 6.76 KB
'use strict';

import Router from 'koa-router';
import moment from 'moment';
import Build from '../../ci/build';
import Deploy from '../../ci/deploy';
import Operation from '../../logger/operation';

import {
    Building,
    Project,
    Server,
    DeployInfo
} from '../../models';

let r = new Router();

const colors = ['primary', 'success', 'info', 'warning', 'danger', 'success-alt', 'info-alt', 'warning-alt', 'danger-alt', 'primary-head', 'success-head', 'danger-head'];
const envs = {
    production: '线上环境',
    preview: '灰度环境',
    test: '测试环境'
};

const p = {
    /**
     * 所有项目首页
     */
    index_page: async(ctx, next) => {
        let projects = await Project.findAll();
        projects.forEach((p, i) => {
            p.color = colors[i % colors.length];
        });
        await ctx.render('action/projects', {
            projects: projects
        });
    },
    /**
     * 单个项目首页
     */
    project_index: async(ctx, next) => {
        let id = ctx.params.id;
        let env = ctx.request.query.env;
        let project = await Project.findById(id);
        let deploy = project.deploy[env];
        deploy.env = env;
        deploy.name = envs[env];


        let promises = deploy.target.map((host) => {
            console.log('read host :' + host);
            return DeployInfo.findOne({
                projectId: project._id,
                host: host,
                env: env
            }).then((info) => {
                return {
                    host: host,
                    hostFm: host.replace(/\./g, '-'),
                    info: info
                };
            });
        });
        let targets = await Promise.all(promises);

        await ctx.render('action/project_index', {
            project: project,
            deploy: deploy,
            targets: targets
        });
    },

    new_page: async(ctx, next) => {
        let serversAll = await Server.findAll();
        let servers = {};
        serversAll.forEach(s => {
            if (servers[s.env]) {
                servers[s.env].push(s);
            } else {
                servers[s.env] = [s];
            }
        });
        await ctx.render('action/project_form', {
            servers: servers,
            project: {
                deploy: {
                    production: {},
                    test: {}
                }
            }
        });

    },
    edit_page: async(ctx, next) => {
        let id = ctx.query.id;
        let project = await Project.findById(id);

        let serversAll = await Server.findAll();
        let servers = {};
        serversAll.forEach(s => {
            if (servers[s.env]) {
                servers[s.env].push(s);
            } else {
                servers[s.env] = [s];
            }
            if (project.deploy[s.env] && project.deploy[s.env].target && project.deploy[s.env].target.indexOf(s.host) >= 0) {
                s.checked = true;
            }
        });

        await ctx.render('action/project_form', {
            project: project,
            servers: servers
        });
    },
    save: async(ctx, next) => {
        let project = ctx.request.body;
        let id = project._id;
        delete project._id;
        if (id) {
            await Project.update({
                _id: id
            }, {
                $set: project
            });
            await Operation.action(ctx.session.user, 'EDIT_PROJECT_INFO', '修改项目信息', {_id: id, name: project.name});
        } else {
            await Project.insert(project);
            await Operation.action(ctx.session.user, 'NEW_PROJECT_INFO', '新增项目信息', {_id: id, name: project.name});
        }
        ctx.redirect('/projects');
        ctx.status = 301;
    },
    buildings_table: async(ctx, next) => {
        let env = ctx.request.query.env;
        let pid = ctx.params.id;
        let buildings = await Building.cfind({
            env: env,
            projectId: pid
        }).sort({
            buildTime: -1
        }).exec();
        buildings.forEach(b => {
            b.updatedAt = moment(b.updatedAt).format('YYYY-MM-DD HH:mm:ss');
        });
        ctx.body = {
            data: buildings
        };
    },
    project_build: async(ctx, next) => {
        let pid = ctx.params.pid;
        let env = ctx.request.body.env;
        let branch = ctx.request.body.branch;
        let p = await Project.findById(pid);
        let build = new Build(p);

        let {
            buildTime,
            distFile
        } = build.build(branch);
        let buildingDoc = await Building.insert({
            buildTime: buildTime,
            project: p.name,
            projectId: pid,
            branch: branch,
            env: env,
            distFile: distFile,
            state: 'waiting',
            createdAt: new Date(),
            updatedAt: new Date()
        });

        let id = buildingDoc[0]._id;

        build.run(id);

        await Operation.action(ctx.session.user, 'NEW_PROJECT_BUILDING', '新增项目构建', {_id: id, project: p.name, branch: branch, env: env});

        ctx.body = {
            code: 200,
            id: id
        };
        await next();
    },
    project_deploy: async(ctx) => {
        let buildingId = ctx.params.building;
        let building = await Building.findById(buildingId);
        if (!building) {
            ctx.body = {
                code: 201,
                msg: '该版本不存在'
            };
        } else if (building.state == 'success') {
            let project = await Project.findByName(building.project);
            let targets = project.deploy[building.env].target;

            targets.forEach(async(host) => {
                let info = {
                    projectId: project._id,
                    host: host,
                    env: building.env,
                    building: building.buildTime,
                    state: 'waiting'
                };
                info._id = await DeployInfo.insertOrUpdate(info);
                let deploy = new Deploy(project, building);
                deploy.deploy(info);
            });

            await Operation.action(ctx.session.user, 'PROJECT_DEPLOY', '项目分发部署', {_id: buildingId, project: project.name, branch: building.branch, env: building.env});

            ctx.body = {
                code: 200,
                building: building
            };
        } else {
            ctx.body = {
                code: 201,
                msg: '该版本未构建成功,暂不能分发'
            };
        }
    }
};

r.get('/', p.index_page);
r.get('/new', p.new_page);
r.get('/edit', p.edit_page);
r.get('/:id', p.project_index);
r.get('/:id/buildings', p.buildings_table);
r.post('/save', p.save);
r.post('/build/:pid', p.project_build);
r.post('/deploy/:building', p.project_deploy);
export default r;