Skip to content

Commit 6d1018f

Browse files
authored
feat: add stats endpoint (#70)
1 parent e212720 commit 6d1018f

File tree

9 files changed

+148
-96
lines changed

9 files changed

+148
-96
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Ideas not as issues yet:
2424

2525

2626
### Testing serverless locally
27-
`yarn add serverless-dotenv-plugin`
27+
`yarn add serverless-dotenv-plugin --dev`
2828

2929
in `serverless.yml` plugins add:
3030
`- serverless-dotenv-plugin`

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
"test-ci": "jest --reporters ./node_modules/jest-junit --collectCoverage"
2424
},
2525
"dependencies": {
26-
"@probot/serverless-lambda": "^0.2.0",
2726
"all-contributors-cli": "^5.10.1",
2827
"compromise": "^11.13.0",
2928
"probot": "^8.0.0-octokit-16-preview"

serverless.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,16 @@ provider:
3737

3838
functions:
3939
githubWebhook:
40-
handler: src/handler.probot
40+
handler: src/serverless-webhook.handler
4141
events:
4242
- http:
4343
path: /
4444
method: post
4545
cors: true
46+
stats:
47+
handler: src/serverless-stats.handler
48+
events:
49+
- http:
50+
path: /stats
51+
method: get
52+
cors: true

src/handler.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/probot/getProbot.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const { createProbot } = require('probot')
2+
const { findPrivateKey } = require('probot/lib/private-key')
3+
4+
let probot
5+
6+
function getProbot() {
7+
probot =
8+
probot ||
9+
createProbot({
10+
id: process.env.APP_ID,
11+
secret: process.env.WEBHOOK_SECRET,
12+
cert: findPrivateKey(),
13+
})
14+
15+
if (process.env.SENTRY_DSN) {
16+
probot.load(require('probot/lib/apps/sentry'))
17+
}
18+
19+
return probot
20+
}
21+
22+
module.exports = getProbot

src/serverless-lambda.js

Lines changed: 0 additions & 84 deletions
This file was deleted.

src/serverless-stats.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
const getProbot = require('./probot/getProbot')
2+
3+
async function getInstallations(app) {
4+
const github = await app.auth()
5+
6+
return github.paginate(
7+
github.apps.listInstallations.endpoint.merge({
8+
per_page: 100,
9+
headers: {
10+
accept: 'application/vnd.github.machine-man-preview+json',
11+
},
12+
}),
13+
response => {
14+
return response.data
15+
},
16+
)
17+
}
18+
19+
async function popularInstallations({ app, installations }) {
20+
let popular = await Promise.all(
21+
installations.map(async installation => {
22+
const { account } = installation
23+
24+
const github = await app.auth(installation.id)
25+
26+
const repositories = await github.paginate(
27+
github.apps.listRepos.endpoint.merge({
28+
per_page: 100,
29+
headers: {
30+
accept:
31+
'application/vnd.github.machine-man-preview+json',
32+
},
33+
}),
34+
response => {
35+
return response.data.repositories.filter(
36+
repository => !repository.private,
37+
)
38+
},
39+
)
40+
41+
account.stars = repositories.reduce((stars, repository) => {
42+
return stars + repository.stargazers_count
43+
}, 0)
44+
45+
return account
46+
}),
47+
)
48+
49+
popular = popular.filter(installation => installation.stars > 0)
50+
return popular.sort((a, b) => b.stars - a.stars).slice(0, 10)
51+
}
52+
53+
async function getStats(probot) {
54+
const app = probot.apps[0]
55+
56+
if (!app) {
57+
throw new Error(
58+
'Stats needs an app, we usually depend on sentry being loaded. You can load sentry by setting the SENTRY_DSN env variable)',
59+
)
60+
}
61+
62+
const installations = await getInstallations(app)
63+
const popular = await popularInstallations({ app, installations })
64+
return {
65+
installations: installations.length,
66+
popular,
67+
}
68+
}
69+
70+
module.exports.handler = async (event, context) => {
71+
context.callbackWaitsForEmptyEventLoop = false
72+
73+
try {
74+
const probot = getProbot()
75+
const stats = await getStats(probot)
76+
return {
77+
statusCode: 200,
78+
body: JSON.stringify(stats),
79+
}
80+
} catch (error) {
81+
return {
82+
statusCode: 500,
83+
body: JSON.stringify(error.message),
84+
}
85+
}
86+
}

src/serverless-webhook.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const getProbot = require('./probot/getProbot')
2+
const appFn = require('./')
3+
4+
module.exports.handler = async (event, context) => {
5+
context.callbackWaitsForEmptyEventLoop = false
6+
7+
try {
8+
const probot = getProbot()
9+
probot.load(appFn)
10+
11+
const name =
12+
event.headers['x-github-event'] || event.headers['X-GitHub-Event']
13+
const payload =
14+
typeof event.body === 'string' ? JSON.parse(event.body) : event.body
15+
await probot.receive({
16+
name,
17+
payload,
18+
})
19+
return {
20+
statusCode: 200,
21+
body: JSON.stringify({
22+
message: `Received ${name}.${payload.action}`,
23+
}),
24+
}
25+
} catch (error) {
26+
return {
27+
statusCode: 500,
28+
body: JSON.stringify(error.message),
29+
}
30+
}
31+
}

yarn.lock

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,6 @@
181181
buffer-equal-constant-time "^1.0.1"
182182
debug "^4.0.0"
183183

184-
"@probot/serverless-lambda@^0.2.0":
185-
version "0.2.0"
186-
resolved "https://registry.yarnpkg.com/@probot/serverless-lambda/-/serverless-lambda-0.2.0.tgz#09ec3c5b77486d8e5e406337b8d46a38418d1019"
187-
188184
"@serverless/platform-sdk@^0.3.0":
189185
version "0.3.0"
190186
resolved "https://registry.yarnpkg.com/@serverless/platform-sdk/-/platform-sdk-0.3.0.tgz#335adeb2759760e4232c321d72b4022e4dce7818"

0 commit comments

Comments
 (0)