diff --git a/pom.xml b/pom.xml
index 7ad0212ee7c84324db81c690a9669fb389682b69..f6e12180d628ad700fecc28f1d89037f92af48ec 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   <artifactId>git-eca</artifactId>
   <version>1.1.0</version>
   <properties>
-    <eclipse-api-version>0.7.7</eclipse-api-version>
+    <eclipse-api-version>0.8.0</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>
diff --git a/src/main/java/org/eclipsefoundation/git/eca/helper/GithubValidationHelper.java b/src/main/java/org/eclipsefoundation/git/eca/helper/GithubValidationHelper.java
index 9f4c34a02151c1f9186befefcf35812791247838..58f9f2a2bac2bd6a3ed0bcb94fa1024738e2c1cb 100644
--- a/src/main/java/org/eclipsefoundation/git/eca/helper/GithubValidationHelper.java
+++ b/src/main/java/org/eclipsefoundation/git/eca/helper/GithubValidationHelper.java
@@ -31,6 +31,7 @@ import org.apache.http.HttpStatus;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.eclipse.microprofile.rest.client.inject.RestClient;
 import org.eclipsefoundation.core.helper.DateTimeHelper;
+import org.eclipsefoundation.core.helper.LoggingHelper;
 import org.eclipsefoundation.core.model.RequestWrapper;
 import org.eclipsefoundation.core.service.APIMiddleware;
 import org.eclipsefoundation.git.eca.api.GithubAPI;
@@ -103,7 +104,8 @@ public class GithubValidationHelper {
      * the request.
      */
     public ValidationResponse validateIncomingRequest(RequestWrapper wrapper, String org, String repoName, Integer prNo) {
-        String fullRepoName = org + '/' + repoName;
+        // use logging helper to sanitize newlines as they aren't needed here
+        String fullRepoName = LoggingHelper.format(org + '/' + repoName);
         // get the installation ID for the given repo if it exists, and if the PR noted exists
         String installationId = ghAppService.getInstallationForRepo(fullRepoName);
         Optional<PullRequest> prResponse = ghAppService.getPullRequest(installationId, fullRepoName, prNo);
@@ -167,7 +169,12 @@ public class GithubValidationHelper {
                 .getAll(i -> ghApi
                         .getCommits(jwtHelper.getGhBearerString(installationId), apiVersion, repositoryFullName, pullRequestNumber),
                         GithubCommit.class);
-        LOGGER.trace("Retrieved {} commits for PR {} in repo {}", commits.size(), pullRequestNumber, repositoryUrl);
+        if (LOGGER.isTraceEnabled()) {
+            LOGGER
+                    .trace("Retrieved {} commits for PR {} in repo {}", commits.size(), pullRequestNumber,
+                            LoggingHelper.format(repositoryUrl));
+        }
+
         // set up the validation request from current data
         return ValidationRequest
                 .builder()
@@ -260,6 +267,7 @@ public class GithubValidationHelper {
      */
     public GithubWebhookTracking updateGithubTrackingIfMissing(RequestWrapper wrapper, Optional<GithubWebhookTracking> tracking,
             PullRequest request, String installationId, String fullRepoName) {
+        String sanitizedRepoName = LoggingHelper.format(fullRepoName);
         // if there is no tracking present, create the missing tracking and persist it
         GithubWebhookTracking updatedTracking;
         if (tracking.isEmpty()) {
@@ -268,14 +276,14 @@ public class GithubValidationHelper {
             updatedTracking.setInstallationId(installationId);
             updatedTracking.setLastUpdated(DateTimeHelper.now());
             updatedTracking.setPullRequestNumber(request.getNumber());
-            updatedTracking.setRepositoryFullName(fullRepoName);
+            updatedTracking.setRepositoryFullName(sanitizedRepoName);
             updatedTracking.setLastKnownState(request.getState());
             updatedTracking.setNeedsRevalidation(false);
             updatedTracking.setManualRevalidationCount(0);
             if (!"open".equalsIgnoreCase(request.getState())) {
                 LOGGER
                         .warn("The PR {} in {} is not in an open state, and will not be validated to follow our validation practice",
-                                updatedTracking.getPullRequestNumber(), fullRepoName);
+                                updatedTracking.getPullRequestNumber(), sanitizedRepoName);
             }
         } else {
             // at least update the state on every run
@@ -287,11 +295,11 @@ public class GithubValidationHelper {
         List<GithubWebhookTracking> savedTracking = dao
                 .add(new RDBMSQuery<>(wrapper, filters.get(GithubWebhookTracking.class)), Arrays.asList(updatedTracking));
         if (savedTracking.isEmpty()) {
-            LOGGER.warn("Unable to create new GH tracking record for request to validate {}#{}", fullRepoName, request.getNumber());
+            LOGGER.warn("Unable to create new GH tracking record for request to validate {}#{}", sanitizedRepoName, request.getNumber());
             return null;
         }
         // return the updated tracking when successful
-        LOGGER.debug("Created/updated GH tracking record for request to validate {}#{}", fullRepoName, request.getNumber());
+        LOGGER.debug("Created/updated GH tracking record for request to validate {}#{}", sanitizedRepoName, request.getNumber());
         return savedTracking.get(0);
     }
 
diff --git a/src/main/java/org/eclipsefoundation/git/eca/helper/ProjectHelper.java b/src/main/java/org/eclipsefoundation/git/eca/helper/ProjectHelper.java
index 49c85eb298367dab23f4d75cf67083eceee346b9..c0e343fba28a4f489b160d9b87e408816b9693d7 100644
--- a/src/main/java/org/eclipsefoundation/git/eca/helper/ProjectHelper.java
+++ b/src/main/java/org/eclipsefoundation/git/eca/helper/ProjectHelper.java
@@ -118,7 +118,6 @@ public final class ProjectHelper {
                         .setProjectId(ig.getProjectId())
                         .setGerritRepos(Collections.emptyList())
                         .setGithubRepos(Collections.emptyList())
-                        .setGitlabRepos(Collections.emptyList())
                         .setGitlab(ig.getGitlab())
                         .setCommitters(ig
                                 .getParticipants()
diff --git a/src/main/java/org/eclipsefoundation/git/eca/resource/GithubWebhooksResource.java b/src/main/java/org/eclipsefoundation/git/eca/resource/GithubWebhooksResource.java
index 86125bbbba346109e726dbe00ceb950909e6899f..c7a6e176c5d50e0ddff70bb7ab8b5861a8aac191 100644
--- a/src/main/java/org/eclipsefoundation/git/eca/resource/GithubWebhooksResource.java
+++ b/src/main/java/org/eclipsefoundation/git/eca/resource/GithubWebhooksResource.java
@@ -26,6 +26,7 @@ import javax.ws.rs.ServerErrorException;
 import javax.ws.rs.core.Response;
 
 import org.apache.http.HttpStatus;
+import org.eclipsefoundation.core.helper.LoggingHelper;
 import org.eclipsefoundation.git.eca.api.models.GithubWebhookRequest;
 import org.eclipsefoundation.git.eca.api.models.GithubWebhookRequest.PullRequest;
 import org.eclipsefoundation.git.eca.dto.GithubWebhookTracking;
@@ -115,18 +116,20 @@ public class GithubWebhooksResource extends GithubAdjacentResource {
             @QueryParam(GitEcaParameterNames.INSTALLATION_ID_RAW) String installationId,
             @QueryParam(GitEcaParameterNames.PULL_REQUEST_NUMBER_RAW) Integer prNo,
             @FormParam("h-captcha-response") String captchaResponse) {
+        String sanitizedRepoName = LoggingHelper.format(fullRepoName);
         // retrieve and check that the PR exists
         Optional<PullRequest> prResponse = ghAppService.getPullRequest(installationId, fullRepoName, prNo);
         if (prResponse.isEmpty()) {
-            throw new NotFoundException(String.format("Cannot find Github PR for repo '%s', pull request number '%d'", fullRepoName, prNo));
+            throw new NotFoundException(
+                    String.format("Cannot find Github PR for repo '%s', pull request number '%d'", sanitizedRepoName, prNo));
         }
 
         // get the tracking if it exists, create it if it doesn't, and fail out if there is an issue
         GithubWebhookTracking tracking = validationHelper
                 .retrieveAndUpdateTrackingInformation(wrapper, installationId, fullRepoName, prResponse.get());
         if (tracking == null) {
-            throw new ServerErrorException(
-                    String.format("Cannot find a tracked pull request with for repo '%s', pull request number '%d'", fullRepoName, prNo),
+            throw new ServerErrorException(String
+                    .format("Cannot find a tracked pull request with for repo '%s', pull request number '%d'", sanitizedRepoName, prNo),
                     HttpStatus.SC_INTERNAL_SERVER_ERROR);
         } else if (!"open".equalsIgnoreCase(tracking.getLastKnownState())) {
             // we do not want to reprocess non-open pull requests
@@ -138,7 +141,7 @@ public class GithubWebhooksResource extends GithubAdjacentResource {
         if (!errors.isEmpty()) {
             // use debug logging as this could be incredibly noisy
             LOGGER
-                    .debug("Captcha challenge failed with the following errors for revalidation request for '{}#{}': {}", fullRepoName,
+                    .debug("Captcha challenge failed with the following errors for revalidation request for '{}#{}': {}", sanitizedRepoName,
                             prNo, errors.stream().map(HCaptchaErrorCodes::getMessage));
             throw new BadRequestException("hCaptcha challenge response failed for this request");
         }
@@ -148,7 +151,7 @@ public class GithubWebhooksResource extends GithubAdjacentResource {
             // get the tracking class, convert back to a GH webhook request, and validate the request
             GithubWebhookRequest request = GithubWebhookRequest.buildFromTracking(tracking);
             boolean isSuccessful = validationHelper.handleGithubWebhookValidation(request, generateRequest(request), wrapper).getPassed();
-            LOGGER.debug("Revalidation for request for '{}#{}' was {}successful.", fullRepoName, prNo, isSuccessful ? "" : " not");
+            LOGGER.debug("Revalidation for request for '{}#{}' was {}successful.", sanitizedRepoName, prNo, isSuccessful ? "" : " not");
 
             // build the url for pull request page
             StringBuilder sb = new StringBuilder();
diff --git a/src/test/java/org/eclipsefoundation/git/eca/resource/ReportsResourceTest.java b/src/test/java/org/eclipsefoundation/git/eca/resource/ReportsResourceTest.java
index 06c6ee66a0b4191e24c887db1951b20ce4c3ad9d..5ea2e7a8cb7f5428f4f9396f06c11320bd9935a6 100644
--- a/src/test/java/org/eclipsefoundation/git/eca/resource/ReportsResourceTest.java
+++ b/src/test/java/org/eclipsefoundation/git/eca/resource/ReportsResourceTest.java
@@ -13,16 +13,14 @@ package org.eclipsefoundation.git.eca.resource;
 
 import java.util.Optional;
 
-import org.apache.http.HttpStatus;
 import org.eclipsefoundation.git.eca.namespace.GitEcaParameterNames;
 import org.eclipsefoundation.git.eca.test.namespaces.SchemaNamespaceHelper;
 import org.eclipsefoundation.testing.helpers.TestCaseHelper;
-import org.eclipsefoundation.testing.templates.RestAssuredTemplates;
-import org.eclipsefoundation.testing.templates.RestAssuredTemplates.EndpointTestCase;
+import org.eclipsefoundation.testing.models.EndpointTestBuilder;
+import org.eclipsefoundation.testing.models.EndpointTestCase;
 import org.junit.jupiter.api.Test;
 
 import io.quarkus.test.junit.QuarkusTest;
-import io.restassured.http.ContentType;
 
 @QuarkusTest
 class ReportsResourceTest {
@@ -85,22 +83,22 @@ class ReportsResourceTest {
      */
     @Test
     void getPrivProjReport_success() {
-        RestAssuredTemplates.testGet(GET_REPORT_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_SUCCESS_CASE).run();
     }
 
     @Test
     void getPrivProjReport_success_validateSchema() {
-        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_SUCCESS_CASE).andCheckSchema().run();
     }
 
     @Test
     void getPrivProjReport_success_validateResponseFormat() {
-        RestAssuredTemplates.testGet_validateResponseFormat(GET_REPORT_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_SUCCESS_CASE).andCheckFormat().run();
     }
 
     @Test
     void getPrivProjReport_failure_badAccessKey() {
-        RestAssuredTemplates.testGet(GET_REPORT_BAD_ACCESS_KEY);
+        EndpointTestBuilder.from(GET_REPORT_BAD_ACCESS_KEY).run();
     }
 
     /*
@@ -108,27 +106,27 @@ class ReportsResourceTest {
      */
     @Test
     void getPrivProjReportActive_success() {
-        RestAssuredTemplates.testGet(GET_REPORT_ACTIVE_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_ACTIVE_SUCCESS_CASE).run();
     }
 
     @Test
     void getPrivProjReportActive_success_validateSchema() {
-        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_ACTIVE_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_ACTIVE_SUCCESS_CASE).andCheckSchema().run();
     }
 
     @Test
     void getPrivProjReportActive_success_validateResponseFormat() {
-        RestAssuredTemplates.testGet_validateResponseFormat(GET_REPORT_ACTIVE_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_ACTIVE_SUCCESS_CASE).andCheckFormat().run();
     }
 
     @Test
     void getPrivProjReportStatus_failure_invalidStatus() {
-        RestAssuredTemplates.testGet(GET_REPORT_BAD_STATUS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_BAD_STATUS_CASE).run();
     }
 
     @Test
     void getPrivProjReportStatus_failure_invalidStatus_validate_schema() {
-        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_BAD_STATUS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_BAD_STATUS_CASE).andCheckSchema().run();
     }
 
     /*
@@ -136,17 +134,17 @@ class ReportsResourceTest {
      */
     @Test
     void getPrivProjReportDeleted_success() {
-        RestAssuredTemplates.testGet(GET_REPORT_DELETED_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_DELETED_SUCCESS_CASE).run();
     }
 
     @Test
     void getPrivProjReportDeleted_success_validateSchema() {
-        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_DELETED_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_DELETED_SUCCESS_CASE).andCheckSchema().run();
     }
 
     @Test
     void getPrivProjReportDeleted_success_validateResponseFormat() {
-        RestAssuredTemplates.testGet_validateResponseFormat(GET_REPORT_DELETED_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_DELETED_SUCCESS_CASE).andCheckFormat().run();
     }
 
     /*
@@ -154,27 +152,27 @@ class ReportsResourceTest {
      */
     @Test
     void getPrivProjReportSince_success() {
-        RestAssuredTemplates.testGet(GET_REPORT_SINCE_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_SINCE_SUCCESS_CASE).run();
     }
 
     @Test
     void getPrivProjReportSince_success_validateSchema() {
-        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_SINCE_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_SINCE_SUCCESS_CASE).andCheckSchema().run();
     }
 
     @Test
     void getPrivProjReportSince_success_validateResponseFormat() {
-        RestAssuredTemplates.testGet_validateResponseFormat(GET_REPORT_SINCE_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_SINCE_SUCCESS_CASE).andCheckFormat().run();
     }
 
     @Test
     void getPrivProjReportSince_failure_invalidStatus() {
-        RestAssuredTemplates.testGet(GET_REPORT_BAD_SINCE_CASE);
+        EndpointTestBuilder.from(GET_REPORT_BAD_SINCE_CASE).run();
     }
 
     @Test
     void getPrivProjReportSince_failure_invalidStatus_validate_schema() {
-        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_BAD_SINCE_CASE);
+        EndpointTestBuilder.from(GET_REPORT_BAD_SINCE_CASE).andCheckSchema().run();
     }
 
     /*
@@ -182,27 +180,27 @@ class ReportsResourceTest {
      */
     @Test
     void getPrivProjReportUntil_success() {
-        RestAssuredTemplates.testGet(GET_REPORT_UNTIL_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_UNTIL_SUCCESS_CASE).run();
     }
 
     @Test
     void getPrivProjReportUntil_success_validateSchema() {
-        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_UNTIL_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_UNTIL_SUCCESS_CASE).andCheckSchema().run();
     }
 
     @Test
     void getPrivProjReportUntil_success_validateResponseFormat() {
-        RestAssuredTemplates.testGet_validateResponseFormat(GET_REPORT_UNTIL_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_UNTIL_SUCCESS_CASE).andCheckFormat().run();
     }
 
     @Test
     void getPrivProjReportUntil_failure_invalidStatus() {
-        RestAssuredTemplates.testGet(GET_REPORT_BAD_UNTIL_CASE);
+        EndpointTestBuilder.from(GET_REPORT_BAD_UNTIL_CASE).run();
     }
 
     @Test
     void getPrivProjReportSUntil_failure_invalidStatus_validate_schema() {
-        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_BAD_UNTIL_CASE);
+        EndpointTestBuilder.from(GET_REPORT_BAD_UNTIL_CASE).andCheckSchema().run();
     }
 
     /*
@@ -210,16 +208,16 @@ class ReportsResourceTest {
      */
     @Test
     void getPrivProjReportRange_success() {
-        RestAssuredTemplates.testGet(GET_REPORT_RANGE_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_RANGE_SUCCESS_CASE).run();
     }
 
     @Test
     void getPrivProjReportRange_success_validateSchema() {
-        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_RANGE_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_RANGE_SUCCESS_CASE).andCheckSchema().run();
     }
 
     @Test
     void getPrivProjReportRange_success_validateResponseFormat() {
-        RestAssuredTemplates.testGet_validateResponseFormat(GET_REPORT_RANGE_SUCCESS_CASE);
+        EndpointTestBuilder.from(GET_REPORT_RANGE_SUCCESS_CASE).andCheckFormat().run();
     }
 }
diff --git a/src/test/java/org/eclipsefoundation/git/eca/resource/StatusResourceTest.java b/src/test/java/org/eclipsefoundation/git/eca/resource/StatusResourceTest.java
index f6e850d2799d4acb7c52644a9066bd74cb1b6714..53ec7cfb52cfe3112a6afa3bd9c68e5d6b3e9fce 100644
--- a/src/test/java/org/eclipsefoundation/git/eca/resource/StatusResourceTest.java
+++ b/src/test/java/org/eclipsefoundation/git/eca/resource/StatusResourceTest.java
@@ -17,7 +17,7 @@ import java.util.Map;
 import org.eclipsefoundation.git.eca.test.namespaces.SchemaNamespaceHelper;
 import org.eclipsefoundation.testing.helpers.TestCaseHelper;
 import org.eclipsefoundation.testing.models.EndpointTestBuilder;
-import org.eclipsefoundation.testing.templates.RestAssuredTemplates.EndpointTestCase;
+import org.eclipsefoundation.testing.models.EndpointTestCase;
 import org.junit.jupiter.api.Test;
 
 import io.quarkus.test.junit.QuarkusTest;
diff --git a/src/test/java/org/eclipsefoundation/git/eca/resource/ValidationResourceTest.java b/src/test/java/org/eclipsefoundation/git/eca/resource/ValidationResourceTest.java
index ba99ddc39d06d1a1f94acf00cc3bd5af1f8b23bf..76d1a24f1bd6886c43de9d0d69657a2433cae316 100644
--- a/src/test/java/org/eclipsefoundation/git/eca/resource/ValidationResourceTest.java
+++ b/src/test/java/org/eclipsefoundation/git/eca/resource/ValidationResourceTest.java
@@ -34,8 +34,9 @@ import org.eclipsefoundation.git.eca.namespace.APIStatusCode;
 import org.eclipsefoundation.git.eca.namespace.ProviderType;
 import org.eclipsefoundation.git.eca.test.namespaces.SchemaNamespaceHelper;
 import org.eclipsefoundation.testing.helpers.TestCaseHelper;
-import org.eclipsefoundation.testing.templates.RestAssuredTemplates;
-import org.eclipsefoundation.testing.templates.RestAssuredTemplates.EndpointTestCase;
+
+import org.eclipsefoundation.testing.models.EndpointTestBuilder;
+import org.eclipsefoundation.testing.models.EndpointTestCase;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -132,17 +133,17 @@ class ValidationResourceTest {
 
     @Test
     void validate() {
-        RestAssuredTemplates.testPost(VALIDATE_SUCCESS_CASE, VALIDATE_SUCCESS_BODY);
+        EndpointTestBuilder.from(VALIDATE_SUCCESS_CASE).doPost(VALIDATE_SUCCESS_BODY).run();
     }
 
     @Test
     void validate_success_responseFormat() {
-        RestAssuredTemplates.testPost_validateResponseFormat(VALIDATE_SUCCESS_CASE, VALIDATE_SUCCESS_BODY);
+        EndpointTestBuilder.from(VALIDATE_SUCCESS_CASE).doPost(VALIDATE_SUCCESS_BODY).andCheckFormat().run();
     }
 
     @Test
     void validate_success_validResponseSchema() {
-        RestAssuredTemplates.testPost_validateSchema(VALIDATE_SUCCESS_CASE, VALIDATE_SUCCESS_BODY);
+        EndpointTestBuilder.from(VALIDATE_SUCCESS_CASE).doPost(VALIDATE_SUCCESS_BODY).andCheckSchema().run();
     }
 
     @Test
@@ -175,8 +176,10 @@ class ValidationResourceTest {
                 .build();
         commits.add(c2);
 
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", commits));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", commits))
+                .run();
     }
 
     @Test
@@ -192,8 +195,10 @@ class ValidationResourceTest {
                 .build();
 
         // No errors expected, should pass as only commit is a valid merge commit
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -209,9 +214,10 @@ class ValidationResourceTest {
                 .build();
 
         // Should be valid as Grunt is a committer on the prototype project
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -227,9 +233,10 @@ class ValidationResourceTest {
                 .build();
 
         // Should be valid as wizard has signed ECA
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype.git", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype.git", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -245,9 +252,10 @@ class ValidationResourceTest {
                 .build();
 
         // Should be valid as signed off by footer is no longer checked
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype.git", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype.git", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -263,9 +271,10 @@ class ValidationResourceTest {
                 .setParents(Collections.emptyList())
                 .build();
 
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -281,9 +290,10 @@ class ValidationResourceTest {
                 .setParents(Collections.emptyList())
                 .build();
 
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -300,9 +310,10 @@ class ValidationResourceTest {
                 .setParents(Collections.emptyList())
                 .build();
 
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -312,7 +323,7 @@ class ValidationResourceTest {
                 Arrays.asList(SUCCESS_COMMIT_WIZARD));
 
         // Should be valid as Wizard has spec project write access + is committer
-        RestAssuredTemplates.testPost(VALIDATE_SUCCESS_CASE, vr);
+        EndpointTestBuilder.from(VALIDATE_SUCCESS_CASE).doPost(vr).run();
 
         // CASE 2: No WG Spec proj write access
         Commit c1 = createStandardUsercommit(USER_GRUNTS, USER_GRUNTS);
@@ -324,12 +335,14 @@ class ValidationResourceTest {
         Map<String, Object> bodyParams = new HashMap<>(FAIL_DOUBLE_ERR_BODY_PARAMS);
         bodyParams.put("commits." + c1.getHash() + ".errors[0].code", APIStatusCode.ERROR_SPEC_PROJECT.getValue());
 
-        RestAssuredTemplates
-                .testPost(TestCaseHelper
+        EndpointTestBuilder
+                .from(TestCaseHelper
                         .prepareTestCase(ECA_BASE_URL, new String[] {}, "")
                         .setStatusCode(403)
                         .setBodyValidationParams(bodyParams)
-                        .build(), vr);
+                        .build())
+                .doPost(vr)
+                .run();
     }
 
     /*
@@ -341,9 +354,10 @@ class ValidationResourceTest {
         Commit c1 = createStandardUsercommit(USER_NEWBIE, USER_WIZARD);
 
         // Error should be singular + that there's no ECA on file
-        RestAssuredTemplates
-                .testPost(VALIDATE_FORBIDDEN_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_FORBIDDEN_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -351,9 +365,10 @@ class ValidationResourceTest {
         Commit c1 = createStandardUsercommit(USER_WIZARD, USER_NEWBIE);
 
         // Error count should be 1 for just the committer access
-        RestAssuredTemplates
-                .testPost(VALIDATE_FORBIDDEN_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_FORBIDDEN_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -362,12 +377,14 @@ class ValidationResourceTest {
 
         ValidationRequest vr = createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1));
 
-        RestAssuredTemplates
-                .testPost(TestCaseHelper
+        EndpointTestBuilder
+                .from(TestCaseHelper
                         .prepareTestCase(ECA_BASE_URL, new String[] {}, "")
                         .setStatusCode(403)
                         .setBodyValidationParams(FAIL_DOUBLE_ERR_BODY_PARAMS)
-                        .build(), vr);
+                        .build())
+                .doPost(vr)
+                .run();
     }
 
     @Test
@@ -376,9 +393,10 @@ class ValidationResourceTest {
 
         // Error should be singular + that there's no Eclipse Account on file for author
         // Status 403 (forbidden) is the standard return for invalid requests
-        RestAssuredTemplates
-                .testPost(VALIDATE_FORBIDDEN_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_FORBIDDEN_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -387,9 +405,10 @@ class ValidationResourceTest {
 
         // Error should be singular + that there's no Eclipse Account on file for committer
         // Status 403 (forbidden) is the standard return for invalid requests
-        RestAssuredTemplates
-                .testPost(VALIDATE_FORBIDDEN_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_FORBIDDEN_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -397,9 +416,10 @@ class ValidationResourceTest {
         Commit c1 = createStandardUsercommit(USER_GRUNTS, USER_RANDO);
 
         // Should be valid as project is not tracked
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample-not-tracked", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample-not-tracked", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -408,9 +428,10 @@ class ValidationResourceTest {
         Commit c1 = createStandardUsercommit(USER_RANDO, USER_RANDO);
 
         // Should be valid as repo is ignored
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn-tck/tck-ignored", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn-tck/tck-ignored", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -419,25 +440,26 @@ class ValidationResourceTest {
         Commit c1 = createStandardUsercommit(USER_RANDO, USER_RANDO);
 
         // Should be valid as repo is ignored
-        RestAssuredTemplates
-                .testPost(VALIDATE_FORBIDDEN_CASE,
-                        createGitHubRequest(true, "http://www.github.com/eclipsefdn-tck/tck-ignored", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_FORBIDDEN_CASE)
+                .doPost(createGitHubRequest(true, "http://www.github.com/eclipsefdn-tck/tck-ignored", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
     void testValidate_success_noCommits() {
 
         // We do not block contributions to non-project repos
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(true, "http://www.github.com/eclipsefdn/prototype.git",
-                                Collections.emptyList()));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(true, "http://www.github.com/eclipsefdn/prototype.git", Collections.emptyList()))
+                .run();
 
         // Strictmode shouldn't affect the result
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype.git",
-                                Collections.emptyList()));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype.git", Collections.emptyList()))
+                .run();
     }
 
     @Test
@@ -445,13 +467,10 @@ class ValidationResourceTest {
         Commit c1 = createStandardUsercommit(USER_WIZARD, USER_NEWBIE);
 
         // We do not block contributions to non-project repos
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, createGitHubRequest(true, "", Arrays.asList(c1)));
+        EndpointTestBuilder.from(VALIDATE_SUCCESS_CASE).doPost(createGitHubRequest(true, "", Arrays.asList(c1))).run();
 
         // Strictmode shouldn't affect the result
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "", Arrays.asList(c1)));
+        EndpointTestBuilder.from(VALIDATE_SUCCESS_CASE).doPost(createGitHubRequest(false, "", Arrays.asList(c1))).run();
     }
 
     @Test
@@ -467,14 +486,12 @@ class ValidationResourceTest {
                 .build();
 
         // We do not block contributions to non-project repos
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, req);
+        EndpointTestBuilder.from(VALIDATE_SUCCESS_CASE).doPost(req).run();
 
         req = req.toBuilder().setStrictMode(false).build();
 
         // Strictmode shouldn't affect the result
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, req);
+        EndpointTestBuilder.from(VALIDATE_SUCCESS_CASE).doPost(req).run();
     }
 
     /*
@@ -486,8 +503,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_PROJBOT, BOT_PROJBOT);
 
         // Should be valid as bots should only commit on their own projects (including aliases)
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -495,9 +514,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_PROJBOT, BOT_PROJBOT);
 
         // Should be valid as bots can commit on any untracked project (legacy support)
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample-untracked", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample-untracked", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -505,9 +525,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_PROJ_GH, BOT_PROJ_GH);
 
         // Should be invalid as bots should only commit on their own projects (including aliases)
-        RestAssuredTemplates
-                .testPost(VALIDATE_FORBIDDEN_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_FORBIDDEN_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -515,9 +536,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_PROTOBOT, BOT_PROTOBOT);
 
         // Should be invalid as wrong email was used for bot (uses Gerrit bot email)
-        RestAssuredTemplates
-                .testPost(VALIDATE_FORBIDDEN_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_FORBIDDEN_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -525,9 +547,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_PROTO_GH, BOT_PROTO_GH);
 
         // Should be valid as bots should only commit on their own projects (including aliases)
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitLabRequest(false, "https://gitlab.eclipse.org/eclipse/dash-second/dash.handbook.test", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitLabRequest(false, "https://gitlab.eclipse.org/eclipse/dash-second/dash.handbook.test", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -535,9 +558,11 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_PROTO_GH, BOT_PROTO_GH);
 
         // Should be valid as bots can commit on any untracked project (legacy support)
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, createGitLabRequest(false,
-                        "https://gitlab.eclipse.org/eclipse/dash/mirror/dash.handbook.untracked", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitLabRequest(false, "https://gitlab.eclipse.org/eclipse/dash/mirror/dash.handbook.untracked",
+                        Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -545,9 +570,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_SPECBOT, BOT_SPECBOT);
 
         // Should be invalid as bots should only commit on their own projects
-        RestAssuredTemplates
-                .testPost(VALIDATE_FORBIDDEN_CASE,
-                        createGitLabRequest(false, "https://gitlab.eclipse.org/eclipse/dash-second/dash.handbook.test", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_FORBIDDEN_CASE)
+                .doPost(createGitLabRequest(false, "https://gitlab.eclipse.org/eclipse/dash-second/dash.handbook.test", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -555,9 +581,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_SPECBOT, BOT_SPECBOT);
 
         // Should be valid as wrong email was used, but is still bot email alias (uses Gerrit bot email)
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitLabRequest(false, "https://gitlab.eclipse.org/eclipse/dash/dash.git", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitLabRequest(false, "https://gitlab.eclipse.org/eclipse/dash/dash.git", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -565,8 +592,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_PROTOBOT, BOT_PROTOBOT);
 
         // Should be valid as bots should only commit on their own projects (including aliases)
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -574,8 +603,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_PROTOBOT, BOT_PROTOBOT);
 
         // Should be valid as bots can commit on any untracked project (legacy support)
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, createGerritRequest(true, "/gitroot/sample/untracked.project", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGerritRequest(true, "/gitroot/sample/untracked.project", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -583,8 +614,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_SPECBOT, BOT_SPECBOT);
 
         // Should be invalid as bots should only commit on their own projects (wrong project)
-        RestAssuredTemplates
-                .testPost(VALIDATE_FORBIDDEN_CASE, createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_FORBIDDEN_CASE)
+                .doPost(createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -592,8 +625,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_PROTO_GH, BOT_PROTO_GH);
 
         // Should be valid as wrong email was used, but is still bot email alias
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -602,8 +637,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(BOT_PROTO_GH, GitUser.builder().setName("protobot-gh").build());
 
         // Should be invalid as there is no email (refuse commit, not server error)
-        RestAssuredTemplates
-                .testPost(VALIDATE_FORBIDDEN_CASE, createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_FORBIDDEN_CASE)
+                .doPost(createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -611,9 +648,10 @@ class ValidationResourceTest {
         GitUser g1 = GitUser.builder().setName("grunter").setMail("other-grunt@test.co").setExternalId("grunter2").build();
         Commit c1 = createNoBodyCommit(g1, g1);
 
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -621,9 +659,10 @@ class ValidationResourceTest {
         GitUser g1 = GitUser.builder().setName("grunter").setMail("grunt@important.co").setExternalId("grunter").build();
         Commit c1 = createNoBodyCommit(g1, g1);
 
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE,
-                        createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGitHubRequest(false, "http://www.github.com/eclipsefdn/prototype", Arrays.asList(c1)))
+                .run();
     }
 
     /*
@@ -637,8 +676,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(g1, g1);
 
         // Should be valid as grunter used a no-reply Github account and has a matching GH handle
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -649,8 +690,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(g1, g1);
 
         // Should be valid as grunter used a no-reply Github account and has a matching GH handle
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -660,8 +703,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(g1, g1);
 
         // Should be invalid as no user exists with "Github" handle that matches some_guy
-        RestAssuredTemplates
-                .testPost(VALIDATE_FORBIDDEN_CASE, createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_FORBIDDEN_CASE)
+                .doPost(createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -671,8 +716,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(g1, g1);
 
         // Should be invalid as no user exists with "Github" handle that matches some_guy
-        RestAssuredTemplates
-                .testPost(VALIDATE_FORBIDDEN_CASE, createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_FORBIDDEN_CASE)
+                .doPost(createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)))
+                .run();
     }
 
     /*
@@ -687,8 +734,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(g2, g1);
 
         // Should be valid as grunter used a no-reply Github account and has a matching GH handle
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)))
+                .run();
     }
 
     @Test
@@ -699,8 +748,10 @@ class ValidationResourceTest {
         Commit c1 = createNoBodyCommit(g1, g2);
 
         // Should be valid as grunter used a no-reply Github account and has a matching GH handle
-        RestAssuredTemplates
-                .testPost(VALIDATE_SUCCESS_CASE, createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)));
+        EndpointTestBuilder
+                .from(VALIDATE_SUCCESS_CASE)
+                .doPost(createGerritRequest(true, "/gitroot/sample/gerrit.other-project", Arrays.asList(c1)))
+                .run();
     }
 
     /*
@@ -710,15 +761,16 @@ class ValidationResourceTest {
     void validateRevalidation_success() {
         ValidationRequest vr = createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(SUCCESS_COMMIT_WIZARD));
 
-        RestAssuredTemplates.testPost(VALIDATE_SUCCESS_CASE, vr);
+        EndpointTestBuilder.from(VALIDATE_SUCCESS_CASE).doPost(vr).run();
 
         Map<String, Object> bodyParams = new HashMap<>(SUCCESS_BODY_PARAMS);
         bodyParams.put("commits." + SUCCESS_COMMIT_WIZARD.getHash() + ".messages[0].code", APIStatusCode.SUCCESS_SKIPPED.getValue());
 
         // repeat call to test that skipped status is passed
-        RestAssuredTemplates
-                .testPost(TestCaseHelper.prepareTestCase(ECA_BASE_URL, new String[] {}, "").setBodyValidationParams(bodyParams).build(),
-                        vr);
+        EndpointTestBuilder
+                .from(TestCaseHelper.prepareTestCase(ECA_BASE_URL, new String[] {}, "").setBodyValidationParams(bodyParams).build())
+                .doPost(vr)
+                .run();
     }
 
     @Test
@@ -728,18 +780,20 @@ class ValidationResourceTest {
         ValidationRequest vr = createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", Arrays.asList(c1));
 
         // should fail with 1 error
-        RestAssuredTemplates.testPost(VALIDATE_FORBIDDEN_CASE, vr);
+        EndpointTestBuilder.from(VALIDATE_FORBIDDEN_CASE).doPost(vr).run();
 
         Map<String, Object> bodyParams = new HashMap<>(FAIL_SINGLE_ERR_BODY_PARAMS);
         bodyParams.put("commits." + c1.getHash() + ".errors[0].code", APIStatusCode.ERROR_AUTHOR.getValue());
 
         // repeat call to test that previously run check still fails
-        RestAssuredTemplates
-                .testPost(TestCaseHelper
+        EndpointTestBuilder
+                .from(TestCaseHelper
                         .prepareTestCase(ECA_BASE_URL, new String[] {}, "")
                         .setStatusCode(403)
                         .setBodyValidationParams(bodyParams)
-                        .build(), vr);
+                        .build())
+                .doPost(vr)
+                .run();
     }
 
     @Test
@@ -756,19 +810,21 @@ class ValidationResourceTest {
         ValidationRequest vr = createGitHubRequest(false, "http://www.github.com/eclipsefdn/sample", commits);
 
         // should fail with 1 error
-        RestAssuredTemplates.testPost(VALIDATE_FORBIDDEN_CASE, vr);
+        EndpointTestBuilder.from(VALIDATE_FORBIDDEN_CASE).doPost(vr).run();
 
         Map<String, Object> bodyParams = new HashMap<>(FAIL_SINGLE_ERR_BODY_PARAMS);
         bodyParams.put("commits." + c2.getHash() + ".errors[0].code", APIStatusCode.ERROR_AUTHOR.getValue());
         bodyParams.put("commits." + SUCCESS_COMMIT_WIZARD.getHash() + ".messages[0].code", APIStatusCode.SUCCESS_SKIPPED.getValue());
 
         // repeat call to test that previously run check still fails
-        RestAssuredTemplates
-                .testPost(TestCaseHelper
+        EndpointTestBuilder
+                .from(TestCaseHelper
                         .prepareTestCase(ECA_BASE_URL, new String[] {}, "")
                         .setStatusCode(403)
                         .setBodyValidationParams(bodyParams)
-                        .build(), vr);
+                        .build())
+                .doPost(vr)
+                .run();
     }
 
     @Test
@@ -786,7 +842,7 @@ class ValidationResourceTest {
                 .setBodyValidationParams(bodyParams)
                 .build();
 
-        RestAssuredTemplates.testPost(testCase, vr);
+        EndpointTestBuilder.from(testCase).doPost(vr).run();
 
         // simulate fixed ECA by updating author and using same hash
         c1 = Commit
@@ -806,7 +862,7 @@ class ValidationResourceTest {
 
         testCase = TestCaseHelper.prepareTestCase(ECA_BASE_URL, new String[] {}, "").setBodyValidationParams(bodyParams).build();
 
-        RestAssuredTemplates.testPost(testCase, vr);
+        EndpointTestBuilder.from(testCase).doPost(vr).run();
     }
 
     /*
@@ -814,17 +870,17 @@ class ValidationResourceTest {
      */
     @Test
     void validateUserLookup_userNotFound() {
-        RestAssuredTemplates.testGet(LOOKUP_NOT_FOUND_CASE);
+        EndpointTestBuilder.from(LOOKUP_NOT_FOUND_CASE).run();
     }
 
     @Test
     void validateUserLookup_userNoECA() {
-        RestAssuredTemplates.testGet(LOOKUP_FORBIDDEN_CASE);
+        EndpointTestBuilder.from(LOOKUP_FORBIDDEN_CASE).run();
     }
 
     @Test
     void validateUserLookup_userSuccess() {
-        RestAssuredTemplates.testGet(LOOKUP_NOT_FOUND_CASE);
+        EndpointTestBuilder.from(LOOKUP_NOT_FOUND_CASE).run();
     }
 
     // The default commit for most users. Used for most user tests
diff --git a/src/test/java/org/eclipsefoundation/git/eca/resource/WebhooksResourceTest.java b/src/test/java/org/eclipsefoundation/git/eca/resource/WebhooksResourceTest.java
index 857e80d80916c7fa264b03652c1458e1f1148b74..c46e7101bad3d3449b7175fa560b74714dec85ac 100644
--- a/src/test/java/org/eclipsefoundation/git/eca/resource/WebhooksResourceTest.java
+++ b/src/test/java/org/eclipsefoundation/git/eca/resource/WebhooksResourceTest.java
@@ -22,8 +22,9 @@ import org.eclipsefoundation.core.exception.ApplicationException;
 import org.eclipsefoundation.git.eca.api.models.SystemHook;
 import org.eclipsefoundation.git.eca.api.models.SystemHook.Owner;
 import org.eclipsefoundation.testing.helpers.TestCaseHelper;
-import org.eclipsefoundation.testing.templates.RestAssuredTemplates;
-import org.eclipsefoundation.testing.templates.RestAssuredTemplates.EndpointTestCase;
+
+import org.eclipsefoundation.testing.models.EndpointTestBuilder;
+import org.eclipsefoundation.testing.models.EndpointTestCase;
 import org.junit.jupiter.api.Test;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -134,32 +135,32 @@ class WebhooksResourceTest {
 
     @Test
     void processCreateHook_success() {
-        RestAssuredTemplates.testPost(CASE_HOOK_SUCCESS, convertHookToJson(PROJECT_CREATE_HOOK_VALID));
+        EndpointTestBuilder.from(CASE_HOOK_SUCCESS).doPost( convertHookToJson(PROJECT_CREATE_HOOK_VALID)).run();
     }
 
     @Test
     void processDeleteHook_success() {
-        RestAssuredTemplates.testPost(CASE_HOOK_SUCCESS, convertHookToJson(PROJECT_DESTROY_HOOK_VALID));
+        EndpointTestBuilder.from(CASE_HOOK_SUCCESS).doPost( convertHookToJson(PROJECT_DESTROY_HOOK_VALID)).run();
     }
 
     @Test
     void processRenameHook_success() {
-        RestAssuredTemplates.testPost(CASE_HOOK_SUCCESS, convertHookToJson(PROJECT_RENAME_HOOK_VALID));
+        EndpointTestBuilder.from(CASE_HOOK_SUCCESS).doPost( convertHookToJson(PROJECT_RENAME_HOOK_VALID)).run();
     }
 
     @Test
     void processCreateHook_success_untrackedEvent() {
-        RestAssuredTemplates.testPost(CASE_HOOK_SUCCESS, convertHookToJson(HOOK_NOT_TRACKED));
+        EndpointTestBuilder.from(CASE_HOOK_SUCCESS).doPost( convertHookToJson(HOOK_NOT_TRACKED)).run();
     }
 
     @Test
     void processCreateHook_success_missingEventName() {
-        RestAssuredTemplates.testPost(CASE_HOOK_SUCCESS, convertHookToJson(HOOK_MISSING_EVENT));
+        EndpointTestBuilder.from(CASE_HOOK_SUCCESS).doPost( convertHookToJson(HOOK_MISSING_EVENT)).run();
     }
 
     @Test
     void processCreateHook_success_missingHeaderParam() {
-        RestAssuredTemplates.testPost(CASE_HOOK_MISSING_HEADER, convertHookToJson(PROJECT_CREATE_HOOK_VALID));
+        EndpointTestBuilder.from(CASE_HOOK_MISSING_HEADER).doPost( convertHookToJson(PROJECT_CREATE_HOOK_VALID)).run();
     }
 
     private String convertHookToJson(SystemHook hook) {
diff --git a/src/test/java/org/eclipsefoundation/git/eca/test/api/MockGithubAPI.java b/src/test/java/org/eclipsefoundation/git/eca/test/api/MockGithubAPI.java
index 441d15d6b65292664fa1460dae8de0c556d9563e..93ec8e10b37f95dec3fca2ecadbeca70fd43ec45 100644
--- a/src/test/java/org/eclipsefoundation/git/eca/test/api/MockGithubAPI.java
+++ b/src/test/java/org/eclipsefoundation/git/eca/test/api/MockGithubAPI.java
@@ -73,7 +73,7 @@ public class MockGithubAPI implements GithubAPI {
     @Override
     public Response getCommits(String bearer, String apiVersion, String repoFull, int pullNumber) {
         List<GithubCommit> results = commits.get(repoFull).get(pullNumber);
-        if (results == null && !results.isEmpty()) {
+        if (results == null || !results.isEmpty()) {
             return Response.status(404).build();
         }
         return Response.ok(results).build();
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 4be050fc7877141f12d23b884d579173386dfb62..f4d54006f9e1fab0189b9f50021c1d8706ce665d 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
@@ -54,8 +54,6 @@ public class MockProjectsAPI implements ProjectsAPI {
         Repo r4 = Repo.builder().setUrl("http://www.github.com/eclipsefdn/tck-proto").build();
         Repo r5 = Repo.builder().setUrl("/gitroot/sample/gerrit.project.git").build();
         Repo r6 = Repo.builder().setUrl("/gitroot/sample/gerrit.other-project").build();
-        Repo r7 = Repo.builder().setUrl("https://gitlab.eclipse.org/eclipse/dash/dash.git").build();
-        Repo r8 = Repo.builder().setUrl("https://gitlab.eclipse.org/eclipse/dash-second/dash.handbook.test").build();
 
         // sample users
         ProjectParticipant u1 = ProjectParticipant.builder().setUrl("").setUsername("da_wizz").setFullName("da_wizz")
@@ -83,7 +81,6 @@ public class MockProjectsAPI implements ProjectsAPI {
                 .setGithub(GithubProject.builder()
                         .setOrg("")
                         .setIgnoredRepos(Collections.emptyList()).build())
-                .setGitlabRepos(Collections.emptyList())
                 .setContributors(Collections.emptyList())
                 .setWorkingGroups(Collections.emptyList())
                 .setIndustryCollaborations(Collections.emptyList())
@@ -98,7 +95,6 @@ public class MockProjectsAPI implements ProjectsAPI {
                 .setSpecProjectWorkingGroup(Collections.emptyMap())
                 .setGithubRepos(Arrays.asList(r3))
                 .setGerritRepos(Arrays.asList(r6))
-                .setGitlabRepos(Arrays.asList(r8))
                 .setCommitters(Arrays.asList(u2))
                 .setProjectLeads(Collections.emptyList())
                 .setGitlab(
@@ -127,7 +123,6 @@ public class MockProjectsAPI implements ProjectsAPI {
                 .setProjectId("spec.proj")
                 .setSpecProjectWorkingGroup(Map.of("id", "proj1", "name", "proj1"))
                 .setGithubRepos(Arrays.asList(r4))
-                .setGitlabRepos(Arrays.asList(r7))
                 .setGerritRepos(Collections.emptyList())
                 .setGitlab(GitlabProject
                         .builder()