Skip to content

Commit 2337b32

Browse files
committed
feat: added the discover module + fetch command
For more info, please check #186
1 parent dcb8119 commit 2337b32

File tree

5 files changed

+222
-14
lines changed

5 files changed

+222
-14
lines changed

src/cli.js

Lines changed: 165 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ const generate = require('./generate')
1515
const util = require('./util')
1616
const repo = require('./repo')
1717
const updateContributors = require('./contributors')
18+
const {getContributors} = require('./discover')
19+
const learner = require('./discover/learner')
1820

1921
const cwd = process.cwd()
2022
const defaultRCFile = path.join(cwd, '.all-contributorsrc')
@@ -72,17 +74,49 @@ function startGeneration(argv) {
7274
}
7375

7476
function addContribution(argv) {
77+
/* Example: (for clarity & debugging purposes)
78+
{
79+
_: [ 'add' ],
80+
projectName: 'cz-cli',
81+
projectOwner: 'commitizen',
82+
repoType: 'github',
83+
repoHost: 'https://github.com',
84+
files: [ 'AC.md' ],
85+
imageSize: 100,
86+
commit: false,
87+
commitConvention: 'angular',
88+
contributors: [],
89+
contributorsPerLine: 7,
90+
'contributors-per-line': 7,
91+
config: '/mnt/c/Users/max/Projects/cz-cli/.all-contributorsrc',
92+
'$0': '../all-contributors-cli/src/cli.js'
93+
}
94+
*/
7595
const username = argv._[1]
7696
const contributions = argv._[2]
7797
// Add or update contributor in the config file
78-
return updateContributors(argv, username, contributions).then(data => {
79-
argv.contributors = data.contributors
80-
return startGeneration(argv).then(() => {
81-
if (argv.commit) {
82-
return util.git.commit(argv, data)
83-
}
84-
})
85-
})
98+
return updateContributors(argv, username, contributions).then(
99+
data => {
100+
argv.contributors = data.contributors
101+
/* Example
102+
[ { login: 'Berkmann18',
103+
name: 'Maximilian Berkmann',
104+
avatar_url: 'https://avatars0.githubusercontent.com/u/8260834?v=4',
105+
profile: 'http://maxcubing.wordpress.com',
106+
contributions: [ 'code', 'ideas' ] },
107+
{ already in argv.contributors } ]
108+
*/
109+
return startGeneration(argv).then(
110+
() => {
111+
if (argv.commit) {
112+
return util.git.commit(argv, data)
113+
}
114+
},
115+
err => console.error('Generation fail:', err),
116+
)
117+
},
118+
err => console.error('Contributor Update fail:', err),
119+
)
86120
}
87121

88122
function checkContributors(argv) {
@@ -96,6 +130,7 @@ function checkContributors(argv) {
96130
configData.repoHost,
97131
)
98132
.then(repoContributors => {
133+
// console.dir(repoContributors) //['jfmengels', 'jakebolam', ...]
99134
const checkKey = repo.getCheckKey(configData.repoType)
100135
const knownContributions = configData.contributors.reduce((obj, item) => {
101136
obj[item[checkKey]] = item.contributions
@@ -132,6 +167,122 @@ function checkContributors(argv) {
132167
})
133168
}
134169

170+
function fetchContributors(argv) {
171+
// console.log('argv=', argv);
172+
// const configData = util.configFile.readConfig(argv.config)
173+
// console.log('configData')
174+
// console.dir(configData)
175+
176+
return getContributors(argv.projectOwner, argv.projectName).then(
177+
repoContributors => {
178+
// repoContributors = {prCreators, prCommentators, issueCreators, issueCommentators, reviewers, commitAuthors, commitCommentators}
179+
// console.dir(repoContributors)
180+
181+
// const checkKey = repo.getCheckKey(configData.repoType)
182+
// const knownContributions = configData.contributors.reduce((obj, item) => {
183+
// obj[item[checkKey]] = item.contributions
184+
// return obj
185+
// }, {})
186+
// console.log('knownContributions', knownContributions) //{ jfmengels: ['code', 'test', 'doc'], ...}
187+
// const knownContributors = configData.contributors.map(
188+
// contributor => contributor[checkKey],
189+
// )
190+
// console.log('knownContributors', knownContributors) //['kentcdodds', 'ben-eb', ...]
191+
192+
// let contributors = new Set(
193+
// repoContributors.prCreators.map(usr => usr.login),
194+
// )
195+
196+
// repoContributors.issueCreators.forEach(usr => contributors.add(usr.login))
197+
// repoContributors.reviewers.forEach(usr => contributors.add(usr.login))
198+
// repoContributors.commitAuthors.forEach(usr => contributors.add(usr.login))
199+
// contributors = Array.from(contributors)
200+
201+
// console.log('ctbs=', contributors);
202+
203+
//~1. Auto-add reviewers for review~
204+
//~2. Auto-add issue creators for any categories found~
205+
//~3. Auto-add commit authors~
206+
//4. Roll onto other contribution categories following https://www.draw.io/#G1uL9saIuZl3rj8sOo9xsLOPByAe28qhwa
207+
208+
const args = {...argv, _: []}
209+
const contributorsToAdd = []
210+
repoContributors.reviewers.forEach(usr => {
211+
// args._ = ['add', usr.login, 'review']
212+
// addContribution(args)
213+
contributorsToAdd.push({login: usr.login, contributions: ['review']})
214+
// console.log(
215+
// `Adding ${chalk.underline('Reviewer')} ${chalk.blue(usr.login)}`,
216+
// )
217+
})
218+
219+
repoContributors.issueCreators.forEach(usr => {
220+
// console.log('usr=', usr.login, 'labels=', usr.labels)
221+
const contributor = {
222+
login: usr.login,
223+
contributions: [],
224+
}
225+
usr.labels.forEach(lbl => {
226+
const guesses = learner.classify(lbl).filter(c => c && c !== 'null')
227+
if (guesses.length) {
228+
const category = guesses[0]
229+
// args._ = ['', usr.login, category]
230+
// addContribution(args)
231+
if (!contributor.contributions.includes(category))
232+
contributor.contributions.push(category)
233+
// console.log(
234+
// `Adding ${chalk.blue(usr.login)} for ${chalk.underline(category)}`,
235+
// )
236+
} //else console.warn(`Oops, I couldn't find any category for the "${lbl}" label`)
237+
})
238+
const existingContributor = contributorsToAdd.filter(
239+
ctrb => ctrb.login === usr.login,
240+
)
241+
if (existingContributor.length) {
242+
existingContributor[0].contributions = [
243+
...new Set(
244+
existingContributor[0].contributions.concat(
245+
contributor.contributions,
246+
),
247+
),
248+
]
249+
} else contributorsToAdd.push(contributor)
250+
})
251+
252+
repoContributors.commitAuthors.forEach(usr => {
253+
// const contributor = {
254+
// login: usr.login,
255+
// contributions: [],
256+
// }
257+
// console.log('commit auth:', usr)
258+
const existingContributor = contributorsToAdd.filter(
259+
ctrb => ctrb.login === usr.login,
260+
)
261+
if (existingContributor.length) {
262+
//there's no label or commit message info so use only code for now
263+
if (!existingContributor[0].contributions.includes('code')) {
264+
existingContributor[0].contributions.push('code')
265+
}
266+
} else
267+
contributorsToAdd.push({login: usr.login, contributions: ['code']})
268+
})
269+
270+
// console.log('contributorsToAdd=', contributorsToAdd)
271+
contributorsToAdd.forEach(contributor => {
272+
console.log(
273+
`Adding ${chalk.blue(contributor.login)} for ${chalk.underline(
274+
contributor.contributions.join('/'),
275+
)}`,
276+
)
277+
args._ = ['', contributor.login, contributor.contributions.join(',')]
278+
// if (contributor.contributions.length) addContribution(args)
279+
// else console.log('Skipping', contributor.login)
280+
})
281+
},
282+
err => console.error('fetch error:', err),
283+
)
284+
}
285+
135286
function onError(error) {
136287
if (error) {
137288
console.error(error.message)
@@ -160,6 +311,10 @@ function promptForCommand(argv) {
160311
'Compare contributors from the repository with the credited ones',
161312
value: 'check',
162313
},
314+
{
315+
name: 'Fetch contributors from the repository',
316+
value: 'fetch',
317+
},
163318
],
164319
when: !argv._[0],
165320
default: 0,
@@ -182,6 +337,8 @@ promptForCommand(yargv)
182337
return addContribution(yargv)
183338
case 'check':
184339
return checkContributors(yargv)
340+
case 'fetch':
341+
return fetchContributors(yargv)
185342
default:
186343
suggestCommands(command)
187344
throw new Error(`Unknown command ${command}`)

src/contributors/index.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@ function isNewContributor(contributorList, username) {
1010

1111
module.exports = function addContributor(options, username, contributions) {
1212
const answersP = prompt(options, username, contributions)
13-
const contributorsP = answersP.then(answers =>
14-
add(options, answers.username, answers.contributions, repo.getUserInfo),
15-
)
13+
const contributorsP = answersP
14+
.then(answers =>
15+
add(options, answers.username, answers.contributions, repo.getUserInfo),
16+
)
17+
//eslint-disable-next-line no-console
18+
.catch(err => console.error('contributorsP error:', err))
1619

17-
const writeContributorsP = contributorsP.then(contributors =>
18-
util.configFile.writeContributors(options.config, contributors),
19-
)
20+
const writeContributorsP = contributorsP
21+
.then(contributors => {
22+
// console.log('opts.config=', options.config, 'contributors=', contributors)
23+
return util.configFile.writeContributors(options.config, contributors)
24+
})
25+
//eslint-disable-next-line no-console
26+
.catch(err => console.error('writeContributorsP error:', err))
2027

2128
return Promise.all([answersP, contributorsP, writeContributorsP]).then(
2229
res => {
@@ -32,5 +39,7 @@ module.exports = function addContributor(options, username, contributions) {
3239
),
3340
}
3441
},
42+
//eslint-disable-next-line no-console
43+
err => console.error('contributors fail: ', err),
3544
)
3645
}

src/discover/index.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const nyc = require('name-your-contributors')
2+
const {Spinner} = require('clui')
3+
4+
const privateToken = (process.env && process.env.PRIVATE_TOKEN) || ''
5+
const loader = new Spinner('Loading...')
6+
7+
const getContributors = function(owner, name, token = privateToken) {
8+
loader.start()
9+
const contributors = nyc.repoContributors({
10+
token,
11+
user: owner,
12+
repo: name,
13+
commits: true,
14+
})
15+
loader.stop()
16+
return contributors
17+
}
18+
19+
module.exports = {getContributors}

src/discover/learner.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const {existsSync} = require('fs')
2+
const Learner = require('ac-learn')
3+
4+
const JSON_PATH = `${__dirname}/learner.json`
5+
6+
//@TODO: Use the JSON methods from `ac-learn` to get the whole thing saveable
7+
const learner = new Learner()
8+
/* eslint-disable no-console */
9+
if (existsSync(JSON_PATH)) {
10+
learner.loadAndDeserializeClassifier(JSON_PATH).then(classifier => {
11+
learner.classifier = classifier
12+
// console.log('Re-using existing classifier')
13+
}, console.error)
14+
} else {
15+
learner.crossValidate(6)
16+
learner.eval()
17+
learner.serializeAndSaveClassifier(JSON_PATH).then(_ => {
18+
// console.log('Classifier saved', classifier)
19+
}, console.error)
20+
}
21+
/* eslint-enable no-console */
22+
23+
module.exports = learner

src/discover/learner.json

Whitespace-only changes.

0 commit comments

Comments
 (0)