diff --git a/pom.xml b/pom.xml index 19c9e454a3889292424af69801f815b34bc084b6..9c176a047a2c63a4239b60a665efde084a13e596 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ <artifactId>git-eca</artifactId> <version>0.0.1</version> <properties> - <eclipse-api-version>0.6.5-SNAPSHOT</eclipse-api-version> + <eclipse-api-version>0.6.6</eclipse-api-version> <compiler-plugin.version>3.8.1</compiler-plugin.version> <maven.compiler.parameters>true</maven.compiler.parameters> <maven.compiler.source>11</maven.compiler.source> @@ -14,7 +14,7 @@ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id> <quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id> - <quarkus.platform.version>2.6.3.Final</quarkus.platform.version> + <quarkus.platform.version>2.9.2.Final</quarkus.platform.version> <surefire-plugin.version>2.22.1</surefire-plugin.version> <auto-value.version>1.8.2</auto-value.version> </properties> diff --git a/src/main/java/org/eclipsefoundation/git/eca/api/ProjectsAPI.java b/src/main/java/org/eclipsefoundation/git/eca/api/ProjectsAPI.java index d599e1f54d293480c2a79a461313446c45d0c343..9e95121240aa50c101b224e1ddff06251bd0cfa3 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/api/ProjectsAPI.java +++ b/src/main/java/org/eclipsefoundation/git/eca/api/ProjectsAPI.java @@ -15,6 +15,7 @@ import javax.enterprise.context.ApplicationScoped; import javax.ws.rs.BeanParam; import javax.ws.rs.GET; import javax.ws.rs.Path; +import javax.ws.rs.Produces; import javax.ws.rs.core.Response; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; @@ -29,7 +30,7 @@ import org.jboss.resteasy.annotations.GZIP; * */ @ApplicationScoped -@Path("/api/projects") +@Path("/api") @RegisterRestClient @GZIP public interface ProjectsAPI { @@ -41,5 +42,11 @@ public interface ProjectsAPI { * @return a list of Eclipse Foundation projects. */ @GET + @Path("projects") Response getProjects(@BeanParam BaseAPIParameters baseParams); + + @GET + @Path("interest-groups") + @Produces("application/json") + Response getInterestGroups(@BeanParam BaseAPIParameters params); } diff --git a/src/main/java/org/eclipsefoundation/git/eca/model/InterestGroupData.java b/src/main/java/org/eclipsefoundation/git/eca/model/InterestGroupData.java new file mode 100644 index 0000000000000000000000000000000000000000..e2fd06bd8cf50dc3194849403206a0b00885cfb2 --- /dev/null +++ b/src/main/java/org/eclipsefoundation/git/eca/model/InterestGroupData.java @@ -0,0 +1,64 @@ +package org.eclipsefoundation.git.eca.model; + +import java.util.List; + +import org.eclipsefoundation.git.eca.model.Project.GitlabProject; +import org.eclipsefoundation.git.eca.model.Project.User; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +@AutoValue +@JsonDeserialize(builder = AutoValue_InterestGroupData.Builder.class) +public abstract class InterestGroupData { + public abstract String getId(); + public abstract String getTitle(); + public abstract String getLogo(); + public abstract String getState(); + public abstract String getFoundationdbProjectId(); + public abstract Descriptor getDescription(); + public abstract Descriptor getScope(); + public abstract List<User> getLeads(); + public abstract List<User> getParticipants(); + public abstract GitlabProject getGitlab(); + + public static Builder builder() { + return new AutoValue_InterestGroupData.Builder(); + } + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "set") + public static abstract class Builder { + public abstract Builder setId(String id); + public abstract Builder setTitle(String title); + public abstract Builder setGitlab(GitlabProject gitlab); + public abstract Builder setLogo(String logo); + public abstract Builder setState(String state); + public abstract Builder setFoundationdbProjectId(String foundationdbProjectId); + public abstract Builder setDescription(Descriptor description); + public abstract Builder setScope(Descriptor scope); + public abstract Builder setLeads(List<User> leads); + public abstract Builder setParticipants(List<User> participants); + public abstract InterestGroupData build(); + } + + @AutoValue + @JsonDeserialize(builder = AutoValue_InterestGroupData_Descriptor.Builder.class) + public static abstract class Descriptor { + public abstract String getSummary(); + public abstract String getFull(); + + public static Builder builder() { + return new AutoValue_InterestGroupData_Descriptor.Builder(); + } + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "set") + public static abstract class Builder { + public abstract Builder setSummary(String summary); + public abstract Builder setFull(String full); + public abstract Descriptor build(); + } + } +} diff --git a/src/main/java/org/eclipsefoundation/git/eca/model/Project.java b/src/main/java/org/eclipsefoundation/git/eca/model/Project.java index 452b6afaa400d2a6897b998a534e406912a9a71b..ba5be582840bfc05fcd2fd1db3f8dddcb083b7dd 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/model/Project.java +++ b/src/main/java/org/eclipsefoundation/git/eca/model/Project.java @@ -38,6 +38,8 @@ public abstract class Project { public abstract List<User> getCommitters(); + public abstract List<User> getProjectLeads(); + @Nullable public abstract List<Repo> getRepos(); @@ -80,6 +82,8 @@ public abstract class Project { public abstract Builder setName(String name); + public abstract Builder setProjectLeads(List<User> projectLeads); + public abstract Builder setCommitters(List<User> committers); public abstract Builder setRepos(@Nullable List<Repo> repos); diff --git a/src/main/java/org/eclipsefoundation/git/eca/resource/ValidationResource.java b/src/main/java/org/eclipsefoundation/git/eca/resource/ValidationResource.java index f2dbdd22d0c30134ce00200664b32fe7ca9e2171..718f7e8ec64df5771e22504a12591ff5d38df726 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/resource/ValidationResource.java +++ b/src/main/java/org/eclipsefoundation/git/eca/resource/ValidationResource.java @@ -45,10 +45,12 @@ import org.eclipsefoundation.git.eca.model.ValidationRequest; import org.eclipsefoundation.git.eca.model.ValidationResponse; import org.eclipsefoundation.git.eca.namespace.APIStatusCode; import org.eclipsefoundation.git.eca.namespace.ProviderType; +import org.eclipsefoundation.git.eca.service.InterestGroupService; import org.eclipsefoundation.git.eca.service.ProjectsService; import org.eclipsefoundation.git.eca.service.UserService; import org.eclipsefoundation.git.eca.service.ValidationService; import org.jboss.resteasy.annotations.jaxrs.QueryParam; +import org.jboss.resteasy.specimpl.MultivaluedMapImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -88,6 +90,8 @@ public class ValidationResource { UserService users; @Inject ValidationService validation; + @Inject + InterestGroupService ig; // Qute templates, generates email bodies @Location("simple_fingerprint_ui") @@ -115,22 +119,27 @@ public class ValidationResource { // filter the projects based on the repo URL. At least one repo in project must // match the repo URL to be valid List<Project> filteredProjects = retrieveProjectsForRequest(req); - ValidationResponse r = ValidationResponse.builder() + ValidationResponse r = ValidationResponse + .builder() .setStrictMode(req.getStrictMode() != null && req.getStrictMode() ? true : false) - .setTrackedProject(!filteredProjects.isEmpty()).setFingerprint(validation.generateRequestHash(req)) + .setTrackedProject(!filteredProjects.isEmpty()) + .setFingerprint(validation.generateRequestHash(req)) .build(); - - List<CommitValidationStatus> statuses = validation.getRequestCommitValidationStatus(wrapper, req, - filteredProjects.isEmpty() ? null : filteredProjects.get(0).getProjectId()); + List<CommitValidationStatus> statuses = validation + .getRequestCommitValidationStatus(wrapper, req, + filteredProjects.isEmpty() ? null : filteredProjects.get(0).getProjectId()); for (Commit c : req.getCommits()) { // get the current status if present - Optional<CommitValidationStatus> status = statuses.stream() - .filter(s -> c.getHash().equals(s.getCommitHash())).findFirst(); + Optional<CommitValidationStatus> status = statuses + .stream() + .filter(s -> c.getHash().equals(s.getCommitHash())) + .findFirst(); // skip the commit validation if already passed if (status.isPresent() && status.get().getErrors().isEmpty()) { - r.addMessage(c.getHash(), "Commit was previously validated, skipping processing", - APIStatusCode.SUCCESS_SKIPPED); + r + .addMessage(c.getHash(), "Commit was previously validated, skipping processing", + APIStatusCode.SUCCESS_SKIPPED); continue; } // process the request, capturing if we should continue processing @@ -141,8 +150,9 @@ public class ValidationResource { break; } } - validation.updateCommitValidationStatus(wrapper, r, req, statuses, - filteredProjects.isEmpty() ? null : filteredProjects.get(0)); + validation + .updateCommitValidationStatus(wrapper, r, req, statuses, + filteredProjects.isEmpty() ? null : filteredProjects.get(0)); return r.toResponse(); } else { // create a stubbed response with the errors @@ -251,13 +261,15 @@ public class ValidationResource { EclipseUser eclipseAuthor = getIdentifiedUser(author); // if the user is a bot, generate a stubbed user if (isAllowedUser(author.getMail()) || users.userIsABot(author.getMail(), filteredProjects)) { - addMessage(response, String.format("Automated user '%1$s' detected for author of commit %2$s", - author.getMail(), c.getHash()), c.getHash()); + addMessage(response, String + .format("Automated user '%1$s' detected for author of commit %2$s", author.getMail(), c.getHash()), + c.getHash()); eclipseAuthor = EclipseUser.createBotStub(author); } else if (eclipseAuthor == null) { addMessage(response, - String.format("Could not find an Eclipse user with mail '%1$s' for author of commit %2$s", - author.getMail(), c.getHash()), + String + .format("Could not find an Eclipse user with mail '%1$s' for author of commit %2$s", + author.getMail(), c.getHash()), c.getHash()); addError(response, "Author must have an Eclipse Account", c.getHash(), APIStatusCode.ERROR_AUTHOR); return true; @@ -267,13 +279,17 @@ public class ValidationResource { EclipseUser eclipseCommitter = getIdentifiedUser(committer); // check if whitelisted or bot if (isAllowedUser(committer.getMail()) || users.userIsABot(committer.getMail(), filteredProjects)) { - addMessage(response, String.format("Automated user '%1$s' detected for committer of commit %2$s", - committer.getMail(), c.getHash()), c.getHash()); + addMessage(response, + String + .format("Automated user '%1$s' detected for committer of commit %2$s", committer.getMail(), + c.getHash()), + c.getHash()); eclipseCommitter = EclipseUser.createBotStub(committer); } else if (eclipseCommitter == null) { addMessage(response, - String.format("Could not find an Eclipse user with mail '%1$s' for committer of commit %2$s", - committer.getMail(), c.getHash()), + String + .format("Could not find an Eclipse user with mail '%1$s' for committer of commit %2$s", + committer.getMail(), c.getHash()), c.getHash()); addError(response, "Committing user must have an Eclipse Account", c.getHash(), APIStatusCode.ERROR_COMMITTER); @@ -326,25 +342,32 @@ public class ValidationResource { userType = "committer"; } if (isCommitter) { - addMessage(r, String.format("Eclipse user '%s'(%s) is a committer on the project.", eclipseUser.getName(), - userType), c.getHash()); + addMessage(r, String + .format("Eclipse user '%s'(%s) is a committer on the project.", eclipseUser.getName(), userType), + c.getHash()); } else { - addMessage(r, String.format("Eclipse user '%s'(%s) is not a committer on the project.", - eclipseUser.getName(), userType), c.getHash()); + addMessage(r, + String + .format("Eclipse user '%s'(%s) is not a committer on the project.", eclipseUser.getName(), + userType), + c.getHash()); // check if the author is signed off if not a committer if (eclipseUser.getECA().getSigned()) { - addMessage(r, - String.format( - "Eclipse user '%s'(%s) has a current Eclipse Contributor Agreement (ECA) on file.", + addMessage(r, String + .format("Eclipse user '%s'(%s) has a current Eclipse Contributor Agreement (ECA) on file.", eclipseUser.getName(), userType), c.getHash()); } else { - addMessage(r, String.format( - "Eclipse user '%s'(%s) does not have a current Eclipse Contributor Agreement (ECA) on file.\n" + addMessage(r, String + .format("Eclipse user '%s'(%s) does not have a current Eclipse Contributor Agreement (ECA) on file.\n" + "If there are multiple commits, please ensure that each author has a ECA.", - eclipseUser.getName(), userType), c.getHash()); - addError(r, String.format("An Eclipse Contributor Agreement is required for Eclipse user '%s'(%s).", - eclipseUser.getName(), userType), c.getHash(), errorCode); + eclipseUser.getName(), userType), + c.getHash()); + addError(r, + String + .format("An Eclipse Contributor Agreement is required for Eclipse user '%s'(%s).", + eclipseUser.getName(), userType), + c.getHash(), errorCode); } } } @@ -376,13 +399,16 @@ public class ValidationResource { // commit to specs if (p.getSpecWorkingGroup() != null && !user.getECA().getCanContributeSpecProject()) { // set error + update response status - r.addError(hash, String.format( - "Project is a specification for the working group '%1$s', but user does not have permission to modify a specification project", - p.getSpecWorkingGroup()), APIStatusCode.ERROR_SPEC_PROJECT); + r + .addError(hash, String + .format("Project is a specification for the working group '%1$s', but user does not have permission to modify a specification project", + p.getSpecWorkingGroup()), + APIStatusCode.ERROR_SPEC_PROJECT); return false; } else { - LOGGER.debug("User '{}' was found to be a committer on current project repo '{}'", user.getMail(), - p.getName()); + LOGGER + .debug("User '{}' was found to be a committer on current project repo '{}'", user.getMail(), + p.getName()); return true; } } @@ -432,6 +458,11 @@ public class ValidationResource { } // check for all projects that make use of the given repo List<Project> availableProjects = projects.getProjects(); + availableProjects + .addAll(cache + .get("all", new MultivaluedMapImpl<>(), Project.class, + () -> ig.adaptInterestGroups(ig.getInterestGroups())) + .orElse(Collections.emptyList())); if (availableProjects == null || availableProjects.isEmpty()) { LOGGER.warn("Could not find any projects to match against"); return Collections.emptyList(); @@ -443,22 +474,33 @@ public class ValidationResource { if (ProviderType.GITLAB.equals(provider)) { // get the path of the project, removing the leading slash String projectNamespace = URI.create(repoUrl).getPath().substring(1).toLowerCase(); - return availableProjects.stream() - .filter(p -> projectNamespace.startsWith(p.getGitlab().getProjectGroup() + "/") && p.getGitlab() - .getIgnoredSubGroups().stream().noneMatch(sg -> projectNamespace.startsWith(sg + "/"))) + return availableProjects + .stream() + .filter(p -> projectNamespace.startsWith(p.getGitlab().getProjectGroup() + "/") && p + .getGitlab() + .getIgnoredSubGroups() + .stream() + .noneMatch(sg -> projectNamespace.startsWith(sg + "/"))) .collect(Collectors.toList()); } else if (ProviderType.GITHUB.equals(provider)) { - return availableProjects.stream() - .filter(p -> p.getGithubRepos().stream() + return availableProjects + .stream() + .filter(p -> p + .getGithubRepos() + .stream() .anyMatch(re -> re.getUrl() != null && re.getUrl().endsWith(repoUrl))) .collect(Collectors.toList()); } else if (ProviderType.GERRIT.equals(provider)) { - return availableProjects.stream() - .filter(p -> p.getGerritRepos().stream() + return availableProjects + .stream() + .filter(p -> p + .getGerritRepos() + .stream() .anyMatch(re -> re.getUrl() != null && re.getUrl().endsWith(repoUrl))) .collect(Collectors.toList()); } else { - return availableProjects.stream() + return availableProjects + .stream() .filter(p -> p.getRepos().stream().anyMatch(re -> re.getUrl().endsWith(repoUrl))) .collect(Collectors.toList()); } diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/InterestGroupService.java b/src/main/java/org/eclipsefoundation/git/eca/service/InterestGroupService.java new file mode 100644 index 0000000000000000000000000000000000000000..9efdc637487785aa1e7d9f9a61d97ce25f978076 --- /dev/null +++ b/src/main/java/org/eclipsefoundation/git/eca/service/InterestGroupService.java @@ -0,0 +1,30 @@ +package org.eclipsefoundation.git.eca.service; + +import java.util.List; + +import org.eclipsefoundation.git.eca.model.InterestGroupData; +import org.eclipsefoundation.git.eca.model.Project; + +/** + * Service for retrieving and interacting with interest groups. + * + * @author Martin Lowe + * + */ +public interface InterestGroupService { + + /** + * Retrieve all available interest groups. + * + * @return list of all available interest groups + */ + List<InterestGroupData> getInterestGroups(); + + /** + * Converts interest groups into projects for processing downstream. + * + * @param igs the interest groups to convert + * @return the converted interest groups + */ + List<Project> adaptInterestGroups(List<InterestGroupData> igs); +} diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultInterestGroupService.java b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultInterestGroupService.java new file mode 100644 index 0000000000000000000000000000000000000000..0fc98e656e79e59a47a9ceaacdf3af8c601fcd5e --- /dev/null +++ b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultInterestGroupService.java @@ -0,0 +1,64 @@ +package org.eclipsefoundation.git.eca.service.impl; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; + +import org.eclipse.microprofile.rest.client.inject.RestClient; +import org.eclipsefoundation.core.service.APIMiddleware; +import org.eclipsefoundation.core.service.CachingService; +import org.eclipsefoundation.git.eca.api.ProjectsAPI; +import org.eclipsefoundation.git.eca.model.InterestGroupData; +import org.eclipsefoundation.git.eca.model.Project; +import org.eclipsefoundation.git.eca.service.InterestGroupService; +import org.jboss.resteasy.specimpl.MultivaluedMapImpl; + +/** + * Default implementation of interest group service. + * + * @author Martin Lowe + */ +@ApplicationScoped +public class DefaultInterestGroupService implements InterestGroupService { + + @Inject + APIMiddleware middleware; + @Inject + CachingService cache; + + @Inject + @RestClient + ProjectsAPI api; + + @Override + public List<InterestGroupData> getInterestGroups() { + return cache + .get("all", new MultivaluedMapImpl<>(), InterestGroupData.class, + () -> middleware.getAll(api::getInterestGroups, InterestGroupData.class)) + .orElse(Collections.emptyList()); + } + + @Override + public List<Project> adaptInterestGroups(List<InterestGroupData> igs) { + return igs + .stream() + .map(ig -> Project + .builder() + .setProjectId(ig.getFoundationdbProjectId()) + .setGerritRepos(Collections.emptyList()) + .setGithubRepos(Collections.emptyList()) + .setGitlabRepos(Collections.emptyList()) + .setRepos(Collections.emptyList()) + .setGitlab(ig.getGitlab()) + .setCommitters(ig.getParticipants()) + .setProjectLeads(ig.getLeads()) + .setName(ig.getTitle()) + .setSpecProjectWorkingGroup(Collections.emptyMap()) + .build()) + .collect(Collectors.toList()); + } + +} diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultValidationService.java b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultValidationService.java index 74b874f0bb765ccfcffaaba1a4b8fe6e5464ce26..76f46ffa0ba3a2b1fd16e8251409d3dd6907ccea 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultValidationService.java +++ b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultValidationService.java @@ -59,17 +59,14 @@ public class DefaultValidationService implements ValidationService { } MultivaluedMap<String, String> params = new MultivaluedMapImpl<>(); params.add(GitEcaParameterNames.FINGERPRINT_RAW, fingerprint); - RDBMSQuery<CommitValidationStatusGrouping> q = new RDBMSQuery<>(wrapper, - filters.get(CommitValidationStatusGrouping.class), params); + RDBMSQuery<CommitValidationStatusGrouping> q = new RDBMSQuery<>(wrapper, filters.get(CommitValidationStatusGrouping.class), params); // set use limit to false to collect all data in one request q.setUseLimit(false); - return dao.get(q).stream().map(statusGrouping -> statusGrouping.getCompositeId().getCommit()) - .collect(Collectors.toList()); + return dao.get(q).stream().map(statusGrouping -> statusGrouping.getCompositeId().getCommit()).collect(Collectors.toList()); } @Override - public List<CommitValidationStatus> getRequestCommitValidationStatus(RequestWrapper wrapper, ValidationRequest req, - String projectId) { + public List<CommitValidationStatus> getRequestCommitValidationStatus(RequestWrapper wrapper, ValidationRequest req, String projectId) { RDBMSQuery<CommitValidationStatus> q = new RDBMSQuery<>(wrapper, filters.get(CommitValidationStatus.class), CommitHelper.getCommitParams(req, projectId)); // set use limit to false to collect all data in one request @@ -80,11 +77,7 @@ public class DefaultValidationService implements ValidationService { @Override public void updateCommitValidationStatus(RequestWrapper wrapper, ValidationResponse r, ValidationRequest req, List<CommitValidationStatus> statuses, Project p) { - // remove existing messaging - RDBMSQuery<CommitValidationMessage> q = new RDBMSQuery<>(wrapper, filters.get(CommitValidationMessage.class), - CommitHelper.getCommitParams(req, CommitHelper.getProjectId(p))); - - List<CommitValidationMessage> messages = new ArrayList<>(); + // iterate over commit responses, and update statuses in DB List<CommitValidationStatus> updatedStatuses = new ArrayList<>(); for (Entry<String, CommitStatus> e : r.getCommits().entrySet()) { if (ValidationResponse.NIL_HASH_PLACEHOLDER.equalsIgnoreCase(e.getKey())) { @@ -92,8 +85,7 @@ public class DefaultValidationService implements ValidationService { continue; } // update the status if present, otherwise make new one. - Optional<CommitValidationStatus> status = statuses.stream() - .filter(s -> e.getKey().equals(s.getCommitHash())).findFirst(); + Optional<CommitValidationStatus> status = statuses.stream().filter(s -> e.getKey().equals(s.getCommitHash())).findFirst(); CommitValidationStatus base; if (status.isPresent()) { base = status.get(); @@ -110,18 +102,19 @@ public class DefaultValidationService implements ValidationService { // get the commit for current status Optional<Commit> commit = req.getCommits().stream().filter(c -> c.getHash().equals(e.getKey())).findFirst(); if (commit.isEmpty()) { - LOGGER.error("Could not find request commit associated with commit messages for commit hash '{}'", - e.getKey()); + LOGGER.error("Could not find request commit associated with commit messages for commit hash '{}'", e.getKey()); continue; } Commit c = commit.get(); // if there are errors, update validation messages if (e.getValue().getErrors().size() > 0 || (base.getErrors() != null && base.getErrors().size() > 0)) { // generate new errors, looking for errors not found in current list - List<CommitValidationMessage> currentErrors = base.getErrors() != null ? base.getErrors() - : new ArrayList<>(); - List<CommitValidationMessage> newErrors = e.getValue().getErrors().stream().filter( - err -> currentErrors.stream().noneMatch(ce -> ce.getStatusCode() == err.getCode().getValue())) + List<CommitValidationMessage> currentErrors = base.getErrors() != null ? base.getErrors() : new ArrayList<>(); + List<CommitValidationMessage> newErrors = e + .getValue() + .getErrors() + .stream() + .filter(err -> currentErrors.stream().noneMatch(ce -> ce.getStatusCode() == err.getCode().getValue())) .map(err -> { CommitValidationMessage m = new CommitValidationMessage(); m.setAuthorEmail(c.getAuthor().getMail()); @@ -132,12 +125,14 @@ public class DefaultValidationService implements ValidationService { m.setProviderId(null); m.setCommit(base); return m; - }).collect(Collectors.toList()); + }) + .collect(Collectors.toList()); LOGGER.debug("Encountered {} new errors for commit with hash '{}'", newErrors.size(), e.getKey()); currentErrors.addAll(newErrors); // remove errors that weren't encountered on this run - currentErrors.removeIf(err -> e.getValue().getErrors().isEmpty() || e.getValue().getErrors().stream() - .noneMatch(msg -> msg.getCode().getValue() == err.getStatusCode())); + currentErrors + .removeIf(err -> e.getValue().getErrors().isEmpty() + || e.getValue().getErrors().stream().noneMatch(msg -> msg.getCode().getValue() == err.getStatusCode())); LOGGER.trace("Encountered {} errors: {}", currentErrors.size(), currentErrors); base.setErrors(currentErrors); } @@ -145,7 +140,8 @@ public class DefaultValidationService implements ValidationService { String fingerprint = generateRequestHash(req); // update the base commit status and messages dao.add(new RDBMSQuery<>(wrapper, filters.get(CommitValidationStatus.class)), updatedStatuses); - dao.add(new RDBMSQuery<>(wrapper, filters.get(CommitValidationStatusGrouping.class)), updatedStatuses.stream() - .map(s -> new CommitValidationStatusGrouping(fingerprint, s)).collect(Collectors.toList())); + dao + .add(new RDBMSQuery<>(wrapper, filters.get(CommitValidationStatusGrouping.class)), + updatedStatuses.stream().map(s -> new CommitValidationStatusGrouping(fingerprint, s)).collect(Collectors.toList())); } } diff --git a/src/test/java/org/eclipsefoundation/git/eca/test/api/MockProjectsAPI.java b/src/test/java/org/eclipsefoundation/git/eca/test/api/MockProjectsAPI.java index cce33fc53101c00670dde87369d1a127c92011d6..103487d5d1f899fc64fc418fe97f31636f30d898 100644 --- a/src/test/java/org/eclipsefoundation/git/eca/test/api/MockProjectsAPI.java +++ b/src/test/java/org/eclipsefoundation/git/eca/test/api/MockProjectsAPI.java @@ -25,6 +25,8 @@ import javax.ws.rs.core.Response; import org.eclipse.microprofile.rest.client.inject.RestClient; import org.eclipsefoundation.core.service.APIMiddleware.BaseAPIParameters; import org.eclipsefoundation.git.eca.api.ProjectsAPI; +import org.eclipsefoundation.git.eca.model.InterestGroupData; +import org.eclipsefoundation.git.eca.model.InterestGroupData.Descriptor; import org.eclipsefoundation.git.eca.model.Project; import org.eclipsefoundation.git.eca.model.Project.GitlabProject; import org.eclipsefoundation.git.eca.model.Project.Repo; @@ -66,36 +68,51 @@ public class MockProjectsAPI implements ProjectsAPI { User u2 = User.builder().setUrl("").setUsername("grunter").build(); // projects - Project p1 = Project.builder().setName("Sample project").setProjectId("sample.proj") + Project p1 = Project + .builder() + .setName("Sample project") + .setProjectId("sample.proj") .setSpecProjectWorkingGroup(Collections.emptyList()) .setGithubRepos(Arrays.asList(r1, r2)) - .setGerritRepos(Arrays.asList(r5)).setCommitters(Arrays.asList(u1, u2)).setGitlab( - GitlabProject.builder().setIgnoredSubGroups(Collections.emptyList()) - .setProjectGroup("") - .build()) + .setGerritRepos(Arrays.asList(r5)) + .setCommitters(Arrays.asList(u1, u2)) + .setProjectLeads(Collections.emptyList()) + .setGitlab(GitlabProject.builder().setIgnoredSubGroups(Collections.emptyList()).setProjectGroup("").build()) .build(); src.add(p1); - Project p2 = Project.builder().setName("Prototype thing").setProjectId("sample.proto") - .setSpecProjectWorkingGroup(Collections.emptyList()).setGithubRepos(Arrays.asList(r3)) - .setGerritRepos(Arrays.asList(r6)).setGitlabRepos(Arrays.asList(r8)) + Project p2 = Project + .builder() + .setName("Prototype thing") + .setProjectId("sample.proto") + .setSpecProjectWorkingGroup(Collections.emptyList()) + .setGithubRepos(Arrays.asList(r3)) + .setGerritRepos(Arrays.asList(r6)) + .setGitlabRepos(Arrays.asList(r8)) .setCommitters(Arrays.asList(u2)) + .setProjectLeads(Collections.emptyList()) .setGitlab( - GitlabProject.builder().setIgnoredSubGroups(Collections.emptyList()) - .setProjectGroup("eclipse/dash-second").build()) + GitlabProject.builder().setIgnoredSubGroups(Collections.emptyList()).setProjectGroup("eclipse/dash-second").build()) .build(); src.add(p2); Map<String, String> map = new HashMap<>(); map.put("id", "proj1"); - Project p3 = Project.builder().setName("Spec project").setProjectId("spec.proj") + Project p3 = Project + .builder() + .setName("Spec project") + .setProjectId("spec.proj") .setSpecProjectWorkingGroup(map) - .setGithubRepos(Arrays.asList(r4)).setGitlabRepos(Arrays.asList(r7)).setGitlab( - GitlabProject.builder() - .setIgnoredSubGroups( - Arrays.asList("eclipse/dash/mirror")) - .setProjectGroup("eclipse/dash").build()) - .setCommitters(Arrays.asList(u1, u2)).build(); + .setGithubRepos(Arrays.asList(r4)) + .setGitlabRepos(Arrays.asList(r7)) + .setGitlab(GitlabProject + .builder() + .setIgnoredSubGroups(Arrays.asList("eclipse/dash/mirror")) + .setProjectGroup("eclipse/dash") + .build()) + .setCommitters(Arrays.asList(u1, u2)) + .setProjectLeads(Collections.emptyList()) + .build(); src.add(p3); } @@ -103,4 +120,38 @@ public class MockProjectsAPI implements ProjectsAPI { public Response getProjects(BaseAPIParameters baseParams) { return Response.ok(baseParams.getPage() == 1 ? new ArrayList<>(src) : Collections.emptyList()).build(); } + + @Override + public Response getInterestGroups(BaseAPIParameters params) { + return Response + .ok(Arrays + .asList(InterestGroupData + .builder() + .setFoundationdbProjectId("foundation-internal.ig.mittens") + .setId("1") + .setLogo("") + .setState("active") + .setTitle("Magical IG Tributed To Eclipse News Sources") + .setDescription(Descriptor.builder().setFull("Sample").setSummary("Sample").build()) + .setScope(Descriptor.builder().setFull("Sample").setSummary("Sample").build()) + .setGitlab(GitlabProject + .builder() + .setIgnoredSubGroups(Collections.emptyList()) + .setProjectGroup("eclipse-ig/mittens") + .build()) + .setLeads(Arrays + .asList(User + .builder() + .setUrl("https://api.eclipse.org/account/profile/zacharysabourin") + .setUsername("zacharysabourin") + .build())) + .setParticipants(Arrays + .asList(User + .builder() + .setUrl("https://api.eclipse.org/account/profile/skilpatrick") + .setUsername("skilpatrick") + .build())) + .build())) + .build(); + } } diff --git a/src/test/java/org/eclipsefoundation/git/eca/test/dao/TestPersistenceDao.java b/src/test/java/org/eclipsefoundation/git/eca/test/dao/TestPersistenceDao.java deleted file mode 100644 index 77491879427966574c7920a43f83fe1ee8b164ef..0000000000000000000000000000000000000000 --- a/src/test/java/org/eclipsefoundation/git/eca/test/dao/TestPersistenceDao.java +++ /dev/null @@ -1,39 +0,0 @@ -/********************************************************************* -* Copyright (c) 2022 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/ -* -* Author: Martin Lowe <martin.lowe@eclipse-foundation.org> -* -* SPDX-License-Identifier: EPL-2.0 -**********************************************************************/ -package org.eclipsefoundation.git.eca.test.dao; - -import javax.enterprise.context.ApplicationScoped; - -import org.eclipsefoundation.persistence.dao.impl.DefaultHibernateDao; -import org.eclipsefoundation.persistence.dto.BareNode; -import org.eclipsefoundation.persistence.model.RDBMSQuery; - -import io.quarkus.test.Mock; - -/** - * Alternate mock DAO that ignores delete operations. Hibernate does updates - * initially rather than delete operations in H2, which cause false negatives in - * tests - * - * @author Martin Lowe - * - */ -@Mock -@ApplicationScoped -public class TestPersistenceDao extends DefaultHibernateDao { - - @Override - public <T extends BareNode> void delete(RDBMSQuery<T> q) { - // TODO do proper deleting code, but this will not impact basic tests/functionality - } - -} diff --git a/src/test/resources/database/default/V1.0.0__default.sql b/src/test/resources/database/default/V1.0.0__default.sql index 99fd9411c5a8f81e82d3f2c59cfb3cbfc1475e54..cf889fb32190e0fa52c008600b9d53290075e01b 100644 --- a/src/test/resources/database/default/V1.0.0__default.sql +++ b/src/test/resources/database/default/V1.0.0__default.sql @@ -3,32 +3,32 @@ CREATE TABLE CommitValidationStatus ( project varchar(100) DEFAULT NULL, lastModified datetime DEFAULT NULL, creationDate datetime DEFAULT NULL, - id bigint(20) NOT NULL AUTO_INCREMENT, + id bigint NOT NULL AUTO_INCREMENT, provider varchar(100) NOT NULL, repoUrl varchar(255) NOT NULL, PRIMARY KEY (id) ); -INSERT INTO CommitValidationStatus(id,commitHash,project,lastModified,creationDate,provider, repoUrl) VALUES(1,'123456789', 'sample.proj', NOW(), NOW(),'GITHUB','http://www.github.com/eclipsefdn/sample'); -INSERT INTO CommitValidationStatus(id,commitHash,project,lastModified,creationDate,provider, repoUrl) VALUES(2,'123456789', 'sample.proto', NOW(), NOW(),'GITLAB',''); -INSERT INTO CommitValidationStatus(id,commitHash,project,lastModified,creationDate,provider, repoUrl) VALUES(3,'987654321', 'sample.proto', NOW(), NOW(),'GITLAB',''); -INSERT INTO CommitValidationStatus(id,commitHash,lastModified,creationDate,provider, repoUrl) VALUES(5,'abc123def456', NOW(), NOW(),'GITHUB','http://www.github.com/eclipsefdn/sample'); +INSERT INTO CommitValidationStatus(commitHash,project,lastModified,creationDate,provider, repoUrl) VALUES('123456789', 'sample.proj', NOW(), NOW(),'GITHUB','http://www.github.com/eclipsefdn/sample'); +INSERT INTO CommitValidationStatus(commitHash,project,lastModified,creationDate,provider, repoUrl) VALUES('123456789', 'sample.proto', NOW(), NOW(),'GITLAB',''); +INSERT INTO CommitValidationStatus(commitHash,project,lastModified,creationDate,provider, repoUrl) VALUES('987654321', 'sample.proto', NOW(), NOW(),'GITLAB',''); +INSERT INTO CommitValidationStatus(commitHash,lastModified,creationDate,provider, repoUrl) VALUES('abc123def456', NOW(), NOW(),'GITHUB','http://www.github.com/eclipsefdn/sample'); CREATE TABLE CommitValidationMessage ( providerId varchar(100) DEFAULT NULL, authorEmail varchar(100) DEFAULT NULL, committerEmail varchar(100) DEFAULT NULL, eclipseId varchar(255) DEFAULT NULL, - id bigint(20) NOT NULL AUTO_INCREMENT, - commit_id int(11) NOT NULL, - statusCode int(11) NOT NULL, + id bigint NOT NULL AUTO_INCREMENT, + commit_id int NOT NULL, + statusCode int NOT NULL, PRIMARY KEY (id) ); -INSERT INTO CommitValidationMessage(id,commit_id,providerId,authorEmail,committerEmail,eclipseId,statusCode) VALUES(4,1,'','','','',-405); +INSERT INTO CommitValidationMessage(commit_id,providerId,authorEmail,committerEmail,eclipseId,statusCode) VALUES(1,'','','','',-405); CREATE TABLE `CommitValidationStatusGrouping` ( `fingerprint` varchar(255) NOT NULL, - `commit_id` bigint(20) NOT NULL, + `commit_id` bigint NOT NULL, PRIMARY KEY (`commit_id`,`fingerprint`) ); INSERT INTO CommitValidationStatusGrouping(fingerprint, commit_id) VALUES('957706b0f31e0ccfc5287c0ebc62dc79', 1); \ No newline at end of file