178 lines
6.2 KiB
JavaScript
Executable File
178 lines
6.2 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
||
|
||
const jwt = require('jsonwebtoken');
|
||
const github = require('@octokit/rest').plugin(require('@octokit/plugin-retry'))({
|
||
retry: { doNotRetry: [ /* Empty — retry on any error code. */ ] }
|
||
})
|
||
const zlib = require('zlib');
|
||
const AWS = require('aws-sdk');
|
||
|
||
const SIZE_CHECK_APP_ID = 14028;
|
||
const SIZE_CHECK_APP_INSTALLATION_ID = 229425;
|
||
|
||
process.on('unhandledRejection', error => {
|
||
console.log(error);
|
||
process.exit(1)
|
||
});
|
||
|
||
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});
|
||
|
||
// Must be in sync with the definition in metrics/binary-size/index.html on the gh-pages branch.
|
||
const platforms = [
|
||
{ 'platform': 'iOS', 'arch': 'armv7' },
|
||
{ 'platform': 'iOS', 'arch': 'arm64' },
|
||
{ 'platform': 'iOS', 'arch': 'Dynamic' },
|
||
{ 'platform': 'Android', 'arch': 'arm-v7' },
|
||
{ 'platform': 'Android', 'arch': 'arm-v8' },
|
||
{ 'platform': 'Android', 'arch': 'x86' },
|
||
{ 'platform': 'Android', 'arch': 'x86_64' }
|
||
];
|
||
|
||
const sizeCheckInfo = [];
|
||
const rows = [];
|
||
const date = new Date().toISOString().substring(0, 19);
|
||
|
||
function query(after) {
|
||
return github.request({
|
||
method: 'POST',
|
||
url: '/graphql',
|
||
headers: {
|
||
// https://developer.github.com/changes/2018-07-11-graphql-checks-preview/
|
||
accept: 'application/vnd.github.antiope-preview'
|
||
},
|
||
query: `query {
|
||
repository(owner: "mapbox", name: "mapbox-gl-native") {
|
||
ref(qualifiedName: "main") {
|
||
target {
|
||
... on Commit {
|
||
history(first: 100, before: "36c6a8ea79bbd2596abb58ffb58debf65a4ea13d" ${after ? `, after: "${after}"` : ''}) {
|
||
pageInfo {
|
||
hasNextPage
|
||
endCursor
|
||
}
|
||
edges {
|
||
node {
|
||
oid
|
||
messageHeadline
|
||
checkSuites(first: 1, filterBy: {appId: ${SIZE_CHECK_APP_ID}}) {
|
||
nodes {
|
||
checkRuns(first: 10) {
|
||
nodes {
|
||
name
|
||
conclusion
|
||
title
|
||
summary
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}`
|
||
}).then((result) => {
|
||
|
||
const history = result.data.data.repository.ref.target.history;
|
||
|
||
for (const edge of history.edges) {
|
||
const commit = edge.node;
|
||
const suite = commit.checkSuites.nodes[0];
|
||
|
||
if (!suite)
|
||
continue;
|
||
const allRuns = commit.checkSuites.nodes[0].checkRuns.nodes;
|
||
|
||
const sizeCheckRuns = allRuns.filter(function (run) {
|
||
return run.name.match(/Size - (\w+) ([\w-]+)/);
|
||
});
|
||
|
||
const row = [`${commit.oid.slice(0, 7)} - ${commit.messageHeadline}`];
|
||
|
||
for (let i = 0; i < platforms.length; i++) {
|
||
const {platform, arch} = platforms[i];
|
||
|
||
const run = sizeCheckRuns.find((run) => {
|
||
const [, p, a] = run.name.match(/Size - (\w+) ([\w-]+)/);
|
||
return platform === p && arch === a;
|
||
});
|
||
|
||
row[i + 1] = run ? +run.summary.match(/is (\d+) bytes/)[1] : undefined;
|
||
}
|
||
rows.push(row);
|
||
}
|
||
|
||
if (history.pageInfo.hasNextPage) {
|
||
return query(history.pageInfo.endCursor);
|
||
} else {
|
||
const latestRun = rows[0]
|
||
const runSizeMeasurements = latestRun.slice(1)
|
||
|
||
for (let i = 0; i < platforms.length; i++) {
|
||
const {platform, arch} = platforms[i];
|
||
|
||
sizeCheckInfo.push(JSON.stringify({
|
||
'sdk': 'maps',
|
||
'platform' : platform,
|
||
'arch': arch,
|
||
'size' : runSizeMeasurements[i],
|
||
'created_at': date
|
||
}));
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
github.apps.createInstallationToken({installation_id: SIZE_CHECK_APP_INSTALLATION_ID})
|
||
.then(({data}) => {
|
||
github.authenticate({type: 'token', token: data.token});
|
||
|
||
return query().then(function() {
|
||
// Uploads to data source used by
|
||
// http://mapbox.github.io/mapbox-gl-native/metrics/binary-size/
|
||
var firstPromise = new AWS.S3({region: 'us-east-1'}).putObject({
|
||
Body: zlib.gzipSync(JSON.stringify(rows.reverse())),
|
||
Bucket: 'mapbox',
|
||
Key: 'mapbox-gl-native/metrics/binary-size/data.json',
|
||
ACL: 'public-read',
|
||
CacheControl: 'max-age=300',
|
||
ContentEncoding: 'gzip',
|
||
ContentType: 'application/json'
|
||
}).promise();
|
||
// Uploads to data source used by Mapbox internal metrics dashboards
|
||
var secondPromise = new AWS.S3({region: 'us-east-1'}).putObject({
|
||
Body: zlib.gzipSync(sizeCheckInfo.join('\n')),
|
||
Bucket: 'mapbox-loading-dock',
|
||
Key: `raw/mobile.binarysize/${date.substring(0,10)}/mapbox-maps-ios-android-${process.env['CIRCLE_SHA1']}.json.gz`,
|
||
CacheControl: 'max-age=300',
|
||
ContentEncoding: 'gzip',
|
||
ContentType: 'application/json'
|
||
}).promise();
|
||
|
||
return Promise.all([firstPromise, secondPromise]).then(data => {
|
||
return console.log("Successfully uploaded all binary size metrics to S3");
|
||
}).catch(err => {
|
||
console.log("Error uploading binary size metrics to S3 " + err.message);
|
||
return err;
|
||
});
|
||
});
|
||
});
|
||
|
||
|