summaryrefslogtreecommitdiff
path: root/scripts/publish_github_stats.js
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/publish_github_stats.js')
-rwxr-xr-xscripts/publish_github_stats.js147
1 files changed, 147 insertions, 0 deletions
diff --git a/scripts/publish_github_stats.js b/scripts/publish_github_stats.js
new file mode 100755
index 0000000000..f79a5082d0
--- /dev/null
+++ b/scripts/publish_github_stats.js
@@ -0,0 +1,147 @@
+#!/usr/bin/env node
+
+const assert = require('assert');
+const jwt = require('jsonwebtoken');
+const github = require('@octokit/rest')();
+const zlib = require('zlib');
+const AWS = require('aws-sdk');
+
+const SIZE_CHECK_APP_ID = 14028;
+const SIZE_CHECK_APP_INSTALLATION_ID = 229425;
+
+// Error handling
+
+process.on('unhandledRejection', error => {
+ console.log(error);
+ process.exit(1)
+});
+
+// Github authorization
+
+const pk = process.env['SIZE_CHECK_APP_PRIVATE_KEY'];
+if (!pk) {
+ console.log('Fork PR; not publishing size.');
+ process.exit(0);
+}
+
+const key = Buffer.from(pk, 'base64').toString('binary');
+const payload = {
+ exp: Math.floor(Date.now() / 1000) + 60,
+ iat: Math.floor(Date.now() / 1000),
+ iss: SIZE_CHECK_APP_ID
+};
+
+const token = jwt.sign(payload, key, {algorithm: 'RS256'});
+github.authenticate({type: 'app', token});
+
+// Metrics: Github statistics
+let openIssuesTotal = 0;
+let openIssuesTotalFromNonMembers = 0;
+let openIssuesTotalCore = 0;
+let openIssuesTotalAndroid = 0;
+let openIssuesTotalIOS = 0;
+let openIssuesTotalGLJSParity = 0;
+let openPullRequestsTotal = 0;
+let openPullRequestsTotalFromNonMembers = 0;
+let openPullRequestsSinceLastMonth = 0;
+let openPullRequestsSinceLastMonthFromNonMembers = 0;
+
+function collectMetricsFromIssues(issues) {
+ const oneMonthAgo = function() { let date = new Date(); date.setMonth(date.getMonth() - 1); return date; }();
+
+ // Metrics
+ issues.data.forEach(function (issue) {
+ const issueCreatedAt = new Date(issue.created_at);
+ const isMapboxAuthor = issue.author_association === "MEMBER";
+
+ if (issue.pull_request) {
+ openPullRequestsTotal++;
+ if (!isMapboxAuthor) {
+ openPullRequestsTotalFromNonMembers++;
+ }
+ if (issueCreatedAt >= oneMonthAgo) {
+ openPullRequestsSinceLastMonth++;
+ if (!isMapboxAuthor) {
+ openPullRequestsSinceLastMonthFromNonMembers++;
+ }
+ }
+ } else {
+ openIssuesTotal++;
+ if (!isMapboxAuthor) {
+ openIssuesTotalFromNonMembers++;
+ }
+ issue.labels.forEach(function (label) {
+ switch (label.name) {
+ case "Core":
+ openIssuesTotalCore++;
+ break;
+ case "Android":
+ openIssuesTotalAndroid++;
+ break;
+ case "iOS":
+ openIssuesTotalIOS++;
+ break;
+ case "GL JS parity":
+ openIssuesTotalGLJSParity++;
+ break;
+ default:
+ break;
+ }
+ });
+ }
+ });
+}
+
+function publishMetrics() {
+ let metrics = {
+ 'created_at': new Date().toISOString().substring(0, 10),
+ 'open_issues_total': openIssuesTotal,
+ 'open_issues_total_from_non_members': openIssuesTotalFromNonMembers,
+ 'open_issues_total_core': openIssuesTotalCore,
+ 'open_issues_total_android': openIssuesTotalAndroid,
+ 'open_issues_total_ios': openIssuesTotalIOS,
+ 'open_issues_total_gl_js_parity': openIssuesTotalGLJSParity,
+ 'open_pull_requests_total': openPullRequestsTotal,
+ 'open_pull_requests_total_from_non_members': openPullRequestsTotalFromNonMembers,
+ 'open_pull_requests_since_last_month': openPullRequestsSinceLastMonth,
+ 'open_pull_requests_since_last_month_from_non_members': openPullRequestsSinceLastMonthFromNonMembers
+ };
+
+ var promise = new AWS.S3({region: 'us-east-1'}).putObject({
+ Body: zlib.gzipSync(JSON.stringify(metrics)),
+ Bucket: 'mapbox-loading-dock',
+ Key: `raw/mobile_staging.github_stats/${metrics['created_at']}/METRIC.json.gz`,
+ CacheControl: 'max-age=300',
+ ContentEncoding: 'gzip',
+ ContentType: 'application/json'
+ }).promise();
+
+ return Promise.all([promise]).then(data => {
+ return console.log("Successfully uploaded Github Stats metrics to S3");
+ }).catch(err => {
+ console.log("Error uploading Github Stats metrics to S3 " + err.message);
+ return err;
+ });
+}
+
+function recursiveListForRepo(query) {
+ assert(query);
+ query.then(result => {
+ collectMetricsFromIssues(result);
+ if (github.hasNextPage(result)) {
+ recursiveListForRepo(github.getNextPage(result));
+ } else {
+ publishMetrics();
+ }
+ }).catch(error => {
+ console.log("Error fetching the repository issues list: " + err.message);
+ });
+}
+
+github.apps.createInstallationToken({ installation_id: SIZE_CHECK_APP_INSTALLATION_ID })
+ .then(({data}) => {
+ github.authenticate({ type: 'token', token: data.token });
+ })
+ .then(() => {
+ recursiveListForRepo(github.issues.listForRepo({ owner: 'mapbox', repo: 'mapbox-gl-native', state: 'open', per_page: 100 }));
+ });