forked from sashasimkin/gihook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
executable file
·170 lines (148 loc) · 4.94 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/env node
/**
* Dependencies.
*/
var express = require('express');
var http = require('http');
var path = require('path');
var app = express();
var exec = require('child_process').exec;
var Logger = require('./lib/Logger');
var TaskManager = require('./lib/TaskManager');
String.prototype.fmt = require('./lib/format');
// Setup express-related settings
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
// Configure arguments
var opts = require("nomnom")
.option('config', {
list: true,
abbr: 'c',
default: ['config'],
help: 'Directories which contains JSON files or paths to JSON-files'
}).option('address', {
position: 0,
help: 'Specify address bind to. E.g. 127.0.0.1:3005 or 0.0.0.0 or only port 3005 address by default 0.0.0.0',
default: '0.0.0.0:3000'
}).option('logs', {
abbr: 'l',
help: 'Set directory for logs, if not set - fallback to logging in console',
default: false
}).option('debug', {
abbr: 'd',
help: 'Enable logging to console',
flag: true,
default: false
}).parse();
// Set logs directory
if(opts.logs) {
Logger.directory = opts.logs;
}
//IP and PORT for web-server
(function() {
// FixMe: I don't like this, but what to do
var address = opts.address ? String(opts.address).split(':') : [];
if(address.length == 1) {
if(!isNaN(parseFloat(address[0])) && isFinite(address[0])) {
address = ['0.0.0.0', parseInt(address[0])];
} else {
address = [address[0], 3000];
}
}
process.env.IP = process.env.IP || address[0];
process.env.PORT = process.env.PORT || address[1];
})();
// development only
if (opts.debug) {
app.use(express.logger('dev'));
app.use(express.errorHandler());
}
// Load configs to persistent for process object
var configs = require("./lib/loadConfigs")(opts.config);
var runTask = function(task) {
var logger = new Logger(task.name);
task.running();
var command = task.commands.shift();
if (!command) {
return task.finished();
}
exec(command, task.options, function(err, stdout, stderr) {
if (stdout) logger.info('[out]["' + command + '"]: ' + stdout);
if (stderr) logger.error('[Error]["' + command + '"]: ' + stderr);
runTask(task);
});
};
//Setup task manager
var queue = new TaskManager();
queue.run(function() {
runTask(this);
}, 1000);
// Main route that responsible for each request
app.post('/:config', function(req, res) {
//Strip request.url, remove first slash
var config_name = req.params.config;
var config = configs[config_name];
var logger = new Logger(config_name);
res.send(".");
if (!config || req.body.zen) {
logger.error('Invalid request for config: ' + config_name);
// Log invalid request
return;
}
var payload = req.body;
//We need object copy!
var task = JSON.parse(JSON.stringify(config));
task.name = config_name;
task.options = {
encoding: "utf-8",
env: process.env,
cwd: task.path
};
if (task.refs) {
var refsType = typeof task.refs;
if (['string', 'object'].indexOf(refsType)) {
if (refsType == 'string') task.refs = [task.refs];
var suitableRef = Object.keys(task.refs).some(function(k) {
return payload.ref.match(task.refs[k]);
});
if (!suitableRef) return logger.info('Ref does not fit. Aborting.');
}
}
// Pre-process commands related to request
if (task.commands.length) {
//Access to payload and task from command definition
task.commands.filter(function(command, i) {
if (command.fmt) {
task.commands[i] = command.fmt({
payload: payload,
task: task
});
return true;
} else {
return logger.info('Unexpected command "{c}". Command must be a string.'.fmt({c: command}));
}
});
// And deal with it for this time. Now let the queue sort it
queue.push(config_name, task);
logger.info('Got valid request on: ' + config_name);
} else {
return logger.info('No commands to execute.');
}
});
app.all('*', function(req, res) {
res.send("There is nothing. Go ahead!");
});
process.on('uncaughtException', function(err) {
if(err.errno === 'EADDRINUSE') {
console.log('Can\'t start server. Address {a} already in use.'.fmt({a: opts.address}));
} else {
console.log(err);
console.log('Please leave traceback on https://github.com/sashasimkin/gihook/issues if you can.');
}
process.exit(1);
});
http.createServer(app).listen(process.env.PORT, process.env.IP, function() {
console.log('GiHook got running on ' + process.env.IP + ':' + process.env.PORT + ' Enjoy!');
});