Skip to content

Instantly share code, notes, and snippets.

@mebibou
Last active November 20, 2016 07:32
Show Gist options
  • Save mebibou/b5dd46f995318ecb598d to your computer and use it in GitHub Desktop.
Save mebibou/b5dd46f995318ecb598d to your computer and use it in GitHub Desktop.
JIRA-STASH Changelog generator
/*
* Usage: node changelog.js [options]
* Options:
* --file Location of the generated CHANGELOG.MD
* --branch Name of the branch to generate the changelog
* --host JIRA host
* --port JIRA port number
* --username JIRA username
* --password JIRA password
* --progress Wether to display a progress bar while creating the changelog
*/
(function() {
'use strict';
var nodegit = require('nodegit'),
JiraApi = require('jira').JiraApi,
dateformat = require('dateformat'),
path = require('path'),
fs = require('fs');
var Changelog = function() {
var _jira = null,
_config = {
protocol: 'http',
version: 'latest',
file: './CHANGELOG.MD',
branch: 'master'
},
ProgressBar = null,
_issuesToLoad = 0,
_versions = [],
_issues = {},
_maxKeyLength = 0;
function _checkConfigElement(key) {
if (!(key in _config)) {
throw new Error('Config ' + key + ' is missing. USage: node changelog.js --' + key + '=<value>');
}
}
process.argv.forEach(function(arg) {
var type = arg.split('=')[0],
value = arg.split('=')[1];
if (type.substring(0, 2) == '--') {
_config[type.substring(2)] = value;
}
});
if (_config.progress !== 'false') {
ProgressBar = require('progress');
}
_checkConfigElement('protocol');
_checkConfigElement('host');
_checkConfigElement('port');
_checkConfigElement('username');
_checkConfigElement('password');
_checkConfigElement('version');
_checkConfigElement('file');
_checkConfigElement('branch');
_jira = new JiraApi(_config.protocol, _config.host, _config.port, _config.username, _config.password, _config.version);
function _fetchKeys(callback) {
callback = callback || false;
nodegit.Repository
.open(path.resolve(__dirname, './.git'))
.then(function(repo) {
return repo.getBranchCommit(_config.branch);
})
.then(function(firstCommit) {
if (!firstCommit) {
throw new Error('Unable to read commit on branch ' + _config.branch);
}
var history = firstCommit.history(nodegit.Revwalk.SORT.Time),
keys = [];
history
.on('commit', function(commit) {
var commitKeys = commit.message().match(/BOEA-[0-9]+/g);
if (commitKeys && commitKeys.length > 0) {
for (var i in commitKeys) {
var key = commitKeys[i];
if (keys.indexOf(key) === -1) {
keys.push(key);
_maxKeyLength = Math.max(_maxKeyLength, key.length);
}
}
}
})
.on('end', function() {
if (callback) {
callback(keys);
}
});
history.start();
})
.done();
}
function _getJIRAIssue(key, callback) {
_jira.findIssue(key, function(error, issue) {
if (error) {
callback(error);
}
else {
var summary = issue.fields.summary,
resolutionDate = issue.fields.resolutiondate,
fixVersion = null,
fixVersions = issue.fields.fixVersions;
if (fixVersions && fixVersions[0]) {
fixVersion = fixVersions[0].name;
if (!_issues[fixVersion]) {
_issues[fixVersion] = [];
_versions.push(fixVersion);
}
_issues[fixVersion].push({
key: key,
summary: summary,
resolutionDate: new Date(resolutionDate)
});
}
callback();
}
});
}
function _recursiveVersionSortFunction(aVersions, bVersions, depth) {
if (aVersions.length > depth && bVersions.length > depth) {
if (aVersions[depth] === bVersions[depth]) {
return _recursiveVersionSortFunction(aVersions, bVersions, depth + 1);
}
else {
return bVersions[depth] - aVersions[depth];
}
}
else {
return 0;
}
}
function _dump() {
_versions.sort(function(a, b) {
return _recursiveVersionSortFunction(a.split('.'), b.split('.'), 0);
});
var changelog = '# CHANGELOG\n\n';
_versions.forEach(function(version) {
changelog += '## VERSION ' + version + '\n\n';
_issues[version].sort(function(a, b) {
return b.resolutionDate.getTime() - a.resolutionDate.getTime();
});
_issues[version].forEach(function(issue) {
changelog += dateformat(issue.resolutionDate, 'dd-mm-yyyy');
changelog += ' (' + issue.key;
for (var i = issue.key.length; i < _maxKeyLength; i++) {
changelog += ' ';
}
changelog += ') ' + issue.summary + '\n';
});
changelog += '\n';
});
fs.writeFile(_config.file, changelog, function(error) {
if (error) {
console.error(error);
}
else {
console.log('Changelog has been created.');
}
});
}
this.create = function() {
_fetchKeys(function(keys) {
var progress = null;
_issuesToLoad = keys.length;
if (ProgressBar) {
progress = new ProgressBar('Reading issue [:bar] :current / :total', {
complete: '=',
incomplete: ' ',
width: 100,
total: _issuesToLoad
});
progress.render();
}
keys.forEach(function(key) {
_getJIRAIssue(key, function() {
if (progress) {
progress.tick();
}
_issuesToLoad--;
if (_issuesToLoad === 0) {
_dump();
}
});
});
});
};
};
new Changelog().create();
})();
@XavierBoubert
Copy link

You can remove the else statment in L150

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment