Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add check command that compares GitHub contributors with credited ones #58

Merged
merged 9 commits into from
Nov 8, 2017
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ Where `username` is the user's GitHub username, and `contribution` is a `,`-sepa
- tutorial: [✅](# "Tutorials")
- video: [📹](# "Videos")

### Check for missing contributors

Use `check` to compare contributors from GitHub with the ones credited in your `.all-contributorsrc` file, in order to make sure that credit is given where it's due.

```console
all-contributors check
```

> Due to GitHub API restrictions, this command only works for projects with less than 500 contributors.


## Configuration

You can configure the project by updating the `.all-contributorsrc` JSON file. The data used to generate the contributors list will be stored in there, and you can configure how you want `all-contributors-cli` to generate the list.
Expand Down
39 changes: 39 additions & 0 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

var path = require('path');
var yargs = require('yargs');
var chalk = require('chalk');
var inquirer = require('inquirer');

var init = require('./lib/init');
Expand All @@ -23,6 +24,8 @@ var argv = yargs
.usage('Usage: $0 add <username> <contribution>')
.command('init', 'Prepare the project to be used with this tool')
.usage('Usage: $0 init')
.command('check', 'Compares contributors from GitHub with the ones credited in .all-contributorsrc')
.usage('Usage: $0 check')
.boolean('commit')
.default('files', ['README.md'])
.default('contributorsPerLine', 7)
Expand Down Expand Up @@ -68,6 +71,37 @@ function addContribution(argv) {
});
}

function checkContributors() {
var configData = util.configFile.readConfig(argv.config);

return util.check(configData.projectOwner, configData.projectName)
.then(ghContributors => {
var knownContributions = configData.contributors.reduce((obj, item) => {
obj[item.login] = item.contributions;
return obj;
}, {});
var knownContributors = configData.contributors.map(contributor => contributor.login);

var missingInConfig = ghContributors.filter(login => knownContributors.indexOf(login) === -1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could probably use includes here.

var missingFromGithub = knownContributors.filter(login => {
return ghContributors.indexOf(login) === -1 && (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could probably use includes here :)

knownContributions[login].includes('code') ||
knownContributions[login].includes('tool')
);
});

if (missingInConfig.length) {
process.stdout.write(chalk.bold('Missing contributors in .all-contributorsrc:\n'));
process.stdout.write(' ' + missingInConfig.join(', ') + '\n');
}

if (missingFromGithub.length) {
process.stdout.write(chalk.bold('Unknown contributors found in .all-contributorsrc:\n'));
process.stdout.write(' ' + missingFromGithub.join(', ') + '\n');
}
});
}

function onError(error) {
if (error) {
console.error(error.message);
Expand All @@ -87,6 +121,9 @@ function promptForCommand(argv) {
}, {
name: 'Re-generate the contributors list',
value: 'generate'
}, {
name: 'Compare contributors from GitHub with the credited ones',
value: 'check'
}],
when: !argv._[0],
default: 0
Expand All @@ -107,6 +144,8 @@ promptForCommand(argv)
return startGeneration(argv);
case 'add':
return addContribution(argv);
case 'check':
return checkContributors();
default:
throw new Error(`Unknown command ${command}`);
}
Expand Down
45 changes: 45 additions & 0 deletions lib/util/check.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict';

var pify = require('pify');
var request = pify(require('request'));

function getNextLink(link) {
if (!link) {
return null;
}

var nextLink = link.split(',').find(s => s.indexOf('rel="next"') > -1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use includes here


if (!nextLink) {
return null;
}

return nextLink.split(';')[0].slice(1, -1);
}

function getContributorsPage(url) {
return request.get({
url: url,
headers: {
'User-Agent': 'request'
}
})
.then(res => {
var body = JSON.parse(res.body);
var contributorsIds = body.map(contributor => contributor.login);

var nextLink = getNextLink(res.headers.link);
if (nextLink) {
return getContributorsPage(nextLink).then(nextContributors => {
return contributorsIds.concat(nextContributors);
})
}

return contributorsIds;
});
}

module.exports = function getContributorsFromGithub(owner, name) {
var url = 'https://api.github.com/repos/' + owner + '/' + name + '/contributors?per_page=100';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use a template literal:

var url = `https://api.github.com/repos/${owner}/${name}/contributors?per_page=100`;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There you go. Also use template literals for the command output

return getContributorsPage(url);
};
3 changes: 2 additions & 1 deletion lib/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ module.exports = {
configFile: require('./config-file'),
contributionTypes: require('./contribution-types'),
git: require('./git'),
markdown: require('./markdown')
markdown: require('./markdown'),
check: require('./check')
};
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"homepage": "https://github.com/jfmengels/all-contributors-cli#readme",
"dependencies": {
"async": "^2.0.0-rc.1",
"chalk": "^2.3.0",
"inquirer": "^3.0.1",
"lodash": "^4.11.2",
"pify": "^2.3.0",
Expand All @@ -39,8 +40,8 @@
"ava": "^0.14.0",
"nock": "^8.0.0",
"nyc": "^6.4.2",
"xo": "^0.15.0",
"semantic-release": "^6.3.2"
"semantic-release": "^6.3.2",
"xo": "^0.15.0"
},
"ava": {
"files": [
Expand Down
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,14 @@ chalk@^2.0.0:
escape-string-regexp "^1.0.5"
supports-color "^4.0.0"

chalk@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba"
dependencies:
ansi-styles "^3.1.0"
escape-string-regexp "^1.0.5"
supports-color "^4.0.0"

chokidar@^1.4.2:
version "1.7.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
Expand Down