Skip to content

Commit aac4017

Browse files
feat(server): support pull request review threads
1 parent 326c8c4 commit aac4017

17 files changed

Lines changed: 907 additions & 76 deletions

File tree

docs/contributor/erd/schema.mmd

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,18 @@ erDiagram
203203
BIGINT author_id FK
204204
BIGINT pull_request_id FK
205205
BIGINT review_id FK
206+
BIGINT in_reply_to_id FK
207+
BIGINT thread_id FK
208+
}
209+
210+
PullRequestReviewThread {
211+
BIGINT root_comment_id PK,FK
212+
TIMESTAMPTZ created_at
213+
TIMESTAMPTZ updated_at
214+
TIMESTAMPTZ resolved_at
215+
VARCHAR(20) state "NOT NULL"
216+
BIGINT last_actor_id FK
217+
BIGINT pull_request_id FK "NOT NULL"
206218
}
207219

208220
PullRequestBadPractice {
@@ -320,6 +332,7 @@ erDiagram
320332
%% One-to-One relationships
321333
ChatMessage ||--|| ChatMessagePart : has
322334
ChatMessage ||--|| ChatThread : references
335+
PullRequestReviewComment ||--|| PullRequestReviewThread : reviewed
323336
Organization ||--|| Workspace : has
324337

325338
%% One-to-Many relationships
@@ -341,8 +354,12 @@ erDiagram
341354
User ||--o{ PullRequestReview : reviewed
342355
Issue ||--o{ PullRequestReview : reviewed
343356
User ||--o{ PullRequestReviewComment : commented_on
357+
PullRequestReviewComment ||--o{ PullRequestReviewComment : commented_on
344358
Issue ||--o{ PullRequestReviewComment : commented_on
345359
PullRequestReview ||--o{ PullRequestReviewComment : commented_on
360+
PullRequestReviewThread ||--o{ PullRequestReviewComment : commented_on
361+
User ||--o{ PullRequestReviewThread : reviewed
362+
Issue ||--o{ PullRequestReviewThread : reviewed
346363
BadPracticeDetection ||--o{ PullRequestBadPractice : has
347364
Issue ||--o{ PullRequestBadPractice : references
348365
Organization ||--o{ Repository : has

server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/pullrequest/PullRequest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import de.tum.in.www1.hephaestus.gitprovider.issue.Issue;
44
import de.tum.in.www1.hephaestus.gitprovider.pullrequestreview.PullRequestReview;
55
import de.tum.in.www1.hephaestus.gitprovider.pullrequestreviewcomment.PullRequestReviewComment;
6+
import de.tum.in.www1.hephaestus.gitprovider.pullrequestreviewthread.PullRequestReviewThread;
67
import de.tum.in.www1.hephaestus.gitprovider.user.User;
78
import jakarta.persistence.*;
89
import java.time.Instant;
@@ -63,6 +64,10 @@ public class PullRequest extends Issue {
6364
@ToString.Exclude
6465
private Set<PullRequestReviewComment> reviewComments = new HashSet<>();
6566

67+
@OneToMany(mappedBy = "pullRequest", cascade = CascadeType.REMOVE, orphanRemoval = true)
68+
@ToString.Exclude
69+
private Set<PullRequestReviewThread> reviewThreads = new HashSet<>();
70+
6671
@Lob
6772
private String badPracticeSummary;
6873

server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/pullrequestreviewcomment/PullRequestReviewComment.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
import de.tum.in.www1.hephaestus.gitprovider.common.BaseGitServiceEntity;
55
import de.tum.in.www1.hephaestus.gitprovider.pullrequest.PullRequest;
66
import de.tum.in.www1.hephaestus.gitprovider.pullrequestreview.PullRequestReview;
7+
import de.tum.in.www1.hephaestus.gitprovider.pullrequestreviewthread.PullRequestReviewThread;
78
import de.tum.in.www1.hephaestus.gitprovider.user.User;
89
import jakarta.persistence.Entity;
910
import jakarta.persistence.EnumType;
1011
import jakarta.persistence.Enumerated;
1112
import jakarta.persistence.JoinColumn;
1213
import jakarta.persistence.Lob;
1314
import jakarta.persistence.ManyToOne;
15+
import jakarta.persistence.OneToMany;
1416
import jakarta.persistence.Table;
17+
import java.util.HashSet;
18+
import java.util.Set;
1519
import lombok.Getter;
1620
import lombok.NoArgsConstructor;
1721
import lombok.Setter;
@@ -96,6 +100,20 @@ public class PullRequestReviewComment extends BaseGitServiceEntity {
96100
@ToString.Exclude
97101
private PullRequest pullRequest;
98102

103+
@ManyToOne
104+
@JoinColumn(name = "in_reply_to_id")
105+
@ToString.Exclude
106+
private PullRequestReviewComment inReplyTo;
107+
108+
@OneToMany(mappedBy = "inReplyTo")
109+
@ToString.Exclude
110+
private Set<PullRequestReviewComment> replies = new HashSet<>();
111+
112+
@ManyToOne
113+
@JoinColumn(name = "thread_id")
114+
@ToString.Exclude
115+
private PullRequestReviewThread thread;
116+
99117
public enum Side {
100118
LEFT,
101119
RIGHT,

server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/pullrequestreviewcomment/PullRequestReviewCommentRepository.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@
22

33
import org.springframework.data.jpa.repository.JpaRepository;
44

5-
public interface PullRequestReviewCommentRepository extends JpaRepository<PullRequestReviewComment, Long> {}
5+
public interface PullRequestReviewCommentRepository
6+
extends JpaRepository<PullRequestReviewComment, Long> {
7+
8+
boolean existsByThreadIdAndId(Long threadId, Long id);
9+
10+
long countByThreadId(Long threadId);
11+
}

server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/pullrequestreviewcomment/github/GitHubPullRequestReviewCommentConverter.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package de.tum.in.www1.hephaestus.gitprovider.pullrequestreviewcomment.github;
22

3+
import de.tum.in.www1.hephaestus.gitprovider.common.AuthorAssociation;
34
import de.tum.in.www1.hephaestus.gitprovider.common.BaseGitServiceEntityConverter;
45
import de.tum.in.www1.hephaestus.gitprovider.common.github.GitHubAuthorAssociationConverter;
56
import de.tum.in.www1.hephaestus.gitprovider.pullrequestreviewcomment.PullRequestReviewComment;
@@ -38,12 +39,18 @@ public PullRequestReviewComment update(
3839
comment.setCommitId(source.getCommitId());
3940
comment.setOriginalCommitId(source.getOriginalCommitId());
4041
comment.setBody(source.getBody());
41-
comment.setHtmlUrl(source.getHtmlUrl().toString());
42-
comment.setAuthorAssociation(authorAssociationConverter.convert(source.getAuthorAssociation()));
43-
comment.setStartLine(source.getPosition());
44-
comment.setOriginalStartLine(source.getOriginalPosition());
45-
comment.setLine(source.getPosition());
46-
comment.setOriginalLine(source.getOriginalPosition());
42+
if (source.getHtmlUrl() != null) {
43+
comment.setHtmlUrl(source.getHtmlUrl().toString());
44+
}
45+
if (source.getAuthorAssociation() != null) {
46+
comment.setAuthorAssociation(authorAssociationConverter.convert(source.getAuthorAssociation()));
47+
} else {
48+
comment.setAuthorAssociation(AuthorAssociation.NONE);
49+
}
50+
comment.setStartLine(source.getStartLine());
51+
comment.setOriginalStartLine(source.getOriginalStartLine());
52+
comment.setLine(source.getLine());
53+
comment.setOriginalLine(source.getOriginalLine());
4754
comment.setStartSide(convertSide(source.getStartSide()));
4855
comment.setSide(convertSide(source.getSide()));
4956
comment.setPosition(source.getPosition());
@@ -52,6 +59,9 @@ public PullRequestReviewComment update(
5259
}
5360

5461
private PullRequestReviewComment.Side convertSide(Side side) {
62+
if (side == null) {
63+
return PullRequestReviewComment.Side.UNKNOWN;
64+
}
5565
switch (side) {
5666
case LEFT:
5767
return PullRequestReviewComment.Side.LEFT;

server/application-server/src/main/java/de/tum/in/www1/hephaestus/gitprovider/pullrequestreviewcomment/github/GitHubPullRequestReviewCommentMessageHandler.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
import de.tum.in.www1.hephaestus.gitprovider.common.github.GitHubMessageHandler;
44
import de.tum.in.www1.hephaestus.gitprovider.pullrequest.github.GitHubPullRequestSyncService;
55
import de.tum.in.www1.hephaestus.gitprovider.pullrequestreviewcomment.PullRequestReviewCommentRepository;
6+
import de.tum.in.www1.hephaestus.gitprovider.pullrequestreviewthread.PullRequestReviewThreadRepository;
67
import de.tum.in.www1.hephaestus.gitprovider.repository.github.GitHubRepositorySyncService;
78
import org.kohsuke.github.GHEvent;
89
import org.kohsuke.github.GHEventPayload;
910
import org.slf4j.Logger;
1011
import org.slf4j.LoggerFactory;
1112
import org.springframework.stereotype.Component;
13+
import org.springframework.transaction.annotation.Transactional;
1214

1315
@Component
1416
public class GitHubPullRequestReviewCommentMessageHandler
@@ -20,21 +22,25 @@ public class GitHubPullRequestReviewCommentMessageHandler
2022
private final GitHubPullRequestReviewCommentSyncService pullRequestReviewCommentSyncService;
2123
private final GitHubPullRequestSyncService pullRequestSyncService;
2224
private final GitHubRepositorySyncService repositorySyncService;
25+
private final PullRequestReviewThreadRepository pullRequestReviewThreadRepository;
2326

24-
private GitHubPullRequestReviewCommentMessageHandler(
27+
public GitHubPullRequestReviewCommentMessageHandler(
2528
PullRequestReviewCommentRepository pullRequestReviewCommentRepository,
2629
GitHubPullRequestReviewCommentSyncService pullRequestReviewCommentSyncService,
2730
GitHubPullRequestSyncService pullRequestSyncService,
28-
GitHubRepositorySyncService repositorySyncService
31+
GitHubRepositorySyncService repositorySyncService,
32+
PullRequestReviewThreadRepository pullRequestReviewThreadRepository
2933
) {
3034
super(GHEventPayload.PullRequestReviewComment.class);
3135
this.pullRequestReviewCommentRepository = pullRequestReviewCommentRepository;
3236
this.pullRequestReviewCommentSyncService = pullRequestReviewCommentSyncService;
3337
this.pullRequestSyncService = pullRequestSyncService;
3438
this.repositorySyncService = repositorySyncService;
39+
this.pullRequestReviewThreadRepository = pullRequestReviewThreadRepository;
3540
}
3641

3742
@Override
43+
@Transactional
3844
protected void handleEvent(GHEventPayload.PullRequestReviewComment eventPayload) {
3945
var action = eventPayload.getAction();
4046
var pullRequest = eventPayload.getPullRequest();
@@ -51,7 +57,16 @@ protected void handleEvent(GHEventPayload.PullRequestReviewComment eventPayload)
5157
pullRequestSyncService.processPullRequest(pullRequest);
5258

5359
if (action.equals("deleted")) {
54-
pullRequestReviewCommentRepository.deleteById(comment.getId());
60+
pullRequestReviewCommentRepository
61+
.findById(comment.getId())
62+
.ifPresent(existingComment -> {
63+
var thread = existingComment.getThread();
64+
if (thread != null && comment.getInReplyToId() <= 0) {
65+
pullRequestReviewThreadRepository.delete(thread);
66+
}
67+
68+
pullRequestReviewCommentRepository.delete(existingComment);
69+
});
5570
} else {
5671
pullRequestReviewCommentSyncService.processPullRequestReviewComment(comment);
5772
}

0 commit comments

Comments
 (0)