Skip to content
This repository was archived by the owner on Nov 8, 2020. It is now read-only.

Commit 14e6791

Browse files
committed
Added --issues flag // #1
1 parent 727da63 commit 14e6791

File tree

7 files changed

+150
-41
lines changed

7 files changed

+150
-41
lines changed

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/.ghuser.io.json
12
/.nyc_output/
23
/.travis.yml
34
/coverage/

README.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ List **all** GitHub repos a user has contributed to **since the beginning of tim
1616
$ github-contribs AurelienLourot
1717
✔ Fetched first day at GitHub: 2015-04-04.
1818
⚠ Be patient. The whole process might take up to an hour... Consider using --since and/or --until
19-
✔ Fetched all commits and PRs.
19+
✔ Fetched all commits and PRs. Consider using --issues to fetch issues as well.
2020
35 repo(s) found:
2121
AurelienLourot/lsankidb
2222
reframejs/reframe
@@ -65,21 +65,44 @@ Instead we noticed that the "Contribution Activity" on the
6565
* https://github.com/users/AurelienLourot/created_repositories?from=2018-05-17&to=2018-05-17
6666
* https://github.com/users/AurelienLourot/created_pull_requests?from=2018-05-17&to=2018-05-17
6767
* https://github.com/users/AurelienLourot/created_pull_request_reviews?from=2018-05-17&to=2018-05-17
68+
* https://github.com/users/AurelienLourot/created_issues?from=2018-07-10&to=2018-07-10
6869

6970
So we're doing the same :)
7071

72+
> **NOTE**: it seems like `created_issues` URLs don't deliver "hot issues" (issues which received
73+
> more comments than others):
74+
>
75+
> ```bash
76+
> $ curl -s "https://github.com/users/AurelienLourot/created_issues?from=2015-09-23&to=2015-09-23"
77+
> <div class="profile-rollup-content">
78+
> </div>
79+
> ```
80+
>
81+
> To get these, we also query the profile itself:
82+
>
83+
> ```bash
84+
> $ curl -s "https://github.com/AurelienLourot?from=2015-09-23" | grep issues/
85+
> <a class="text-gray-dark" href="/jfrog/build-info/issues/60">Publish properties aren&#39;t used by build-info-extractor-gradle?</a>
86+
> ```
87+
7188
### Why is it so slow?
7289
7390
We hit a [rate limit](https://en.wikipedia.org/wiki/Rate_limiting). And since it's not an official
7491
API, we can't use a token to raise the limit.
7592
7693
### Isn't it likely to break?
7794
78-
Yes, it is since that interface isn't public. We're monitoring it and will react as fast as we can
79-
when it breaks.
95+
Yes, it is since that interface isn't public. We're monitoring it<sup>[1](#footnote1)</sup> and will
96+
react as fast as we can when it breaks.
97+
98+
<a name="footnote1"><sup>1</sup></a> [ghuser.io](https://github.com/AurelienLourot/ghuser.io) runs
99+
this tool every day.<br/>
80100
81101
## Changelog
82102
103+
**2.2.0** (2018-08-09):
104+
* [#1](https://github.com/AurelienLourot/github-contribs/issues/1) - Added `--issues` flag.
105+
83106
**2.1.0** (2018-06-25):
84107
* Exported helper function `prevDay()`.
85108

cli.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
const cli = meow(`
1212
usage:
13-
$ github-contribs [--quiet|--verbose] [--since YYYY-MM-DD] [--until YYYY-MM-DD] USER
13+
$ github-contribs [--quiet|--verbose] [--since YYYY-MM-DD] [--until YYYY-MM-DD] [--issues] USER
1414
$ github-contribs --help
1515
$ github-contribs --version
1616
@@ -22,12 +22,14 @@ optional arguments:
2222
--verbose show debugging information
2323
--since YYYY-MM-DD limit the results (default: first day at GitHub)
2424
--until YYYY-MM-DD limit the results (default: today)
25+
--issues fetches not only commits and PRs but also issues
2526
--version show program's version number and exit
2627
--help show this help message and exit
2728
`, {
2829
boolean: [
2930
'quiet',
3031
'verbose',
32+
'issues',
3133
],
3234
string: [
3335
'since',
@@ -51,8 +53,10 @@ optional arguments:
5153
}
5254

5355
const user = cli.input[0];
54-
const repos = await githubContribs.fetch(user, cli.flags.since, cli.flags.until,
55-
!cli.flags.quiet && ora, cli.flags.verbose && console);
56+
const repos = await githubContribs.fetch(
57+
user, cli.flags.since, cli.flags.until, !cli.flags.quiet && ora, cli.flags.verbose && console,
58+
cli.flags.issues
59+
);
5660
if (!cli.flags.quiet) {
5761
console.log(`${repos.size} repo(s) found:`);
5862
}

docs/advanced.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ $ github-contribs AurelienLourot
1414
GitHub API key found.
1515
✔ Fetched first day at GitHub: 2015-04-04.
1616
⚠ Be patient. The whole process might take up to an hour... Consider using --since and/or --until
17-
✔ Fetched all commits and PRs.
17+
✔ Fetched all commits and PRs. Consider using --issues to fetch issues as well.
1818
35 repo(s) found:
1919
AurelienLourot/lsankidb
2020
reframejs/reframe

index.js

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
const htmlparser = require('htmlparser');
88
const moment = require('moment');
99

10-
const fetchContribs = async (user, since, until, ora, console) => {
10+
const fetchContribs = async (user, since, until, ora, console, alsoIssues) => {
1111
ora = ora || (() => {
1212
return {
1313
start() { return this; },
@@ -21,7 +21,7 @@
2121
};
2222

2323
const joinDate = await getFirstDayAtGithub(user, ora);
24-
const result = await getContribs(user, joinDate, since, until, ora, console);
24+
const result = await getContribs(user, joinDate, since, until, ora, console, alsoIssues);
2525
return result;
2626
};
2727

@@ -82,7 +82,7 @@
8282
return result;
8383
};
8484

85-
const getContribs = async (user, joinDate, since, until, ora, console) => {
85+
const getContribs = async (user, joinDate, since, until, ora, console, alsoIssues) => {
8686
const commitsHtmlToRepos = html => {
8787
const repos = new Set();
8888

@@ -116,7 +116,7 @@
116116
return repos;
117117
};
118118

119-
const prsHtmlToRepos = html => {
119+
const issuesHtmlToRepos = html => {
120120
const repos = new Set();
121121

122122
const handler = new htmlparser.DefaultHandler((error, dom) => {});
@@ -149,6 +149,39 @@
149149
return repos;
150150
};
151151

152+
const hotIssuesHtmlToRepos = html => {
153+
const repos = new Set();
154+
155+
const regex = /<a.*href="\/(.*)\/(.*)\/issues\//g;
156+
let linkToIssue;
157+
while ((linkToIssue = regex.exec(html))) {
158+
const owner = linkToIssue[1];
159+
const name = linkToIssue[2];
160+
repos.add(`${owner}/${name}`);
161+
}
162+
163+
return repos;
164+
};
165+
166+
const progressMsg = (isDone, alsoIssues, numOfQueriedDays, numOfDaysToQuery) => {
167+
let result = (isDone && 'Fetched') || 'Fetching';
168+
result += ' all commits';
169+
result += (alsoIssues && ', PRs and issues') || ' and PRs';
170+
171+
if (isDone) {
172+
result += '.';
173+
} else if (numOfQueriedDays && numOfDaysToQuery) {
174+
result += ` [${numOfQueriedDays}/${numOfDaysToQuery}]`;
175+
} else {
176+
result += '...';
177+
}
178+
179+
if (!alsoIssues) {
180+
result += ' Consider using --issues to fetch issues as well.';
181+
}
182+
return result;
183+
};
184+
152185
let oldestDate = joinDate;
153186
if (since) {
154187
oldestDate = new Date(Math.max(oldestDate, stringToDate(since)));
@@ -175,22 +208,50 @@
175208
`https://github.com/users/${user}/created_commits?from=${currDateStr}&to=${currDateStr}`
176209
);
177210
const userCommitsHtml = await userCommits.text();
211+
const commitsRepos = commitsHtmlToRepos(userCommitsHtml);
212+
178213
const userPRs = await fetchRetry(
179214
`https://github.com/users/${user}/created_pull_requests?from=${currDateStr}&to=${currDateStr}`,
180215
);
181216
const userPRsHtml = await userPRs.text();
182-
const commitsRepos = commitsHtmlToRepos(userCommitsHtml);
183-
const prsRepos = prsHtmlToRepos(userPRsHtml);
217+
const prsRepos = issuesHtmlToRepos(userPRsHtml);
218+
219+
let issuesRepos = [];
220+
let hotIssuesRepos = [];
221+
if (alsoIssues) {
222+
const userIssues = await fetchRetry(
223+
`https://github.com/users/${user}/created_issues?from=${currDateStr}&to=${currDateStr}`,
224+
);
225+
const userIssuesHtml = await userIssues.text();
226+
issuesRepos = issuesHtmlToRepos(userIssuesHtml);
227+
228+
const userHotIssues = await fetchRetry(
229+
`https://github.com/${user}?from=${currDateStr}`,
230+
);
231+
const userHotIssuesHtml = await userHotIssues.text();
232+
hotIssuesRepos = hotIssuesHtmlToRepos(userHotIssuesHtml);
233+
}
234+
184235
progressSpinner.stop(); // temporary stop for logging
185236
for (const repo of commitsRepos) {
186-
console.log(`${currDateStr}: (commits) ${repo}`);
237+
console.log(`${currDateStr}: (commits) ${repo}`);
187238
result.add(repo);
188239
}
189240
for (const repo of prsRepos) {
190-
console.log(`${currDateStr}: (PRs) ${repo}`);
241+
console.log(`${currDateStr}: (PRs) ${repo}`);
242+
result.add(repo);
243+
}
244+
for (const repo of issuesRepos) {
245+
console.log(`${currDateStr}: (issues) ${repo}`);
191246
result.add(repo);
192247
}
193-
progressSpinner.start(`Fetching all commits and PRs [${++numOfQueriedDays}/${numOfDaysToQuery}]`);
248+
for (const repo of hotIssuesRepos) {
249+
console.log(`${currDateStr}: (hot issues) ${repo}`);
250+
result.add(repo);
251+
}
252+
progressSpinner.start(
253+
progressMsg(false, alsoIssues, ++numOfQueriedDays, numOfDaysToQuery)
254+
);
194255
})();
195256
};
196257
})();
@@ -205,9 +266,9 @@
205266
ora(warning).warn();
206267

207268
const result = new Set();
208-
const progressSpinner = ora('Fetching all commits and PRs...').start();
269+
const progressSpinner = ora(progressMsg(false, alsoIssues)).start();
209270
await new PromisePool(getContribsOnOneDay, 5).start();
210-
progressSpinner.succeed('Fetched all commits and PRs.');
271+
progressSpinner.succeed(progressMsg(true, alsoIssues));
211272
return result;
212273
};
213274

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ghuser/github-contribs",
3-
"version": "2.1.0",
3+
"version": "2.2.0",
44
"description": "List all GitHub repos a user has contributed to since the beginning of time.",
55
"license": "Unlicense",
66
"repository": {
@@ -72,6 +72,6 @@
7272
".js"
7373
],
7474
"check-coverage": true,
75-
"lines": 80
75+
"lines": 84
7676
}
7777
}

test.js

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,55 @@
11
import test from 'ava';
22
import m from '.';
33

4+
const ora = string => {
5+
if (string) {
6+
console.log(string);
7+
}
8+
return {
9+
start(string) {
10+
if (string) {
11+
console.log(string);
12+
}
13+
return this;
14+
},
15+
stop() {},
16+
succeed(string) {
17+
if (string) {
18+
console.log(string);
19+
}
20+
},
21+
warn() {},
22+
};
23+
};
24+
425
test('fetches commits and PRs', async t => {
526
/* AurelienLourot had the following activity:
627
* 2017-08-26: nothing
728
* 2017-08-27: 14 commits in AurelienLourot/mybeir.ut
829
* 2017-08-28: 1 PR in tt-gf/ant-ivy */
930

10-
const ora = string => {
11-
if (string) {
12-
console.log(string);
13-
}
14-
return {
15-
start(string) {
16-
if (string) {
17-
console.log(string);
18-
}
19-
return this;
20-
},
21-
stop() {},
22-
succeed(string) {
23-
if (string) {
24-
console.log(string);
25-
}
26-
},
27-
warn() {},
28-
};
29-
};
30-
3131
const result = await m.fetch('AurelienLourot', '2017-08-26', '2017-08-28', ora, console);
3232
t.is(result.size, 2);
3333
t.true(result.has('AurelienLourot/mybeir.ut'));
3434
t.true(result.has('tt-gf/ant-ivy'));
3535
});
36+
37+
test('fetches issues', async t => {
38+
/* RichardLitt had the following activity:
39+
* 2018-08-07: 1 issue in orbitdb/welcome */
40+
41+
const result = await m.fetch('RichardLitt', '2018-08-07', '2018-08-07', ora, console, true);
42+
t.is(result.size, 1);
43+
t.true(result.has('orbitdb/welcome'));
44+
});
45+
46+
test('fetches hot issues', async t => {
47+
/* AurelienLourot had the following activity:
48+
* 2015-09-23: 1 commit in AurelienLourot/AurelienLourot.github.io
49+
1 hot issue in jfrog/build-info */
50+
51+
const result = await m.fetch('AurelienLourot', '2015-09-23', '2015-09-23', ora, console, true);
52+
t.is(result.size, 2);
53+
t.true(result.has('AurelienLourot/AurelienLourot.github.io'));
54+
t.true(result.has('jfrog/build-info'));
55+
});

0 commit comments

Comments
 (0)