Skip to content

Commit 1a5fb33

Browse files
committed
Added config file
1 parent fc9fbf0 commit 1a5fb33

File tree

4 files changed

+45
-30
lines changed

4 files changed

+45
-30
lines changed

config.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"timeout": 480000,
3+
"program": "matlab"
4+
}

coverage.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var timestamp;
2828
var token = process.env.COVERALLS_TOKEN;
2929

3030
/**
31-
* Formates list of classes from XML file and return object formatted for the Coveralls API.
31+
* Formats list of classes from XML file and return object formatted for the Coveralls API.
3232
* @see {@link https://docs.coveralls.io/api-reference|Coveralls API docs}
3333
* @param {Array} classList - An array of class objects from the loaded XML file.
3434
* @param {String} path - The root path of the code repository.
@@ -41,7 +41,7 @@ var token = process.env.COVERALLS_TOKEN;
4141
const formatCoverage = function(classList, path, sha) {
4242
var job = {};
4343
var sourceFiles = [];
44-
typeof path != "undefined" ? 'C:\\Users\\User\\' : path; // default FIXME
44+
path = typeof path != "undefined" ? process.env.HOMEPATH : path; // default to home dir
4545
// For each class, create file object containing array of lines covered and add to sourceFile array
4646
classList.forEach( async c => {
4747
let file = {}; // Initialize file object
@@ -59,7 +59,7 @@ const formatCoverage = function(classList, path, sha) {
5959
});
6060

6161
job.repo_token = token; // env secret token?
62-
job.service_name = 'continuous-integration/ZTEST';
62+
job.service_name = `continuous-integration/${process.env.USERDOMAIN}`;
6363
// The associated pull request ID of the build. Used for updating the status and/or commenting.
6464
job.service_pull_request = '';
6565
job.source_files = sourceFiles;

index.js

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
* @requires module:express
99
* @requires module:localtunnel
1010
* @requires module:github-webhook-handler
11+
* @todo save auxiliary configuration into a separate config file
12+
* @todo add abort option for when new commits added
1113
*/
14+
import * as path from 'path';
15+
1216
const fs = require('fs');
1317
const express = require('express')
1418
const srv = express();
@@ -21,6 +25,10 @@ const localtunnel = require('localtunnel');
2125

2226
const id = process.env.GITHUB_APP_IDENTIFIER;
2327
const secret = process.env.GITHUB_WEBHOOK_SECRET;
28+
const appdata = process.env.APPDATA || process.env.HOMEPATH;
29+
const dbFile = path.join(appdata, '.ci-db.json') // cache of test results
30+
const config = require('./config.json');
31+
const timeout = config.timeout || 8*60000
2432

2533
// Configure a secure tunnel
2634
const openTunnel = async () => {
@@ -78,11 +86,11 @@ srv.post('/github', async (req, res, next) => {
7886
});
7987

8088
/**
81-
* Load MATLAB test results from db.json file.
89+
* Load MATLAB test results from ci-db.json file.
8290
* @param {string, array} id - Function to call with job and done callback when.
8391
*/
8492
function loadTestRecords(id) {
85-
let obj = JSON.parse(fs.readFileSync('./db.json', 'utf8'));
93+
let obj = JSON.parse(fs.readFileSync(dbFile, 'utf8'));
8694
if (!Array.isArray(obj)) obj = [obj]; // Ensure array
8795
let records = obj.filter(o => id.includes(o.commit));
8896
// If single arg return as object, otherwise keep as array
@@ -99,7 +107,7 @@ function compareCoverage(data) {
99107
let records = loadTestRecords(Object.values(ids));
100108
// Filter duplicates just in case
101109
records = records.filter((set => o => !set.has(o.commit) && set.add(o.commit))(new Set));
102-
has_coverage = records.every(o => (typeof o.coverage !== 'undefined' && o.coverage > 0));
110+
let has_coverage = records.every(o => (typeof o.coverage !== 'undefined' && o.coverage > 0));
103111
// Check if any errored or failed to update coverage
104112
if (records.filter(o => o.status === 'error').length > 0) {
105113
status = 'failure';
@@ -113,6 +121,7 @@ function compareCoverage(data) {
113121
description = 'Coverage ' + (coverage > 0 ? 'increased' : 'decreased')
114122
+ ' from ' + Math.round(records[1].coverage*100)/100 + '%'
115123
+ ' to ' + Math.round(records[0].coverage*100)/100 + '%';
124+
// TODO Maybe remove test from pile if we already have it?
116125
} else {
117126
for (let commit in ids) {
118127
// Check test isn't already on the pile
@@ -146,22 +155,22 @@ function compareCoverage(data) {
146155
state: status,
147156
target_url: `${process.env.WEBHOOK_PROXY_URL}/events/${ids.head}`, // fail
148157
description: description,
149-
context: 'coverage/ZTEST' // TODO Generalize
158+
context: `coverage/${process.env.USERDOMAIN}`
150159
});
151160
}
152161

153162
// Serve the test results for requested commit id
154163
srv.get('/github/:id', function (req, res) {
155164
console.log('Request for test log for commit ' + req.params.id.substring(0,6))
156-
let log = `.\\src\\matlab_tests-${req.params.id}.log`;
165+
let log = `.\\src\\matlab_tests-${req.params.id}.log`; // TODO Generalize
157166
fs.readFile(log, 'utf8', (err, data) => {
158167
if (err) {
159168
res.statusCode = 404;
160169
res.send(`Record for commit ${req.params.id} not found`);
161170
} else {
162171
res.statusCode = 200;
163-
preText = '<html lang="en-GB"><body><pre>';
164-
postText = '</pre></body></html>';
172+
let preText = '<html lang="en-GB"><body><pre>';
173+
let postText = '</pre></body></html>';
165174
res.send(preText + data + postText);
166175

167176
}
@@ -191,7 +200,7 @@ srv.get('/coverage/:repo/:branch', async (req, res) => {
191200
let id = data.object.sha;
192201
var report = {'schemaVersion': 1, 'label': 'coverage'};
193202
try { // Try to load coverage record
194-
record = await loadTestRecords(id);
203+
let record = await loadTestRecords(id);
195204
if (typeof record == 'undefined' || record['coverage'] == '') {throw 404} // Test not found for commit
196205
if (record['status'] === 'error') {throw 500} // Test found for commit but errored
197206
report['message'] = Math.round(record['coverage']*100)/100 + '%';
@@ -276,7 +285,7 @@ queue.process(async (job, done) => {
276285
// If the repo is a submodule, modify path
277286
var path = process.env.REPO_PATH;
278287
if (job.data['repo'] === 'alyx-matlab' || job.data['repo'] === 'signals') {
279-
path = path + '\\' + job.data['repo'];}
288+
path = path + path.sep + job.data['repo'];}
280289
if (job.data['repo'] === 'alyx') { sha = 'dev' } // For Alyx checkout master
281290
// Checkout commit
282291
checkout = cp.execFile('checkout.bat ', [sha, path], (error, stdout, stderr) => {
@@ -293,12 +302,13 @@ queue.process(async (job, done) => {
293302
const timer = setTimeout(function() {
294303
console.log('Max test time exceeded')
295304
job.data['status'] = 'error';
296-
job.data['context'] = 'Tests stalled after ~8 min';
297-
runTests.kill();
298-
done(new Error('Job stalled')) }, 8*60000);
305+
job.data['context'] = `Tests stalled after ~${(timeout / 60000).toFixed(0)} min`;
306+
runTests.kill();
307+
done(new Error('Job stalled')) }, timeout);
299308
let args = ['-r', `runAllTests (""${job.data.sha}"",""${job.data.repo}"")`,
300-
'-wait', '-log', '-nosplash', '-logfile', `.\\src\\matlab_tests-${job.data.sha}.log`];
301-
runTests = cp.execFile('matlab', args, (error, stdout, stderr) => {
309+
'-wait', '-log', '-nosplash', '-logfile', `.\\src\\matlab_tests-${job.data.sha}.log`]; // TODO Generalize
310+
let program = config.program || 'matlab'
311+
runTests = cp.execFile(program, args, (error, stdout, stderr) => {
302312
clearTimeout(timer);
303313
if (error) { // Send error status
304314
// Isolate error from log
@@ -325,7 +335,7 @@ queue.on('finish', job => { // On job end post result to API
325335
console.log(`Job ${job.id} complete`)
326336
// If job was part of coverage test and error'd, call compare function
327337
// (otherwise this is done by the on complete callback after writing coverage to file)
328-
if (typeof job.data.coverage !== 'undefined' && job.data['status'] == 'error') {
338+
if (typeof job.data.coverage !== 'undefined' && job.data['status'] === 'error') {
329339
compareCoverage(job.data);
330340
}
331341
if (job.data.skipPost === true) { return; }
@@ -339,7 +349,7 @@ queue.on('finish', job => { // On job end post result to API
339349
state: job.data['status'],
340350
target_url: `${process.env.WEBHOOK_PROXY_URL}/github/${job.data.sha}`, // FIXME replace url
341351
description: job.data['context'],
342-
context: 'continuous-integration/ZTEST'
352+
context: `continuous-integration/${process.env.USERDOMAIN}`
343353
});
344354
});
345355

@@ -358,11 +368,11 @@ queue.on('complete', job => { // On job end post result to API
358368
hits += file.coverage.filter(x => x > 0).length;
359369
}
360370
// Load data and save
361-
let records = JSON.parse(fs.readFileSync('./db.json', 'utf8'));
371+
let records = JSON.parse(fs.readFileSync(dbFile, 'utf8'));
362372
if (!Array.isArray(records)) records = [records]; // Ensure array
363373
for (let o of records) { if (o.commit === job.data.sha) {o.coverage = hits / (hits + misses) * 100; break; }} // Add percentage
364374
// Save object
365-
fs.writeFile('./db.json', JSON.stringify(records), function(err) {
375+
fs.writeFile(dbFile, JSON.stringify(records), function(err) {
366376
if (err) { console.log(err); return; }
367377
// If this test was to ascertain coverage, call comparison function
368378
if (typeof job.data.coverage !== 'undefined') { compareCoverage(job.data); }
@@ -399,7 +409,7 @@ handler.on('push', async function (event) {
399409
state: 'pending',
400410
target_url: `${process.env.WEBHOOK_PROXY_URL}/events/${head_commit}`, // fail
401411
description: 'Tests running',
402-
context: 'continuous-integration/ZTEST'
412+
context: `continuous-integration/${process.env.USERDOMAIN}`
403413
});
404414
// Add a new test job to the queue
405415
queue.add({
@@ -438,7 +448,7 @@ handler.on('pull_request', async function (event) {
438448
state: 'pending',
439449
target_url: `${process.env.WEBHOOK_PROXY_URL}/events/${head_commit}`, // fail
440450
description: 'Tests running',
441-
context: 'continuous-integration/ZTEST'
451+
context: `continuous-integration/${process.env.USERDOMAIN}`
442452
});
443453
}
444454

@@ -454,7 +464,7 @@ handler.on('pull_request', async function (event) {
454464
state: 'pending',
455465
target_url: `${process.env.WEBHOOK_PROXY_URL}/events/${head_commit}`, // fail
456466
description: 'Checking coverage',
457-
context: 'coverage/ZTEST'
467+
context: `coverage/${process.env.USERDOMAIN}`
458468
});
459469
// Check coverage exists
460470
let data = {

queue.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class Queue extends EventEmitter {
9191
console.log('Job running')
9292
};
9393
}
94-
};
94+
}
9595

9696
/** Class representing a job in the Queue. */
9797
class Job extends EventEmitter {
@@ -100,7 +100,7 @@ class Job extends EventEmitter {
100100
* Create a job object with associated data.
101101
* @param {number} id - Job ID (unique in current Queue pile).
102102
* @param {Object} data - Data to hold in object, may be used by Queue process function.
103-
* @param {boolean} running - Indicates whether job is currently being processed.
103+
* @property {boolean} running - Indicates whether job is currently being processed.
104104
* @event module:Job~end
105105
*/
106106
constructor(id, data) {
@@ -115,18 +115,19 @@ class Job extends EventEmitter {
115115
/**
116116
* Set running attribute. If setting to false from true, emit 'end' event.
117117
* @param {boolean} bool - Value to set running.
118+
* @todo rename to be consistent with property
118119
*/
119120
set isRunning(bool) {
120-
if (bool == false && this.running === true) {
121+
if (bool === false && this.running === true) {
121122
this.running = false;
122123
this.emit('end');
123124
} else {
124-
if (bool == true) {
125+
if (bool === true) {
125126
this.running = true;
126127
}
127128
}
128129
}
129130

130-
};
131+
}
131132

132-
module.exports = Queue; // Export Queue
133+
module.exports = Queue; // Export Queue

0 commit comments

Comments
 (0)