Authored by 姜枫

add php support

... ... @@ -86,7 +86,7 @@ class Build {
_cloneCode(branch) {
var self = this;
this._state('cloning_code');
let clone_script = `git clone -b ${branch} ${this.project.gitlab}`;
let clone_script = `git clone --depth 1 -b ${branch} ${this.project.gitlab}`;
this._log(`>>>>>>>>> ${clone_script} >>>>>>>>>>>`);
return new Promise((reslove, reject) => {
... ... @@ -157,7 +157,7 @@ class Build {
});
} else {
this._log(`>>>>>>>>> no build script >>>>>>>>>>>`);
return Promise.reslove();
return Promise.resolve();
}
}
... ... @@ -199,6 +199,7 @@ class Build {
_log(line) {
// ws.broadcast(`/building/${this.project._id}/log`, line);
console.log(line);
fsp.appendFile(this.logFile, line + '\n');
}
}
... ...
... ... @@ -9,7 +9,7 @@
import ssh from 'ssh2';
import path from 'path';
import fs from 'fs';
import config from '../../config/config';
import ws from '../../lib/ws';
import {
... ... @@ -35,19 +35,14 @@ class Deploy {
}
async deploy(cb) {
let server = await Server.findByHost(this.host);
this.id = await DeployInfo.insertOrUpdate(this.info);
this.server = server;
this.callback = cb;
setImmediate(function(){
this.sshDeploy({
host: server.host,
username: server.username,
password: server.password,
port: server.port
})
}.bind(this));
// setImmediate(async function(){
// this.sshDeploy(this._getSshInfo());
// }.bind(this));
this.server = await this._getSshInfo();
this.sshDeploy(this.server);
return this.id;
}
... ... @@ -58,11 +53,34 @@ class Deploy {
this.state = 'closed';
}
async _getSshInfo() {
let server = await Server.findByHost(this.host);
if (this.project.type === 'php') {
return {
host: server.host,
username: 'om',
privateKey: fs.readFileSync(path.join(__dirname, './id_rsa_ssh')),
port: server.port,
deployDir: server.deployDir
};
} else {
return {
host: server.host,
username: server.username,
password: server.password,
port: server.port,
deployDir: server.deployDir
};
}
}
sshDeploy(serverInfo) {
console.log('ssh connecting', JSON.stringify(serverInfo));
let conn = new ssh.Client();
let self = this;
this._state('connecting');
this.conn = conn;
conn.on('ready', async() => {
console.log(`connected ${serverInfo.host}`);
... ... @@ -79,7 +97,7 @@ class Deploy {
} catch (e) {
self._state('fail');
self._log(e);
self.callback(err, null);
self.callback(e, null);
} finally {
conn.end();
}
... ... @@ -167,35 +185,41 @@ class Deploy {
_startup(conn) {
let self = this;
let startup = this.project.scripts.start;
return new Promise((resolve, reject) => {
self._state('starting');
self._log(`>>>> ${startup}`);
conn.exec(`cd ${self.remoteRunningDir} && ${startup}`, (err, stream) => {
if (err) {
reject(err);
} else {
stream.stdout.on('data', (data) => {
self._log(data.toString());
});
stream.stderr.on('data', (data) => {
self._log(data.toString());
});
stream.on('exit', (code) => {
if (code === 0) {
self._state('running');
resolve();
} else {
reject('startup fail');
}
});
}
if (startup) {
return new Promise((resolve, reject) => {
self._state('starting');
self._log(`>>>> ${startup}`);
conn.exec(`cd ${self.remoteRunningDir} && ${startup}`, (err, stream) => {
if (err) {
reject(err);
} else {
stream.stdout.on('data', (data) => {
self._log(data.toString());
});
stream.stderr.on('data', (data) => {
self._log(data.toString());
});
stream.on('exit', (code) => {
if (code === 0) {
self._state('running');
resolve();
} else {
reject('startup fail');
}
});
}
});
});
});
} else {
return Promise.resolve();
}
}
async _state(state) {
ws.broadcast(`/deploy/${this.project._id}`, {
host: this.info.host,
host: this.host,
state: state
});
await DeployInfo.updateState(this.id, state);
... ... @@ -203,7 +227,7 @@ class Deploy {
_log(msg) {
ws.broadcast(`/deploy/${this.project._id}/log`, {
host: this.info.host,
host: this.host,
msg: msg
});
}
... ...
'use strict'
import Deploy from './deploy';
import {
DeployInfo,
Server
} from '../models';
class DeployPhp extends Deploy {
constructor(project, building, host) {
super(project, building, host);
console.log('===============' + this.host);
}
async _getSshInfo() {
let server = await Server.findByHost(this.host);
this.server = server;
console.info(this.host, server);
return {
host: server.host,
username: 'vagrant',
privateKey: server.privateKey,
port: server.port
};
}
}
export default DeployPhp;
... ...
... ... @@ -10,6 +10,7 @@ class DeployPool {
}
deploy(de) {
de.error = 0;
this.pool.push(de);
this.run();
}
... ... @@ -21,11 +22,17 @@ class DeployPool {
if (de) {
let id = await de.deploy(function(err) {
if (err && this.running.has(de.id)) {
console.log(err);
this.pool.push(de);
console.log(`deploy fail ${de.id} : ` + err);
de.error = (de.error + 1) || 1;
if (de.error < 3) {
this.pool.push(de);
}
}
this.running.delete(de.id);
this.run();
setTimeout(function(){
this.run();
}.bind(this), 1000);
}.bind(this));
this.running.set(id, de);
... ...
-----BEGIN RSA PRIVATE KEY-----
MIIEoAIBAAKCAQEApCym5Tg6OU56OpCQS4Cgj0iDVc/Stc3EpzZ6oJjGLQ6qadat
QfJZJmdx8QIxgkG20WZBfiz+4uMYtrWFGW0XaYMeYncGbSPC3Pdb5k0PVtAdXoCB
Zazb+iB86Am4QpgtGhiv+5Y1Wge1BmDBdTscob2bAotk0+IEdxwCcvf41b2IlS03
LtOsUnzz+jNhfPqRgFXfQO+sHnnOsH3V0BEOCpKcNvBlGgRNGcrMsiSNEFBFKFBp
NM6TTYBivuhwdndSkbIVWyjO8JHOpovetqCeA/ijro4hrS92y3twyaglGvt0yTLQ
/nBsJL98853ByqufOWzwVv9CinW5pw83oPPc9wIBIwKCAQBr4tQS+RBRi1ei1AcN
C2IyRZgicqBo160dbPF/elZYH5SOsaUOFEk2fn4TZ9dkOc/osOk1qIo9U2gDCZH6
xAgSIva1u+5HuGocLYWItkvol2PBwikljtmy/2gGMkXinoQJ1bV5cVZCehffnqsD
5QQvxb2ilh2vzwo/pLEm+rl2gs/Q1STQfGpyrVWchS39ZlR69XHvypXsu/Y3g5Zk
QMoI3T52+xkKDdwQYA09Wkzl8yLpdi6iRkc12kvsA/8jrh5gxy4nOzq13Q88t3ge
jbqHf40dOv4GJJ5TtJ33w/6fgH0GF1l8KKcbJa+YlR0NlvO0tA3fpRO5VkogTTy7
RUPjAoGBANQXtHi8oETfFuaWHTxeNPo5+pmc2y6c1McU/BupgT8N8bMt7vbNKSbz
gxczz8BEIPzkdH1bn5InvjlqSibbIY4v2Bu03cbrc74Y9UOIrZNcnS1QZ2LLdxFH
mNXv55wZxvzocj1AN7Y2eJbm+zElSV117y9441WV2T6bSSQZH7pjAoGBAMYpbAv9
SY3QBT0zHvVlguoyM66FF9wkhwA75gHQyQrY4O4nbRCLeCUuwKx6AwndkMU5ooN+
Efj1MzA7YI2y88KtMHCiPtARwooPzVOxiqwFr5+g+X8bJ6EaxJ9VlkhRRGu2F3rf
5JY/ZpgOLvUhZklXduNoY4EHGSui9391+21dAoGAGD05Ml6zOxIugMCy4lPozCPi
IC8u/gNLhHdtRP1t21IM/ojoHDS0PvdCLomUFfkoV2qQ+GI+H1T/zAwlu0w+WWSN
ugYKt6XhV43S4yWQLhk2iNX9L9y9JovW8+DnRQpCoI+YBwAGXfeYwMnw0mqpTIKB
vEhUfs9MByewlmlFdGMCgYAQ/Dx2DmVj7UJHEwKnUdgFcgRuC2hx9ICZnrvxhuyp
KIhO7W+/lu0KgFmoYjrGVNHlBPCsL2CgT4gLcs3DALXO26UQ9/bBYJulbxGZdZ4s
AHzEiiQDlJz/Li4cSSojdK4X3GhpnimJOKJkzgQGYfLTFiAiHuP1Hd2WBqd/9Ct+
ZwKBgFLN0st1/kwm6y2hFTFblf7pKY0rIEFyw/RN4CEtvSwyyPgsVjqFaWmTZZsH
d3KhGUglAwIDO3W5wz71zujOtJgpmcrTQEBYRYOsN+S9pP6l8DyDGzKhJNuqBUx3
uZfu7LoI2plIcWEyWJZ4gylgKndATo21WdyiNlbLxLQI2ZXm
-----END RSA PRIVATE KEY-----
\ No newline at end of file
... ...
... ... @@ -5,6 +5,7 @@ import moment from 'moment';
import Rp from 'request-promise';
import Build from '../../ci/build';
import Deploy from '../../ci/deploy';
import DeployPhp from '../../ci/deploy_php';
import Restart from '../../ci/restart';
import DeleteRestart from '../../ci/delete_restart';
import Operation from '../../logger/operation';
... ... @@ -247,6 +248,12 @@ const p = {
if (!doc || doc.state !== 'running' || doc.building !== building.buildTime) {
let deploy = new Deploy(project, building, host);
// if (project.type === 'php') {
// deploy = new DeployPhp(project, building, host);
// } else {
// deploy = new Deploy(project, building, host);
// }
DeployPool.deploy(deploy);
}
});
... ...
... ... @@ -42,6 +42,7 @@ const servers = {
port,
env,
cloud,
privateKey,
deployDir
} = ctx.request.body;
let server = {
... ... @@ -51,6 +52,7 @@ const servers = {
port: port,
env: env,
cloud: cloud,
privateKey: privateKey,
deployDir: deployDir
};
if (_id) {
... ...
... ... @@ -38,7 +38,7 @@
</div>
<!-- form-group -->
</div>
<div class="col-sm-6">
<div class="col-sm-3">
<div class="form-group">
<label class="control-label">Name(不能修改,须和gitlab中的名称一致)</label>
<input type="text" name="name" value="{{project.name}}" class="form-control"
... ... @@ -47,7 +47,7 @@
<!-- form-group -->
</div>
<!-- col-sm-6 -->
<div class="col-sm-6">
<div class="col-sm-3">
<div class="form-group">
<label class="control-label">Name</label>
<input type="text" name="subname" value="{{project.subname}}" class="form-control"
... ... @@ -57,6 +57,18 @@
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="control-label">项目类型</label>
<div class="radio">
<label style="width: 30%"><input type="radio" {{#equals project.type 'node'}}checked=""{{/equals}} value="node"
name="type"> NODE</label>
<label style="width: 30%"><input type="radio" {{#equals project.type 'php'}}checked=""{{/equals}} value="php"
name="type"> PHP</label>
</div>
</div>
<!-- form-group -->
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="control-label">Repository Url</label>
<input type="text" name="gitlab" value="{{project.gitlab}}" class="form-control"
placeholder="Gitlab 地址">
... ... @@ -65,6 +77,7 @@
</div>
<!-- col-sm-6 -->
</div>
<hr />
<!-- row -->
<div class="row">
<div class="col-sm-12">
... ...
... ... @@ -118,7 +118,14 @@
<input type="text" name="deployDir" class="form-control" placeholder="部署目录" value="{{deployDir}}">
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="control-label">密钥</label>
<textarea name="privateKey" placeholder="私钥" class="form-control" style="height: 100px">{{privateKey}}</textarea>
</div>
</div>
</div>
<!-- row -->
</div>
<!-- panel-body -->
... ...