Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
72b2218
feat: added NYC for auto-fetching
Berkmann18 Apr 11, 2019
6b668bc
chore(discover): addded a label classifier
Berkmann18 Apr 12, 2019
a6dedd8
feat(discover): improved the "label matcher"
Berkmann18 Apr 12, 2019
2111d5b
refactor(discover): renamed label matcher
Berkmann18 Apr 13, 2019
695df58
feat(discover): improved category mapping [wip]
Berkmann18 Apr 16, 2019
88b9c35
chore(findCategory): corrected jest disfunction
Berkmann18 Apr 17, 2019
0743d16
chore(discover): added more label stuff
Berkmann18 Apr 19, 2019
c133607
chore(labels): added a `getAt` method + test
Berkmann18 Apr 21, 2019
730dd12
feat(discover): improved `findBestCategory` [wip]
Berkmann18 Apr 22, 2019
5810b35
chore(discover): tokenizer and more [wip]
Berkmann18 Apr 22, 2019
0190a41
refactor(discover): refactor `findCategory` and `labels`
Berkmann18 Apr 22, 2019
46b9839
refactor(discover): tweaks [wip]
Berkmann18 Apr 22, 2019
76abf6e
feat(discover): further improvements [wip]
Berkmann18 Apr 22, 2019
48becb1
refactor(discover): a lot of changes
Berkmann18 Apr 23, 2019
aba6cd9
style(discover): lint fix
Berkmann18 Apr 23, 2019
9cbbcec
feat(discover): added labels
Berkmann18 Apr 24, 2019
21ef617
feat(discover): improvements
Berkmann18 Apr 24, 2019
66f21eb
chore(discover): added helpers
Berkmann18 Apr 24, 2019
fd8c62d
chore(discover): refactoring and various changes
Berkmann18 Apr 25, 2019
19301a2
refactor(discover): multiple refactoring + improvements
Berkmann18 Apr 25, 2019
b00621f
chore(discover): small tweak
Berkmann18 Apr 25, 2019
0ffb9be
feat(findCategory): improved accuracy
Berkmann18 Apr 26, 2019
3d37419
chore(findCategory): removed commented code
Berkmann18 May 13, 2019
e2e5d45
feat: added `ac-learn`
Berkmann18 May 21, 2019
ea21919
refactor: wip
Berkmann18 May 21, 2019
4d4aa1e
Merge branch 'master'
Berkmann18 May 21, 2019
fa61c95
refactor: [wip]
Berkmann18 May 22, 2019
4eb95d1
feat(cli): added commit authors to the list + temp changes
Berkmann18 May 22, 2019
5717fae
ci(circleci): changed node version to 10.15.3
Berkmann18 May 22, 2019
e3c7331
chore(discover): file removal + step update
Berkmann18 May 22, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2.1

docker_defaults: &docker_defaults
docker:
- image: circleci/node:8.14.0
- image: circleci/node:10.15.3

commands:
prep_env:
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

- [
all-contributors-cli
](#all-contributors-cli)
- [The problem](#the-problem)
- [This solution](#this-solution)
- [Using the all-contributors-cli](#using-the-all-contributors-cli)
- [Contributors](#contributors)
- [LICENSE](#license)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

> [There is now a GitHub Bot](https://github.com/all-contributors/all-contributors-bot) for automating the maintenance of your contributors table ✨<br />Say goodbye to command line tool dependencies and hello to the [@all-contributors bot 🤖](https://github.com/all-contributors/all-contributors-bot)

<h1 align="center">
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,19 @@
"homepage": "https://github.com/all-contributors/all-contributors-cli#readme",
"dependencies": {
"@babel/runtime": "^7.2.0",
"ac-learn": "^1.0.1",
"async": "^2.0.0-rc.1",
"chalk": "^2.3.0",
"clui": "^0.3.6",
"didyoumean": "^1.2.1",
"inquirer": "^6.2.1",
"js-tokens": "^4.0.0",
"json-fixer": "^1.3.1-0",
"lodash": "^4.11.2",
"name-your-contributors": "mntnr/name-your-contributors#master",
"pify": "^4.0.1",
"request": "^2.72.0",
"string-similarity": "^3.0.0",
"yargs": "^13.1.0"
},
"devDependencies": {
Expand Down
177 changes: 169 additions & 8 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const generate = require('./generate')
const util = require('./util')
const repo = require('./repo')
const updateContributors = require('./contributors')
const {getContributors} = require('./discover')
const learner = require('./discover/learner')

const cwd = process.cwd()
const defaultRCFile = path.join(cwd, '.all-contributorsrc')
Expand Down Expand Up @@ -72,17 +74,52 @@ function startGeneration(argv) {
}

function addContribution(argv) {
// console.log('argv=', argv);
/* Example:
{
_: [ 'add' ],
projectName: 'cz-cli',
projectOwner: 'commitizen',
repoType: 'github',
repoHost: 'https://github.com',
files: [ 'AC.md' ],
imageSize: 100,
commit: false,
commitConvention: 'angular',
contributors: [],
contributorsPerLine: 7,
'contributors-per-line': 7,
config: '/mnt/c/Users/max/Projects/cz-cli/.all-contributorsrc',
'$0': '../all-contributors-cli/src/cli.js'
}
*/
const username = argv._[1]
const contributions = argv._[2]
// console.log('username=', username, 'contributions=', contributions)
// Add or update contributor in the config file
return updateContributors(argv, username, contributions).then(data => {
argv.contributors = data.contributors
return startGeneration(argv).then(() => {
if (argv.commit) {
return util.git.commit(argv, data)
}
})
})
return updateContributors(argv, username, contributions).then(
data => {
argv.contributors = data.contributors
// console.log('argv contributors=', argv.contributors)
/* Example
[ { login: 'Berkmann18',
name: 'Maximilian Berkmann',
avatar_url: 'https://avatars0.githubusercontent.com/u/8260834?v=4',
profile: 'http://maxcubing.wordpress.com',
contributions: [ 'code', 'ideas' ] },
{ already in argv.contributors } ]
*/
return startGeneration(argv).then(
() => {
if (argv.commit) {
return util.git.commit(argv, data)
}
},
err => console.error('Generation fail:', err),
)
},
err => console.error('Contributor Update fail:', err),
)
}

function checkContributors(argv) {
Expand All @@ -96,6 +133,8 @@ function checkContributors(argv) {
configData.repoHost,
)
.then(repoContributors => {
// console.log('repoContributors=')
// console.dir(repoContributors) //['jfmengels', 'jakebolam', ...]
const checkKey = repo.getCheckKey(configData.repoType)
const knownContributions = configData.contributors.reduce((obj, item) => {
obj[item[checkKey]] = item.contributions
Expand Down Expand Up @@ -132,6 +171,122 @@ function checkContributors(argv) {
})
}

function fetchContributors(argv) {
// console.log('argv=', argv);
// const configData = util.configFile.readConfig(argv.config)
// console.log('configData')
// console.dir(configData)

return getContributors(argv.projectOwner, argv.projectName).then(
repoContributors => {
// repoContributors = {prCreators, prCommentators, issueCreators, issueCommentators, reviewers, commitAuthors, commitCommentators}
// console.dir(repoContributors)

// const checkKey = repo.getCheckKey(configData.repoType)
// const knownContributions = configData.contributors.reduce((obj, item) => {
// obj[item[checkKey]] = item.contributions
// return obj
// }, {})
// console.log('knownContributions', knownContributions) //{ jfmengels: ['code', 'test', 'doc'], ...}
// const knownContributors = configData.contributors.map(
// contributor => contributor[checkKey],
// )
// console.log('knownContributors', knownContributors) //['kentcdodds', 'ben-eb', ...]

// let contributors = new Set(
// repoContributors.prCreators.map(usr => usr.login),
// )

// repoContributors.issueCreators.forEach(usr => contributors.add(usr.login))
// repoContributors.reviewers.forEach(usr => contributors.add(usr.login))
// repoContributors.commitAuthors.forEach(usr => contributors.add(usr.login))
// contributors = Array.from(contributors)

// console.log('ctbs=', contributors);

//~1. Auto-add reviewers for review~
//~2. Auto-add issue creators for any categories found~
//~3. Auto-add commit authors~
//4. Roll onto other contribution categories following https://www.draw.io/#G1uL9saIuZl3rj8sOo9xsLOPByAe28qhwa

const args = {...argv, _: []}
const contributorsToAdd = []
repoContributors.reviewers.forEach(usr => {
// args._ = ['add', usr.login, 'review']
// addContribution(args)
contributorsToAdd.push({login: usr.login, contributions: ['review']})
// console.log(
// `Adding ${chalk.underline('Reviewer')} ${chalk.blue(usr.login)}`,
// )
})

repoContributors.issueCreators.forEach(usr => {
// console.log('usr=', usr.login, 'labels=', usr.labels)
const contributor = {
login: usr.login,
contributions: [],
}
usr.labels.forEach(lbl => {
const guesses = learner.classify(lbl).filter(c => c && c !== 'null')
if (guesses.length) {
const category = guesses[0]
// args._ = ['', usr.login, category]
// addContribution(args)
if (!contributor.contributions.includes(category))
contributor.contributions.push(category)
// console.log(
// `Adding ${chalk.blue(usr.login)} for ${chalk.underline(category)}`,
// )
} //else console.warn(`Oops, I couldn't find any category for the "${lbl}" label`)
})
const existingContributor = contributorsToAdd.filter(
ctrb => ctrb.login === usr.login,
)
if (existingContributor.length) {
existingContributor[0].contributions = [
...new Set(
existingContributor[0].contributions.concat(
contributor.contributions,
),
),
]
} else contributorsToAdd.push(contributor)
})

repoContributors.commitAuthors.forEach(usr => {
// const contributor = {
// login: usr.login,
// contributions: [],
// }
// console.log('commit auth:', usr)
const existingContributor = contributorsToAdd.filter(
ctrb => ctrb.login === usr.login,
)
if (existingContributor.length) {
//there's no label or commit message info so use only code for now
if (!existingContributor[0].contributions.includes('code')) {
existingContributor[0].contributions.push('code')
}
} else
contributorsToAdd.push({login: usr.login, contributions: ['code']})
})

// console.log('contributorsToAdd=', contributorsToAdd)
contributorsToAdd.forEach(contributor => {
console.log(
`Adding ${chalk.blue(contributor.login)} for ${chalk.underline(
contributor.contributions.join('/'),
)}`,
)
args._ = ['', contributor.login, contributor.contributions.join(',')]
// if (contributor.contributions.length) addContribution(args)
// else console.log('Skipping', contributor.login)
})
},
err => console.error('fetch error:', err),
)
}

function onError(error) {
if (error) {
console.error(error.message)
Expand Down Expand Up @@ -160,6 +315,10 @@ function promptForCommand(argv) {
'Compare contributors from the repository with the credited ones',
value: 'check',
},
{
name: 'Fetch contributors from the repository',
value: 'fetch',
},
],
when: !argv._[0],
default: 0,
Expand All @@ -182,6 +341,8 @@ promptForCommand(yargv)
return addContribution(yargv)
case 'check':
return checkContributors(yargv)
case 'fetch':
return fetchContributors(yargv)
default:
suggestCommands(command)
throw new Error(`Unknown command ${command}`)
Expand Down
22 changes: 16 additions & 6 deletions src/contributors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,21 @@ function isNewContributor(contributorList, username) {

module.exports = function addContributor(options, username, contributions) {
const answersP = prompt(options, username, contributions)
const contributorsP = answersP.then(answers =>
add(options, answers.username, answers.contributions, repo.getUserInfo),
)
// console.log('options=', options)
const contributorsP = answersP
.then(answers =>
add(options, answers.username, answers.contributions, repo.getUserInfo),
)
//eslint-disable-next-line no-console
.catch(err => console.error('contributorsP error:', err))

const writeContributorsP = contributorsP.then(contributors =>
util.configFile.writeContributors(options.config, contributors),
)
const writeContributorsP = contributorsP
.then(contributors => {
// console.log('opts.config=', options.config, 'contributors=', contributors)
return util.configFile.writeContributors(options.config, contributors)
})
//eslint-disable-next-line no-console
.catch(err => console.error('writeContributorsP error:', err))

return Promise.all([answersP, contributorsP, writeContributorsP]).then(
res => {
Expand All @@ -32,5 +40,7 @@ module.exports = function addContributor(options, username, contributions) {
),
}
},
//eslint-disable-next-line no-console
err => console.error('contributors fail: ', err),
)
}
19 changes: 19 additions & 0 deletions src/discover/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const nyc = require('name-your-contributors')
const {Spinner} = require('clui')

const privateToken = (process.env && process.env.PRIVATE_TOKEN) || ''
const loader = new Spinner('Loading...')

const getContributors = function(owner, name, token = privateToken) {
loader.start()
const contributors = nyc.repoContributors({
token,
user: owner,
repo: name,
commits: true,
})
loader.stop()
return contributors
}

module.exports = {getContributors}
22 changes: 22 additions & 0 deletions src/discover/learner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const {existsSync} = require('fs')
const Learner = require('ac-learn')

const JSON_PATH = `${__dirname}/learner.json`

const learner = new Learner()
/* eslint-disable no-console */
if (existsSync(JSON_PATH)) {
learner.loadAndDeserializeClassifier(JSON_PATH).then(classifier => {
learner.classifier = classifier
// console.log('Re-using existing classifier')
}, console.error)
} else {
learner.crossValidate(6)
learner.eval()
learner.serializeAndSaveClassifier(JSON_PATH).then(_ => {
// console.log('Classifier saved', classifier)
}, console.error)
}
/* eslint-enable no-console */

module.exports = learner
Loading