Skip to content

Commit

Permalink
fix(best-github-integration): Simplify authentication + Git based ord…
Browse files Browse the repository at this point in the history
…er (#74)

* fix(best-github-integration): Simplify authentication
* Fix CircleCI
* Guard for env variable
* Git ordering
  • Loading branch information
diervo authored Feb 6, 2018
1 parent 57f2d08 commit a2f92ed
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
environment:
- CUSTOM_BASH_ENV: ~/.bashrc
- CIRCLE_ENV_BROKEN: $CIRCLE_SHA1
- PATH_GIT_APP_CERT: ~/best/git_app.pem
- GIT_APP_CERT_PATH: ~/best/git_app.pem

steps:
- checkout
Expand Down
2 changes: 1 addition & 1 deletion packages/best-cli/src/run_compare.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function runCompare(globalConfig, configs, outputStream) {
const compareResults = await compareBenchmarkStats(baseCommit, compareCommit, projectName, storageProvider);

if (gitIntegration) {
await pushBenchmarkComparison(baseCommit, compareCommit, compareResults);
await pushBenchmarkComparison(baseCommit, compareCommit, compareResults, globalConfig);
}

return compareResults;
Expand Down
1 change: 1 addition & 0 deletions packages/best-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"url": "https://github.com/salesforce/best"
},
"dependencies": {
"@best/github-integration": "0.0.10",
"@best/store-aws": "0.0.10",
"apicache": "^1.2.0",
"express": "^4.16.2",
Expand Down
53 changes: 48 additions & 5 deletions packages/best-frontend/server/api_v1.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,52 @@
const apicache = require('apicache');
const memoize = require('memoizee');
const crypto = require('crypto');
const gitIntegration = require("@best/github-integration");

const cache = apicache.middleware;
const onlyStatus200 = (req, res) => res.statusCode === 0;
const cacheSuccesses = cache('2 minutes', onlyStatus200);
const memoizeConfig = { promise: true };

// -- Globals configs ---------------------

const GIT_ORG = process.env.GIT_ORG;
const GIT_PROJECTS = process.env.GIT_PROJECTS || '{}';
let GIT_ORG_API;
let PROJECTS = {};

const memoizeConfig = { promise: true };
let memoizedGetBenchPerCommit;

function addRoutes(router, store) {
// memoize calls when routers gets invoked
// -- Internal APIs ------------------------

async function getOrganizationInstallation(org) {
const APP = gitIntegration.createGithubApp();
const gitAppAuth = await APP.authAsApp();
const installations = await gitAppAuth.apps.getInstallations({});
const repoInstallation = installations.data.find((i) => i.account.login === org);
const installationId = repoInstallation.id;
const owner = repoInstallation.account.login;
const gitOrgApi = await APP.authAsInstallation(installationId);
return gitOrgApi;
}

function initialize(store) {
if (GIT_ORG) {
PROJECTS = JSON.parse(GIT_PROJECTS[0] === '\'' ? GIT_PROJECTS.slice(1, -1) : GIT_PROJECTS);
getOrganizationInstallation(GIT_ORG).then((gitAPI) => {
GIT_ORG_API = gitAPI;
}, () => {
console.log(`Unable to initialize Github API`);
});
}
// Memoize calls when routers gets invoked
memoizedGetBenchPerCommit = memoize(async (project, commit) =>
Object.freeze(store.getAllBenchmarkStatsPerCommit(project, commit), memoizeConfig)
);
}

function addRoutes(router, store) {
initialize(store);
router.get('/cache/index', (req, res) => res.json(apicache.getIndex()));
router.get('/cache/clear', (req, res) => res.json(apicache.clear()));

Expand Down Expand Up @@ -81,12 +113,23 @@ function addRoutes(router, store) {
}

async function getLastCommitStats(store, projectName, branch, size = 30) {
const gitRepo = PROJECTS[projectName];
let gitLastCommits = [];
if (GIT_ORG_API && gitRepo) {
const [owner, repo] = gitRepo.split('/');
const { data } = await GIT_ORG_API.repos.getCommits({ owner, repo, per_page: size });
gitLastCommits = data.map(c => c.sha.slice(0, 7));
}

const commits = await store.getCommits(projectName, branch);
const lastCommits = commits.slice(0, size);
return Promise.all(lastCommits.map(async (commit) => {
const lastCommits = gitLastCommits.length ? gitLastCommits.reverse().filter((i) => commits.indexOf(i) !== -1 ) : commits.slice(0, size);

const lastCommitBenchmarks = await Promise.all(lastCommits.map(async (commit) => {
let benchmarks = await memoizedGetBenchPerCommit(projectName, commit);
return { commit, benchmarks };
}));

return lastCommitBenchmarks;
}

exports.addRoutes = addRoutes;
Expand Down
1 change: 0 additions & 1 deletion packages/best-frontend/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const onlyStatus200 = (req, res) => res.statusCode === 2000;
const cacheSuccesses = cache('5 minutes', onlyStatus200);

// -- Routes ---------------------------

// API for benchmarks, stats & artifacts
app.use('/api/v1', ApiV1.addRoutes(express.Router(), storeInstance));

Expand Down
1 change: 1 addition & 0 deletions packages/best-github-integration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"main": "build/index.js",
"module": "src/index.js",
"dependencies": {
"base-64": "^0.1.0",
"@best/messager": "0.0.10",
"@best/utils": "0.0.10",
"expand-tilde": "~2.0.2",
Expand Down
9 changes: 7 additions & 2 deletions packages/best-github-integration/src/git-app.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint camelcase: 0 */
import fs from 'fs';
import jwt from 'jsonwebtoken';
import base64 from 'base-64';
import expandTilde from 'expand-tilde';
import GitHubApi from 'github';

Expand All @@ -14,8 +15,12 @@ const APP_ID = process.env.GIT_APP_ID;
* (OUTPUT) In the CI we do:
* echo -e "$GIT_APP_CERT" | base64 -d >> ${PATH_GIT_APP_CERT}
*/
const PATH_GIT_APP_CERT = process.env.PATH_GIT_APP_CERT;
const APP_CERT = PATH_GIT_APP_CERT ? fs.readFileSync(expandTilde(PATH_GIT_APP_CERT)) : null;

const GIT_APP_CERT_PATH = process.env.GIT_APP_CERT_PATH;
const GIT_APP_CERT_BASE64 = process.env.GIT_APP_CERT_BASE64;

const APP_CERT_BASE64 = GIT_APP_CERT_BASE64 ? (GIT_APP_CERT_BASE64[0] === '\'' ? base64.decode(GIT_APP_CERT_BASE64.slice(1, -1)) : base64.decode(GIT_APP_CERT_BASE64)) : null;
const APP_CERT = GIT_APP_CERT_PATH ? fs.readFileSync(expandTilde(GIT_APP_CERT_PATH)) : APP_CERT_BASE64;

function generateJwt(id, cert) {
const payload = {
Expand Down
7 changes: 5 additions & 2 deletions packages/best-github-integration/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@ import { generateComparisonComment } from './comment';
const PULL_REQUEST_URL = process.env.PULL_REQUEST;
const REPO_NAME = process.env.REPO_NAME;

export async function pushBenchmarkComparison(baseCommit, targetCommit, compareStats) {
export async function pushBenchmarkComparison(baseCommit, targetCommit, compareStats, { gitRepository }) {
if (!isCI) {
// throw new Error('GitIntegration is only supposed to run on a CI environment');
console.log('[NOT A CI] - The output will not be pushed.\n');
console.log(generateComparisonComment(baseCommit, targetCommit, compareStats), '\n');
return;
}

const repoOwner = gitRepository.owner;
const APP = createGithubApp();
const gitAppAuth = await APP.authAsApp();
const installations = await gitAppAuth.apps.getInstallations({});
const repoInstallation = installations.data[0];
const repoInstallation = installations.data.find((i) => i.account.login === repoOwner);
const installationId = repoInstallation.id;
const owner = repoInstallation.account.login;
const gitHubInstallation = await APP.authAsInstallation(installationId);
Expand All @@ -30,3 +31,5 @@ export async function pushBenchmarkComparison(baseCommit, targetCommit, compareS
number: pullRequestId,
});
}

export { createGithubApp };
21 changes: 12 additions & 9 deletions packages/best-store-aws/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,18 @@ export async function storeBenchmarkResults(
export async function getAllBenchmarkStatsPerCommit(projectName, commit) {
const s3 = getS3Instance();
const benchmarks = await s3.getBenchmarkUrlsForCommit(projectName, commit);
console.log(AWS_TEXT + ` Fetching benchmarks for commit ${commit}...`);
return Promise.all(
benchmarks.map(async url => {
const fullUrl = url + '/stats.json';
console.log(AWS_TEXT + ` Fetching benchmark ${fullUrl}`);
const response = await fetch(fullUrl);
return response.json();
}),
);
if (benchmarks && benchmarks.length) {
console.log(AWS_TEXT + ` Fetching benchmarks for commit ${commit}...`);
return Promise.all(
benchmarks.map(async url => {
const fullUrl = url + '/stats.json';
console.log(AWS_TEXT + ` Fetching benchmark ${fullUrl}`);
const response = await fetch(fullUrl);
return response.json();
}),
);
}
return benchmarks;
}

export function getProjects() {
Expand Down
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,10 @@ balanced-match@^1.0.0:
version "1.0.0"
resolved "http://npm.lwcjs.org/balanced-match/-/balanced-match-1.0.0/89b4d199ab2bee49de164ea02b89ce462d71b767.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"

base-64@^0.1.0:
version "0.1.0"
resolved "http://npm.lwcjs.org/base-64/-/base-64-0.1.0/780a99c84e7d600260361511c4877613bf24f6bb.tgz#780a99c84e7d600260361511c4877613bf24f6bb"

[email protected]:
version "0.1.5"
resolved "http://npm.lwcjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5/73926771923b5a19747ad666aa5cd4bf9c6e9ce8.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
Expand Down

0 comments on commit a2f92ed

Please sign in to comment.