refactor: Update GitHubUtil to use HostedCodeRepository/HostedCodeRepository

This commit is contained in:
Simon Larsen 2024-06-12 15:11:50 +01:00
parent 7d8036e3eb
commit cf7d4c7720
No known key found for this signature in database
GPG Key ID: 96C5DCA24769DBCA
7 changed files with 203 additions and 69 deletions

View File

@ -1,15 +1,16 @@
import URL from "../API/URL";
import PullRequestState from "./PullRequestState";
import URL from '../API/URL';
import PullRequestState from './PullRequestState';
export default interface PullRequest {
export default interface PullRequest {
url: URL;
id: number;
pullRequestId: number;
pullRequestNumber: number;
state: PullRequestState;
title: string;
body: string;
title: string;
body: string;
createdAt: Date;
updatedAt: Date;
headRefName: string; // this is the branch name of the pull request
repoOrganizationName: string;
repoName: string;
}
}

View File

@ -1,7 +1,7 @@
enum PullRequestState {
enum PullRequestState {
Open = 'open',
Closed = 'closed',
All = 'all'
All = 'all',
}
export default PullRequestState;
export default PullRequestState;

View File

@ -3,7 +3,6 @@ import CodeRepositoryFile from './CodeRepositoryFile';
import Dictionary from 'Common/Types/Dictionary';
export default class CodeRepositoryUtil {
public static async getGitCommitHashForFile(data: {
repoPath: string;
filePath: string;
@ -27,9 +26,7 @@ export default class CodeRepositoryUtil {
const totalPath: string = `${repoPath}/${directoryPath}`;
const files: Dictionary<CodeRepositoryFile> = {};
const output: string = await Execute.executeCommand(
`ls ${totalPath}`
);
const output: string = await Execute.executeCommand(`ls ${totalPath}`);
const fileNames: Array<string> = output.split('\n');
@ -41,9 +38,7 @@ export default class CodeRepositoryUtil {
}
const isDirectory: boolean = (
await Execute.executeCommand(
`file "${totalPath}/${fileName}"`
)
await Execute.executeCommand(`file "${totalPath}/${fileName}"`)
).includes('directory');
if (isDirectory) {
@ -75,7 +70,6 @@ export default class CodeRepositoryUtil {
repoPath: string;
directoryPath: string;
}): Promise<Dictionary<CodeRepositoryFile>> {
let files: Dictionary<CodeRepositoryFile> = {};
const { files: filesInDirectory, subDirectories } =

View File

@ -1,22 +1,114 @@
import ServiceRepository from "Model/Models/ServiceRepository";
import HostedCodeRepository from "../HostedCodeRepository/HostedCodeRepository";
import HostedCodeRepository from '../HostedCodeRepository/HostedCodeRepository';
import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse';
import HTTPResponse from 'Common/Types/API/HTTPResponse';
import URL from 'Common/Types/API/URL';
import PullRequest from 'Common/Types/CodeRepository/PullRequest';
import PullRequestState from 'Common/Types/CodeRepository/PullRequestState';
import PullRequest from "Common/Types/CodeRepository/PullRequest";
import OneUptimeDate from 'Common/Types/Date';
import { JSONArray, JSONObject } from 'Common/Types/JSON';
import API from 'Common/Utils/API';
export default class GitHubUtil extends HostedCodeRepository {
public override async getPullRequestsByService(data: {
serviceRepository: ServiceRepository;
pullRequestState: PullRequestState;
baseBranchName?: string | undefined;
}): Promise<Array<PullRequest>> {
const gitHubToken: string = this.authToken;
const { serviceRepository } = data;
return [];
// fetch all open pull requests for the repository on github
private getPullRequestFromJSONObject(data: {
pullRequest: JSONObject;
organizationName: string;
repositoryName: string;
}): PullRequest {
return {
pullRequestId: data.pullRequest['id'] as number,
pullRequestNumber: data.pullRequest['number'] as number,
title: data.pullRequest['title'] as string,
body: data.pullRequest['body'] as string,
url: URL.fromString(data.pullRequest['url'] as string),
state: data.pullRequest['state'] as PullRequestState,
createdAt: OneUptimeDate.fromString(
data.pullRequest['created_at'] as string
),
updatedAt: OneUptimeDate.fromString(
data.pullRequest['updated_at'] as string
),
repoOrganizationName: data.organizationName,
repoName: data.repositoryName,
headRefName:
data.pullRequest['head'] &&
(data.pullRequest['head'] as JSONObject)['ref']
? ((data.pullRequest['head'] as JSONObject)[
'ref'
] as string)
: '',
};
}
}
public async getPullRequestByNumber(data: {
organizationName: string;
repositoryName: string;
pullRequestNumber: number;
}): Promise<PullRequest> {
const gitHubToken: string = this.authToken;
const url: URL = URL.fromString(
`https://api.github.com/repos/${data.organizationName}/${data.repositoryName}/pulls/${data.pullRequestNumber}`
);
const result: HTTPErrorResponse | HTTPResponse<JSONObject> =
await API.get(
url,
{},
{
Authorization: `Bearer ${gitHubToken}`,
Accept: 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
}
);
if (result instanceof HTTPErrorResponse) {
throw result;
}
return this.getPullRequestFromJSONObject({
pullRequest: result.data,
organizationName: data.organizationName,
repositoryName: data.repositoryName,
});
}
public override async getPullRequests(data: {
pullRequestState: PullRequestState;
baseBranchName: string;
organizationName: string;
repositoryName: string;
}): Promise<Array<PullRequest>> {
const gitHubToken: string = this.authToken;
const url: URL = URL.fromString(
`https://api.github.com/repos/${data.organizationName}/${data.repositoryName}/pulls?base=${data.baseBranchName}&state=${data.pullRequestState}`
);
const result: HTTPErrorResponse | HTTPResponse<JSONArray> =
await API.get(
url,
{},
{
Authorization: `Bearer ${gitHubToken}`,
Accept: 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
}
);
if (result instanceof HTTPErrorResponse) {
throw result;
}
const pullRequests: Array<PullRequest> = result.data.map(
(pullRequest: JSONObject) => {
return this.getPullRequestFromJSONObject({
pullRequest: pullRequest,
organizationName: data.organizationName,
repositoryName: data.repositoryName,
});
}
);
return pullRequests;
}
}

View File

@ -1,14 +1,12 @@
import PullRequestState from "Common/Types/CodeRepository/PullRequestState";
import BadDataException from "Common/Types/Exception/BadDataException";
import NotImplementedException from "Common/Types/Exception/NotImplementedException";
import ServiceRepository from "Model/Models/ServiceRepository";
import PullRequest from "Common/Types/CodeRepository/PullRequest";
export default class HostedCodeRepository {
import PullRequest from 'Common/Types/CodeRepository/PullRequest';
import PullRequestState from 'Common/Types/CodeRepository/PullRequestState';
import BadDataException from 'Common/Types/Exception/BadDataException';
import NotImplementedException from 'Common/Types/Exception/NotImplementedException';
import ServiceRepository from 'Model/Models/ServiceRepository';
export default class HostedCodeRepository {
public constructor(data: { authToken: string }) {
if(!data.authToken){
if (!data.authToken) {
throw new BadDataException('authToken is required');
}
@ -18,22 +16,66 @@ export default class HostedCodeRepository {
public authToken: string = '';
public async numberOfPullRequestsExistForService(data: {
serviceRepository: ServiceRepository,
pullRequestState: PullRequestState,
baseBranchName?: string | undefined
}): Promise<number>{
return (await this.getPullRequestsByService({
serviceRepository: data.serviceRepository,
pullRequestState: data.pullRequestState,
baseBranchName: data.baseBranchName
})).length;
serviceRepository: ServiceRepository;
pullRequestState: PullRequestState;
baseBranchName: string | undefined;
organizationName: string;
repositoryName: string;
}): Promise<number> {
return (
await this.getPullRequestsByService({
serviceRepository: data.serviceRepository,
pullRequestState: data.pullRequestState,
baseBranchName: data.baseBranchName,
organizationName: data.organizationName,
repositoryName: data.repositoryName,
})
).length;
}
public async getPullRequestsByService(_data: {
public async getPullRequestsByService(data: {
serviceRepository: ServiceRepository;
pullRequestState: PullRequestState;
baseBranchName?: string | undefined;
organizationName: string;
repositoryName: string;
}): Promise<Array<PullRequest>> {
if (!data.serviceRepository) {
throw new BadDataException('serviceRepository is required');
}
if (!data.serviceRepository.serviceCatalog) {
throw new BadDataException(
'serviceRepository.serviceCatalog is required'
);
}
if (!data.serviceRepository.serviceCatalog.name) {
throw new BadDataException(
'serviceRepository.serviceCatalog.name is required'
);
}
const pullRequests: Array<PullRequest> = await this.getPullRequests({
pullRequestState: data.pullRequestState,
baseBranchName: data.baseBranchName,
organizationName: data.organizationName,
repositoryName: data.repositoryName,
});
return pullRequests.filter((pullRequest: PullRequest) => {
return pullRequest.headRefName.includes(
`oneuptime-${data.serviceRepository.serviceCatalog?.name?.toLowerCase()}`
);
});
}
public async getPullRequests(_data: {
pullRequestState: PullRequestState;
baseBranchName?: string | undefined;
organizationName: string;
repositoryName: string;
}): Promise<Array<PullRequest>> {
throw new NotImplementedException();
}
}
}

View File

@ -1,11 +1,11 @@
import { CodeRepositoryResult } from './Utils/CodeRepository';
import InitUtil from './Utils/Init';
import ServiceRepositoryUtil from './Utils/ServiceRepository';
import Dictionary from 'Common/Types/Dictionary';
import { PromiseVoidFunction } from 'Common/Types/FunctionTypes';
import CodeRepositoryFile from 'CommonServer/Utils/CodeRepository/CodeRepositoryFile';
import logger from 'CommonServer/Utils/Logger';
import dotenv from 'dotenv';
import ServiceRepositoryUtil from './Utils/ServiceRepository';
dotenv.config();
@ -14,12 +14,17 @@ logger.info('OneUptime Copilot is starting...');
const init: PromiseVoidFunction = async (): Promise<void> => {
const codeRepositoryResult: CodeRepositoryResult = await InitUtil.init();
for(const serviceRepository of codeRepositoryResult.servicesRepository) {
const filesInService: Dictionary<CodeRepositoryFile> = await ServiceRepositoryUtil.getFilesInServiceDirectory({
serviceRepository,
});
for (const serviceRepository of codeRepositoryResult.servicesRepository) {
const filesInService: Dictionary<CodeRepositoryFile> =
await ServiceRepositoryUtil.getFilesInServiceDirectory({
serviceRepository,
});
logger.info(`Files found in ${serviceRepository.serviceCatalog?.name}: ${Object.keys(filesInService).length}`);
logger.info(
`Files found in ${serviceRepository.serviceCatalog?.name}: ${
Object.keys(filesInService).length
}`
);
}
};

View File

@ -1,13 +1,13 @@
import Dictionary from "Common/Types/Dictionary";
import CodeRepositoryFile from "CommonServer/Utils/CodeRepository/CodeRepositoryFile";
import { GetLocalRepositoryPath } from '../Config';
import Dictionary from 'Common/Types/Dictionary';
import CodeRepositoryCommonServerUtil from 'CommonServer/Utils/CodeRepository/CodeRepository';
import { GetLocalRepositoryPath } from "../Config";
import ServiceRepository from "Model/Models/ServiceRepository";
import CodeRepositoryFile from 'CommonServer/Utils/CodeRepository/CodeRepositoryFile';
import ServiceRepository from 'Model/Models/ServiceRepository';
export default class ServiceRepositoryUtil {
public static async getFilesInServiceDirectory(data: {serviceRepository: ServiceRepository} ): Promise<Dictionary<CodeRepositoryFile>> {
public static async getFilesInServiceDirectory(data: {
serviceRepository: ServiceRepository;
}): Promise<Dictionary<CodeRepositoryFile>> {
const { serviceRepository } = data;
const allFiles: Dictionary<CodeRepositoryFile> =
@ -18,4 +18,4 @@ export default class ServiceRepositoryUtil {
return allFiles;
}
}
}