Automatically refresh the codebase upon merging
Each time changes are merged in Gerrit, the updated codebase is uploaded
to ChatGPT to be accessible for new assistants.
Change-Id: I968c9cf2f4aad070e2184b1d9222aca33f1bed59
Signed-off-by: Patrizio <patrizio.gelosi@amarulasolutions.com>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/listener/IEventHandlerType.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/listener/IEventHandlerType.java
new file mode 100644
index 0000000..829900f
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/listener/IEventHandlerType.java
@@ -0,0 +1,10 @@
+package com.googlesource.gerrit.plugins.chatgpt.interfaces.listener;
+
+public interface IEventHandlerType {
+ enum PreprocessResult {
+ OK, EXIT, SWITCH_TO_PATCH_SET_CREATED
+ }
+
+ PreprocessResult preprocessEvent();
+ void processEvent() throws Exception;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTask.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTask.java
index 872b308..2faacfb 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTask.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTask.java
@@ -2,33 +2,47 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
-import com.google.gerrit.extensions.client.ChangeKind;
import com.google.gerrit.server.data.ChangeAttribute;
-import com.google.gerrit.server.data.PatchSetAttribute;
+import com.google.gerrit.server.events.ChangeMergedEvent;
+import com.google.gerrit.server.events.CommentAddedEvent;
+import com.google.gerrit.server.events.PatchSetCreatedEvent;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.chatgpt.PatchSetReviewer;
import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
+import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.chatgpt.interfaces.listener.IEventHandlerType;
import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClient;
import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.git.GitRepoFiles;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import static com.google.gerrit.extensions.client.ChangeKind.REWORK;
-
@Slf4j
public class EventHandlerTask implements Runnable {
@VisibleForTesting
public enum Result {
OK, NOT_SUPPORTED, FAILURE
}
+ public enum SupportedEvents {
+ PATCH_SET_CREATED,
+ COMMENT_ADDED,
+ CHANGE_MERGED
+ }
- private final static Map<String, Boolean> EVENT_COMMENT_MAP = Map.of(
- "patchset-created", false,
- "comment-added", true
+ public static final Map<SupportedEvents, Class<?>> EVENT_CLASS_MAP = Map.of(
+ SupportedEvents.PATCH_SET_CREATED, PatchSetCreatedEvent.class,
+ SupportedEvents.COMMENT_ADDED, CommentAddedEvent.class,
+ SupportedEvents.CHANGE_MERGED, ChangeMergedEvent.class
+ );
+
+ private static final Map<String, SupportedEvents> EVENT_TYPE_MAP = Map.of(
+ "patchset-created", SupportedEvents.PATCH_SET_CREATED,
+ "comment-added", SupportedEvents.COMMENT_ADDED,
+ "change-merged", SupportedEvents.CHANGE_MERGED
);
private final Configuration config;
@@ -36,6 +50,11 @@
private final ChangeSetData changeSetData;
private final GerritChange change;
private final PatchSetReviewer reviewer;
+ private final GitRepoFiles gitRepoFiles;
+ private final PluginDataHandlerProvider pluginDataHandlerProvider;
+
+ private SupportedEvents processing_event_type;
+ private IEventHandlerType eventHandlerType;
@Inject
EventHandlerTask(
@@ -43,13 +62,17 @@
ChangeSetData changeSetData,
GerritChange change,
PatchSetReviewer reviewer,
- GerritClient gerritClient
+ GerritClient gerritClient,
+ GitRepoFiles gitRepoFiles,
+ PluginDataHandlerProvider pluginDataHandlerProvider
) {
this.changeSetData = changeSetData;
this.change = change;
this.reviewer = reviewer;
this.gerritClient = gerritClient;
this.config = config;
+ this.gitRepoFiles = gitRepoFiles;
+ this.pluginDataHandlerProvider = pluginDataHandlerProvider;
}
@Override
@@ -59,13 +82,13 @@
@VisibleForTesting
public Result execute() {
- if (!preProcessEvent(change, changeSetData)) {
+ if (!preProcessEvent()) {
return Result.NOT_SUPPORTED;
}
try {
log.info("Processing change: {}", change.getFullChangeId());
- reviewer.review(change);
+ eventHandlerType.processEvent();
log.info("Finished processing change: {}", change.getFullChangeId());
} catch (Exception e) {
log.error("Error while processing change: {}", change.getFullChangeId(), e);
@@ -77,41 +100,43 @@
return Result.OK;
}
- private boolean preProcessEvent(GerritChange change, ChangeSetData changeSetData) {
+ private boolean preProcessEvent() {
String eventType = Optional.ofNullable(change.getEventType()).orElse("");
log.info("Event type {}", eventType);
- if (!EVENT_COMMENT_MAP.containsKey(eventType)) {
+ processing_event_type = EVENT_TYPE_MAP.get(eventType);
+ if (processing_event_type == null) {
return false;
}
if (!isReviewEnabled(change)) {
return false;
}
- boolean isCommentEvent = EVENT_COMMENT_MAP.get(eventType);
- if (isCommentEvent) {
- if (!gerritClient.retrieveLastComments(change)) {
- if (changeSetData.getForcedReview() || changeSetData.getForceDisplaySystemMessage()) {
- isCommentEvent = false;
- } else {
- log.info("No comments found for review");
+
+ while (true) {
+ eventHandlerType = getEventHandlerType();
+ switch (eventHandlerType.preprocessEvent()) {
+ case EXIT -> {
return false;
}
+ case SWITCH_TO_PATCH_SET_CREATED -> {
+ processing_event_type = SupportedEvents.PATCH_SET_CREATED;
+ continue;
+ }
}
- } else {
- if (!isPatchSetReviewEnabled(change)) {
- log.debug("Patch Set review disabled");
- return false;
- }
- }
- log.debug("Flag `isCommentEvent` set to {}", isCommentEvent);
- change.setIsCommentEvent(isCommentEvent);
- if (!isCommentEvent) {
- gerritClient.retrievePatchSetInfo(change);
+ break;
}
return true;
}
+ private IEventHandlerType getEventHandlerType() {
+ return switch (processing_event_type) {
+ case PATCH_SET_CREATED -> new EventHandlerTypePatchSetReview(config, changeSetData, change, reviewer, gerritClient);
+ case COMMENT_ADDED -> new EventHandlerTypeCommentAdded(changeSetData, change, reviewer, gerritClient);
+ case CHANGE_MERGED -> new EventHandlerTypeChangeMerged(config, changeSetData, change, gitRepoFiles, pluginDataHandlerProvider);
+ };
+ }
+
private boolean isReviewEnabled(GerritChange change) {
List<String> enabledProjects = Splitter.on(",").omitEmptyStrings()
.splitToList(config.getEnabledProjects());
@@ -132,34 +157,6 @@
return true;
}
- private boolean isPatchSetReviewEnabled(GerritChange change) {
- if (!config.getGptReviewPatchSet()) {
- log.debug("Disabled review function for created or updated PatchSets.");
- return false;
- }
- Optional<PatchSetAttribute> patchSetAttributeOptional = change.getPatchSetAttribute();
- if (patchSetAttributeOptional.isEmpty()) {
- log.info("PatchSetAttribute event properties not retrieved");
- return false;
- }
- PatchSetAttribute patchSetAttribute = patchSetAttributeOptional.get();
- ChangeKind patchSetEventKind = patchSetAttribute.kind;
- if (patchSetEventKind != REWORK) {
- log.debug("Change kind '{}' not processed", patchSetEventKind);
- return false;
- }
- String authorUsername = patchSetAttribute.author.username;
- if (gerritClient.isDisabledUser(authorUsername)) {
- log.info("Review of PatchSets from user '{}' is disabled.", authorUsername);
- return false;
- }
- if (gerritClient.isWorkInProgress(change)) {
- log.debug("Skipping Patch Set processing due to its WIP status.");
- return false;
- }
- return true;
- }
-
private Optional<String> getTopic(GerritChange change) {
try {
ChangeAttribute changeAttribute = change.getPatchSetEvent().change.get();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypeChangeMerged.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypeChangeMerged.java
new file mode 100644
index 0000000..6d033ba
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypeChangeMerged.java
@@ -0,0 +1,52 @@
+package com.googlesource.gerrit.plugins.chatgpt.listener;
+
+import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
+import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.chatgpt.interfaces.listener.IEventHandlerType;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt.ChatGptAssistantBase;
+import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt.ChatGptAssistantReview;
+import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.git.GitRepoFiles;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class EventHandlerTypeChangeMerged implements IEventHandlerType {
+ private final Configuration config;
+ private final ChangeSetData changeSetData;
+ private final GerritChange change;
+ private final GitRepoFiles gitRepoFiles;
+ private final PluginDataHandlerProvider pluginDataHandlerProvider;
+
+ EventHandlerTypeChangeMerged(
+ Configuration config,
+ ChangeSetData changeSetData,
+ GerritChange change,
+ GitRepoFiles gitRepoFiles,
+ PluginDataHandlerProvider pluginDataHandlerProvider
+ ) {
+ this.config = config;
+ this.changeSetData = changeSetData;
+ this.change = change;
+ this.gitRepoFiles = gitRepoFiles;
+ this.pluginDataHandlerProvider = pluginDataHandlerProvider;
+ }
+
+ @Override
+ public PreprocessResult preprocessEvent() {
+ return PreprocessResult.OK;
+ }
+
+ @Override
+ public void processEvent() {
+ ChatGptAssistantBase chatGptAssistant = new ChatGptAssistantBase(
+ config,
+ changeSetData,
+ change,
+ gitRepoFiles,
+ pluginDataHandlerProvider
+ );
+ chatGptAssistant.flushAssistantIds();
+ chatGptAssistant.createVectorStore();
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypeCommentAdded.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypeCommentAdded.java
new file mode 100644
index 0000000..ec730b7
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypeCommentAdded.java
@@ -0,0 +1,49 @@
+package com.googlesource.gerrit.plugins.chatgpt.listener;
+
+import com.googlesource.gerrit.plugins.chatgpt.PatchSetReviewer;
+import com.googlesource.gerrit.plugins.chatgpt.interfaces.listener.IEventHandlerType;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClient;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class EventHandlerTypeCommentAdded implements IEventHandlerType {
+ private final ChangeSetData changeSetData;
+ private final GerritChange change;
+ private final PatchSetReviewer reviewer;
+ private final GerritClient gerritClient;
+
+ EventHandlerTypeCommentAdded(
+ ChangeSetData changeSetData,
+ GerritChange change,
+ PatchSetReviewer reviewer,
+ GerritClient gerritClient
+ ) {
+ this.changeSetData = changeSetData;
+ this.change = change;
+ this.reviewer = reviewer;
+ this.gerritClient = gerritClient;
+
+ }
+
+ @Override
+ public PreprocessResult preprocessEvent() {
+ if (!gerritClient.retrieveLastComments(change)) {
+ if (changeSetData.getForcedReview()) {
+ return PreprocessResult.SWITCH_TO_PATCH_SET_CREATED;
+ } else {
+ log.info("No comments found for review");
+ return PreprocessResult.EXIT;
+ }
+ }
+ change.setIsCommentEvent(true);
+
+ return PreprocessResult.OK;
+ }
+
+ @Override
+ public void processEvent() throws Exception {
+ reviewer.review(change);
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypePatchSetReview.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypePatchSetReview.java
new file mode 100644
index 0000000..d372f9e
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypePatchSetReview.java
@@ -0,0 +1,84 @@
+package com.googlesource.gerrit.plugins.chatgpt.listener;
+
+import com.google.gerrit.extensions.client.ChangeKind;
+import com.google.gerrit.server.data.PatchSetAttribute;
+import com.googlesource.gerrit.plugins.chatgpt.PatchSetReviewer;
+import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
+import com.googlesource.gerrit.plugins.chatgpt.interfaces.listener.IEventHandlerType;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClient;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Optional;
+
+import static com.google.gerrit.extensions.client.ChangeKind.REWORK;
+
+@Slf4j
+public class EventHandlerTypePatchSetReview implements IEventHandlerType {
+ private final Configuration config;
+ private final ChangeSetData changeSetData;
+ private final GerritChange change;
+ private final PatchSetReviewer reviewer;
+ private final GerritClient gerritClient;
+
+ EventHandlerTypePatchSetReview(
+ Configuration config,
+ ChangeSetData changeSetData,
+ GerritChange change,
+ PatchSetReviewer reviewer,
+ GerritClient gerritClient
+ ) {
+ this.config = config;
+ this.changeSetData = changeSetData;
+ this.change = change;
+ this.reviewer = reviewer;
+ this.gerritClient = gerritClient;
+ }
+
+ @Override
+ public PreprocessResult preprocessEvent() {
+ if (!isPatchSetReviewEnabled(change)) {
+ log.debug("Patch Set review disabled");
+ return PreprocessResult.EXIT;
+ }
+ gerritClient.retrievePatchSetInfo(change);
+
+ return PreprocessResult.OK;
+ }
+
+ @Override
+ public void processEvent() throws Exception {
+ reviewer.review(change);
+ }
+
+ private boolean isPatchSetReviewEnabled(GerritChange change) {
+ if (!config.getGptReviewPatchSet()) {
+ log.debug("Disabled review function for created or updated PatchSets.");
+ return false;
+ }
+ Optional<PatchSetAttribute> patchSetAttributeOptional = change.getPatchSetAttribute();
+ if (patchSetAttributeOptional.isEmpty()) {
+ log.info("PatchSetAttribute event properties not retrieved");
+ return false;
+ }
+ PatchSetAttribute patchSetAttribute = patchSetAttributeOptional.get();
+ ChangeKind patchSetEventKind = patchSetAttribute.kind;
+ // The only Change kind that automatically triggers the review is REWORK. If review is forced via command, this
+ // condition is bypassed
+ if (patchSetEventKind != REWORK && !changeSetData.getForcedReview()) {
+ log.debug("Change kind '{}' not processed", patchSetEventKind);
+ return false;
+ }
+ String authorUsername = patchSetAttribute.author.username;
+ if (gerritClient.isDisabledUser(authorUsername)) {
+ log.info("Review of PatchSets from user '{}' is disabled.", authorUsername);
+ return false;
+ }
+ if (gerritClient.isWorkInProgress(change)) {
+ log.debug("Skipping Patch Set processing due to its WIP status.");
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/GerritListener.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/GerritListener.java
index 2e60049..82d4cbd 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/GerritListener.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/GerritListener.java
@@ -4,11 +4,7 @@
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.config.GerritInstanceId;
-import com.google.gerrit.server.events.PatchSetEvent;
-import com.google.gerrit.server.events.Event;
-import com.google.gerrit.server.events.EventListener;
-import com.google.gerrit.server.events.CommentAddedEvent;
-import com.google.gerrit.server.events.PatchSetCreatedEvent;
+import com.google.gerrit.server.events.*;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.chatgpt.config.ConfigCreator;
@@ -17,6 +13,8 @@
import java.util.Objects;
+import static com.googlesource.gerrit.plugins.chatgpt.listener.EventHandlerTask.EVENT_CLASS_MAP;
+
@Slf4j
public class GerritListener implements EventListener {
private final String myInstanceId;
@@ -40,8 +38,8 @@
log.debug("Ignore event from another instance");
return;
}
- if (!(event instanceof CommentAddedEvent || event instanceof PatchSetCreatedEvent)) {
- log.debug("The event is not a PatchSetCreatedEvent, it is: {}", event);
+ if (!EVENT_CLASS_MAP.containsValue(event.getClass())) {
+ log.debug("The event {} is not managed by the plugin", event);
return;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/commands/ClientCommands.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/commands/ClientCommands.java
index 5489ff7..7e8ce7c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/commands/ClientCommands.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/commands/ClientCommands.java
@@ -127,7 +127,6 @@
else if (command == COMMAND_SET.CONFIGURE) {
if (config.getEnableMessageDebugging()) {
changeSetData.setHideChatGptReview(true);
- changeSetData.setForceDisplaySystemMessage(true);
dynamicConfiguration.updateConfiguration(modifiedDynamicConfig, shouldResetDynamicConfig);
}
else {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/ChangeSetData.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/ChangeSetData.java
index ab5cd23..083d9f9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/ChangeSetData.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/ChangeSetData.java
@@ -24,7 +24,6 @@
// Command variables
private Boolean forcedReview = false;
private Boolean forcedReviewLastPatchSet = false;
- private Boolean forceDisplaySystemMessage = false;
private Boolean replyFilterEnabled = true;
private Boolean debugReviewMode = false;
private Boolean hideChatGptReview = false;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistantBase.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistantBase.java
index 9b26bac..ba4f1c8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistantBase.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistantBase.java
@@ -27,6 +27,9 @@
@Slf4j
public class ChatGptAssistantBase extends ClientBase {
+ protected static final String KEY_REVIEW_ASSISTANT_ID = "reviewAssistantId";
+ protected static final String KEY_REQUESTS_ASSISTANT_ID = "requestsAssistantId";
+
@Getter
protected String keyAssistantId;
@@ -54,8 +57,7 @@
String assistantId = projectDataHandler.getValue(keyAssistantId);
if (assistantId == null || config.getForceCreateAssistant()) {
log.debug("Setup Assistant for project {}", change.getProjectNameKey());
- String fileId = uploadRepoFiles();
- String vectorStoreId = createVectorStore(fileId);
+ String vectorStoreId = createVectorStore();
assistantId = createAssistant(vectorStoreId);
projectDataHandler.setValue(keyAssistantId, assistantId);
log.info("Project assistant created with ID: {}", assistantId);
@@ -65,6 +67,28 @@
}
}
+ public String createVectorStore() {
+ String vectorStoreId = projectDataHandler.getValue(KEY_VECTOR_STORE_ID);
+ if (vectorStoreId == null) {
+ String fileId = uploadRepoFiles();
+ ChatGptVectorStore vectorStore = new ChatGptVectorStore(fileId, config, change);
+ ChatGptResponse createVectorStoreResponse = vectorStore.createVectorStore();
+ vectorStoreId = createVectorStoreResponse.getId();
+ projectDataHandler.setValue(KEY_VECTOR_STORE_ID, vectorStoreId);
+ log.info("Vector Store created with ID: {}", vectorStoreId);
+ }
+ else {
+ log.info("Vector Store found for the project. Vector Store ID: {}", vectorStoreId);
+ }
+ return vectorStoreId;
+ }
+
+ public void flushAssistantIds() {
+ projectDataHandler.removeValue(KEY_VECTOR_STORE_ID);
+ projectDataHandler.removeValue(KEY_REVIEW_ASSISTANT_ID);
+ projectDataHandler.removeValue(KEY_REQUESTS_ASSISTANT_ID);
+ }
+
private String uploadRepoFiles() {
String repoFiles = gitRepoFiles.getGitRepoFiles(config, change);
Path repoPath = createTempFileWithContent(sanitizeFilename(change.getProjectName()), ".json", repoFiles);
@@ -74,21 +98,6 @@
return chatGptFilesResponse.getId();
}
- private String createVectorStore(String fileId) {
- String vectorStoreId = projectDataHandler.getValue(KEY_VECTOR_STORE_ID);
- if (vectorStoreId == null) {
- ChatGptVectorStore vectorStore = new ChatGptVectorStore(fileId, config, change);
- ChatGptResponse createVectorStoreResponse = vectorStore.createVectorStore();
- vectorStoreId = createVectorStoreResponse.getId();
- projectDataHandler.setValue(KEY_VECTOR_STORE_ID, vectorStoreId);
- log.info("Vector store created with ID: {}", vectorStoreId);
- }
- else {
- log.info("Vector store found for the project. Assistant ID: {}", vectorStoreId);
- }
- return vectorStoreId;
- }
-
private String createAssistant(String vectorStoreId) {
Request request = createRequest(vectorStoreId);
log.debug("ChatGPT Create Assistant request: {}", request);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistantRequests.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistantRequests.java
index c78d349..f2f0b5a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistantRequests.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistantRequests.java
@@ -9,8 +9,6 @@
@Slf4j
public class ChatGptAssistantRequests extends ChatGptAssistantBase {
- public static final String KEY_REQUESTS_ASSISTANT_ID = "requestsAssistantId";
-
public ChatGptAssistantRequests(
Configuration config,
ChangeSetData changeSetData,
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistantReview.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistantReview.java
index 26176f7..abc8ac9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistantReview.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistantReview.java
@@ -9,8 +9,6 @@
@Slf4j
public class ChatGptAssistantReview extends ChatGptAssistantBase {
- public static final String KEY_REVIEW_ASSISTANT_ID = "reviewAssistantId";
-
public ChatGptAssistantReview(
Configuration config,
ChangeSetData changeSetData,
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatefulTest.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatefulTest.java
index 9dccaae..f47db19 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatefulTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatefulTest.java
@@ -7,6 +7,8 @@
import com.google.gerrit.extensions.common.DiffInfo;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.RestApiException;
+import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandler;
+import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptResponseContent;
import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.UriResourceLocatorStateful;
import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.prompt.ChatGptPromptStateful;
@@ -25,8 +27,9 @@
import java.io.ByteArrayInputStream;
import java.net.URI;
-
+import static com.googlesource.gerrit.plugins.chatgpt.listener.EventHandlerTask.SupportedEvents;
import static com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt.ChatGptRun.COMPLETED_STATUS;
+import static com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt.ChatGptVectorStore.KEY_VECTOR_STORE_ID;
import static com.googlesource.gerrit.plugins.chatgpt.settings.Settings.GERRIT_PATCH_SET_FILENAME;
import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
import static java.net.HttpURLConnection.HTTP_OK;
@@ -46,6 +49,7 @@
private String formattedPatchContent;
private ChatGptPromptStateful chatGptPromptStateful;
private String requestContent;
+ private PluginDataHandler projectHandler;
public ChatGptReviewStatefulTest() {
MockitoAnnotations.openMocks(this);
@@ -58,8 +62,11 @@
when(globalConfig.getString(Mockito.eq("gptMode"), Mockito.anyString()))
.thenReturn(MODES.stateful.name());
+ setupPluginData();
+ PluginDataHandlerProvider provider = new PluginDataHandlerProvider(mockPluginDataPath, getGerritChange());
+ projectHandler = provider.getProjectScope();
// Mock the pluginDataHandlerProvider to return the mocked project pluginDataHandler
- when(pluginDataHandlerProvider.getProjectScope()).thenReturn(pluginDataHandler);
+ when(pluginDataHandlerProvider.getProjectScope()).thenReturn(projectHandler);
}
protected void initTest() {
@@ -184,7 +191,7 @@
String reviewUserPrompt = chatGptPromptStateful.getDefaultGptThreadReviewMessage(formattedPatchContent);
- handleEventBasedOnType(false);
+ handleEventBasedOnType(SupportedEvents.PATCH_SET_CREATED);
ArgumentCaptor<ReviewInput> captor = testRequestSent();
Assert.assertEquals(reviewUserPrompt, requestContent);
@@ -205,7 +212,7 @@
.withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
.withBodyFile("chatGptResponseRequestStateful.json")));
- handleEventBasedOnType(true);
+ handleEventBasedOnType(SupportedEvents.COMMENT_ADDED);
ArgumentCaptor<ReviewInput> captor = testRequestSent();
Assert.assertEquals(promptTagComments, requestContent);
@@ -231,7 +238,7 @@
.withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
.withBodyFile("chatGptResponseThreadMessageText.json")));
- handleEventBasedOnType(true);
+ handleEventBasedOnType(SupportedEvents.COMMENT_ADDED);
ArgumentCaptor<ReviewInput> captor = testRequestSent();
Assert.assertEquals(promptTagComments, requestContent);
@@ -257,10 +264,18 @@
.withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
.withBodyFile("chatGptResponseThreadMessageJson.json")));
- handleEventBasedOnType(true);
+ handleEventBasedOnType(SupportedEvents.COMMENT_ADDED);
ArgumentCaptor<ReviewInput> captor = testRequestSent();
Assert.assertEquals(promptTagComments, requestContent);
Assert.assertEquals(reviewMessageCommitMessage, getCapturedMessage(captor, GERRIT_PATCH_SET_FILENAME));
}
+
+ @Test
+ public void gerritMergedCommits() {
+ projectHandler.removeValue(KEY_VECTOR_STORE_ID);
+ handleEventBasedOnType(SupportedEvents.CHANGE_MERGED);
+
+ Assert.assertEquals(CHAT_GPT_VECTOR_ID, projectHandler.getValue(KEY_VECTOR_STORE_ID));
+ }
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatelessTest.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatelessTest.java
index 101eb61..1adb0c7 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatelessTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatelessTest.java
@@ -28,6 +28,7 @@
import java.util.Arrays;
import java.util.Map;
+import static com.googlesource.gerrit.plugins.chatgpt.listener.EventHandlerTask.SupportedEvents;
import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.joinWithNewLine;
import static java.net.HttpURLConnection.HTTP_OK;
import static org.mockito.Mockito.mock;
@@ -124,7 +125,7 @@
String reviewUserPrompt = getReviewUserPrompt();
chatGptPromptStateless.setCommentEvent(false);
- handleEventBasedOnType(false);
+ handleEventBasedOnType(SupportedEvents.PATCH_SET_CREATED);
ArgumentCaptor<ReviewInput> captor = testRequestSent();
String systemPrompt = prompts.get(0).getAsJsonObject().get("content").getAsString();
@@ -152,7 +153,7 @@
.withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
.withBodyFile("chatGptResponseReview.json")));
- handleEventBasedOnType(false);
+ handleEventBasedOnType(SupportedEvents.PATCH_SET_CREATED);
ArgumentCaptor<ReviewInput> captor = testRequestSent();
String userPrompt = prompts.get(1).getAsJsonObject().get("content").getAsString();
@@ -167,7 +168,7 @@
when(globalConfig.getString(Mockito.eq("disabledGroups"), Mockito.anyString()))
.thenReturn(GERRIT_USER_GROUP);
- Assert.assertEquals(EventHandlerTask.Result.NOT_SUPPORTED, handleEventBasedOnType(false));
+ Assert.assertEquals(EventHandlerTask.Result.NOT_SUPPORTED, handleEventBasedOnType(SupportedEvents.PATCH_SET_CREATED));
}
@Test
@@ -181,7 +182,7 @@
.withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
.withBodyFile("chatGptResponseRequestStateless.json")));
- handleEventBasedOnType(true);
+ handleEventBasedOnType(SupportedEvents.COMMENT_ADDED);
int commentPropertiesSize = gerritClient.getClientData(getGerritChange()).getCommentProperties().size();
String commentUserPrompt = joinWithNewLine(Arrays.asList(
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java
index 6a09527..f664bf9 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java
@@ -17,10 +17,7 @@
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.data.AccountAttribute;
import com.google.gerrit.server.data.PatchSetAttribute;
-import com.google.gerrit.server.events.CommentAddedEvent;
-import com.google.gerrit.server.events.Event;
-import com.google.gerrit.server.events.PatchSetCreatedEvent;
-import com.google.gerrit.server.events.PatchSetEvent;
+import com.google.gerrit.server.events.*;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
@@ -67,6 +64,7 @@
import java.util.function.Consumer;
import static com.google.gerrit.extensions.client.ChangeKind.REWORK;
+import static com.googlesource.gerrit.plugins.chatgpt.listener.EventHandlerTask.EVENT_CLASS_MAP;
import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -272,9 +270,9 @@
}
}
- protected EventHandlerTask.Result handleEventBasedOnType(boolean isCommentEvent) {
- Consumer<Event> typeSpecificSetup = getTypeSpecificSetup(isCommentEvent);
- Event event = isCommentEvent ? mock(CommentAddedEvent.class) : mock(PatchSetCreatedEvent.class);
+ protected EventHandlerTask.Result handleEventBasedOnType(EventHandlerTask.SupportedEvents triggeredEvent) {
+ Consumer<Event> typeSpecificSetup = getTypeSpecificSetup(triggeredEvent);
+ Event event = getMockedEvent(triggeredEvent);
setupCommonEventMocks((PatchSetEvent) event); // Apply common mock configurations
typeSpecificSetup.accept(event);
@@ -295,7 +293,7 @@
}
protected ArgumentCaptor<ReviewInput> testRequestSent() throws RestApiException {
- ArgumentCaptor<ReviewInput> reviewInputCaptor = ArgumentCaptor.forClass(ReviewInput.class);
+ ArgumentCaptor<ReviewInput> reviewInputCaptor = ArgumentCaptor.forClass(ReviewInput.class);
verify(revisionApiMock).review(reviewInputCaptor.capture());
gptRequestBody = getGson().fromJson(patchSetReviewer.getChatGptClient().getRequestBody(), JsonObject.class);
return reviewInputCaptor;
@@ -349,25 +347,29 @@
}
@NonNull
- private Consumer<Event> getTypeSpecificSetup(boolean isCommentEvent) {
- Consumer<Event> typeSpecificSetup;
-
- if (isCommentEvent) {
- typeSpecificSetup = event -> {
+ private Consumer<Event> getTypeSpecificSetup(EventHandlerTask.SupportedEvents triggeredEvent) {
+ return switch (triggeredEvent) {
+ case COMMENT_ADDED -> event -> {
CommentAddedEvent commentEvent = (CommentAddedEvent) event;
commentEvent.author = this::createTestAccountAttribute;
commentEvent.patchSet = this::createPatchSetAttribute;
commentEvent.eventCreatedOn = TEST_TIMESTAMP;
when(commentEvent.getType()).thenReturn("comment-added");
};
- } else {
- typeSpecificSetup = event -> {
+ case PATCH_SET_CREATED -> event -> {
PatchSetCreatedEvent patchEvent = (PatchSetCreatedEvent) event;
patchEvent.patchSet = this::createPatchSetAttribute;
when(patchEvent.getType()).thenReturn("patchset-created");
};
- }
- return typeSpecificSetup;
+ case CHANGE_MERGED -> event -> {
+ ChangeMergedEvent mergedEvent = (ChangeMergedEvent) event;
+ when(mergedEvent.getType()).thenReturn("change-merged");
+ };
+ };
+ }
+
+ private Event getMockedEvent(EventHandlerTask.SupportedEvents triggeredEvent) {
+ return (Event) mock(EVENT_CLASS_MAP.get(triggeredEvent));
}
private void setupCommonEventMocks(PatchSetEvent event) {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptTestBase.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptTestBase.java
index b3488b4..d04186d 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptTestBase.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptTestBase.java
@@ -4,12 +4,35 @@
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.Mock;
+
+import java.nio.file.Path;
+
+import static org.mockito.Mockito.when;
public class ChatGptTestBase {
protected static final Project.NameKey PROJECT_NAME = Project.NameKey.parse("myProject");
protected static final Change.Key CHANGE_ID = Change.Key.parse("myChangeId");
protected static final BranchNameKey BRANCH_NAME = BranchNameKey.create(PROJECT_NAME, "myBranchName");
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
+
+ @Mock
+ protected Path mockPluginDataPath;
+
+ protected Path realPluginDataPath;
+
+ protected void setupPluginData() {
+ realPluginDataPath = tempFolder.getRoot().toPath().resolve("global.data");
+ Path realProjectDataPath = tempFolder.getRoot().toPath().resolve(PROJECT_NAME + ".data");
+
+ // Mock the PluginData annotation project behavior
+ when(mockPluginDataPath.resolve(PROJECT_NAME + ".data")).thenReturn(realProjectDataPath);
+ }
+
protected GerritChange getGerritChange() {
return new GerritChange(ChatGptTestBase.PROJECT_NAME, ChatGptTestBase.BRANCH_NAME, ChatGptTestBase.CHANGE_ID);
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/PluginDataTest.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/PluginDataTest.java
index d3b687a..f6e6f83 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/PluginDataTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/PluginDataTest.java
@@ -1,40 +1,26 @@
package com.googlesource.gerrit.plugins.chatgpt;
import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.when;
import java.nio.file.Files;
-import java.nio.file.Path;
import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandler;
import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class PluginDataTest extends ChatGptTestBase {
- @Rule
- public TemporaryFolder tempFolder = new TemporaryFolder();
-
- @Mock
- private Path mockPluginDataPath;
-
- private Path realPluginDataPath;
@Before
public void setUp() {
- // Setup temporary folder for tests
- realPluginDataPath = tempFolder.getRoot().toPath().resolve("global.data");
- Path realProjectDataPath = tempFolder.getRoot().toPath().resolve(PROJECT_NAME + ".data");
+ setupPluginData();
- // Mock the PluginData annotation behavior
+ // Mock the PluginData annotation global behavior
when(mockPluginDataPath.resolve("global.data")).thenReturn(realPluginDataPath);
- when(mockPluginDataPath.resolve(PROJECT_NAME + ".data")).thenReturn(realProjectDataPath);
}
@Test