refactor: Improve comments in code and update job function in app.py

This commit is contained in:
Simon Larsen
2024-06-20 13:14:39 +01:00
parent 6e5081a4e3
commit 1260e482cf
5 changed files with 172 additions and 9 deletions

View File

@@ -1,7 +1,7 @@
enum CopilotActionType {
IMPROVE_COMMENTS = "IMPROVE_COMMENTS",
FIX_GRAMMAR_AND_SPELLING = "FIX_GRAMMAR_AND_SPELLING",
IMPROVE_VARIABLE_NAMES = "IMPROVE_VARIABLE_NAMES",
IMPROVE_COMMENTS = "Improve Comments",
FIX_GRAMMAR_AND_SPELLING = "Fix Grammar and Spelling",
IMPROVE_VARIABLE_NAMES = "Improve Variable Names",
}
export default CopilotActionType;

View File

@@ -4,9 +4,10 @@ import CopilotActionType from "Common/Types/Copilot/CopilotActionType";
import BadDataException from "Common/Types/Exception/BadDataException";
import LLM from "../LLM/LLM";
import { GetLlmType } from "../../Config";
import Text from "Common/Types/Text";
export interface CopilotActionRunResult {
result: string;
code: string;
}
export interface CopilotActionPrompt {
@@ -15,6 +16,7 @@ export interface CopilotActionPrompt {
export interface CopilotActionVars {
code: string;
filePath: string;
}
export default class CopilotActionBase {
@@ -35,17 +37,82 @@ export default class CopilotActionBase {
return data.result;
}
public async getBranchName(): Promise<string> {
const randomText: string = Text.generateRandomText(5);
return `${Text.pascalCaseToDashes(this.copilotActionType).toLowerCase()}-${randomText}`;
}
public async getPullRequestTitle(data: {
vars: CopilotActionVars;
}): Promise<string> {
return `OneUptime Copilot: ${this.copilotActionType} on ${data.vars.filePath}`;
}
public async getPullRequestBody(data: {
vars: CopilotActionVars;
}): Promise<string> {
return `OneUptime Copilot: ${this.copilotActionType} on ${data.vars.filePath}`;
}
public async getCommitMessage(data: {
vars: CopilotActionVars;
}): Promise<string> {
return `OneUptime Copilot: ${this.copilotActionType} on ${data.vars.filePath}`;
}
public async cleanup(
actionResult: CopilotActionRunResult,
): Promise<CopilotActionRunResult> {
// this code contains text as well. The code is in betwen ```<type> and ```. Please extract the code and return it.
// for example code can be in the format of
// ```python
// print("Hello World")
// ```
// so the code to be extracted is print("Hello World")
// the code can be in multiple lines as well.
if (!actionResult.code) {
return actionResult;
}
if (!actionResult.code.includes("```")) {
return actionResult;
}
const extractedCode: string =
actionResult.code.match(/```.*\n([\s\S]*?)```/)?.[1] ?? "";
return {
code: extractedCode,
};
}
public async isNoOperation(_data: {
vars: CopilotActionVars;
result: CopilotActionRunResult;
}): Promise<boolean> {
return false;
}
public async execute(data: {
vars: CopilotActionVars;
}): Promise<CopilotActionRunResult> {
}): Promise<CopilotActionRunResult | null> {
const prompt: CopilotActionPrompt = await this.getPrompt({
vars: data.vars,
});
const result: CopilotActionRunResult = await LLM.getResponse(prompt);
if (await this.isNoOperation({ vars: data.vars, result: result })) {
return null;
}
const cleanedResult: CopilotActionRunResult = await this.cleanup(result);
return await this.onAfterExecute({
result: result,
result: cleanedResult,
vars: data.vars,
});
}

View File

@@ -1,5 +1,9 @@
import CopilotActionType from "Common/Types/Copilot/CopilotActionType";
import CopilotActionBase, { CopilotActionPrompt } from "./CopilotActionsBase";
import CopilotActionBase, {
CopilotActionPrompt,
CopilotActionRunResult,
CopilotActionVars,
} from "./CopilotActionsBase";
export default class ImproveComments extends CopilotActionBase {
public constructor() {
@@ -8,11 +12,25 @@ export default class ImproveComments extends CopilotActionBase {
});
}
public override async isNoOperation(data: {
vars: CopilotActionVars;
result: CopilotActionRunResult;
}): Promise<boolean> {
if (data.result.result.includes("--all-good--")) {
return true;
}
return false;
}
protected override async _getPrompt(): Promise<CopilotActionPrompt> {
const prompt: string = `Please improve the comments in this code.
Please only comment code that is hard to understand.
If you do not find any code that is hard to understand, then please do not add any comments.
Please only reply with code and nothing else.
If you find that the code is already well commented, please reply with the following text:
--all-good--
Here is the code:

View File

@@ -6,16 +6,24 @@ import CopilotActionBase, {
CopilotActionVars,
} from "./CopilotActionsBase";
import BadDataException from "Common/Types/Exception/BadDataException";
import CodeRepositoryUtil from "../../Utils/CodeRepository";
import ServiceRepository from "Model/Models/ServiceRepository";
const actionDictionary: Dictionary<CopilotActionBase> = {
[CopilotActionType.IMPROVE_COMMENTS]: new ImproveComments(),
};
export enum CopilotExecuteResult {
ActionExecuted = "ActionExecuted",
NoActionRequired = "NoActionRequired",
}
export default class CopilotActionService {
public static async execute(data: {
serviceRepository: ServiceRepository;
copilotActionType: CopilotActionType;
vars: CopilotActionVars;
}): Promise<CopilotActionRunResult> {
}): Promise<CopilotExecuteResult> {
if (!actionDictionary[data.copilotActionType]) {
throw new BadDataException("Invalid CopilotActionType");
}
@@ -24,8 +32,66 @@ export default class CopilotActionService {
data.copilotActionType
] as CopilotActionBase;
return await action.execute({
const result: CopilotActionRunResult | null = await action.execute({
vars: data.vars,
});
if (!result) {
return CopilotExecuteResult.NoActionRequired; // no need to do anything
}
const branchName: string = CodeRepositoryUtil.getBranchName({
branchName: await action.getBranchName(),
serviceRepository: data.serviceRepository,
});
const commitMessage: string = await action.getCommitMessage({
vars: data.vars,
});
// create a branch
await CodeRepositoryUtil.createBranch({
serviceRepository: data.serviceRepository,
branchName: branchName,
});
// write to
const filePath: string = data.vars.filePath;
const code: string = result.code;
await CodeRepositoryUtil.writeToFile({
filePath: filePath,
content: code,
});
// commit changes
await CodeRepositoryUtil.commitChanges({
message: commitMessage,
});
// push changes
await CodeRepositoryUtil.pushChanges({
branchName: branchName,
serviceRepository: data.serviceRepository,
});
// create a PR
await CodeRepositoryUtil.createPullRequest({
branchName: branchName,
serviceRepository: data.serviceRepository,
title: await action.getPullRequestTitle({ vars: data.vars }),
body: await action.getPullRequestBody({ vars: data.vars }),
});
// switch to main branch.
await CodeRepositoryUtil.switchToMainBranch();
return CopilotExecuteResult.ActionExecuted;
}
}

View File

@@ -228,6 +228,18 @@ export default class CodeRepositoryUtil {
}
}
public static async switchToMainBranch(): Promise<void> {
const codeRepository: CodeRepositoryModel = await this.getCodeRepository();
if (!codeRepository.mainBranchName) {
throw new BadDataException("Main Branch Name is required");
}
await this.checkoutBranch({
branchName: codeRepository.mainBranchName!,
});
}
public static async createPullRequest(data: {
branchName: string;
title: string;