diff --git a/pom.xml b/pom.xml
index 98925c046dffd638fe1d099687cfff7a74652177..98fd510e66d8e10a7b38c888f945bde3bc68d792 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,6 +18,12 @@
     <surefire-plugin.version>2.22.1</surefire-plugin.version>
     <auto-value.version>1.8.2</auto-value.version>
     <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
+    <sonar.sources>src/main</sonar.sources>
+    <sonar.tests>src/test</sonar.tests>
+    <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
+    <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
+    <sonar.coverage.jacoco.xmlReportPaths>${project.basedir}/target/jacoco-report/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
+    <sonar.junit.reportPath>${project.build.directory}/surefire-reports</sonar.junit.reportPath>
   </properties>
   <repositories>
     <repository>
@@ -158,6 +164,11 @@
       <version>${eclipse-api-version}</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>io.quarkus</groupId>
+      <artifactId>quarkus-jacoco</artifactId>
+      <scope>test</scope>
+    </dependency>
 
     <!-- Following H2/devservices deps are made to circumvent need for docker -->
     <dependency>
diff --git a/src/main/java/org/eclipsefoundation/git/eca/api/models/Project.java b/src/main/java/org/eclipsefoundation/git/eca/api/models/Project.java
index fa07ce5d1a85dfe6aa2814978606a02ca2dd1e13..f04d4b0eb85d8d66a12db38ba30986af7bf31697 100644
--- a/src/main/java/org/eclipsefoundation/git/eca/api/models/Project.java
+++ b/src/main/java/org/eclipsefoundation/git/eca/api/models/Project.java
@@ -30,7 +30,7 @@ import com.google.auto.value.extension.memoized.Memoized;
  *
  */
 @AutoValue
-@JsonDeserialize(builder = AutoValue_Project.Builder.class)
+@JsonDeserialize(builder = $AutoValue_Project.Builder.class)
 public abstract class Project {
     public abstract String getProjectId();
 
@@ -125,7 +125,7 @@ public abstract class Project {
 
     @AutoValue
     @JsonDeserialize(builder = AutoValue_Project_GitlabProject.Builder.class)
-    public static abstract class GitlabProject {
+    public abstract static class GitlabProject {
         public abstract String getProjectGroup();
 
         public abstract List<String> getIgnoredSubGroups();
diff --git a/src/main/java/org/eclipsefoundation/git/eca/dto/CommitValidationStatus.java b/src/main/java/org/eclipsefoundation/git/eca/dto/CommitValidationStatus.java
index 7c82d88fff239c59c4854064017d138545769912..3f7e4d7c3c59fb853cfbe88f2ffe838f4858f411 100644
--- a/src/main/java/org/eclipsefoundation/git/eca/dto/CommitValidationStatus.java
+++ b/src/main/java/org/eclipsefoundation/git/eca/dto/CommitValidationStatus.java
@@ -11,8 +11,10 @@
 **********************************************************************/
 package org.eclipsefoundation.git.eca.dto;
 
+import java.io.Serializable;
 import java.time.ZonedDateTime;
 import java.util.List;
+import java.util.Objects;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -39,7 +41,7 @@ import org.eclipsefoundation.persistence.model.ParameterizedSQLStatementBuilder;
 
 @Table
 @Entity
-public class CommitValidationStatus extends BareNode {
+public class CommitValidationStatus extends BareNode implements Serializable {
     public static final DtoTable TABLE = new DtoTable(CommitValidationStatus.class, "cvs");
 
     @Id
@@ -192,6 +194,33 @@ public class CommitValidationStatus extends BareNode {
         this.errors = errors;
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result
+                + Objects.hash(commitHash, creationDate, errors, estimatedLoc, id, lastModified, project, provider, repoUrl, userMail);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!super.equals(obj)) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        CommitValidationStatus other = (CommitValidationStatus) obj;
+        return Objects.equals(commitHash, other.commitHash) && Objects.equals(creationDate, other.creationDate)
+                && Objects.equals(errors, other.errors) && Objects.equals(estimatedLoc, other.estimatedLoc) && Objects.equals(id, other.id)
+                && Objects.equals(lastModified, other.lastModified) && Objects.equals(project, other.project) && provider == other.provider
+                && Objects.equals(repoUrl, other.repoUrl) && Objects.equals(userMail, other.userMail);
+    }
+
     @Override
     public String toString() {
         StringBuilder builder = new StringBuilder();
diff --git a/src/main/java/org/eclipsefoundation/git/eca/dto/CommitValidationStatusGrouping.java b/src/main/java/org/eclipsefoundation/git/eca/dto/CommitValidationStatusGrouping.java
index 7f01f5bf00047d10ba5e202c15d305b007ddea0e..5584332b54329b8ee48962cbcb2b270bff2e36e1 100644
--- a/src/main/java/org/eclipsefoundation/git/eca/dto/CommitValidationStatusGrouping.java
+++ b/src/main/java/org/eclipsefoundation/git/eca/dto/CommitValidationStatusGrouping.java
@@ -12,6 +12,7 @@
 package org.eclipsefoundation.git.eca.dto;
 
 import java.io.Serializable;
+import java.util.Objects;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -66,6 +67,29 @@ public class CommitValidationStatusGrouping extends BareNode {
         this.compositeId = compositeId;
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + Objects.hash(compositeId);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!super.equals(obj)) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        CommitValidationStatusGrouping other = (CommitValidationStatusGrouping) obj;
+        return Objects.equals(compositeId, other.compositeId);
+    }
+
     @Embeddable
     public static class GroupingCompositeId implements Serializable {
         private static final long serialVersionUID = 1L;
@@ -116,14 +140,16 @@ public class CommitValidationStatusGrouping extends BareNode {
                 // fingerprint check
                 String fingerprint = params.getFirst(GitEcaParameterNames.FINGERPRINT.getName());
                 if (StringUtils.isNotBlank(fingerprint)) {
-                    stmt.addClause(new ParameterizedSQLStatement.Clause(
-                            TABLE.getAlias() + ".compositeId.fingerprint = ?", new Object[] { fingerprint }));
+                    stmt
+                            .addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".compositeId.fingerprint = ?",
+                                    new Object[] { fingerprint }));
                 }
                 // commit id check
                 String commitId = params.getFirst(GitEcaParameterNames.COMMIT_ID.getName());
                 if (StringUtils.isNumeric(commitId)) {
-                    stmt.addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".compositeId.commit.id = ?",
-                            new Object[] { Integer.valueOf(commitId) }));
+                    stmt
+                            .addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".compositeId.commit.id = ?",
+                                    new Object[] { Integer.valueOf(commitId) }));
                 }
             }
             return stmt;
diff --git a/src/main/java/org/eclipsefoundation/git/eca/dto/PrivateProjectEvent.java b/src/main/java/org/eclipsefoundation/git/eca/dto/PrivateProjectEvent.java
index 02891c92c7f32e0c6a5df4db9ac5935af6697438..b8f0a620a67b1562400f29e12b9f41bd9c4ba605 100644
--- a/src/main/java/org/eclipsefoundation/git/eca/dto/PrivateProjectEvent.java
+++ b/src/main/java/org/eclipsefoundation/git/eca/dto/PrivateProjectEvent.java
@@ -16,6 +16,7 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.util.List;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 import javax.inject.Inject;
@@ -104,6 +105,52 @@ public class PrivateProjectEvent extends BareNode {
         this.deletionDate = deletionDate;
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + Objects.hash(compositeId, creationDate, deletionDate, efUsername, parentProject);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!super.equals(obj)) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        PrivateProjectEvent other = (PrivateProjectEvent) obj;
+        return Objects.equals(compositeId, other.compositeId) && Objects.equals(creationDate, other.creationDate)
+                && Objects.equals(deletionDate, other.deletionDate) && Objects.equals(efUsername, other.efUsername)
+                && Objects.equals(parentProject, other.parentProject);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("PrivateProjectEvent [userId=");
+        builder.append(getCompositeId().getUserId());
+        builder.append(", projectId=");
+        builder.append(getCompositeId().getProjectId());
+        builder.append(", projectPath=");
+        builder.append(getCompositeId().getProjectPath());
+        builder.append(", ef_username=");
+        builder.append(getEFUsername());
+        builder.append(", parentProject=");
+        builder.append(getParentProject());
+        builder.append(", creationDate=");
+        builder.append(getCreationDate());
+        builder.append(", deletionDate=");
+        builder.append(getDeletionDate());
+        builder.append("]");
+        return builder.toString();
+    }
+
     @Embeddable
     public static class EventCompositeId implements Serializable {
         private static final long serialVersionUID = 1L;
@@ -137,27 +184,6 @@ public class PrivateProjectEvent extends BareNode {
         }
     }
 
-    @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append("PrivateProjectEvent [userId=");
-        builder.append(getCompositeId().getUserId());
-        builder.append(", projectId=");
-        builder.append(getCompositeId().getProjectId());
-        builder.append(", projectPath=");
-        builder.append(getCompositeId().getProjectPath());
-        builder.append(", ef_username=");
-        builder.append(getEFUsername());
-        builder.append(", parentProject=");
-        builder.append(getParentProject());
-        builder.append(", creationDate=");
-        builder.append(getCreationDate());
-        builder.append(", deletionDate=");
-        builder.append(getDeletionDate());
-        builder.append("]");
-        return builder.toString();
-    }
-
     @Singleton
     public static class PrivateProjectEventFilter implements DtoFilter<PrivateProjectEvent> {
 
@@ -170,8 +196,9 @@ public class PrivateProjectEvent extends BareNode {
 
             String userId = params.getFirst(GitEcaParameterNames.USER_ID.getName());
             if (StringUtils.isNumeric(userId)) {
-                statement.addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".compositeId.userId = ?",
-                        new Object[] { Integer.valueOf(userId) }));
+                statement
+                        .addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".compositeId.userId = ?",
+                                new Object[] { Integer.valueOf(userId) }));
             }
 
             String projectId = params.getFirst(GitEcaParameterNames.PROJECT_ID.getName());
@@ -183,49 +210,42 @@ public class PrivateProjectEvent extends BareNode {
 
             List<String> projectIds = params.get(GitEcaParameterNames.PROJECT_IDS.getName());
             if (projectIds != null) {
-                statement.addClause(
-                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".compositeId.projectId IN ?",
-                                new Object[] {
-                                        projectIds.stream().map(Integer::valueOf).collect(Collectors.toList()) }));
+                statement
+                        .addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".compositeId.projectId IN ?",
+                                new Object[] { projectIds.stream().map(Integer::valueOf).collect(Collectors.toList()) }));
             }
 
             List<String> notInProjectIds = params.get(GitEcaParameterNames.NOT_IN_PROJECT_IDS.getName());
             if (notInProjectIds != null) {
-                statement.addClause(
-                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".compositeId.projectId NOT IN ?",
-                                new Object[] {
-                                        notInProjectIds.stream().map(Integer::valueOf).collect(Collectors.toList()) }));
+                statement
+                        .addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".compositeId.projectId NOT IN ?",
+                                new Object[] { notInProjectIds.stream().map(Integer::valueOf).collect(Collectors.toList()) }));
 
-                statement.addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".deletionDate IS NULL",
-                        new Object[] {}));
+                statement.addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".deletionDate IS NULL", new Object[] {}));
             }
 
             String projectPath = params.getFirst(GitEcaParameterNames.PROJECT_PATH.getName());
             if (StringUtils.isNotBlank(projectPath)) {
-                statement.addClause(
-                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".compositeId.projectPath = ?",
+                statement
+                        .addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".compositeId.projectPath = ?",
                                 new Object[] { projectPath }));
             }
 
             String parentProject = params.getFirst(GitEcaParameterNames.PARENT_PROJECT.getName());
             if (StringUtils.isNumeric(parentProject)) {
-                statement.addClause(
-                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".parentProject = ?",
+                statement
+                        .addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".parentProject = ?",
                                 new Object[] { Integer.valueOf(parentProject) }));
             }
 
             String active = params.getFirst(GitEcaParameterNames.STATUS_ACTIVE.getName());
             if (StringUtils.isNotBlank(active)) {
-                statement.addClause(
-                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".deletionDate IS NULL",
-                                new Object[] {}));
+                statement.addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".deletionDate IS NULL", new Object[] {}));
             }
 
             String deleted = params.getFirst(GitEcaParameterNames.STATUS_DELETED.getName());
             if (StringUtils.isNotBlank(deleted)) {
-                statement.addClause(
-                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".deletionDate IS NOT NULL",
-                                new Object[] {}));
+                statement.addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".deletionDate IS NOT NULL", new Object[] {}));
             }
 
             String since = params.getFirst(GitEcaParameterNames.SINCE.getName());
@@ -233,17 +253,17 @@ public class PrivateProjectEvent extends BareNode {
 
             // Get date range or only one time filter
             if (StringUtils.isNotBlank(since) && StringUtils.isNotBlank(until)) {
-                statement.addClause(
-                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".creationDate BETWEEN ? AND ?",
+                statement
+                        .addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".creationDate BETWEEN ? AND ?",
                                 new Object[] { LocalDateTime.of(LocalDate.parse(since), LocalTime.of(0, 0)),
                                         LocalDateTime.of(LocalDate.parse(until), LocalTime.of(23, 59)) }));
             } else if (StringUtils.isNotBlank(since)) {
-                statement.addClause(
-                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".creationDate > ?",
+                statement
+                        .addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".creationDate > ?",
                                 new Object[] { LocalDateTime.of(LocalDate.parse(since), LocalTime.of(0, 0)) }));
             } else if (StringUtils.isNotBlank(until)) {
-                statement.addClause(
-                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".creationDate < ?",
+                statement
+                        .addClause(new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".creationDate < ?",
                                 new Object[] { LocalDateTime.of(LocalDate.parse(until), LocalTime.of(23, 59)) }));
             }
 
diff --git a/src/main/java/org/eclipsefoundation/git/eca/model/ValidationResponse.java b/src/main/java/org/eclipsefoundation/git/eca/model/ValidationResponse.java
index 54a9f8219eca39e5a104ad8ed0961e8d36568eae..0ba5ad5cf8e192fef657984827c63dcceda80636 100644
--- a/src/main/java/org/eclipsefoundation/git/eca/model/ValidationResponse.java
+++ b/src/main/java/org/eclipsefoundation/git/eca/model/ValidationResponse.java
@@ -34,7 +34,7 @@ import com.google.auto.value.extension.memoized.Memoized;
  */
 @AutoValue
 @JsonNaming(LowerCamelCaseStrategy.class)
-@JsonDeserialize(builder = AutoValue_ValidationResponse.Builder.class)
+@JsonDeserialize(builder = $AutoValue_ValidationResponse.Builder.class)
 public abstract class ValidationResponse {
     public static final String NIL_HASH_PLACEHOLDER = "_nil";
 
diff --git a/src/main/resources/templates/simple_fingerprint_ui.html b/src/main/resources/templates/simple_fingerprint_ui.html
index f0eb2bea4a13405b6465d80c7d7994b245eaa32a..c7652fd21102c45fd9c9b3a5bca1d224f561c942 100644
--- a/src/main/resources/templates/simple_fingerprint_ui.html
+++ b/src/main/resources/templates/simple_fingerprint_ui.html
@@ -87,7 +87,7 @@
       </div>
       
       <a id="more-details" href="#accordion" class="big" data-toggle="collapse">More details
-        <i class="margin-left-10 icon-toggle glyphicon glyphicon-plus"></i>
+        <i class="margin-left-10 icon-toggle glyphicon glyphicon-plus" aria-hidden="true"></i>
       </a>
       <div id="accordion" class="collapse">
         <div class="panel list-group">
@@ -175,16 +175,16 @@
           <aside class="main-sidebar-default-margin" id="main-sidebar">
             <ul id="leftnav" class="ul-left-nav fa-ul hidden-print">
               <li class="separator"><a class="separator" href="https://www.eclipse.org/legal/ECA.php"> ECA </a></li>
-              <li><i class="fa fa-caret-right fa-fw"></i> <a href="https://accounts.eclipse.org/user/eca"
+              <li><i class="fa fa-caret-right fa-fw" aria-hidden="true"></i> <a href="https://accounts.eclipse.org/user/eca"
                   target="_self"> Sign
                 </a></li>
               <li class="separator"><a class="separator" href="https://www.eclipse.org/legal/licenses.php"> Licenses
                 </a></li>
-              <li><i class="fa fa-caret-right fa-fw"></i> <a href="https://www.eclipse.org/legal/licenses.php#approved"
+              <li><i class="fa fa-caret-right fa-fw" aria-hidden="true"></i> <a href="https://www.eclipse.org/legal/licenses.php#approved"
                   target="_self"> Approved 3rd Party </a></li>
-              <li><i class="fa fa-caret-right fa-fw"></i> <a
+              <li><i class="fa fa-caret-right fa-fw" aria-hidden="true"></i> <a
                   href="https://www.eclipse.org/legal/licenses.php#nonapproved" target="_self"> Non Approved </a></li>
-              <li><i class="fa fa-caret-right fa-fw"></i> <a href="https://www.eclipse.org/legal/noncodelicenses.php"
+              <li><i class="fa fa-caret-right fa-fw" aria-hidden="true"></i> <a href="https://www.eclipse.org/legal/noncodelicenses.php"
                   target="_self"> Docs &amp; examples </a></li>
             </ul>
           </aside>
diff --git a/src/test/java/org/eclipsefoundation/git/eca/service/impl/CachedUserServiceTest.java b/src/test/java/org/eclipsefoundation/git/eca/service/impl/CachedUserServiceTest.java
index 87af6dec504161f92ef113dda57b2136ee99db81..cd2da33dc199fa3122ce321025550d53fb39331b 100644
--- a/src/test/java/org/eclipsefoundation/git/eca/service/impl/CachedUserServiceTest.java
+++ b/src/test/java/org/eclipsefoundation/git/eca/service/impl/CachedUserServiceTest.java
@@ -35,7 +35,7 @@ import io.quarkus.test.junit.QuarkusTest;
  *
  */
 @QuarkusTest
-public class CachedUserServiceTest {
+class CachedUserServiceTest {
 
     @Inject
     UserService users;
@@ -46,8 +46,8 @@ public class CachedUserServiceTest {
     void getUser_success() {
         EclipseUser u = users.getUser("grunt@important.co");
         // assert that this is the user we expect and that it exists
-        Assertions.assertTrue(u != null);
-        Assertions.assertTrue(u.getName().equals("grunter"));
+        Assertions.assertNotNull(u);
+        Assertions.assertEquals("grunter", u.getName());
     }
 
     @Test
@@ -55,7 +55,7 @@ public class CachedUserServiceTest {
         EclipseUser u = users.getUser("123456789+grunter@users.noreply.github.com");
         // assert that this is the user we expect and that it exists
         Assertions.assertNotNull(u);
-        Assertions.assertTrue(u.getName().equals("grunter"));
+        Assertions.assertEquals("grunter", u.getName());
     }
 
     @Test
@@ -78,8 +78,8 @@ public class CachedUserServiceTest {
     void getUserByGithubUsername_success() {
         EclipseUser u = users.getUserByGithubUsername("grunter");
         // assert that this is the user we expect and that it exists
-        Assertions.assertTrue(u != null);
-        Assertions.assertTrue(u.getMail().equals("grunt@important.co"));
+        Assertions.assertNotNull(u);
+        Assertions.assertEquals("grunt@important.co", u.getMail());
     }
 
     @Test
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
index 4d28ba44717ead6563452e792698d6fb9dd5faa8..ba7455409d09aa157add6f3e9367082b706675bd 100644
--- a/src/test/resources/application.properties
+++ b/src/test/resources/application.properties
@@ -1,3 +1,4 @@
+quarkus.jacoco.includes=**/git/eca/**/*
 
 org.eclipsefoundation.git.eca.api.ProjectsAPI/mp-rest/url=https://projects.eclipse.org
 org.eclipsefoundation.git.eca.api.BotsAPI/mp-rest/url=https://api.eclipse.org