Skip to content

Commit 943012d

Browse files
committed
alpha build, MVP for github & bitbucket cloud platforms
1 parent 20a5218 commit 943012d

27 files changed

+865
-145
lines changed

src/main/java/org/perpectiveteam/plugins/aisummarize/AiSummarizePlugin.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@
55

66
import org.perpectiveteam.plugins.aisummarize.config.AiSummarizeConfig;
77
import org.perpectiveteam.plugins.aisummarize.hooks.PostJobInScanner;
8-
import org.perpectiveteam.plugins.aisummarize.pullrequest.almclient.ALMClientFactory;
8+
import org.perpectiveteam.plugins.aisummarize.pullrequest.PostAnalysisIssueVisitor;
9+
import org.perpectiveteam.plugins.aisummarize.pullrequest.almclient.bitbucket.cloud.BitbucketCloudClientFactory;
10+
import org.perpectiveteam.plugins.aisummarize.pullrequest.almclient.bitbucket.cloud.BitbucketConfiguration;
11+
import org.perpectiveteam.plugins.aisummarize.pullrequest.almclient.bitbucket.cloud.HttpClientBuilderFactory;
912
import org.perpectiveteam.plugins.aisummarize.pullrequest.almclient.github.GitHubClientFactory;
13+
import org.perpectiveteam.plugins.aisummarize.summarize.SummarizeExecutorFactory;
14+
import org.perpectiveteam.plugins.aisummarize.pullrequest.almclient.ALMClientFactory;
1015
import org.sonar.api.Plugin;
1116
import org.sonar.api.PropertyType;
1217
import org.sonar.api.SonarQubeSide;
@@ -27,6 +32,9 @@ public String getName() {
2732

2833
@Override
2934
public void load(CoreExtension.Context context) {
35+
if (SonarQubeSide.COMPUTE_ENGINE == context.getRuntime().getSonarQubeSide()) {
36+
context.addExtensions(PostAnalysisIssueVisitor.class);
37+
}
3038
// Not used currently
3139
}
3240

@@ -42,6 +50,10 @@ private List<Object> getExtensions() {
4250
ALMClientFactory.class,
4351
PostJobInScanner.class,
4452
GitHubClientFactory.class,
53+
BitbucketConfiguration.class,
54+
HttpClientBuilderFactory.class,
55+
BitbucketCloudClientFactory.class,
56+
SummarizeExecutorFactory.class,
4557

4658
PropertyDefinition.builder(AiSummarizeConfig.FILE_LIMIT)
4759
.name("File Limit")

src/main/java/org/perpectiveteam/plugins/aisummarize/ai/AIPromptBuilder.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import java.util.List;
44

55
import org.perpectiveteam.plugins.aisummarize.pullrequest.dtobuilder.FileDiff;
6-
import org.perpectiveteam.plugins.aisummarize.pullrequest.dtobuilder.LineChange;
76
import org.sonar.api.utils.log.Logger;
87
import org.sonar.api.utils.log.Loggers;
98

@@ -15,13 +14,23 @@ public String buildPrompt(List<FileDiff> fileDiffs) {
1514
//TODO: Allow to define prompt and enabled data from the admin panel (e.g. by templating).
1615
LOG.info("Building AI prompt for {} files", fileDiffs.size());
1716
StringBuilder sb = new StringBuilder();
18-
sb.append("Analyze the following code changes across multiple files.\n");
19-
sb.append("For each file, summarize the change, explain the intent, and identify any potential risks.Keep in mind the peculiarities of Magento 2 platform.\n");
17+
sb.append("Please review the following code below:\n");
18+
sb.append("Consider:\n" +
19+
"1. Code quality and adherence to best practices\n" +
20+
"2. Potential bugs or edge cases\n" +
21+
"3. Performance optimizations\n" +
22+
"4. Readability and maintainability\n" +
23+
"5. Any security concerns\n" +
24+
"Suggest improvements and explain your reasoning for each suggestion.\n.");
2025
sb.append("Provide a summary in markdown markup.\n");
2126

2227
int validFileCount = 0;
2328
for (FileDiff fileDiff : fileDiffs) {
24-
if (fileDiff.filePath.isEmpty() || fileDiff.rawContent.isEmpty() || fileDiff.changes.isEmpty()) {
29+
if(fileDiff.rawContent == null || fileDiff.filePath.isEmpty() || fileDiff.rawContent.isEmpty()) {
30+
fileDiff.rawContent = "There is no previous version, probably a new file";
31+
LOG.debug("Missing previous file version for: " + fileDiff.filePath);
32+
}
33+
if (fileDiff.filePath.isEmpty() || fileDiff.changes.isEmpty()) {
2534
LOG.debug("Skipping file with missing data: {}", fileDiff.filePath);
2635
continue;
2736
}
@@ -34,14 +43,9 @@ public String buildPrompt(List<FileDiff> fileDiffs) {
3443
sb.append(fileDiff.rawContent).append("\n");
3544
sb.append("-----\n\n");
3645

37-
sb.append("Diff:\n");
46+
sb.append("Patch:\n");
3847
sb.append("-----\n");
39-
for (LineChange change : fileDiff.changes) {
40-
sb.append("old line: ").append(change.oldLineNumber)
41-
.append(" new line: ").append(change.newLineNumber)
42-
.append(" ").append(change.type)
43-
.append(": ").append(change.content).append("\n");
44-
}
48+
sb.append(fileDiff.changes).append("\n");
4549
sb.append("-----\n\n");
4650
}
4751

src/main/java/org/perpectiveteam/plugins/aisummarize/ai/connector/providers/OpenAIConnector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public String getCompletion(String prompt) {
4444

4545
ObjectMapper mapper = new ObjectMapper();
4646
ObjectNode payload = mapper.createObjectNode();
47-
payload.put("model", "nvidia/llama-3.1-nemotron-ultra-253b-v1:free");
47+
payload.put("model", "deepseek/deepseek-prover-v2:free");
4848
payload.put("temperature", 0.7);
4949

5050
ArrayNode messages = payload.putArray("messages");

src/main/java/org/perpectiveteam/plugins/aisummarize/hooks/PostJobInScanner.java

Lines changed: 11 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
11
package org.perpectiveteam.plugins.aisummarize.hooks;
22

3-
import java.util.List;
43
import java.util.Optional;
54

6-
import org.perpectiveteam.plugins.aisummarize.config.AiSummarizeConfig;
7-
import org.perpectiveteam.plugins.aisummarize.pullrequest.AnalysisDetails;
8-
import org.perpectiveteam.plugins.aisummarize.pullrequest.PostAnalysisIssueVisitor;
9-
import org.perpectiveteam.plugins.aisummarize.pullrequest.PullRequestDiffFetcher;
10-
import org.perpectiveteam.plugins.aisummarize.pullrequest.almclient.ALMClient;
11-
import org.perpectiveteam.plugins.aisummarize.pullrequest.almclient.ALMClientFactory;
12-
import org.perpectiveteam.plugins.aisummarize.pullrequest.dtobuilder.PullRequestDiff;
13-
import org.perpectiveteam.plugins.aisummarize.summarize.SummarizeWithAI;
5+
import org.perpectiveteam.plugins.aisummarize.summarize.SummarizeExecutor;
6+
import org.perpectiveteam.plugins.aisummarize.summarize.SummarizeExecutorFactory;
147
import org.slf4j.Logger;
158
import org.slf4j.LoggerFactory;
16-
import org.sonar.api.ce.posttask.Branch;
179
import org.sonar.api.ce.posttask.PostProjectAnalysisTask;
1810
import org.sonar.api.config.Configuration;
1911
import org.sonar.db.DbClient;
@@ -25,19 +17,20 @@ public class PostJobInScanner implements PostProjectAnalysisTask {
2517
private static final Logger LOGGER = LoggerFactory.getLogger(PostJobInScanner.class);
2618

2719
private final DbClient dbClient;
28-
private final PostAnalysisIssueVisitor postAnalysisIssueVisitor;
20+
//private final PostAnalysisIssueVisitor postAnalysisIssueVisitor;
2921
private final Configuration configuration;
30-
private final ALMClientFactory almClientFactory;
22+
private final SummarizeExecutorFactory summarizeExecutorFactory;
3123

3224
public PostJobInScanner(
3325
DbClient dbClient,
3426
Configuration configuration,
35-
ALMClientFactory almClientFactory
27+
SummarizeExecutorFactory summarizeExecutorFactory
28+
//PostAnalysisIssueVisitor postAnalysisIssueVisitor
3629
) {
37-
this.postAnalysisIssueVisitor = new PostAnalysisIssueVisitor();
30+
//this.postAnalysisIssueVisitor = postAnalysisIssueVisitor;
3831
this.dbClient = dbClient;
3932
this.configuration = configuration;
40-
this.almClientFactory = almClientFactory;
33+
this.summarizeExecutorFactory = summarizeExecutorFactory;
4134
}
4235

4336
@Override
@@ -46,19 +39,6 @@ public void finished(Context context) {
4639
LOGGER.info("PostJobInScanner.finished method called");
4740
ProjectAnalysis projectAnalysis = context.getProjectAnalysis();
4841

49-
Optional<Branch> optionalPullRequest =
50-
projectAnalysis.getBranch().filter(branch -> Branch.Type.PULL_REQUEST == branch.getType());
51-
if (optionalPullRequest.isEmpty()) {
52-
LOGGER.trace("Current analysis is not for a Pull Request. Task being skipped");
53-
return;
54-
}
55-
56-
Optional<String> optionalPullRequestId = optionalPullRequest.get().getName();
57-
if (optionalPullRequestId.isEmpty()) {
58-
LOGGER.warn("No pull request ID has been submitted with the Pull Request. Analysis will be skipped");
59-
return;
60-
}
61-
6242
ProjectAlmSettingDto projectAlmSettingDto;
6343
Optional<AlmSettingDto> optionalAlmSettingDto;
6444
try (DbSession dbSession = dbClient.openSession(false)) {
@@ -89,28 +69,10 @@ public void finished(Context context) {
8969
}
9070

9171
try {
92-
AiSummarizeConfig aiConfig = new AiSummarizeConfig(configuration);
93-
String prNumber = optionalPullRequestId.get();
94-
95-
ALMClient almClient = almClientFactory.createClient(currentAlmId, almSettingDto, projectAlmSettingDto);
96-
97-
PullRequestDiff pullRequestDiff = new PullRequestDiffFetcher(almClient)
98-
.fetchDiff(prNumber);
99-
100-
SummarizeWithAI summarizer = new SummarizeWithAI(prNumber, aiConfig);
101-
102-
String summary = summarizer.execute(pullRequestDiff);
103-
LOGGER.info("AI summarization completed successfully");
104-
LOGGER.info("Summary: {}", summary);
105-
106-
//TODO: add SQ issues to prompt
107-
AnalysisDetails analysisDetails =
108-
new AnalysisDetails(optionalPullRequestId.get(), postAnalysisIssueVisitor.getIssues(), projectAnalysis);
109-
110-
almClient.postSummaryIssue(prNumber, summary);
111-
72+
SummarizeExecutor summarizeExecutor = summarizeExecutorFactory.createExecutor(currentAlmId, almSettingDto, projectAnalysis, projectAlmSettingDto);
73+
summarizeExecutor.analyzeAndSummarize();
11274

113-
// TODO: Store the summary in SonarQube or send it as a report to the ALM platform
75+
// TODO: Store the summary in SonarQube (?)
11476
} catch (Exception e) {
11577
LOGGER.error("Error during AI summarization", e);
11678
}

src/main/java/org/perpectiveteam/plugins/aisummarize/pullrequest/PatchParser.java

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/main/java/org/perpectiveteam/plugins/aisummarize/pullrequest/PullRequestDiffFetcher.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.perpectiveteam.plugins.aisummarize.pullrequest;
22

3+
import java.io.IOException;
34
import java.util.List;
45

56
import org.perpectiveteam.plugins.aisummarize.pullrequest.almclient.ALMClient;
@@ -17,9 +18,9 @@ public PullRequestDiffFetcher(ALMClient almClient) {
1718
this.almClient = almClient;
1819
}
1920

20-
public PullRequestDiff fetchDiff(String pullRequestNumber) {
21-
LOG.info("Fetching PR diff for PR #{}", pullRequestNumber);
22-
List<FileDiff> files = almClient.fetchPullRequestFilesDiff(pullRequestNumber);
21+
public PullRequestDiff fetchDiff() throws IOException {
22+
LOG.info("Fetching PR diff for PR #{}", almClient.getPrNumber());
23+
List<FileDiff> files = almClient.fetchPullRequestFilesDiff();
2324
LOG.info("Fetched {} files from PR", files.size());
2425

2526
PullRequestDiff diff = new PullRequestDiff();
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package org.perpectiveteam.plugins.aisummarize.pullrequest.almclient;
22

3+
import java.io.IOException;
34
import java.util.List;
45

56
import org.perpectiveteam.plugins.aisummarize.pullrequest.dtobuilder.FileDiff;
67

78
public interface ALMClient {
8-
List<FileDiff> fetchPullRequestFilesDiff(String pullRequestNumber);
9-
void postSummaryIssue(String prNumber, String comment);
9+
List<FileDiff> fetchPullRequestFilesDiff() throws IOException;
10+
void postSummaryIssue(String comment) throws IOException;
11+
String getPrNumber();
1012
}

src/main/java/org/perpectiveteam/plugins/aisummarize/pullrequest/almclient/ALMClientFactory.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.perpectiveteam.plugins.aisummarize.config.AiSummarizeConfig;
44
import org.sonar.api.ce.ComputeEngineSide;
5+
import org.sonar.api.ce.posttask.PostProjectAnalysisTask.ProjectAnalysis;
56
import org.sonar.api.server.ServerSide;
67
import org.sonar.db.alm.setting.AlmSettingDto;
78
import org.sonar.db.alm.setting.ALM;
@@ -16,9 +17,8 @@
1617
@ServerSide
1718
@ComputeEngineSide
1819
public class ALMClientFactory {
19-
//TODO: log issues
20-
//private static final Logger LOG = Loggers.get(ALMClientFactory.class);
2120
private final AiSummarizeConfig config;
21+
2222
@Autowired
2323
public ALMClientFactory(List<ALMClientFactoryDelegate> delegates, AiSummarizeConfig config) {
2424
this.delegateMap = delegates.stream().collect(Collectors.toMap(ALMClientFactoryDelegate::getAlm, d -> d));
@@ -28,13 +28,18 @@ public ALMClientFactory(List<ALMClientFactoryDelegate> delegates, AiSummarizeCon
2828

2929
private final Map<ALM, ALMClientFactoryDelegate> delegateMap;
3030

31-
public ALMClient createClient(String currentAlmId, AlmSettingDto almSettingDto, ProjectAlmSettingDto projectAlmSettingDto) throws IOException {
31+
public ALMClient createClient(
32+
String currentAlmId,
33+
AlmSettingDto almSettingDto,
34+
ProjectAnalysis projectAnalysis,
35+
ProjectAlmSettingDto projectAlmSettingDto
36+
) throws IOException {
3237
ALM alm = ALM.fromId(currentAlmId);
3338
int fileLimit = config.getFileLimit();
3439
ALMClientFactoryDelegate delegate = delegateMap.get(alm);
3540
if (delegate == null) {
3641
throw new IllegalArgumentException("No factory for ALM: " + currentAlmId);
3742
}
38-
return delegate.createClient(almSettingDto, projectAlmSettingDto, fileLimit);
43+
return delegate.createClient(almSettingDto, projectAlmSettingDto, projectAnalysis, fileLimit);
3944
}
4045
}

src/main/java/org/perpectiveteam/plugins/aisummarize/pullrequest/almclient/ALMClientFactoryDelegate.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.perpectiveteam.plugins.aisummarize.pullrequest.almclient;
22

3+
import org.sonar.api.ce.posttask.PostProjectAnalysisTask.ProjectAnalysis;
34
import org.sonar.db.alm.setting.ALM;
45
import org.sonar.db.alm.setting.AlmSettingDto;
56
import org.sonar.db.alm.setting.ProjectAlmSettingDto;
@@ -9,5 +10,10 @@
910
public interface ALMClientFactoryDelegate {
1011
ALM getAlm();
1112

12-
ALMClient createClient(AlmSettingDto almSettingDto, ProjectAlmSettingDto projectAlmSettingDto, int fileLimit) throws IOException;
13+
ALMClient createClient(
14+
AlmSettingDto almSettingDto,
15+
ProjectAlmSettingDto projectAlmSettingDto,
16+
ProjectAnalysis projectAnalysis,
17+
int fileLimit
18+
) throws IOException;
1319
}

0 commit comments

Comments
 (0)