feat: added the discover module + fetch command

For more info, please check #186
This commit is contained in:
Berkmann18 2019-07-17 11:26:54 +01:00
parent cdd00deedf
commit 06cebabb85
5 changed files with 222 additions and 14 deletions

View file

@ -11,6 +11,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')
@ -64,16 +66,48 @@ function startGeneration(argv) {
function addContribution(argv) {
util.configFile.readConfig(argv.config) // ensure the config file exists
const username = argv._[1] === undefined ? undefined : String(argv._[1])
/* Example: (for clarity & debugging purposes)
{
_: [ '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 contributions = argv._[2]
// 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
/* 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) {
@ -87,6 +121,7 @@ function checkContributors(argv) {
configData.repoHost,
)
.then(repoContributors => {
// console.dir(repoContributors) //['jfmengels', 'jakebolam', ...]
const checkKey = repo.getCheckKey(configData.repoType)
const knownContributions = configData.contributors.reduce((obj, item) => {
obj[item[checkKey]] = item.contributions
@ -123,6 +158,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.stack || error.message || error)
@ -151,6 +302,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,
@ -173,6 +328,8 @@ promptForCommand(yargv)
return addContribution(yargv)
case 'check':
return checkContributors(yargv)
case 'fetch':
return fetchContributors(yargv)
default:
throw new Error(`Unknown command ${command}`)
}

View file

@ -10,13 +10,20 @@ 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),
)
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 => {
@ -32,5 +39,7 @@ module.exports = function addContributor(options, username, contributions) {
),
}
},
//eslint-disable-next-line no-console
err => console.error('contributors fail: ', err),
)
}

19
src/discover/index.js Normal file
View file

@ -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}

23
src/discover/learner.js Normal file
View file

@ -0,0 +1,23 @@
const {existsSync} = require('fs')
const Learner = require('ac-learn')
const JSON_PATH = `${__dirname}/learner.json`
//@TODO: Use the JSON methods from `ac-learn` to get the whole thing saveable
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

View file