/
logstat.js
executable file
·123 lines (116 loc) · 3.12 KB
/
logstat.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
const get = require('simple-get');
const path = require('path');
const colors = require('colors');
const fs = require('fs');
const travisUrl = 'https://api.travis-ci.org';
const travisPath = 'radare/radare2';
async function travis(api, root, cb) {
return new Promise((resolve, reject) => {
const url = root
? [travisUrl, 'repos', travisPath, api].join('/')
: [travisUrl, api].join('/');
get.concat(url, (err, res, data) => {
if (err) {
return reject(err);
}
const msg = data.toString();
try {
resolve(JSON.parse(msg));
} catch (err) {
resolve(msg);
}
});
});
}
function parseLogs(log) {
const obj = {
txt: '',
fx: 0,
xx: 0,
br: 0,
issues: []
};
if (log) {
let issue = '';
let issueFound = false;
let last = '';
for (let line of log.split('\n')) {
const plain = line.replace(/\033\[..m/g, '');
if (line.length === 0) {
continue;
}
if (plain.indexOf('FX]') !== -1) {
obj.fx++;
}
if (plain.indexOf('XX]') !== -1) {
obj.xx++;
if (line.indexOf('XX]' !== -1)) {
const w = last.split(' ').slice(5).join(' ');
// console.log(' ' + line + colors.yellow(w));
obj.issues.push(line + colors.yellow(w));
} else {
const w = line.split(' ');
// console.log(' ' + w[0]);
obj.issues.push(w[0]);
}
} else if (plain.indexOf('BR]') !== -1) {
obj.br++;
}
last = line;
}
}
return obj;
}
async function processJob(job) {
console.log(colors.green(`[BUILD] ${job.id} (${job.state}) ${job.message}`));
console.log(colors.yellow(`[-----] ${job.id} ${job.started_at} ${job.commit}`));
const buildInfo = await travis('builds/' + job.id, false);
for (let job of buildInfo.matrix) {
const logFile = 'log-' + job.id + '.txt';
const logExists = fs.existsSync(logFile);
const travisLog = logExists
? { log: fs.readFileSync(logFile).toString() }
: await travis(`jobs/${job.id}`, false);
const log = (travisLog && travisLog.log)? travisLog.log.replace(/\r/g, '\n'): '';
const result = parseLogs(log);
if (!logExists) {
fs.writeFileSync(logFile, log);
}
const status = job.finished_at === null? '(running)': '(finished)';
console.log(' [JOB]', job.id, 'XX:', result.xx, 'BR:', result.br, 'FX:', result.fx, status);
for (let issue of result.issues) {
console.log(' ', issue);
}
}
}
async function main(limit) {
try {
const builds = await travis('builds', true);
let lastBuild;
for (let build of builds) {
await processJob(build);
if (--limit === 0) {
break;
}
}
} catch (err) {
console.error('Oops' , err);
}
}
function run(p) {
p.then(process.exit).catch(console.error);
}
if (process.argv.length > 2) {
const arg = process.argv[2];
if (arg === '-h') {
console.log('Usage: logstat [file|+limit]');
} else {
if (+arg) {
run(main(+arg));
} else {
console.log(parseLogs(fs.readFileSync(process.argv[2]).toString()));
}
}
} else {
run(main(-1));
}