Skip to content

Commit

Permalink
CI test and upgrades (Azure#1408)
Browse files Browse the repository at this point in the history
* refactor

* refactor

* dependency

* promise

* pick up batches

* promisy

* use node 8
  • Loading branch information
olydis authored Jul 17, 2017
1 parent aa82684 commit 124bde6
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 279 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: node_js
node_js:
- "6"
- "8"
services:
- docker
env:
Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@
"description": "Tests for Azure REST API Specifications",
"license": "MIT",
"devDependencies": {
"fs-extra": "^3.0.1",
"mocha": "*",
"async": "^2.1.4",
"glob": "^5.0.14",
"json-schema-ref-parser": "^3.1.2",
"lodash": "^3.10.1",
"request": "^2.61.0",
"z-schema": "^3.16.1",
"oav": "^0.4.1",
"underscore": "^1.8.3",
"js-yaml": "^3.8.2",
"azure-storage": "^2.1.0"
},
Expand Down
140 changes: 47 additions & 93 deletions scripts/getStatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,14 @@ var exec = require('child_process').exec,
path = require('path'),
fs = require('fs'),
glob = require('glob'),
_ = require('underscore'),
oav = require('oav');
oav = require('oav'),
utils = require("../test/util/utils");

exports = module.exports;
exports.globPath = path.join(__dirname, '../', '/**/swagger/*.json');
exports.swaggers = _(glob.sync(exports.globPath));

var swaggersToProcess = exports.swaggers;
var swaggersToProcess = utils.swaggers;
var finalResult = {};
var filename = `log_${getTimeStamp()}.log`;
var filename = `log_${utils.getTimeStamp()}.log`;
var logFilepath = path.join(getLogDir(), filename);

function getTimeStamp() {
// We pad each value so that sorted directory listings show the files in chronological order
function pad(number) {
if (number < 10) {
return '0' + number;
}

return number;
}

var now = new Date();
return now.getFullYear()
+ pad(now.getMonth() + 1)
+ pad(now.getDate())
+ "_"
+ pad(now.getHours())
+ pad(now.getMinutes())
+ pad(now.getSeconds());
}

function updateResult(spec, errors, updateLog) {
if (!finalResult[spec]) {
finalResult[spec] = errors;
Expand All @@ -47,7 +23,6 @@ function updateResult(spec, errors, updateLog) {
if (updateLog) {
writeContent(JSON.stringify(finalResult, null, 2));
}
return;
}

function getLogDir() {
Expand All @@ -67,97 +42,76 @@ function createLogFile() {
if (!fs.existsSync(logFilepath)) {
fs.writeFileSync(logFilepath, '');
}
return;
}

//appends the content to the log file
function writeContent(content) {
fs.writeFileSync(logFilepath, content);
}

//executes promises sequentially by chaining them.
function executePromisesSequentially(promiseFactories) {
let result = Promise.resolve();
promiseFactories.forEach(function (promiseFactory) {
result = result.then(promiseFactory);
});
return result;
};

//runs the linter on a given swagger spec.
function runLinter(swagger) {
return new Promise((res) => {
let cmd = 'autorest --azure-validator=true --input-file=' + swagger + ' --message-format=json';
console.log(`\t- Running Linter.`);
exec(cmd, { encoding: 'utf8', maxBuffer: 1024 * 1024 * 64 }, (err, stdout, stderr) => {
let resultObject = [];
if (err) {
console.log(`An error occurred while running the linter on ${swagger}:`);
console.dir(err, { depth: null, colors: true });
} else {
//console.log('>>>> Actual result...');
//console.log(resultString);
let resultString = stdout + stderr;
if (resultString.indexOf('{') !== -1) {
resultString = "[" + resultString.substring(resultString.indexOf('{')).trim().replace(/\}\n\{/g, "},\n{") + "]";
//console.log('>>>>>> Trimmed Result...');
//console.log(resultString);
try {
resultObject = JSON.parse(resultString);
//console.log('>>>>>> Parsed Result...');
//console.dir(resultObject, {depth: null, colors: true});
} catch (e) {
console.log(`An error occurred while executing JSON.parse() on the linter output for ${swagger}:`);
console.dir(resultString);
console.dir(e, { depth: null, colors: true });
}
}
}
res(resultObject);
});
});
async function runLinter(swagger) {
// TODO: update to use config file... but report grouping is by Swagger right now
let cmd = 'autorest --validation --azure-validator --input-file=' + swagger + ' --message-format=json';
console.log(`\t- Running Linter.`);
const {err, stdout, stderr } = await new Promise(res => exec(cmd, { encoding: 'utf8', maxBuffer: 1024 * 1024 * 64 },
(err, stdout, stderr) => res({ err: err, stdout: stdout, stderr: stderr })));
let resultObject = [];
let resultString = stdout + stderr;
//console.log('>>>> Actual result...');
//console.log(resultString);
if (resultString.indexOf('{') !== -1) {
resultString = "[" + resultString.substring(resultString.indexOf('{')).trim().replace(/\}\n\{/g, "},\n{") + "]";
//console.log('>>>>>> Trimmed Result...');
//console.log(resultString);
try {
resultObject = JSON.parse(resultString);
//console.log('>>>>>> Parsed Result...');
//console.dir(resultObject, {depth: null, colors: true});
} catch (e) {
console.log(`An error occurred while executing JSON.parse() on the linter output for ${swagger}:`);
console.dir(resultString);
console.dir(e, { depth: null, colors: true });
}
}
return resultObject;
}

//runs the semantic validator on a given swagger spec.
function runSemanticValidator(swagger) {
console.log('\t- Running Semantic Validator.')
return oav.validateSpec(swagger, {consoleLogLevel: 'off'}).then(function (validationResult) {
//console.dir(validationResult, { depth: null, colors: true });
return Promise.resolve(validationResult.validateSpec.errors);
return validationResult.validateSpec.errors;
}).catch(function (err) {
console.dir(err, { depth: null, colors: true });
});
}

//runs the validation and linting tools on all the swaggers in the repo.
async function runTools(swagger) {
console.log(`Processing "${swagger}":`);
const validationErrors = await runSemanticValidator(swagger);
updateResult(swagger, validationErrors, true);
const linterErrors = await runLinter(swagger);
updateResult(swagger, linterErrors, true);
}

//main function
function runScript() {
async function runScript() {
// Useful when debugging a test for a particular swagger.
// Just update the regex. That will return an array of filtered items.
// swaggersToProcess = swaggersToProcess.filter(function (item) {
// return (item.match(/.*arm-network/ig) !== null);
// });
createLogFile();
console.log(`The results will be logged here: "${logFilepath}".`)
let promiseFactories = _(swaggersToProcess).map(function (swagger) {
return function () { return runTools(swagger); };
});
return executePromisesSequentially(promiseFactories);
}

//runs the validation and linting tools on all the swaggers in the repo.
function runTools(swagger) {
console.log(`Processing "${swagger}":`);
return runSemanticValidator(swagger).then(function (validationErrors) {
updateResult(swagger, validationErrors, true);
return swagger;
}).then(function (swagger) {
return runLinter(swagger).then(function (linterErrors) {
updateResult(swagger, linterErrors, true);
//console.dir(finalResult, { depth: null, colors: true });
return finalResult;
});
});
console.log(`The results will be logged here: "${logFilepath}".`);
for (const swagger of swaggersToProcess) {
await runTools(swagger);
}
//console.dir(finalResult, { depth: null, colors: true });
return finalResult;
}

//magic starts here
runScript();
runScript();
104 changes: 41 additions & 63 deletions scripts/momentOfTruth.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const exec = require('child_process').exec,
path = require('path'),
util = require('util'),
utils = require('../test/util/utils'),
_ = require('underscore'),
fs = require('fs'),
request = require('request');

Expand All @@ -17,7 +16,7 @@ let configsToProcess = utils.getConfigFilesChangedInPR();
let targetBranch = utils.getTargetBranch();
let sourceBranch = utils.getSourceBranch();
let pullRequestNumber = utils.getPullRequestNumber();
let linterCmd = `autorest --azure-validator --message-format=json `;
let linterCmd = `autorest --validation --azure-validator --message-format=json `;
let gitCheckoutCmd = `git checkout ${targetBranch}`;
let gitLogCmd = `git log -3`;
var filename = `${pullRequestNumber}_${utils.getTimeStamp()}.json`;
Expand Down Expand Up @@ -50,57 +49,45 @@ function createLogFile() {
if (!fs.existsSync(logFilepath)) {
fs.writeFileSync(logFilepath, '');
}
return;
}

//appends the content to the log file
function writeContent(content) {
fs.writeFileSync(logFilepath, content);
}

//executes promises sequentially by chaining them.
function executePromisesSequentially(promiseFactories) {
let result = Promise.resolve();
promiseFactories.forEach(function (promiseFactory) {
result = result.then(promiseFactory);
});
return result;
};

// Executes linter on given swagger path and returns structured JSON of linter output
function getLinterResult(swaggerPath) {
async function getLinterResult(swaggerPath) {
if (swaggerPath === null || swaggerPath === undefined || typeof swaggerPath.valueOf() !== 'string' || !swaggerPath.trim().length) {
throw new Error('swaggerPath is a required parameter of type "string" and it cannot be an empty string.');
}

return new Promise((result) => {
let jsonResult = [];
if (!fs.existsSync(swaggerPath)) {
result([]);
return;
let jsonResult = [];
if (!fs.existsSync(swaggerPath)) {
return [];
}
let cmd = linterCmd + swaggerPath;
console.log(`Executing: ${cmd}`);
const {err, stdout, stderr } = await new Promise(res => exec(cmd, { encoding: 'utf8', maxBuffer: 1024 * 1024 * 64 },
(err, stdout, stderr) => res({ err: err, stdout: stdout, stderr: stderr })));

let resultString = stderr;
if (resultString.indexOf('{') !== -1) {
resultString = "[" + resultString.substring(resultString.indexOf('{')).trim().replace(/\}\n\{/g, "},\n{") + "]";
//console.log('>>>>>> Trimmed Result...');
//console.log(resultString);
try {
jsonResult = JSON.parse(resultString);
//console.log('>>>>>> Parsed Result...');
//console.dir(resultObject, {depth: null, colors: true});
return jsonResult;
} catch (e) {
console.log(`An error occurred while executing JSON.parse() on the linter output for ${swaggerPath}:`);
console.dir(resultString);
console.dir(e, { depth: null, colors: true });
}
let cmd = linterCmd + swaggerPath;
console.log(`Executing: ${cmd}`);
exec(cmd, { encoding: 'utf8', maxBuffer: 1024 * 1024 * 64 }, (err, stdout, stderr) => {
let resultString = stderr;
if (resultString.indexOf('{') !== -1) {
resultString = "[" + resultString.substring(resultString.indexOf('{')).trim().replace(/\}\n\{/g, "},\n{") + "]";
//console.log('>>>>>> Trimmed Result...');
//console.log(resultString);
try {
jsonResult = JSON.parse(resultString);
//console.log('>>>>>> Parsed Result...');
//console.dir(resultObject, {depth: null, colors: true});
result(jsonResult);
} catch (e) {
console.log(`An error occurred while executing JSON.parse() on the linter output for ${swaggerPath}:`);
console.dir(resultString);
console.dir(e, { depth: null, colors: true });
result([]);
}
}
});
});
}
return [];
};

// Uploads the result file to Azure Blob Storage
Expand All @@ -117,13 +104,11 @@ function uploadToAzureStorage(json) {
}

// Run linter tool
function runTools(swagger, beforeOrAfter) {
async function runTools(swagger, beforeOrAfter) {
console.log(`Processing "${swagger}":`);
return getLinterResult(swagger).then(function (linterErrors) {
console.log(linterErrors);
updateResult(swagger, linterErrors, beforeOrAfter);
return;
});
const linterErrors = await getLinterResult(swagger);
console.log(linterErrors);
updateResult(swagger, linterErrors, beforeOrAfter);
};

// Updates final result json to be written to the output file
Expand All @@ -135,7 +120,6 @@ function updateResult(spec, errors, beforeOrAfter) {
finalResult['files'][spec][beforeOrAfter] = {};
}
finalResult['files'][spec][beforeOrAfter] = errors;
return;
}

//main function
Expand All @@ -151,22 +135,16 @@ function runScript() {
createLogFile();
console.log(`The results will be logged here: "${logFilepath}".`)

let afterPRPromiseFactories = _(configsToProcess).map(function (swagger) {
return function () { return runTools(swagger, 'after'); };
});

let beforePromiseFactories = _(configsToProcess).map(function (swagger) {
return function () { return runTools(swagger, 'before'); };
});

executePromisesSequentially(afterPRPromiseFactories).then(() => {
execSync(`${gitCheckoutCmd}`, { encoding: 'utf8' });
execSync(`${gitLogCmd}`, { encoding: 'utf8' });
executePromisesSequentially(beforePromiseFactories).then(() => {
writeContent(JSON.stringify(finalResult, null, 2));
return uploadToAzureStorage(finalResult);
})
});
for (const configFile of configsToProcess) {
await runTools(configFile, 'after');
}
execSync(`${gitCheckoutCmd}`, { encoding: 'utf8' });
execSync(`${gitLogCmd}`, { encoding: 'utf8' });
for (const configFile of configsToProcess) {
await runTools(configFile, 'before');
}
writeContent(JSON.stringify(finalResult, null, 2));
return uploadToAzureStorage(finalResult);
}

// magic starts here
Expand Down
Loading

0 comments on commit 124bde6

Please sign in to comment.