Showing
6 changed files
with
67 additions
and
38 deletions
@@ -9,6 +9,7 @@ import sh from 'shelljs'; | @@ -9,6 +9,7 @@ import sh from 'shelljs'; | ||
9 | import moment from 'moment'; | 9 | import moment from 'moment'; |
10 | import path from 'path'; | 10 | import path from 'path'; |
11 | import fsp from 'fs-promise'; | 11 | import fsp from 'fs-promise'; |
12 | +import fs from 'fs'; | ||
12 | import config from '../../config/config'; | 13 | import config from '../../config/config'; |
13 | import Tar from './tar'; | 14 | import Tar from './tar'; |
14 | import ws from '../../lib/ws'; | 15 | import ws from '../../lib/ws'; |
@@ -76,6 +77,8 @@ class Build { | @@ -76,6 +77,8 @@ class Build { | ||
76 | if (!sh.test('-e', this.rootPath)) { | 77 | if (!sh.test('-e', this.rootPath)) { |
77 | sh.mkdir('-p', this.rootPath); | 78 | sh.mkdir('-p', this.rootPath); |
78 | } | 79 | } |
80 | + this.logFile = path.join(this.rootPath, 'building.log'); | ||
81 | + sh.touch(this.logFile); | ||
79 | } | 82 | } |
80 | 83 | ||
81 | _cloneCode(branch) { | 84 | _cloneCode(branch) { |
@@ -91,13 +94,17 @@ class Build { | @@ -91,13 +94,17 @@ class Build { | ||
91 | async: true | 94 | async: true |
92 | }); | 95 | }); |
93 | 96 | ||
94 | - child.stdout.on('data', (data) => { | ||
95 | - self._log(data); | ||
96 | - }); | 97 | + child.stdout.pipe(fs.createWriteStream(self.logFile, { |
98 | + flags: 'a' | ||
99 | + })); | ||
97 | 100 | ||
98 | - child.stderr.on('data', (data) => { | ||
99 | - self._log(data); | ||
100 | - }); | 101 | + child.stderr.pipe(fs.createWriteStream(self.logFile, { |
102 | + flags: 'a' | ||
103 | + })); | ||
104 | + | ||
105 | + // child.stderr.on('data', (data) => { | ||
106 | + // self._log(data); | ||
107 | + // }); | ||
101 | 108 | ||
102 | child.on('close', (code) => { | 109 | child.on('close', (code) => { |
103 | if (code == 0) { | 110 | if (code == 0) { |
@@ -121,13 +128,19 @@ class Build { | @@ -121,13 +128,19 @@ class Build { | ||
121 | async: true | 128 | async: true |
122 | }); | 129 | }); |
123 | 130 | ||
124 | - child.stdout.on('data', (data) => { | ||
125 | - self._log(data); | ||
126 | - }); | 131 | + // child.stdout.on('data', (data) => { |
132 | + // self._log(data); | ||
133 | + // }); | ||
127 | 134 | ||
128 | - child.stderr.on('data', (data) => { | ||
129 | - self._log(data); | ||
130 | - }); | 135 | + // child.stderr.on('data', (data) => { |
136 | + // self._log(data); | ||
137 | + // }); | ||
138 | + child.stdout.pipe(fs.createWriteStream(self.logFile, { | ||
139 | + flags: 'a' | ||
140 | + })); | ||
141 | + child.stderr.pipe(fs.createWriteStream(self.logFile, { | ||
142 | + flags: 'a' | ||
143 | + })); | ||
131 | 144 | ||
132 | child.on('close', (code) => { | 145 | child.on('close', (code) => { |
133 | if (code == 0) { | 146 | if (code == 0) { |
@@ -157,7 +170,8 @@ class Build { | @@ -157,7 +170,8 @@ class Build { | ||
157 | } | 170 | } |
158 | 171 | ||
159 | _log(line) { | 172 | _log(line) { |
160 | - ws.broadcast(`/building/${this.project._id}/log`, line); | 173 | + // ws.broadcast(`/building/${this.project._id}/log`, line); |
174 | + fsp.appendFile(this.logFile, line + '\n'); | ||
161 | } | 175 | } |
162 | } | 176 | } |
163 | 177 |
@@ -134,7 +134,7 @@ class Deploy { | @@ -134,7 +134,7 @@ class Deploy { | ||
134 | self._state('unziped'); | 134 | self._state('unziped'); |
135 | reslove(); | 135 | reslove(); |
136 | } else { | 136 | } else { |
137 | - reject('unzip fail'); | 137 | + reject('unzip fail: ' + script); |
138 | } | 138 | } |
139 | }); | 139 | }); |
140 | } | 140 | } |
@@ -143,7 +143,7 @@ class Deploy { | @@ -143,7 +143,7 @@ class Deploy { | ||
143 | } | 143 | } |
144 | 144 | ||
145 | _startup(conn) { | 145 | _startup(conn) { |
146 | - let self =this; | 146 | + let self = this; |
147 | let startup = this.project.scripts.start; | 147 | let startup = this.project.scripts.start; |
148 | return new Promise((reslove, reject) => { | 148 | return new Promise((reslove, reject) => { |
149 | self._state('starting'); | 149 | self._state('starting'); |
@@ -172,7 +172,7 @@ class Deploy { | @@ -172,7 +172,7 @@ class Deploy { | ||
172 | }); | 172 | }); |
173 | } | 173 | } |
174 | 174 | ||
175 | - async _state(state){ | 175 | + async _state(state) { |
176 | ws.broadcast(`/deploy/${this.project._id}`, { | 176 | ws.broadcast(`/deploy/${this.project._id}`, { |
177 | host: this.info.host, | 177 | host: this.info.host, |
178 | state: state | 178 | state: state |
@@ -204,7 +204,7 @@ class Deploy { | @@ -204,7 +204,7 @@ class Deploy { | ||
204 | } | 204 | } |
205 | 205 | ||
206 | get localFile() { | 206 | get localFile() { |
207 | - return path.join(config.buildDir, this.building.distFile); | 207 | + return path.join(config.buildDir, this.building.distFile); |
208 | } | 208 | } |
209 | } | 209 | } |
210 | 210 |
@@ -45,7 +45,7 @@ const p = { | @@ -45,7 +45,7 @@ const p = { | ||
45 | deploy.name = envs[env]; | 45 | deploy.name = envs[env]; |
46 | let targets = []; | 46 | let targets = []; |
47 | 47 | ||
48 | - deploy.target.forEach(async (host) => { | 48 | + deploy.target.forEach(async(host) => { |
49 | let info = await DeployInfo.findOne({ | 49 | let info = await DeployInfo.findOne({ |
50 | projectId: project._id, | 50 | projectId: project._id, |
51 | host: host, | 51 | host: host, |
@@ -53,6 +53,7 @@ const p = { | @@ -53,6 +53,7 @@ const p = { | ||
53 | }); | 53 | }); |
54 | targets.push({ | 54 | targets.push({ |
55 | host: host, | 55 | host: host, |
56 | + hostFm: host.replace(/\./g, '-'), | ||
56 | info: info | 57 | info: info |
57 | }) | 58 | }) |
58 | }); | 59 | }); |
@@ -144,7 +145,10 @@ const p = { | @@ -144,7 +145,10 @@ const p = { | ||
144 | let p = await Project.findById(pid); | 145 | let p = await Project.findById(pid); |
145 | let build = new Build(p); | 146 | let build = new Build(p); |
146 | 147 | ||
147 | - let { buildTime, distFile } = build.build(env); | 148 | + let { |
149 | + buildTime, | ||
150 | + distFile | ||
151 | + } = build.build(env); | ||
148 | let buildingDoc = await Building.insert({ | 152 | let buildingDoc = await Building.insert({ |
149 | buildTime: buildTime, | 153 | buildTime: buildTime, |
150 | project: p.name, | 154 | project: p.name, |
@@ -177,7 +181,7 @@ const p = { | @@ -177,7 +181,7 @@ const p = { | ||
177 | let project = await Project.findByName(building.project); | 181 | let project = await Project.findByName(building.project); |
178 | let targets = project.deploy[building.env].target; | 182 | let targets = project.deploy[building.env].target; |
179 | 183 | ||
180 | - targets.forEach(async (host) => { | 184 | + targets.forEach(async(host) => { |
181 | let info = { | 185 | let info = { |
182 | projectId: project._id, | 186 | projectId: project._id, |
183 | host: host, | 187 | host: host, |
@@ -19,7 +19,7 @@ | @@ -19,7 +19,7 @@ | ||
19 | <div class="panel panel-default" data-env='{{deploy.env}}'> | 19 | <div class="panel panel-default" data-env='{{deploy.env}}'> |
20 | <div class="panel-heading"> | 20 | <div class="panel-heading"> |
21 | <div class="pull-right"> | 21 | <div class="pull-right"> |
22 | - <a class="btn btn-info btn-rounded mr5 log-btn"><i class="fa fa-eye"></i> 查看实时日志</a> | 22 | + <a class="btn btn-info btn-rounded mr5 log-btn"><i class="fa fa-eye"></i> 查看构建日志</a> |
23 | <a class="btn btn-warning btn-rounded mr5 rollback-btn"><i class="fa fa-reply"></i> 回滚</a> | 23 | <a class="btn btn-warning btn-rounded mr5 rollback-btn"><i class="fa fa-reply"></i> 回滚</a> |
24 | <a class="btn btn-success btn-rounded mr20 build-btn"><i class="glyphicon glyphicon-plus"></i> 新增构建</a> | 24 | <a class="btn btn-success btn-rounded mr20 build-btn"><i class="glyphicon glyphicon-plus"></i> 新增构建</a> |
25 | <a href="" class="tooltips panel-minimize"><i class="fa fa-minus"></i></a> | 25 | <a href="" class="tooltips panel-minimize"><i class="fa fa-minus"></i></a> |
@@ -49,7 +49,7 @@ | @@ -49,7 +49,7 @@ | ||
49 | <div class="panel-body"> | 49 | <div class="panel-body"> |
50 | <div class="row"> | 50 | <div class="row"> |
51 | {{#each targets}} | 51 | {{#each targets}} |
52 | - <div class="col-md-4" id="d-{{host}}"> | 52 | + <div class="col-md-4" id="d-{{hostFm}}"> |
53 | <div class="panel panel-info noborder"> | 53 | <div class="panel panel-info noborder"> |
54 | <div class="panel-heading noborder"> | 54 | <div class="panel-heading noborder"> |
55 | <div class="panel-btns"> | 55 | <div class="panel-btns"> |
@@ -65,6 +65,9 @@ | @@ -65,6 +65,9 @@ | ||
65 | <h5 class="md-title mt10">当前状态</h5> | 65 | <h5 class="md-title mt10">当前状态</h5> |
66 | <span class="label label-success deploy-log-btn" data-host="{{host}}"><i class="fa fa-spinner fa-spin fa-fw margin-bottom"></i> <b>{{#if info}}{{info.state}}{{^}}未知部署{{/if}}</b></span> | 66 | <span class="label label-success deploy-log-btn" data-host="{{host}}"><i class="fa fa-spinner fa-spin fa-fw margin-bottom"></i> <b>{{#if info}}{{info.state}}{{^}}未知部署{{/if}}</b></span> |
67 | </div> | 67 | </div> |
68 | + <div class="col-xs-6"> | ||
69 | + | ||
70 | + </div> | ||
68 | </div> | 71 | </div> |
69 | </div><!-- panel-body --> | 72 | </div><!-- panel-body --> |
70 | </div><!-- panel --> | 73 | </div><!-- panel --> |
@@ -120,9 +123,11 @@ | @@ -120,9 +123,11 @@ | ||
120 | return '<button '+(disabled? 'disabled' : '')+' class="btn btn-success btn-xs deploy-btn" data-id="'+data+'" data-build='+row.buildTime+'>分发</button>'; | 123 | return '<button '+(disabled? 'disabled' : '')+' class="btn btn-success btn-xs deploy-btn" data-id="'+data+'" data-build='+row.buildTime+'>分发</button>'; |
121 | }, | 124 | }, |
122 | targets: 3 | 125 | targets: 3 |
123 | - }], | ||
124 | - initComplete: function(){ | ||
125 | - $('.deploy-btn').click(function(){ | 126 | + }] |
127 | + }); | ||
128 | + | ||
129 | + $(this).on( 'draw.dt', function () { | ||
130 | + $('.deploy-btn').click(function(){ | ||
126 | var id = $(this).data('id'); | 131 | var id = $(this).data('id'); |
127 | var build = $(this).data('build'); | 132 | var build = $(this).data('build'); |
128 | layer.confirm('确定发布版本<code>' + build + '</code>吗?', { | 133 | layer.confirm('确定发布版本<code>' + build + '</code>吗?', { |
@@ -131,8 +136,7 @@ | @@ -131,8 +136,7 @@ | ||
131 | doDeploy(id); | 136 | doDeploy(id); |
132 | }); | 137 | }); |
133 | }); | 138 | }); |
134 | - } | ||
135 | - }); | 139 | + } ); |
136 | }); | 140 | }); |
137 | 141 | ||
138 | function doDeploy(build){ | 142 | function doDeploy(build){ |
@@ -211,21 +215,22 @@ | @@ -211,21 +215,22 @@ | ||
211 | } | 215 | } |
212 | }); | 216 | }); |
213 | 217 | ||
214 | - ws.on('/building/{{project._id}}/log', function(data){ | ||
215 | - if(tag == '') { | ||
216 | - cm.replaceRange("> " + data + "\n", {line: Infinity}); | ||
217 | - } | ||
218 | - }); | 218 | + // ws.on('/building/{{project._id}}/log', function(data){ |
219 | + // if(tag == '') { | ||
220 | + // cm.replaceRange("> " + data + "\n", {line: Infinity}); | ||
221 | + // } | ||
222 | + // }); | ||
219 | 223 | ||
220 | ws.on('/deploy/{{project._id}}', function(data){ | 224 | ws.on('/deploy/{{project._id}}', function(data){ |
221 | - $('#d-' + data.host).find('b').text(data.state); | 225 | + console.log(data); |
226 | + $('#d-' + data.host.replace(/\./g, '-')).find('b').text(data.state); | ||
222 | }); | 227 | }); |
223 | 228 | ||
224 | - ws.on('/deploy/{{project._id}}/log', function(data){ | ||
225 | - if(tag == data.host){ | ||
226 | - cm.replaceRange("> " +data.msg+ "\n", {line: Infinity}); | ||
227 | - } | ||
228 | - }); | 229 | + // ws.on('/deploy/{{project._id}}/log', function(data){ |
230 | + // if(tag == data.host){ | ||
231 | + // cm.replaceRange("> " +data.msg+ "\n", {line: Infinity}); | ||
232 | + // } | ||
233 | + // }); | ||
229 | }); | 234 | }); |
230 | ws.on('error', function(){ | 235 | ws.on('error', function(){ |
231 | console.log('connect fail'); | 236 | console.log('connect fail'); |
1 | 'use strict'; | 1 | 'use strict'; |
2 | 2 | ||
3 | +import _ from 'lodash'; | ||
4 | + | ||
3 | const helpers = { | 5 | const helpers = { |
4 | equals: (a, b, opts) => { | 6 | equals: (a, b, opts) => { |
5 | if (a === b) { | 7 | if (a === b) { |
@@ -7,6 +9,9 @@ const helpers = { | @@ -7,6 +9,9 @@ const helpers = { | ||
7 | } else { | 9 | } else { |
8 | return opts.inverse(this); | 10 | return opts.inverse(this); |
9 | } | 11 | } |
12 | + }, | ||
13 | + replace: (str, pattern, replacement) => { | ||
14 | + return _.replace(str, new RegExp(pattern), replacement); | ||
10 | } | 15 | } |
11 | }; | 16 | }; |
12 | 17 |
@@ -43,6 +43,7 @@ | @@ -43,6 +43,7 @@ | ||
43 | "koa-mount": "^2.0.0", | 43 | "koa-mount": "^2.0.0", |
44 | "koa-router": "^7.0.1", | 44 | "koa-router": "^7.0.1", |
45 | "koa-static": "^3.0.0", | 45 | "koa-static": "^3.0.0", |
46 | + "lodash": "^4.13.1", | ||
46 | "moment": "^2.13.0", | 47 | "moment": "^2.13.0", |
47 | "nedb": "^1.8.0", | 48 | "nedb": "^1.8.0", |
48 | "nedb-promise": "^2.0.0", | 49 | "nedb-promise": "^2.0.0", |
-
Please register or login to post a comment