bananareporter
Version:
Easily generate a report from multiple sources
142 lines (141 loc) • 6.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.GithubIntegration = exports.GithubConfig = void 0;
const base_1 = require("./base");
// import {Axios} from 'axios'
const common_1 = require("../util/common");
const zod_1 = require("zod");
const axios_1 = require("axios");
const dayjs = require("dayjs");
const logger_1 = require("../util/logger");
const objectPath = require("object-path");
exports.GithubConfig = zod_1.z.object({
committerUsername: zod_1.z.string().min(1),
/**
* needed only if you want to access commits
* made to private repositories
*/
token: zod_1.z.string().min(1).optional(),
filters: zod_1.z.array(zod_1.z.object({
on: zod_1.z.string().min(1),
regex: zod_1.z.string().min(1),
})).nonempty().optional(),
domain: zod_1.z.string().optional().default('api.github.com'),
apiVersion: zod_1.z.string().startsWith('2').optional().default('2022-11-28'),
protocol: zod_1.z.union([zod_1.z.literal('http'), zod_1.z.literal('https')]).optional().default('https'),
// TODO should be extended from a base integration
from: common_1.zIsoString.optional(),
to: common_1.zIsoString.optional(),
delay: zod_1.z.number().min(0).optional(),
});
class GithubIntegration extends base_1.IntegrationBase {
constructor(_rawConfig, bananaReporterConfig) {
var _a, _b, _c;
super(_rawConfig, bananaReporterConfig);
logger_1.logger.debug('github integration');
this.config = exports.GithubConfig.parse(_rawConfig);
logger_1.logger.debug('github integration config', this.config);
this.bananaReporterConfig = bananaReporterConfig;
this.delayToUse = (_a = this.config.delay) !== null && _a !== void 0 ? _a : this.bananaReporterConfig.delay;
logger_1.logger.debug(`github integration delayToUse ${this.delayToUse}`);
this.dateRange = {
from: (_b = this.config.from) !== null && _b !== void 0 ? _b : this.bananaReporterConfig.from,
to: (_c = this.config.to) !== null && _c !== void 0 ? _c : this.bananaReporterConfig.to,
};
logger_1.logger.debug('github integration dateRange', this.dateRange);
const baseURL = `${this.config.protocol}://${this.config.domain}`;
logger_1.logger.debug(`github integration baseURL ${baseURL}`);
this.httpClient = axios_1.default.create({
baseURL,
headers: {
Authorization: this.config.token ? `Bearer ${this.config.token}` : undefined,
'X-GitHub-Api-Version': this.config.apiVersion,
Accept: 'application/vnd.github+json',
},
timeout: 35000,
});
}
async httpRequest(path, config) {
logger_1.logger.debug(`github integration http request ${path}`, config);
const res = await this.httpClient(path, {
...config,
});
return res.data;
}
async fetchData() {
let page = 1;
let commitList = [];
while (page > 0) {
logger_1.logger.debug(`github integration working on ${page}`);
/* eslint-disable no-await-in-loop */
const commits = await this.getUserCommits(this.config.committerUsername, {
from: this.dateRange.from,
to: this.dateRange.to,
page,
});
// no more data, break loop
if (commits.items.length === 0) {
logger_1.logger.debug('github integration no more commits to process');
break;
}
// eslint-disable-next-line unicorn/prefer-spread
commitList = commitList.concat(commits.items);
logger_1.logger.debug(`github integration commitList ${commitList.length} (added ${commits.items.length} commits)`);
page += 1;
await (0, common_1.delay)(this.delayToUse);
}
// format data to common obj
for (const filter of this.config.filters || []) {
const targetKey = filter.on;
commitList = commitList.filter(c => {
const regex = new RegExp(filter.regex);
const value = objectPath.get(c, targetKey);
if (typeof value === 'undefined') {
const errorMsg = `while filtering commit ${c.sha} unable to find the key ${targetKey} in the commit's object (available keys: ${Object.keys(c).join(',')})`;
logger_1.logger.error(errorMsg);
throw new Error(errorMsg);
}
return regex.test(value);
});
}
const formattedData = commitList.map(e => this.toBananaReporterObj(e));
return formattedData;
}
async getUserCommits(username, options) {
var _a;
const fromDate = dayjs(options.from);
const toDate = dayjs(options.to);
const from = fromDate.format('YYYY-MM-DD');
const to = toDate.format('YYYY-MM-DD');
logger_1.logger.debug(`github integration getUserCommits from ${from} to ${to}`);
const page = (_a = options.page) !== null && _a !== void 0 ? _a : 1;
const url = '/search/commits';
const commits = await this.httpRequest(url, {
params: {
q: `committer:${username} committer-date:${from}..${to}`,
sort: 'asc',
// eslint-disable-next-line camelcase
per_page: 100,
page,
},
});
return commits;
}
toBananaReporterObj(rawData) {
const projectId = rawData.repository.id;
const projectName = rawData.repository.name;
const description = `${rawData.commit.message} git:${rawData.sha.slice(0, 7)}`;
return {
id: rawData.sha,
date: rawData.commit.committer.date,
username: rawData.commit.committer.name,
description,
projectId: String(projectId),
projectName,
type: GithubIntegration.type,
__raw: this.bananaReporterConfig.includeRawObject ? rawData : undefined,
};
}
}
exports.GithubIntegration = GithubIntegration;
GithubIntegration.type = base_1.SourceType.Enum.github;