diff --git a/src/main/java/org/eclipsefoundation/git/eca/resource/StatusResource.java b/src/main/java/org/eclipsefoundation/git/eca/resource/StatusResource.java index 630ae1f1063cf1ba305b9b7c95eb077225559362..98fd73d3b2d6350d1e8735cc9aacfe2351026fc9 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/resource/StatusResource.java +++ b/src/main/java/org/eclipsefoundation/git/eca/resource/StatusResource.java @@ -36,6 +36,7 @@ import org.eclipsefoundation.git.eca.namespace.ProviderType; import org.eclipsefoundation.git.eca.service.GithubApplicationService; import org.eclipsefoundation.git.eca.service.ValidationService; import org.eclipsefoundation.git.eca.service.ValidationStatusService; +import org.jboss.resteasy.client.exception.ResteasyWebApplicationException; import io.quarkus.qute.Location; import io.quarkus.qute.Template; @@ -49,6 +50,12 @@ import io.quarkus.qute.Template; @Path("eca/status") public class StatusResource extends GithubAdjacentResource { + // parameter names for the status error page + private static final String INCLUDE_INSTALL_LINK_PARAMETER = "includeInstallLink"; + private static final String MESSAGE_PARAMETER = "message"; + private static final String PULL_REQUEST_NUMBER_PARAMETER = "pullRequestNumber"; + private static final String REPO_URL_PARAMETER = "repoUrl"; + @Inject GithubApplicationService ghAppService; @Inject @@ -64,6 +71,8 @@ public class StatusResource extends GithubAdjacentResource { // Qute templates, generates UI status page @Location("simple_fingerprint_ui") Template statusUiTemplate; + @Location("error") + Template errorTemplate; /** * Standard endpoint for retrieving raw validation information on a historic request, using the fingerprint for lookups. @@ -97,10 +106,10 @@ public class StatusResource extends GithubAdjacentResource { .ok() .entity(statusUiTemplate .data("statuses", statuses) - .data("pullRequestNumber", null) + .data(PULL_REQUEST_NUMBER_PARAMETER, null) .data("fullRepoName", null) .data("project", ps.isEmpty() ? null : ps.get(0)) - .data("repoUrl", statuses.get(0).getRepoUrl()) + .data(REPO_URL_PARAMETER, statuses.get(0).getRepoUrl()) .data("installationId", null) .render()) .build(); @@ -120,47 +129,89 @@ public class StatusResource extends GithubAdjacentResource { @Path("gh/{org}/{repoName}/{prNo}") public Response getCommitValidationForGithub(@PathParam("org") String org, @PathParam("repoName") String repoName, @PathParam("prNo") Integer prNo) { + // get the repo full name, used in a few lookups String repoFullName = org + '/' + repoName; - // check that the passed repo has a valid installation - String installationId = ghAppService.getInstallationForRepo(org, repoName); - if (StringUtils.isBlank(installationId)) { - throw new BadRequestException("Repo " + repoFullName + " requested, but does not have visible installation, returning"); - } - // generate the URL used to retrieve valid projects String repoUrl = GithubValidationHelper.getRepoUrl(org, repoName); - // get the data about the current request, and check that we have some validation statuses - ValidationRequest req = validationHelper.generateRequest(installationId, repoFullName, prNo, repoUrl); - List<CommitValidationStatus> statuses = validationStatus - .getHistoricValidationStatusByShas(wrapper, req.getCommits().stream().map(Commit::getHash).collect(Collectors.toList())); - // check if we have any data, and if there is none, attempt to validate the request information - if (statuses.isEmpty()) { - // run the validation for the current request - ValidationResponse r = validationHelper.validateIncomingRequest(wrapper, org, repoName, prNo); - if (r == null) { - throw new BadRequestException("Cannot validate request for " + repoFullName + "#" + prNo + " as it is already closed"); + try { + // check that the passed repo has a valid installation + String installationId = ghAppService.getInstallationForRepo(org, repoName); + if (StringUtils.isBlank(installationId)) { + return Response + .ok() + .entity(errorTemplate + .data(MESSAGE_PARAMETER, "No Github ECA app installation could be found for the current pull request.") + .data(REPO_URL_PARAMETER, repoUrl) + .data(PULL_REQUEST_NUMBER_PARAMETER, prNo) + .data(INCLUDE_INSTALL_LINK_PARAMETER, true) + .render()) + .build(); } - // retrieve the status of the commits to display on the status page - statuses = validationStatus - .getHistoricValidationStatusByShas(wrapper, r.getCommits().keySet().stream().collect(Collectors.toList())); - } + // get the data about the current request, and check that we have some validation statuses + ValidationRequest req = validationHelper.generateRequest(installationId, repoFullName, prNo, repoUrl); + List<CommitValidationStatus> statuses = validationStatus + .getHistoricValidationStatusByShas(wrapper, + req.getCommits().stream().map(Commit::getHash).collect(Collectors.toList())); + // check if we have any data, and if there is none, attempt to validate the request information + if (statuses.isEmpty()) { + // run the validation for the current request adhoc + ValidationResponse r = validationHelper.validateIncomingRequest(wrapper, org, repoName, prNo); + if (r == null) { + return Response + .ok() + .entity(errorTemplate + .data(MESSAGE_PARAMETER, + "The currently selected PR is in a non-opened state, and will not be validated.") + .data(REPO_URL_PARAMETER, repoUrl) + .data(PULL_REQUEST_NUMBER_PARAMETER, prNo) + .data(INCLUDE_INSTALL_LINK_PARAMETER, false) + .render()) + .build(); + } + + // retrieve the status of the commits to display on the status page + statuses = validationStatus + .getHistoricValidationStatusByShas(wrapper, r.getCommits().keySet().stream().collect(Collectors.toList())); + } - // get projects for use in queries + UI - List<Project> ps = projects.retrieveProjectsForRepoURL(repoUrl, ProviderType.GITHUB); - // render and return the status UI - return Response - .ok() - .entity(statusUiTemplate - .data("statuses", statuses) - .data("pullRequestNumber", prNo) - .data("fullRepoName", repoFullName) - .data("project", ps.isEmpty() ? null : ps.get(0)) - .data("repoUrl", repoUrl) - .data("installationId", installationId) - .render()) - .build(); + // get projects for use in queries + UI + List<Project> ps = projects.retrieveProjectsForRepoURL(repoUrl, ProviderType.GITHUB); + // render and return the status UI + return Response + .ok() + .entity(statusUiTemplate + .data("statuses", statuses) + .data(PULL_REQUEST_NUMBER_PARAMETER, prNo) + .data("fullRepoName", repoFullName) + .data("project", ps.isEmpty() ? null : ps.get(0)) + .data(REPO_URL_PARAMETER, repoUrl) + .data("installationId", installationId) + .render()) + .build(); + } catch (BadRequestException e) { + return Response + .ok() + .entity(errorTemplate + .data(MESSAGE_PARAMETER, + "Request made to validate content that is not eligible for validation (either closed, or with no identifiable changes to validate).") + .data(REPO_URL_PARAMETER, repoUrl) + .data(PULL_REQUEST_NUMBER_PARAMETER, prNo) + .data(INCLUDE_INSTALL_LINK_PARAMETER, false) + .render()) + .build(); + } catch (NotFoundException | ResteasyWebApplicationException e) { + return Response + .ok() + .entity(errorTemplate + .data(MESSAGE_PARAMETER, + "Could not find a pull request given the passed parameters, please check the URL and try again.") + .data(REPO_URL_PARAMETER, repoUrl) + .data(PULL_REQUEST_NUMBER_PARAMETER, prNo) + .data(INCLUDE_INSTALL_LINK_PARAMETER, false) + .render()) + .build(); + } } - } diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html new file mode 100644 index 0000000000000000000000000000000000000000..9a1c92daa6067ddebb9feac15ab96aa1bdbd6223 --- /dev/null +++ b/src/main/resources/templates/error.html @@ -0,0 +1,22 @@ +{#include eclipse_header} + {#title}Git ECA Validation{/} +{/include} +{#include eclipse_breadcrumb /} +<div class="container" id="main-page-content"> + <div id="main-content-row" class="row"> + <section id="main-content" class="col-md-18 col-sm-16 margin-bottom-20"> + <h1>Git ECA Validation Status</h1> + <p>{message}</p> + <p>If you think this is an error, please report a new issue to the <a href="https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/issues">Eclipse Foundation Helpdesk</a></p> + <h2>Helpful links</h2> + <ul> + <li><a href="{repoUrl}">Target repository</a> + <li><a href="{repoUrl}/{pullRequestNumber}">Pull request</a> + {#if includeInstallLink} + <li><a href="https://github.com/apps/eclipse-eca-validation/installations/select_target">Install the application</a> + {/if} + </ul> + </section> + </div> +</div> +{#include eclipse_footer /} \ No newline at end of file