Skip to content
Snippets Groups Projects
Verified Commit f9a74562 authored by Jordi Gómez's avatar Jordi Gómez
Browse files

feat: migrating some Autovalue classes to records + small changes

parent 23e3f8b4
No related branches found
No related tags found
No related merge requests found
Pipeline #73412 failed
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!--
Copyright (c) 2020
2025 Eclipse Foundation
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipsefoundation</groupId>
<artifactId>git-eca</artifactId>
......@@ -15,7 +28,7 @@
<quarkus.platform.version>3.15.4</quarkus.platform.version>
<surefire-plugin.version>3.3.1</surefire-plugin.version>
<maven.compiler.parameters>true</maven.compiler.parameters>
<eclipse-api-version>1.2.3</eclipse-api-version>
<eclipse-api-version>1.2.5</eclipse-api-version>
<auto-value.version>1.10.4</auto-value.version>
<org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
<sonar.sources>src/main</sonar.sources>
......@@ -75,8 +88,8 @@
<artifactId>quarkus-smallrye-jwt</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-mailer</artifactId>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-mailer</artifactId>
</dependency>
<!-- Annotation preprocessors - reduce all of the boiler plate -->
......@@ -97,6 +110,12 @@
<version>${org.mapstruct.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.soabase.record-builder</groupId>
<artifactId>record-builder-processor</artifactId>
<version>45</version>
<scope>provided</scope>
</dependency>
<!-- Test requirements -->
<dependency>
......@@ -168,6 +187,11 @@
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<path>
<groupId>io.soabase.record-builder</groupId>
<artifactId>record-builder-processor</artifactId>
<version>45</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
......@@ -184,4 +208,4 @@
</plugin>
</plugins>
</build>
</project>
</project>
\ No newline at end of file
......@@ -10,53 +10,24 @@
package org.eclipsefoundation.git.eca.api.models;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.auto.value.AutoValue;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import io.soabase.recordbuilder.core.RecordBuilder;
/**
* Model response for repos/{org}/{repo}/issues/{issueNumber}/comments
*/
@AutoValue
@JsonDeserialize(builder = AutoValue_GithubIssueComment.Builder.class)
public abstract class GithubIssueComment {
public abstract String getBody();
public abstract Long getId();
public abstract GithubUser getUser();
@AutoValue
@JsonDeserialize(builder = AutoValue_GithubIssueComment_GithubUser.Builder.class)
public abstract static class GithubUser {
public abstract Long getId();
public static Builder builder() {
return new AutoValue_GithubIssueComment_GithubUser.Builder();
}
@AutoValue.Builder
@JsonPOJOBuilder(withPrefix = "set")
public abstract static class Builder {
public abstract Builder setId(Long id);
public abstract GithubUser build();
}
}
public static Builder builder() {
return new AutoValue_GithubIssueComment.Builder();
}
@AutoValue.Builder
@JsonPOJOBuilder(withPrefix = "set")
public abstract static class Builder {
public abstract Builder setBody(String body);
public abstract Builder setId(Long id);
public abstract Builder setUser(GithubUser user);
public abstract GithubIssueComment build();
}
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@RecordBuilder
public record GithubIssueComment(
String body,
Long id,
GithubUser user
) {
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@RecordBuilder
public static record GithubUser(
Long id
) {}
}
......@@ -10,51 +10,13 @@
package org.eclipsefoundation.git.eca.api.models;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.auto.value.AutoValue;
import io.soabase.recordbuilder.core.RecordBuilder;
/**
* Model for creating a comment on a GitHub issue or pull request.
* Uses the issues API endpoint which works for both issues and PRs.
*/
@AutoValue
@JsonDeserialize(builder = AutoValue_GithubIssueCommentRequest.Builder.class)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public abstract class GithubIssueCommentRequest {
/**
* Gets the comment body text.
*
* @return the comment body text
*/
public abstract String getBody();
/**
* Creates a new builder for this class.
*
* @return a new builder instance
*/
public static Builder builder() {
return new AutoValue_GithubIssueCommentRequest.Builder();
}
@AutoValue.Builder
@JsonPOJOBuilder(withPrefix = "set")
public abstract static class Builder {
/**
* Sets the comment body text.
*
* @param body the comment text to set
* @return this builder instance
*/
public abstract Builder setBody(String body);
/**
* Builds a new GithubIssueCommentRequest instance.
*
* @return the built instance
*/
public abstract GithubIssueCommentRequest build();
}
}
\ No newline at end of file
@RecordBuilder
public record GithubIssueCommentRequest(String body) {}
\ No newline at end of file
......@@ -9,29 +9,14 @@
*/
package org.eclipsefoundation.git.eca.config;
import io.smallrye.config.ConfigMapping;
import java.util.Optional;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import jakarta.enterprise.context.ApplicationScoped;
/**
* The intention of this class is to provide an static bot ID, given that this app only supports one installation, this way we can avoid
* having to retrieve this information from the API on every start, or storing it in the DB.
*/
@ApplicationScoped
public class GithubBotConfig {
@ConfigProperty(name = "eclipse.github.bot.id")
Optional<Integer> botId;
/**
* Gets the GitHub bot ID.
*
* @return the bot ID as an Optional Integer
*/
public Optional<Integer> getBotId() {
return botId;
}
@ConfigMapping(prefix = "eclipse.github.bot")
public interface GithubBotConfig {
Optional<Long> id();
}
......@@ -35,6 +35,7 @@ import org.eclipsefoundation.git.eca.api.models.GithubCommit.ParentCommit;
import org.eclipsefoundation.git.eca.api.models.GithubCommitStatusRequest;
import org.eclipsefoundation.git.eca.api.models.GithubIssueComment;
import org.eclipsefoundation.git.eca.api.models.GithubIssueCommentRequest;
import org.eclipsefoundation.git.eca.api.models.GithubIssueCommentRequestBuilder;
import org.eclipsefoundation.git.eca.api.models.GithubWebhookRequest;
import org.eclipsefoundation.git.eca.api.models.GithubWebhookRequest.PullRequest;
import org.eclipsefoundation.git.eca.config.GithubBotConfig;
......@@ -153,7 +154,7 @@ public class GithubHelper {
}
LOGGER.debug("Found {} commits for '{}#{}'", commitShas.size(), fullRepoName, prNo);
// retrieve the webhook tracking info, or generate an entry to track this PR
// retrieve the webhook tracking info, or generate an entry to track this PR if it's missing.
GithubWebhookTracking updatedTracking = retrieveAndUpdateTrackingInformation(wrapper, installationId, org, repoName,
prResponse.get());
if (updatedTracking == null) {
......@@ -472,9 +473,12 @@ public class GithubHelper {
throw new IllegalStateException("Pull request should not be null when handling validation");
}
LOGGER
.trace("Generated access token for installation {}: {}", request.getInstallation().getId(),
jwtHelper.getGithubAccessToken(request.getInstallation().getId()).getToken());
if (LOGGER.isTraceEnabled()) {
LOGGER
.trace("Generated access token for installation {}: {}", request.getInstallation().getId(),
jwtHelper.getGithubAccessToken(request.getInstallation().getId()).getToken());
}
ghApi
.updateStatus(jwtHelper.getGhBearerString(request.getInstallation().getId()), apiVersion,
request.getRepository().getOwner().getLogin(), request.getRepository().getName(), pr.getHead().getSha(),
......@@ -499,24 +503,23 @@ public class GithubHelper {
* @return List of all comments from the pull request
*/
private List<GithubIssueComment> getAllPullRequestCommentsByUserId(String bearer, String apiVersion, String org, String repo,
int prNumber, int userId) {
int prNumber, Long userId) {
int perPage = 100; // GitHub's maximum items per page
int page = 1; // Start from the first page
List<GithubIssueComment> allComments = new ArrayList<>();
// Given that there's no pagination in the response, we need to query until we get an empty response, that would mean that we've
// reached the end
while (true) {
RestResponse<List<GithubIssueComment>> response = ghApi
.getComments(bearer, apiVersion, org, repo, prNumber, perPage, page);
while (page < 50) {
RestResponse<List<GithubIssueComment>> response = ghApi.getComments(bearer, apiVersion, org, repo, prNumber, perPage, page);
List<GithubIssueComment> comments = response.getEntity();
if (Objects.isNull(comments) || comments.isEmpty()) {
if (comments == null || comments.isEmpty()) {
break;
}
// We only want the comments made by the bot user
allComments.addAll(comments.stream().filter(comment -> comment.getUser().getId() == userId).collect(Collectors.toList()));
allComments.addAll(comments.stream().filter(comment -> comment.user().id() == userId).collect(Collectors.toList()));
page++;
}
......@@ -546,17 +549,17 @@ public class GithubHelper {
Set<String> nonMentionedUsers = Set.copyOf(usernames);
if (botConfig.getBotId().isPresent()) {
if (botConfig.id().isPresent()) {
// Get existing comments using pagination
List<GithubIssueComment> comments = getAllPullRequestCommentsByUserId(ghBearerString, apiVersion, login, repositoryName,
pullRequestNumber, botConfig.getBotId().get());
pullRequestNumber, botConfig.id().get());
nonMentionedUsers = usernames
.stream()
.filter(username -> comments
.stream()
.noneMatch(
comment -> Objects.requireNonNullElse(comment.getBody(), "").contains(String.format("@%s", username))))
comment -> Objects.requireNonNullElse(comment.body(), "").contains(String.format("@%s", username))))
.collect(Collectors.toSet());
}
......@@ -566,18 +569,20 @@ public class GithubHelper {
return;
}
GithubIssueCommentRequest comment = GithubIssueCommentRequest
GithubIssueCommentRequest comment = GithubIssueCommentRequestBuilder
.builder()
.setBody(failureMessage.data("reasons", errors).data("usernames", nonMentionedUsers).render())
.body(failureMessage.data("reasons", errors).data("usernames", nonMentionedUsers).render())
.build();
LOGGER
.trace("Generated access token for installation {}: {}", request.getInstallation().getId(),
jwtHelper.getGithubAccessToken(request.getInstallation().getId()).getToken());
if (LOGGER.isTraceEnabled()) {
LOGGER
.trace("Generated access token for installation {}: {}", request.getInstallation().getId(),
jwtHelper.getGithubAccessToken(request.getInstallation().getId()).getToken());
}
LOGGER
.trace("Adding new comment to PR {} in repo {}/{}: {}", pullRequestNumber, TransformationHelper.formatLog(login),
TransformationHelper.formatLog(repositoryName), comment.getBody());
TransformationHelper.formatLog(repositoryName), comment.body());
ghApi.addComment(ghBearerString, apiVersion, login, repositoryName, pullRequestNumber, comment);
}
......
......@@ -301,7 +301,7 @@ class GithubHelperTest {
// Get the comments and verify content
List<GithubIssueComment> comments = ghApi.getComments("", "", orgName, repoName, prNumber, 30, 1).getEntity();
assertEquals(1, comments.stream().filter(comment -> comment.getBody().equals(expectedBody)).toList().size(),
assertEquals(1, comments.stream().filter(comment -> comment.body().equals(expectedBody)).toList().size(),
"Expected one comment with the expected body");
}
......
......@@ -30,6 +30,8 @@ import org.eclipsefoundation.git.eca.api.models.GithubCommit.GitCommitUser;
import org.eclipsefoundation.git.eca.api.models.GithubCommit.GithubCommitUser;
import org.eclipsefoundation.git.eca.api.models.GithubCommitStatusRequest;
import org.eclipsefoundation.git.eca.api.models.GithubIssueComment;
import org.eclipsefoundation.git.eca.api.models.GithubIssueCommentBuilder;
import org.eclipsefoundation.git.eca.api.models.GithubIssueCommentGithubUserBuilder;
import org.eclipsefoundation.git.eca.api.models.GithubIssueCommentRequest;
import org.eclipsefoundation.git.eca.api.models.GithubWebhookRequest.PullRequest;
import org.eclipsefoundation.git.eca.config.GithubBotConfig;
......@@ -139,11 +141,10 @@ public class MockGithubAPI implements GithubAPI {
public Response addComment(String bearer, String apiVersion, String organization, String repo, int issueNumber,
GithubIssueCommentRequest commentRequest) {
String repoFullName = organization + '/' + repo;
GithubIssueComment comment = GithubIssueComment
.builder()
.setId(Long.valueOf(0))
.setBody(commentRequest.getBody())
.setUser(GithubIssueComment.GithubUser.builder().setId(Long.valueOf(githubBotConfig.getBotId().orElse(0))).build())
GithubIssueComment comment = GithubIssueCommentBuilder.builder()
.id(0L)
.body(commentRequest.body())
.user(GithubIssueCommentGithubUserBuilder.builder().id(githubBotConfig.id().orElse(0L)).build())
.build();
comments.computeIfAbsent(repoFullName, k -> new HashMap<>()).computeIfAbsent(issueNumber, k -> new ArrayList<>()).add(comment);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment