Skip to content

Commit

Permalink
Add changelog-generator based on prior work by @satya164 (react-nativ…
Browse files Browse the repository at this point in the history
…e-community#61)

I added the changelog-generator from https://github.com/callstack/react-native-releases-script with some updates: it now follows keep a changelog's format and implements yargs to make it more user friendly. Give it a shot using changelog-generator.js.
  • Loading branch information
turnrye authored Nov 6, 2018
1 parent ae71bab commit afc59e1
Show file tree
Hide file tree
Showing 4 changed files with 1,265 additions and 828 deletions.
272 changes: 272 additions & 0 deletions changelog-generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
#!/usr/bin/env node

'use strict';

const argv = require('yargs')
.usage('$0 [args]', 'Generate a React Native changelog from the commits and PRs')
.options({
'base': {
alias: 'b',
describe: 'the base version to compare against (most often, this is the current stable)',
demandOption: true
},
'compare': {
alias: 'c',
describe: 'the new version (most often, this is the release candidate)',
demandOption: true
}
})
.version(false)
.help('help')
.argv

const base = argv.base + '-stable';
const compare = argv.compare + '-stable';

function fetchJSON(host, path) {
return new Promise((resolve, reject) => {
let data = '';

require('https').get({
host,
path,
headers: { 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)' },
}).on('response', response => {
response.on('data', chunk => {
data += chunk;
});

response.on('end', () => {
try {
const json = JSON.parse(data);
resolve(json);
} catch (e) {
reject(e);
}
});

response.on('error', error => {
reject(error);
});
});
});
}

function filterCICommits(commits) {
return commits.filter(item => {
const text = item.commit.message.toLowerCase();
return !(text.includes('travis') || text.includes('circleci') || text.includes('circle ci') || text.includes('bump version numbers'));
});
}

function isAndroidCommit(change) {
return /\b(android|java)\b/i.test(change) || /android/i.test(change);
}

function isIOSCommit(change) {
return /\b(ios|xcode|swift|objective-c|iphone|ipad)\b/i.test(change) || /ios\b/i.test(change) || /\brct/i.test(change);
}

function isAdded(change) {
return /\b(add|adds|added)\b/i.test(change);
}

function isChanged(change) {
return /\b(changes|changed)\b/i.test(change);
}

function isDeprecated(change) {
return /\b(deprecated|deprecate)\b/i.test(change);
}

function isRemoved(change) {
return /\b(remove|removed)\b/i.test(change);
}

function isFixed(change) {
return /\b(fix|fixes|fixed)\b/i.test(change);
}

function isSecurity(change) {
return /\b(security)\b/i.test(change);
}

function getChangeMessage(item) {
return `- ${item.commit.message.split('\n')[0]} ([${item.sha.slice(0, 7)}](https://github.com/facebook/react-native/commit/${item.sha.slice(0, 7)})${item.author ? ' by [@' + item.author.login + '](https://github.com/' + item.author.login + ')' : ''})`;
}

function getChangelogDesc(commits) {
const acc = {
added: { android: [], ios: [], general: [] },
changed: { android: [], ios: [], general: [] },
deprecated: { android: [], ios: [], general: [] },
removed: { android: [], ios: [], general: [] },
fixed: { android: [], ios: [], general: [] },
security: { android: [], ios: [], general: [] },
unknown: { android: [], ios: [], general: [] },
};

commits.forEach(item => {
const change = item.commit.message.split('\n')[0];
const message = getChangeMessage(item);

if (isAdded(change)) {
if (isAndroidCommit(change)) {
acc.added.android.push(message);
} else if (isIOSCommit(change)) {
acc.added.ios.push(message);
} else {
acc.added.general.push(message);
}
} else if (isChanged(change)) {
if (isAndroidCommit(change)) {
acc.changed.android.push(message);
} else if (isIOSCommit(change)) {
acc.changed.ios.push(message);
} else {
acc.changed.general.push(message);
}
} else if (isDeprecated(change)) {
if (isAndroidCommit(change)) {
acc.deprecated.android.push(message);
} else if (isIOSCommit(change)) {
acc.deprecated.ios.push(message);
} else {
acc.deprecated.general.push(message);
}
} else if (isRemoved(change)) {
if (isAndroidCommit(change)) {
acc.removed.android.push(message);
} else if (isIOSCommit(change)) {
acc.removed.ios.push(message);
} else {
acc.removed.general.push(message);
}
} else if (isFixed(change)) {
if (isAndroidCommit(change)) {
acc.fixed.android.push(message);
} else if (isIOSCommit(change)) {
acc.fixed.ios.push(message);
} else {
acc.fixed.general.push(message);
}
} else if (isSecurity(change)) {
if (isAndroidCommit(change)) {
acc.security.android.push(message);
} else if (isIOSCommit(change)) {
acc.security.ios.push(message);
} else {
acc.security.general.push(message);
}
} else {
if (isAndroidCommit(change)) {
acc.unknown.android.push(message);
} else if (isIOSCommit(change)) {
acc.unknown.ios.push(message);
} else {
acc.unknown.general.push(message);
}
}
});

return acc;
}

function buildMarkDown(data) {
return `
## [${argv.compare}.0]
### Added
${data.added.general.join('\n')}
#### Android specific
${data.added.android.join('\n')}
#### iOS specific
${data.added.ios.join('\n')}
### Changed
${data.changed.general.join('\n')}
#### Android specific
${data.changed.android.join('\n')}
#### iOS specific
${data.changed.ios.join('\n')}
### Deprecated
${data.deprecated.general.join('\n')}
#### Android specific
${data.deprecated.android.join('\n')}
#### iOS specific
${data.deprecated.ios.join('\n')}
### Removed
${data.removed.general.join('\n')}
#### Android specific
${data.removed.android.join('\n')}
#### iOS specific
${data.removed.ios.join('\n')}
### Fixed
${data.fixed.general.join('\n')}
#### Android specific
${data.fixed.android.join('\n')}
#### iOS specific
${data.fixed.ios.join('\n')}
### Security
${data.security.general.join('\n')}
#### Android specific
${data.security.android.join('\n')}
#### iOS specific
${data.security.ios.join('\n')}
### Unknown
${data.unknown.general.join('\n')}
#### Android Unknown
${data.unknown.android.join('\n')}
#### iOS Unkown
${data.unknown.ios.join('\n')}
`;
}

fetchJSON('api.github.com', '/repos/facebook/react-native/compare/' + base + '...' + compare)
.then(data => data.commits)
.then(filterCICommits)
.then(getChangelogDesc)
.then(buildMarkDown)
.then(data => console.log(data))
.catch(e => console.error(e));
Loading

0 comments on commit afc59e1

Please sign in to comment.