mirror of
https://github.com/all-contributors/cli.git
synced 2025-01-10 05:56:29 +00:00
feat: added the discover module + fetch
command
For more info, please check #186
This commit is contained in:
parent
cdd00deedf
commit
06cebabb85
5 changed files with 222 additions and 14 deletions
173
src/cli.js
173
src/cli.js
|
@ -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}`)
|
||||
}
|
||||
|
|
|
@ -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
19
src/discover/index.js
Normal 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
23
src/discover/learner.js
Normal 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
|
0
src/discover/learner.json
Normal file
0
src/discover/learner.json
Normal file
Loading…
Reference in a new issue