mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-01-17 07:10:03 +00:00
418 lines
13 KiB
TypeScript
418 lines
13 KiB
TypeScript
import CopilotCodeRepository from "../../Models/DatabaseModels/CopilotCodeRepository";
|
|
import CopilotActionService, {
|
|
Service as CopilotActionServiceType,
|
|
} from "../Services/CopilotActionService";
|
|
import {
|
|
ExpressRequest,
|
|
ExpressResponse,
|
|
NextFunction,
|
|
} from "../Utils/Express";
|
|
import Response from "../Utils/Response";
|
|
import BaseAPI from "./BaseAPI";
|
|
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
import ObjectID from "../../Types/ObjectID";
|
|
import CopilotAction from "../../Models/DatabaseModels/CopilotAction";
|
|
import CopilotCodeRepositoryService from "../Services/CopilotCodeRepositoryService";
|
|
import CodeRepositoryAuthorization from "../Middleware/CodeRepositoryAuthorization";
|
|
import CopilotActionStatus from "../../Types/Copilot/CopilotActionStatus";
|
|
import CopilotActionTypePriority from "../../Models/DatabaseModels/CopilotActionTypePriority";
|
|
import CopilotActionTypePriorityService from "../Services/CopilotActionTypePriorityService";
|
|
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
import JSONFunctions from "../../Types/JSONFunctions";
|
|
import CopilotActionType from "../../Types/Copilot/CopilotActionType";
|
|
import { JSONObject } from "../../Types/JSON";
|
|
import OneUptimeDate from "../../Types/Date";
|
|
|
|
export default class CopilotActionAPI extends BaseAPI<
|
|
CopilotAction,
|
|
CopilotActionServiceType
|
|
> {
|
|
public constructor() {
|
|
super(CopilotAction, CopilotActionService);
|
|
|
|
this.router.get(
|
|
`${new this.entityType()
|
|
.getCrudApiPath()
|
|
?.toString()}/copilot-action-types-by-priority/:secretkey`,
|
|
CodeRepositoryAuthorization.isAuthorizedRepository,
|
|
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
try {
|
|
const secretkey: string = req.params["secretkey"]!;
|
|
|
|
if (!secretkey) {
|
|
throw new BadDataException("Secret key is required");
|
|
}
|
|
|
|
const codeRepository: CopilotCodeRepository | null =
|
|
await CopilotCodeRepositoryService.findOneBy({
|
|
query: {
|
|
secretToken: new ObjectID(secretkey),
|
|
},
|
|
select: {
|
|
_id: true,
|
|
},
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
if (!codeRepository) {
|
|
throw new BadDataException(
|
|
"Code repository not found. Secret key is invalid.",
|
|
);
|
|
}
|
|
|
|
const copilotActionTypes: Array<CopilotActionTypePriority> =
|
|
await CopilotActionTypePriorityService.findBy({
|
|
query: {
|
|
codeRepositoryId: codeRepository.id!,
|
|
},
|
|
select: {
|
|
_id: true,
|
|
actionType: true,
|
|
priority: true,
|
|
},
|
|
skip: 0,
|
|
sort: {
|
|
priority: SortOrder.Ascending,
|
|
},
|
|
limit: LIMIT_PER_PROJECT,
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
return Response.sendJsonObjectResponse(req, res, {
|
|
actionTypes: CopilotActionTypePriority.toJSONArray(
|
|
copilotActionTypes,
|
|
CopilotActionTypePriority,
|
|
),
|
|
});
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
},
|
|
);
|
|
|
|
this.router.get(
|
|
`${new this.entityType()
|
|
.getCrudApiPath()
|
|
?.toString()}/copilot-actions-in-queue/:secretkey`,
|
|
CodeRepositoryAuthorization.isAuthorizedRepository,
|
|
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
try {
|
|
const secretkey: string = req.params["secretkey"]!;
|
|
|
|
if (!secretkey) {
|
|
throw new BadDataException("Secret key is required");
|
|
}
|
|
|
|
const serviceCatalogId: string = req.body["serviceCatalogId"]!;
|
|
|
|
if (!serviceCatalogId) {
|
|
throw new BadDataException("Service catalog id is required");
|
|
}
|
|
|
|
const codeRepository: CopilotCodeRepository | null =
|
|
await CopilotCodeRepositoryService.findOneBy({
|
|
query: {
|
|
secretToken: new ObjectID(secretkey),
|
|
},
|
|
select: {
|
|
_id: true,
|
|
},
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
if (!codeRepository) {
|
|
throw new BadDataException(
|
|
"Code repository not found. Secret key is invalid.",
|
|
);
|
|
}
|
|
|
|
const copilotActions: Array<CopilotAction> =
|
|
await CopilotActionService.findBy({
|
|
query: {
|
|
codeRepositoryId: codeRepository.id!,
|
|
serviceCatalogId: new ObjectID(serviceCatalogId),
|
|
copilotActionStatus: CopilotActionStatus.IN_QUEUE,
|
|
},
|
|
select: {
|
|
_id: true,
|
|
codeRepositoryId: true,
|
|
serviceCatalogId: true,
|
|
copilotActionStatus: true,
|
|
copilotActionType: true,
|
|
copilotActionProp: true,
|
|
createdAt: true,
|
|
copilotPullRequest: {
|
|
_id: true,
|
|
pullRequestId: true,
|
|
copilotPullRequestStatus: true,
|
|
},
|
|
},
|
|
skip: 0,
|
|
limit: LIMIT_PER_PROJECT,
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
return Response.sendJsonObjectResponse(req, res, {
|
|
copilotActions: CopilotAction.toJSONArray(
|
|
copilotActions,
|
|
CopilotAction,
|
|
),
|
|
});
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
},
|
|
);
|
|
|
|
this.router.get(
|
|
`${new this.entityType()
|
|
.getCrudApiPath()
|
|
?.toString()}/get-copilot-action/:secretkey`,
|
|
CodeRepositoryAuthorization.isAuthorizedRepository,
|
|
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
try {
|
|
const secretkey: string = req.params["secretkey"]!;
|
|
|
|
if (!secretkey) {
|
|
throw new BadDataException("Secret key is required");
|
|
}
|
|
|
|
const serviceCatalogId: string = req.body["serviceCatalogId"]!;
|
|
|
|
if (!serviceCatalogId) {
|
|
throw new BadDataException("Service catalog id is required");
|
|
}
|
|
|
|
const codeRepository: CopilotCodeRepository | null =
|
|
await CopilotCodeRepositoryService.findOneBy({
|
|
query: {
|
|
secretToken: new ObjectID(secretkey),
|
|
},
|
|
select: {
|
|
_id: true,
|
|
},
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
if (!codeRepository) {
|
|
throw new BadDataException(
|
|
"Code repository not found. Secret key is invalid.",
|
|
);
|
|
}
|
|
|
|
const actionType: CopilotActionType = req.body["actionType"]!;
|
|
|
|
if (!actionType) {
|
|
throw new BadDataException("Action type is required");
|
|
}
|
|
|
|
const actionProps: JSONObject = req.body["actionProps"]!;
|
|
|
|
const copilotAction: CopilotAction | null =
|
|
await CopilotActionService.findOneBy({
|
|
query: {
|
|
codeRepositoryId: codeRepository.id!,
|
|
serviceCatalogId: new ObjectID(serviceCatalogId),
|
|
copilotActionType: actionType,
|
|
copilotActionProp: actionProps as any,
|
|
},
|
|
select: {
|
|
_id: true,
|
|
codeRepositoryId: true,
|
|
serviceCatalogId: true,
|
|
copilotActionStatus: true,
|
|
copilotActionType: true,
|
|
createdAt: true,
|
|
copilotPullRequest: {
|
|
_id: true,
|
|
pullRequestId: true,
|
|
copilotPullRequestStatus: true,
|
|
},
|
|
},
|
|
sort: {
|
|
createdAt: SortOrder.Descending,
|
|
},
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
return Response.sendJsonObjectResponse(req, res, {
|
|
copilotAction: copilotAction
|
|
? CopilotAction.toJSONObject(copilotAction, CopilotAction)
|
|
: null,
|
|
});
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
},
|
|
);
|
|
|
|
this.router.post(
|
|
`${new this.entityType()
|
|
.getCrudApiPath()
|
|
?.toString()}/create-copilot-action/:secretkey`,
|
|
CodeRepositoryAuthorization.isAuthorizedRepository,
|
|
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
try {
|
|
const secretkey: string = req.params["secretkey"]!;
|
|
|
|
if (!secretkey) {
|
|
throw new BadDataException("Secret key is required");
|
|
}
|
|
|
|
const codeRepository: CopilotCodeRepository | null =
|
|
await CopilotCodeRepositoryService.findOneBy({
|
|
query: {
|
|
secretToken: new ObjectID(secretkey),
|
|
},
|
|
select: {
|
|
_id: true,
|
|
projectId: true,
|
|
},
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
if (!codeRepository) {
|
|
throw new BadDataException(
|
|
"Code repository not found. Secret key is invalid.",
|
|
);
|
|
}
|
|
|
|
const copilotAction: CopilotAction = CopilotAction.fromJSON(
|
|
req.body["copilotAction"],
|
|
CopilotAction,
|
|
) as CopilotAction;
|
|
|
|
copilotAction.codeRepositoryId = codeRepository.id!;
|
|
copilotAction.projectId = codeRepository.projectId!;
|
|
copilotAction.copilotActionStatus = CopilotActionStatus.IN_QUEUE;
|
|
|
|
const createdAction: CopilotAction =
|
|
await CopilotActionService.create({
|
|
data: copilotAction,
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
return Response.sendEntityResponse(
|
|
req,
|
|
res,
|
|
createdAction,
|
|
CopilotAction,
|
|
);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
},
|
|
);
|
|
|
|
this.router.post(
|
|
`${new this.entityType()
|
|
.getCrudApiPath()
|
|
?.toString()}/update-copilot-action/:secretkey`,
|
|
CodeRepositoryAuthorization.isAuthorizedRepository,
|
|
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
try {
|
|
const secretkey: string = req.params["secretkey"]!;
|
|
|
|
if (!secretkey) {
|
|
throw new BadDataException("Secret key is required");
|
|
}
|
|
|
|
const codeRepository: CopilotCodeRepository | null =
|
|
await CopilotCodeRepositoryService.findOneBy({
|
|
query: {
|
|
secretToken: new ObjectID(secretkey),
|
|
},
|
|
select: {
|
|
_id: true,
|
|
projectId: true,
|
|
},
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
if (!codeRepository) {
|
|
throw new BadDataException(
|
|
"Code repository not found. Secret key is invalid.",
|
|
);
|
|
}
|
|
|
|
req.body = JSONFunctions.deserialize(req.body);
|
|
|
|
const {
|
|
actionStatus,
|
|
pullRequestId,
|
|
commitHash,
|
|
statusMessage,
|
|
logs,
|
|
actionId,
|
|
}: {
|
|
actionStatus: CopilotActionStatus;
|
|
pullRequestId?: ObjectID | undefined;
|
|
commitHash?: string | undefined;
|
|
statusMessage?: string | undefined;
|
|
logs?: Array<string> | undefined;
|
|
actionId: ObjectID;
|
|
} = req.body;
|
|
|
|
const exisingAction: CopilotAction | null =
|
|
await CopilotActionService.findOneBy({
|
|
query: {
|
|
_id: actionId,
|
|
codeRepositoryId: codeRepository.id!,
|
|
},
|
|
select: {
|
|
_id: true,
|
|
},
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
if (!exisingAction) {
|
|
throw new BadDataException("Action not found");
|
|
}
|
|
|
|
await CopilotActionService.updateOneBy({
|
|
query: {
|
|
_id: actionId,
|
|
codeRepositoryId: codeRepository.id!,
|
|
},
|
|
data: {
|
|
copilotActionStatus: actionStatus!,
|
|
copilotPullRequestId: pullRequestId!,
|
|
commitHash: commitHash!,
|
|
statusMessage: statusMessage!,
|
|
statusChangedAt: OneUptimeDate.getCurrentDate(),
|
|
logs: logs?.join("\n") || "",
|
|
},
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
return Response.sendEmptySuccessResponse(req, res);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
},
|
|
);
|
|
}
|
|
}
|