From adf26a73ec552c65999660622fce58cd03c0d5ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20G=C3=B3mez?= <jordi.gomez@eclipse-foundation.org> Date: Mon, 7 Apr 2025 12:09:18 +0200 Subject: [PATCH 01/10] feat: adding email notification when certian revalidation threshold is met --- pom.xml | 19 +- .../git/eca/service/MailerService.java | 27 ++ .../service/impl/DefaultMailerService.java | 104 +++++++ .../eca/tasks/GithubRevalidationQueue.java | 267 +++++++++++------- .../templates/emails/revalidation_alert.txt | 10 + src/test/resources/application.properties | 11 +- 6 files changed, 324 insertions(+), 114 deletions(-) create mode 100644 src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java create mode 100644 src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java create mode 100644 src/main/resources/templates/emails/revalidation_alert.txt diff --git a/pom.xml b/pom.xml index 93dcd59b..ec754369 100644 --- a/pom.xml +++ b/pom.xml @@ -1,8 +1,5 @@ -<?xml version="1.0"?> -<project - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" - xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.eclipsefoundation</groupId> <artifactId>git-eca</artifactId> @@ -25,8 +22,7 @@ <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.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> <sonar.host.url>https://sonarcloud.io</sonar.host.url> <sonar.organization>eclipse-foundation-it</sonar.organization> @@ -38,10 +34,8 @@ <id>eclipsefdn</id> <url>https://repo.eclipse.org/content/repositories/eclipsefdn/</url> <releases> - <enabled>true</enabled> </releases> <snapshots> - <enabled>true</enabled> </snapshots> </repository> </repositories> @@ -80,6 +74,10 @@ <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-jwt</artifactId> </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-mailer</artifactId> + </dependency> <!-- Annotation preprocessors - reduce all of the boiler plate --> <dependency> @@ -179,8 +177,7 @@ <configuration> <skipTests>false</skipTests> <systemPropertyVariables> - <java.util.logging.manager> - org.jboss.logmanager.LogManager</java.util.logging.manager> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> <maven.home>${maven.home}</maven.home> </systemPropertyVariables> </configuration> diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java b/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java new file mode 100644 index 00000000..fc3d65f0 --- /dev/null +++ b/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2025 Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipsefoundation.git.eca.service; + +import org.eclipsefoundation.git.eca.dto.GithubWebhookTracking; + +/** + * A service for sending email notifications related to GitHub webhook events. + * This interface defines methods for sending different types of email alerts + * to appropriate parties based on webhook tracking data. + */ +public interface MailerService { + /** + * Sends a revalidation alert for a tracked GitHub webhook event. + * This method is responsible for notifying relevant parties about the need to revalidate a webhook tracking event. + * + * @param tracking the GitHub webhook tracking information containing details about the event that needs revalidation + */ + void sendRevalidationAlert(GithubWebhookTracking tracking, Integer threshold); +} diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java new file mode 100644 index 00000000..48922653 --- /dev/null +++ b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2025 Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * Author: Jordi Gómez <jordi.gomez@eclipse-foundation.org> + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipsefoundation.git.eca.service.impl; + +import java.util.List; +import java.util.Optional; + +import org.eclipsefoundation.git.eca.dto.GithubWebhookTracking; +import org.eclipsefoundation.git.eca.service.MailerService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.quarkus.mailer.Mail; +import io.quarkus.mailer.Mailer; +import io.quarkus.qute.Location; +import io.quarkus.qute.Template; +import io.smallrye.config.ConfigMapping; +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class DefaultMailerService implements MailerService { + public static final Logger LOGGER = LoggerFactory.getLogger(DefaultMailerService.class); + private final EclipseMailerConfig config; + private final Mailer mailer; + + @Location("emails/revalidation-alert") + Template revalidationAlertTemplate; + + public DefaultMailerService(EclipseMailerConfig config, Mailer mailer) { + this.config = config; + this.mailer = mailer; + } + + @Override + public void sendRevalidationAlert(GithubWebhookTracking tracking, Integer threshold) { + var revalidationAlertConfig = config.revalidationAlert(); + + if (revalidationAlertConfig.to().isEmpty()) { + LOGGER.warn("No recipients configured for revalidation alert. Skipping email notification."); + return; + } + + String subject = "GitHub Webhook Revalidation Alert"; + + Mail messageBuilder = new Mail(); + + messageBuilder.setSubject(subject); + messageBuilder.setText(revalidationAlertTemplate.data("attempts", threshold) + .data("requestId", tracking.getId()) + .data("repository", tracking.getRepositoryFullName()) + .data("pullRequest", tracking.getPullRequestNumber()) + .data("lastState", tracking.getLastKnownState()) + .data("lastUpdated", tracking.getLastUpdated().toString()) + .render()); + + messageBuilder.addTo(revalidationAlertConfig.to().toArray(String[]::new)); + revalidationAlertConfig.authorMessage().replyTo() + .ifPresent(messageBuilder::addReplyTo); + revalidationAlertConfig.authorMessage().bcc() + .ifPresent(bcc -> messageBuilder.addBcc(bcc.toArray(String[]::new))); + + mailer.send(messageBuilder); + LOGGER.info("Revalidation alert sent to: {}", revalidationAlertConfig.to()); + } + + /** + * Represents configuration for the default mailer service. + * + * @author Martin Lowe + * + */ + @ConfigMapping(prefix = "eclipse.mailer") + public interface EclipseMailerConfig { + + public RevalidationAlert revalidationAlert(); + + /** + * This interface defines the contract for specifying recipients and message + * configuration when sending revalidation alerts within the ECA validation + * process. + */ + public interface RevalidationAlert { + public List<String> to(); + + public MessageConfiguration authorMessage(); + } + + public interface MessageConfiguration { + public Optional<String> replyTo(); + + public Optional<List<String>> bcc(); + } + } + +} diff --git a/src/main/java/org/eclipsefoundation/git/eca/tasks/GithubRevalidationQueue.java b/src/main/java/org/eclipsefoundation/git/eca/tasks/GithubRevalidationQueue.java index bdb9f0c6..fc64cae3 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/tasks/GithubRevalidationQueue.java +++ b/src/main/java/org/eclipsefoundation/git/eca/tasks/GithubRevalidationQueue.java @@ -14,11 +14,13 @@ package org.eclipsefoundation.git.eca.tasks; import java.net.URI; import java.util.Arrays; import java.util.List; +import java.util.Objects; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipsefoundation.git.eca.dto.GithubWebhookTracking; import org.eclipsefoundation.git.eca.helper.GithubHelper; import org.eclipsefoundation.git.eca.namespace.GitEcaParameterNames; +import org.eclipsefoundation.git.eca.service.MailerService; import org.eclipsefoundation.http.model.FlatRequestWrapper; import org.eclipsefoundation.http.model.RequestWrapper; import org.eclipsefoundation.http.namespace.DefaultUrlParameterNames; @@ -40,115 +42,176 @@ import jakarta.ws.rs.core.MultivaluedHashMap; import jakarta.ws.rs.core.MultivaluedMap; /** - * Scheduled regular task that will interact with the backend persistence to look for requests that are in a - * failed/unvalidated state after an error while processing that could not be recovered. These requests will be - * reprocessed using the same logic as the standard validation, updating the timestamp on completion and either setting - * the revalidation flag to false or incrementing the number of repeated revalidations needed for the request for + * Scheduled regular task that will interact with the backend persistence to + * look for requests that are in a + * failed/unvalidated state after an error while processing that could not be + * recovered. These requests will be + * reprocessed using the same logic as the standard validation, updating the + * timestamp on completion and either setting + * the revalidation flag to false or incrementing the number of repeated + * revalidations needed for the request for * tracking, depending on the succcess of the revalidation. */ @ApplicationScoped public class GithubRevalidationQueue { - private static final Logger LOGGER = LoggerFactory.getLogger(GithubRevalidationQueue.class); - - // full repo name should be 2 parts, org and actual repo name - private static final int FULL_REPO_NAME_PARTS = 2; - - @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.enabled", defaultValue = "true") - Instance<Boolean> isEnabled; - - @Inject - PersistenceDao dao; - @Inject - FilterService filters; - - @Inject - GithubHelper validationHelper; - - @PostConstruct - void init() { - // indicate to log whether enabled to reduce log spam - LOGGER.info("Github revalidation queue task is{} enabled.", Boolean.TRUE.equals(isEnabled.get()) ? "" : " not"); + private static final Logger LOGGER = LoggerFactory.getLogger(GithubRevalidationQueue.class); + + // full repo name should be 2 parts, org and actual repo name + private static final int FULL_REPO_NAME_PARTS = 2; + + @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.enabled", defaultValue = "true") + Instance<Boolean> isEnabled; + + @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.notification-threshold", defaultValue = "3") + Instance<Integer> revalidationThreshold; + + @Inject + PersistenceDao dao; + @Inject + FilterService filters; + @Inject + GithubHelper validationHelper; + @Inject + MailerService mailerService; + + @PostConstruct + void init() { + // indicate to log whether enabled to reduce log spam + LOGGER.info("Github revalidation queue task is{} enabled.", Boolean.TRUE.equals(isEnabled.get()) ? "" : " not"); + } + + /** + * Every 5s, this method will attempt to load a Github webhook validation + * request that has the needs revalidation flag + * set to true. This will retrieve the oldest request in queue and will attempt + * to revalidate it. + */ + @Scheduled(every = "${eclipse.git-eca.tasks.gh-revalidation.frequency:60s}") + @ActivateRequestContext + public void revalidate() { + // if not enabled, don't process any potentially OOD records + if (!Boolean.TRUE.equals(isEnabled.get())) { + return; } - /** - * Every 5s, this method will attempt to load a Github webhook validation request that has the needs revalidation flag - * set to true. This will retrieve the oldest request in queue and will attempt to revalidate it. - */ - @Scheduled(every = "${eclipse.git-eca.tasks.gh-revalidation.frequency:60s}") - @ActivateRequestContext - public void revalidate() { - // if not enabled, don't process any potentially OOD records - if (!Boolean.TRUE.equals(isEnabled.get())) { - return; - } - - // set up params for looking up the top of the revalidation queue - MultivaluedMap<String, String> params = new MultivaluedHashMap<>(); - params.add(GitEcaParameterNames.NEEDS_REVALIDATION_RAW, "true"); - params.add(PersistenceUrlParameterNames.SORT.getName(), "lastUpdated"); - params.add(DefaultUrlParameterNames.PAGESIZE.getName(), "1"); - - // build the request and query to lookup the longest standing request that needs revalidation - RequestWrapper wrap = new FlatRequestWrapper(URI.create("https://api.eclipse.org/git/eca/revalidation-queue")); - RDBMSQuery<GithubWebhookTracking> trackingQuery = new RDBMSQuery<>(wrap, filters.get(GithubWebhookTracking.class), params); - - List<GithubWebhookTracking> oldestRevalidation = dao.get(trackingQuery); - if (oldestRevalidation.isEmpty()) { - LOGGER.debug("No queued revalidation requests found"); - } else { - reprocessRequest(oldestRevalidation.get(0), wrap); - } + // set up params for looking up the top of the revalidation queue + MultivaluedMap<String, String> params = new MultivaluedHashMap<>(); + params.add(GitEcaParameterNames.NEEDS_REVALIDATION_RAW, "true"); + params.add(PersistenceUrlParameterNames.SORT.getName(), "lastUpdated"); + params.add(DefaultUrlParameterNames.PAGESIZE.getName(), "1"); + + // build the request and query to lookup the longest standing request that needs + // revalidation + RequestWrapper wrap = new FlatRequestWrapper(URI.create("https://api.eclipse.org/git/eca/revalidation-queue")); + RDBMSQuery<GithubWebhookTracking> trackingQuery = new RDBMSQuery<>(wrap, filters.get(GithubWebhookTracking.class), + params); + + List<GithubWebhookTracking> oldestRevalidation = dao.get(trackingQuery); + if (oldestRevalidation.isEmpty()) { + LOGGER.debug("No queued revalidation requests found"); + } else { + reprocessRequest(oldestRevalidation.get(0), wrap); + } + } + + /** + * Reprocess the given record, attempting to run the ECA validation logic again. + * If it passes, the revalidation flag is + * set to false and the time code is updated. If the processing fails again, the + * failure count gets incremented and the + * updated time is set so that another entry can be updated, as to not block on + * potentially broken records. + * + * @param requestToRevalidate the webhook tracking request to attempt to + * revalidate + * @param wrap the current stubbed request wrapper used for + * queries. + */ + private void reprocessRequest(GithubWebhookTracking requestToRevalidate, RequestWrapper wrap) { + LOGGER + .debug("Attempting revalidation of request w/ ID {}, in repo {}#{}", requestToRevalidate.getId(), + requestToRevalidate.getRepositoryFullName(), requestToRevalidate.getPullRequestNumber()); + + // update the number of times this status has revalidated (tracking) + requestToRevalidate + .setManualRevalidationCount(requestToRevalidate.getManualRevalidationCount() == null ? 1 + : requestToRevalidate.getManualRevalidationCount() + 1); + + // Check if notification threshold is reached and send email if needed + checkRevalidationThreshold(requestToRevalidate); + + // wrap in try-catch to avoid errors from stopping the record updates + try { + // split the full repo name into the org and repo name + String[] repoFullNameParts = requestToRevalidate.getRepositoryFullName().split("/"); + if (repoFullNameParts.length != FULL_REPO_NAME_PARTS) { + throw new IllegalStateException("Record with ID '" + Long.toString(requestToRevalidate.getId()) + + "' is in an invalid state (repository full name is not valid)"); + } + + // run the validation and then check if it succeeded. Use the forced flag since + // we want to try even if there are no + // changes + validationHelper + .validateIncomingRequest(wrap, repoFullNameParts[0], repoFullNameParts[1], + requestToRevalidate.getPullRequestNumber(), + true); + // if we have gotten here, then the validation has completed and can be removed + // from queue + requestToRevalidate.setNeedsRevalidation(false); + LOGGER.debug("Sucessfully revalidated request w/ ID {}", requestToRevalidate.getId()); + } catch (RuntimeException e) { + // log the message so we can see what happened + LOGGER.error("Error while revalidating request w/ ID {}", requestToRevalidate.getId(), e); + } finally { + // whether successful or failed, update the updated time field + requestToRevalidate.setLastUpdated(DateTimeHelper.now()); + + // if in a closed state, we shouldn't try to revalidate again as it will never + // be valid + // if a PR is reopened, it should create a new event and validate anyways + if ("closed".equalsIgnoreCase(requestToRevalidate.getLastKnownState())) { + LOGGER.debug("Tracking request {} set to not revalidate as it was closed", requestToRevalidate.getId()); + requestToRevalidate.setNeedsRevalidation(false); + } + // push the update with the potentially updated validation flag or error count + dao.add(new RDBMSQuery<>(wrap, filters.get(GithubWebhookTracking.class)), Arrays.asList(requestToRevalidate)); + } + } + + /** + * Checks if the manual revalidation count has reached the configured threshold + * and sends an email notification if it has. + * + * @param tracking the webhook tracking object + */ + private void checkRevalidationThreshold(GithubWebhookTracking tracking) { + Integer threshold = revalidationThreshold.get(); + + // If manual revalidation count is null or less than threshold, do nothing + if (Objects.isNull(tracking.getManualRevalidationCount()) || + tracking.getManualRevalidationCount() < threshold) { + return; } - /** - * Reprocess the given record, attempting to run the ECA validation logic again. If it passes, the revalidation flag is - * set to false and the time code is updated. If the processing fails again, the failure count gets incremented and the - * updated time is set so that another entry can be updated, as to not block on potentially broken records. - * - * @param requestToRevalidate the webhook tracking request to attempt to revalidate - * @param wrap the current stubbed request wrapper used for queries. - */ - private void reprocessRequest(GithubWebhookTracking requestToRevalidate, RequestWrapper wrap) { - LOGGER - .debug("Attempting revalidation of request w/ ID {}, in repo {}#{}", requestToRevalidate.getId(), - requestToRevalidate.getRepositoryFullName(), requestToRevalidate.getPullRequestNumber()); - - // update the number of times this status has revalidated (tracking) - requestToRevalidate - .setManualRevalidationCount(requestToRevalidate.getManualRevalidationCount() == null ? 1 - : requestToRevalidate.getManualRevalidationCount() + 1); - // wrap in try-catch to avoid errors from stopping the record updates - try { - // split the full repo name into the org and repo name - String[] repoFullNameParts = requestToRevalidate.getRepositoryFullName().split("/"); - if (repoFullNameParts.length != FULL_REPO_NAME_PARTS) { - throw new IllegalStateException("Record with ID '" + Long.toString(requestToRevalidate.getId()) - + "' is in an invalid state (repository full name is not valid)"); - } - - // run the validation and then check if it succeeded. Use the forced flag since we want to try even if there are no - // changes - validationHelper - .validateIncomingRequest(wrap, repoFullNameParts[0], repoFullNameParts[1], requestToRevalidate.getPullRequestNumber(), - true); - // if we have gotten here, then the validation has completed and can be removed from queue - requestToRevalidate.setNeedsRevalidation(false); - LOGGER.debug("Sucessfully revalidated request w/ ID {}", requestToRevalidate.getId()); - } catch (RuntimeException e) { - // log the message so we can see what happened - LOGGER.error("Error while revalidating request w/ ID {}", requestToRevalidate.getId(), e); - } finally { - // whether successful or failed, update the updated time field - requestToRevalidate.setLastUpdated(DateTimeHelper.now()); - - // if in a closed state, we shouldn't try to revalidate again as it will never be valid - // if a PR is reopened, it should create a new event and validate anyways - if ("closed".equalsIgnoreCase(requestToRevalidate.getLastKnownState())) { - LOGGER.debug("Tracking request {} set to not revalidate as it was closed", requestToRevalidate.getId()); - requestToRevalidate.setNeedsRevalidation(false); - } - // push the update with the potentially updated validation flag or error count - dao.add(new RDBMSQuery<>(wrap, filters.get(GithubWebhookTracking.class)), Arrays.asList(requestToRevalidate)); - } + // Check if count equals threshold (to send notification only once when threshold is reached) + if (tracking.getManualRevalidationCount() == threshold) { + sendRevalidationAlert(tracking); + } + } + + /** + * Sends an email alert about a webhook that has reached the revalidation + * threshold. + * + * @param tracking the webhook tracking object + */ + private void sendRevalidationAlert(GithubWebhookTracking tracking) { + try { + mailerService.sendRevalidationAlert(tracking, revalidationThreshold.get()); + LOGGER.info("Sent revalidation alert email for request ID {}", tracking.getId()); + } catch (RuntimeException e) { + LOGGER.error("Failed to send revalidation alert email for request ID {}", tracking.getId(), e); } + } } diff --git a/src/main/resources/templates/emails/revalidation_alert.txt b/src/main/resources/templates/emails/revalidation_alert.txt new file mode 100644 index 00000000..de4e2fdd --- /dev/null +++ b/src/main/resources/templates/emails/revalidation_alert.txt @@ -0,0 +1,10 @@ +A GitHub webhook has reached the revalidation threshold of {attempts} attempts. + +Details: +- Request ID: {requestId} +- Repository: {repository} +- Pull Request: #{pullRequest} +- Last State: {lastState} +- Last Updated: {lastUpdated} + +Please investigate this issue as it may indicate a persistent problem. \ No newline at end of file diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index 44c99d18..3c69227e 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -23,6 +23,14 @@ quarkus.keycloak.devservices.enabled=false quarkus.oidc-client.enabled=false smallrye.jwt.sign.key.location=test.pem +# Quarkus Mailer +quarkus.mailer.auth-methods=DIGEST-MD5 CRAM-SHA256 CRAM-SHA1 CRAM-MD5 PLAIN LOGIN +quarkus.mailer.from=membership.coordination@eclipse-foundation.org +# Uses gmail by default, can be overridden +quarkus.mailer.host=smtp.gmail.com +quarkus.mailer.port=465 +quarkus.mailer.ssl=true + # hCaptcha test key and secret eclipse.hcaptcha.site-key=20000000-ffff-ffff-ffff-000000000002 eclipse.hcaptcha.secret=0x0000000000000000000000000000000000000000 @@ -35,9 +43,10 @@ eclipse.git-eca.mail.allow-list=noreply@github.com eclipse.git-eca.reports.access-key=samplekey eclipse.git-eca.tasks.gh-revalidation.enabled=false eclipse.git-eca.tasks.gh-installation.enabled=false +eclipse.git-eca.tasks.gh-revalidation.notification-threshold=100 ## Misc eclipse.gitlab.access-token=token_val ## Disable private project scan in test mode -eclipse.scheduled.private-project.enabled=false \ No newline at end of file +eclipse.scheduled.private-project.enabled=false -- GitLab From 7f09f19e3dcd0d00d4682598fe11a2e3085570f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20G=C3=B3mez?= <jordi.gomez@eclipse-foundation.org> Date: Tue, 8 Apr 2025 13:25:39 +0200 Subject: [PATCH 02/10] refactor: moving MailerConfig to its standalone class --- .../service/impl/DefaultMailerService.java | 33 ----------------- .../eca/service/impl/EclipseMailerConfig.java | 35 +++++++++++++++++++ 2 files changed, 35 insertions(+), 33 deletions(-) create mode 100644 src/main/java/org/eclipsefoundation/git/eca/service/impl/EclipseMailerConfig.java diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java index 48922653..4adde3eb 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java +++ b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java @@ -11,9 +11,6 @@ */ package org.eclipsefoundation.git.eca.service.impl; -import java.util.List; -import java.util.Optional; - import org.eclipsefoundation.git.eca.dto.GithubWebhookTracking; import org.eclipsefoundation.git.eca.service.MailerService; import org.slf4j.Logger; @@ -23,7 +20,6 @@ import io.quarkus.mailer.Mail; import io.quarkus.mailer.Mailer; import io.quarkus.qute.Location; import io.quarkus.qute.Template; -import io.smallrye.config.ConfigMapping; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped @@ -72,33 +68,4 @@ public class DefaultMailerService implements MailerService { LOGGER.info("Revalidation alert sent to: {}", revalidationAlertConfig.to()); } - /** - * Represents configuration for the default mailer service. - * - * @author Martin Lowe - * - */ - @ConfigMapping(prefix = "eclipse.mailer") - public interface EclipseMailerConfig { - - public RevalidationAlert revalidationAlert(); - - /** - * This interface defines the contract for specifying recipients and message - * configuration when sending revalidation alerts within the ECA validation - * process. - */ - public interface RevalidationAlert { - public List<String> to(); - - public MessageConfiguration authorMessage(); - } - - public interface MessageConfiguration { - public Optional<String> replyTo(); - - public Optional<List<String>> bcc(); - } - } - } diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/impl/EclipseMailerConfig.java b/src/main/java/org/eclipsefoundation/git/eca/service/impl/EclipseMailerConfig.java new file mode 100644 index 00000000..c90ffc87 --- /dev/null +++ b/src/main/java/org/eclipsefoundation/git/eca/service/impl/EclipseMailerConfig.java @@ -0,0 +1,35 @@ +package org.eclipsefoundation.git.eca.service.impl; + +import java.util.List; +import java.util.Optional; + +import io.smallrye.config.ConfigMapping; + +/** + * Represents configuration for the default mailer service. + * + * @author Martin Lowe + * + */ +@ConfigMapping(prefix = "eclipse.mailer") +public interface EclipseMailerConfig { + + public RevalidationAlert revalidationAlert(); + + /** + * This interface defines the contract for specifying recipients and message + * configuration when sending revalidation alerts within the ECA validation + * process. + */ + public interface RevalidationAlert { + public List<String> to(); + + public MessageConfiguration authorMessage(); + } + + public interface MessageConfiguration { + public Optional<String> replyTo(); + + public Optional<List<String>> bcc(); + } +} \ No newline at end of file -- GitLab From 888f4eac91d83d800ea3cbf54b3090c3fc7dd2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20G=C3=B3mez?= <jordi.gomez@eclipse-foundation.org> Date: Tue, 8 Apr 2025 13:26:52 +0200 Subject: [PATCH 03/10] docs: rewording wrongly defined comments --- .../git/eca/service/MailerService.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java b/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java index fc3d65f0..489ff1a5 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java +++ b/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java @@ -12,16 +12,14 @@ package org.eclipsefoundation.git.eca.service; import org.eclipsefoundation.git.eca.dto.GithubWebhookTracking; /** - * A service for sending email notifications related to GitHub webhook events. - * This interface defines methods for sending different types of email alerts - * to appropriate parties based on webhook tracking data. + * Service responsible for sending email notifications. */ public interface MailerService { /** - * Sends a revalidation alert for a tracked GitHub webhook event. - * This method is responsible for notifying relevant parties about the need to revalidate a webhook tracking event. - * - * @param tracking the GitHub webhook tracking information containing details about the event that needs revalidation + * Notifies a configured recipient about an stuck revalidation request. + * + * @param tracking the GithubWebhookTracking object containing information about the request + * @param threshold the used threshold for the revalidation alert */ void sendRevalidationAlert(GithubWebhookTracking tracking, Integer threshold); } -- GitLab From de863da24e4b20739ece775007556620648eab6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20G=C3=B3mez?= <jordi.gomez@eclipse-foundation.org> Date: Tue, 8 Apr 2025 13:30:26 +0200 Subject: [PATCH 04/10] feat: adding footer indicating is an automated email --- src/main/resources/templates/emails/revalidation_alert.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/resources/templates/emails/revalidation_alert.txt b/src/main/resources/templates/emails/revalidation_alert.txt index de4e2fdd..bab58a52 100644 --- a/src/main/resources/templates/emails/revalidation_alert.txt +++ b/src/main/resources/templates/emails/revalidation_alert.txt @@ -7,4 +7,7 @@ Details: - Last State: {lastState} - Last Updated: {lastUpdated} -Please investigate this issue as it may indicate a persistent problem. \ No newline at end of file +Please investigate this issue as it may indicate a persistent problem. + +------------------------------------------------------------------------------------------- +This is an automated email from api.eclipse.org/git/eca. Please do not reply to this email. \ No newline at end of file -- GitLab From 4c34713555f952492b1b563948bf71c612823a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20G=C3=B3mez?= <jordi.gomez@eclipse-foundation.org> Date: Tue, 8 Apr 2025 13:31:21 +0200 Subject: [PATCH 05/10] feat: adding option to disable revalidation alert --- .../eca/tasks/GithubRevalidationQueue.java | 101 +++++++++--------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/src/main/java/org/eclipsefoundation/git/eca/tasks/GithubRevalidationQueue.java b/src/main/java/org/eclipsefoundation/git/eca/tasks/GithubRevalidationQueue.java index fc64cae3..2c3b3b2a 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/tasks/GithubRevalidationQueue.java +++ b/src/main/java/org/eclipsefoundation/git/eca/tasks/GithubRevalidationQueue.java @@ -1,9 +1,8 @@ /** * Copyright (c) 2023 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/ + * 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> * @@ -42,15 +41,12 @@ import jakarta.ws.rs.core.MultivaluedHashMap; import jakarta.ws.rs.core.MultivaluedMap; /** - * Scheduled regular task that will interact with the backend persistence to - * look for requests that are in a - * failed/unvalidated state after an error while processing that could not be - * recovered. These requests will be - * reprocessed using the same logic as the standard validation, updating the - * timestamp on completion and either setting - * the revalidation flag to false or incrementing the number of repeated - * revalidations needed for the request for - * tracking, depending on the succcess of the revalidation. + * Scheduled regular task that will interact with the backend persistence to look for requests that + * are in a failed/unvalidated state after an error while processing that could not be recovered. + * These requests will be reprocessed using the same logic as the standard validation, updating the + * timestamp on completion and either setting the revalidation flag to false or incrementing the + * number of repeated revalidations needed for the request for tracking, depending on the succcess + * of the revalidation. */ @ApplicationScoped public class GithubRevalidationQueue { @@ -62,7 +58,12 @@ public class GithubRevalidationQueue { @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.enabled", defaultValue = "true") Instance<Boolean> isEnabled; - @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.notification-threshold", defaultValue = "3") + @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.notification-enabled", + defaultValue = "true") + Instance<Boolean> isRevalidationAlertEnabled; + + @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.notification-threshold", + defaultValue = "100") Instance<Integer> revalidationThreshold; @Inject @@ -77,14 +78,14 @@ public class GithubRevalidationQueue { @PostConstruct void init() { // indicate to log whether enabled to reduce log spam - LOGGER.info("Github revalidation queue task is{} enabled.", Boolean.TRUE.equals(isEnabled.get()) ? "" : " not"); + LOGGER.info("Github revalidation queue task is{} enabled.", + Boolean.TRUE.equals(isEnabled.get()) ? "" : " not"); } /** - * Every 5s, this method will attempt to load a Github webhook validation - * request that has the needs revalidation flag - * set to true. This will retrieve the oldest request in queue and will attempt - * to revalidate it. + * Every 5s, this method will attempt to load a Github webhook validation request that has the + * needs revalidation flag set to true. This will retrieve the oldest request in queue and will + * attempt to revalidate it. */ @Scheduled(every = "${eclipse.git-eca.tasks.gh-revalidation.frequency:60s}") @ActivateRequestContext @@ -102,9 +103,10 @@ public class GithubRevalidationQueue { // build the request and query to lookup the longest standing request that needs // revalidation - RequestWrapper wrap = new FlatRequestWrapper(URI.create("https://api.eclipse.org/git/eca/revalidation-queue")); - RDBMSQuery<GithubWebhookTracking> trackingQuery = new RDBMSQuery<>(wrap, filters.get(GithubWebhookTracking.class), - params); + RequestWrapper wrap = + new FlatRequestWrapper(URI.create("https://api.eclipse.org/git/eca/revalidation-queue")); + RDBMSQuery<GithubWebhookTracking> trackingQuery = + new RDBMSQuery<>(wrap, filters.get(GithubWebhookTracking.class), params); List<GithubWebhookTracking> oldestRevalidation = dao.get(trackingQuery); if (oldestRevalidation.isEmpty()) { @@ -115,22 +117,18 @@ public class GithubRevalidationQueue { } /** - * Reprocess the given record, attempting to run the ECA validation logic again. - * If it passes, the revalidation flag is - * set to false and the time code is updated. If the processing fails again, the - * failure count gets incremented and the - * updated time is set so that another entry can be updated, as to not block on - * potentially broken records. + * Reprocess the given record, attempting to run the ECA validation logic again. If it passes, the + * revalidation flag is set to false and the time code is updated. If the processing fails again, + * the failure count gets incremented and the updated time is set so that another entry can be + * updated, as to not block on potentially broken records. * - * @param requestToRevalidate the webhook tracking request to attempt to - * revalidate - * @param wrap the current stubbed request wrapper used for - * queries. + * @param requestToRevalidate the webhook tracking request to attempt to revalidate + * @param wrap the current stubbed request wrapper used for queries. */ private void reprocessRequest(GithubWebhookTracking requestToRevalidate, RequestWrapper wrap) { - LOGGER - .debug("Attempting revalidation of request w/ ID {}, in repo {}#{}", requestToRevalidate.getId(), - requestToRevalidate.getRepositoryFullName(), requestToRevalidate.getPullRequestNumber()); + LOGGER.debug("Attempting revalidation of request w/ ID {}, in repo {}#{}", + requestToRevalidate.getId(), requestToRevalidate.getRepositoryFullName(), + requestToRevalidate.getPullRequestNumber()); // update the number of times this status has revalidated (tracking) requestToRevalidate @@ -145,17 +143,16 @@ public class GithubRevalidationQueue { // split the full repo name into the org and repo name String[] repoFullNameParts = requestToRevalidate.getRepositoryFullName().split("/"); if (repoFullNameParts.length != FULL_REPO_NAME_PARTS) { - throw new IllegalStateException("Record with ID '" + Long.toString(requestToRevalidate.getId()) - + "' is in an invalid state (repository full name is not valid)"); + throw new IllegalStateException( + "Record with ID '" + Long.toString(requestToRevalidate.getId()) + + "' is in an invalid state (repository full name is not valid)"); } // run the validation and then check if it succeeded. Use the forced flag since // we want to try even if there are no // changes - validationHelper - .validateIncomingRequest(wrap, repoFullNameParts[0], repoFullNameParts[1], - requestToRevalidate.getPullRequestNumber(), - true); + validationHelper.validateIncomingRequest(wrap, repoFullNameParts[0], repoFullNameParts[1], + requestToRevalidate.getPullRequestNumber(), true); // if we have gotten here, then the validation has completed and can be removed // from queue requestToRevalidate.setNeedsRevalidation(false); @@ -171,26 +168,32 @@ public class GithubRevalidationQueue { // be valid // if a PR is reopened, it should create a new event and validate anyways if ("closed".equalsIgnoreCase(requestToRevalidate.getLastKnownState())) { - LOGGER.debug("Tracking request {} set to not revalidate as it was closed", requestToRevalidate.getId()); + LOGGER.debug("Tracking request {} set to not revalidate as it was closed", + requestToRevalidate.getId()); requestToRevalidate.setNeedsRevalidation(false); } // push the update with the potentially updated validation flag or error count - dao.add(new RDBMSQuery<>(wrap, filters.get(GithubWebhookTracking.class)), Arrays.asList(requestToRevalidate)); + dao.add(new RDBMSQuery<>(wrap, filters.get(GithubWebhookTracking.class)), + Arrays.asList(requestToRevalidate)); } } /** - * Checks if the manual revalidation count has reached the configured threshold - * and sends an email notification if it has. + * Checks if the manual revalidation count has reached the configured threshold and sends an email + * notification if it has and the notification alert is enabled. * * @param tracking the webhook tracking object */ private void checkRevalidationThreshold(GithubWebhookTracking tracking) { + // If revalidation alert is not enabled, do nothing + if (!Boolean.TRUE.equals(isRevalidationAlertEnabled.get())) + return; + Integer threshold = revalidationThreshold.get(); // If manual revalidation count is null or less than threshold, do nothing - if (Objects.isNull(tracking.getManualRevalidationCount()) || - tracking.getManualRevalidationCount() < threshold) { + if (Objects.isNull(tracking.getManualRevalidationCount()) + || tracking.getManualRevalidationCount() < threshold) { return; } @@ -201,8 +204,7 @@ public class GithubRevalidationQueue { } /** - * Sends an email alert about a webhook that has reached the revalidation - * threshold. + * Sends an email alert about a webhook that has reached the revalidation threshold. * * @param tracking the webhook tracking object */ @@ -211,7 +213,8 @@ public class GithubRevalidationQueue { mailerService.sendRevalidationAlert(tracking, revalidationThreshold.get()); LOGGER.info("Sent revalidation alert email for request ID {}", tracking.getId()); } catch (RuntimeException e) { - LOGGER.error("Failed to send revalidation alert email for request ID {}", tracking.getId(), e); + LOGGER.error("Failed to send revalidation alert email for request ID {}", tracking.getId(), + e); } } } -- GitLab From de9b5ff990fe68ded41ef6aba8532fc91dbc226a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20G=C3=B3mez?= <jordi.gomez@eclipse-foundation.org> Date: Tue, 8 Apr 2025 13:32:13 +0200 Subject: [PATCH 06/10] chore(formatting): updating code formatting --- .../git/eca/service/MailerService.java | 7 +++---- .../git/eca/service/impl/DefaultMailerService.java | 14 +++++--------- .../git/eca/service/impl/EclipseMailerConfig.java | 7 +++---- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java b/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java index 489ff1a5..a2dde623 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java +++ b/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java @@ -1,9 +1,8 @@ /** * Copyright (c) 2025 Eclipse Foundation * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ + * This program and the accompanying materials are made available under the terms of the Eclipse + * Public License 2.0 which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 */ @@ -18,7 +17,7 @@ public interface MailerService { /** * Notifies a configured recipient about an stuck revalidation request. * - * @param tracking the GithubWebhookTracking object containing information about the request + * @param tracking the GithubWebhookTracking object containing information about the request * @param threshold the used threshold for the revalidation alert */ void sendRevalidationAlert(GithubWebhookTracking tracking, Integer threshold); diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java index 4adde3eb..2f1ca9a1 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java +++ b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java @@ -1,9 +1,8 @@ /** * Copyright (c) 2025 Eclipse Foundation * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ + * 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: Jordi Gómez <jordi.gomez@eclipse-foundation.org> * @@ -51,16 +50,13 @@ public class DefaultMailerService implements MailerService { messageBuilder.setSubject(subject); messageBuilder.setText(revalidationAlertTemplate.data("attempts", threshold) - .data("requestId", tracking.getId()) - .data("repository", tracking.getRepositoryFullName()) + .data("requestId", tracking.getId()).data("repository", tracking.getRepositoryFullName()) .data("pullRequest", tracking.getPullRequestNumber()) .data("lastState", tracking.getLastKnownState()) - .data("lastUpdated", tracking.getLastUpdated().toString()) - .render()); + .data("lastUpdated", tracking.getLastUpdated().toString()).render()); messageBuilder.addTo(revalidationAlertConfig.to().toArray(String[]::new)); - revalidationAlertConfig.authorMessage().replyTo() - .ifPresent(messageBuilder::addReplyTo); + revalidationAlertConfig.authorMessage().replyTo().ifPresent(messageBuilder::addReplyTo); revalidationAlertConfig.authorMessage().bcc() .ifPresent(bcc -> messageBuilder.addBcc(bcc.toArray(String[]::new))); diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/impl/EclipseMailerConfig.java b/src/main/java/org/eclipsefoundation/git/eca/service/impl/EclipseMailerConfig.java index c90ffc87..2a200eff 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/service/impl/EclipseMailerConfig.java +++ b/src/main/java/org/eclipsefoundation/git/eca/service/impl/EclipseMailerConfig.java @@ -17,9 +17,8 @@ public interface EclipseMailerConfig { public RevalidationAlert revalidationAlert(); /** - * This interface defines the contract for specifying recipients and message - * configuration when sending revalidation alerts within the ECA validation - * process. + * This interface defines the contract for specifying recipients and message configuration when + * sending revalidation alerts within the ECA validation process. */ public interface RevalidationAlert { public List<String> to(); @@ -32,4 +31,4 @@ public interface EclipseMailerConfig { public Optional<List<String>> bcc(); } -} \ No newline at end of file +} -- GitLab From d7d9c4a1f11a71894a0463441bc565bd5bde989f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20G=C3=B3mez?= <jordi.gomez@eclipse-foundation.org> Date: Tue, 8 Apr 2025 17:39:09 +0200 Subject: [PATCH 07/10] chore: updating application.properties --- .../git/eca/service/impl/DefaultMailerService.java | 2 +- src/test/resources/application.properties | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java index 2f1ca9a1..5e378285 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java +++ b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java @@ -27,7 +27,7 @@ public class DefaultMailerService implements MailerService { private final EclipseMailerConfig config; private final Mailer mailer; - @Location("emails/revalidation-alert") + @Location("emails/revalidation_alert") Template revalidationAlertTemplate; public DefaultMailerService(EclipseMailerConfig config, Mailer mailer) { diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index 3c69227e..205ea9ab 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -45,6 +45,9 @@ eclipse.git-eca.tasks.gh-revalidation.enabled=false eclipse.git-eca.tasks.gh-installation.enabled=false eclipse.git-eca.tasks.gh-revalidation.notification-threshold=100 +## Revalidation alert email config +eclipse.mailer.revalidation-alert.to=webdev@eclipse-foundation.org + ## Misc eclipse.gitlab.access-token=token_val -- GitLab From f45eff79ccc88fc499742227b0cf86e0adf37c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20G=C3=B3mez?= <jordi.gomez@eclipse-foundation.org> Date: Wed, 9 Apr 2025 10:03:28 +0200 Subject: [PATCH 08/10] refactor: moving MailerConfig to the config folder --- .../MailerConfig.java} | 14 ++++++++++++-- .../git/eca/service/impl/DefaultMailerService.java | 5 +++-- 2 files changed, 15 insertions(+), 4 deletions(-) rename src/main/java/org/eclipsefoundation/git/eca/{service/impl/EclipseMailerConfig.java => config/MailerConfig.java} (63%) diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/impl/EclipseMailerConfig.java b/src/main/java/org/eclipsefoundation/git/eca/config/MailerConfig.java similarity index 63% rename from src/main/java/org/eclipsefoundation/git/eca/service/impl/EclipseMailerConfig.java rename to src/main/java/org/eclipsefoundation/git/eca/config/MailerConfig.java index 2a200eff..4b9d7192 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/service/impl/EclipseMailerConfig.java +++ b/src/main/java/org/eclipsefoundation/git/eca/config/MailerConfig.java @@ -1,4 +1,14 @@ -package org.eclipsefoundation.git.eca.service.impl; +/** + * Copyright (c) 2025 Eclipse Foundation + * + * This program and the accompanying materials are made available under the terms of the Eclipse + * Public License 2.0 which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * Author: Jordi Gómez <jordi.gomez@eclipse-foundation.org> + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipsefoundation.git.eca.config; import java.util.List; import java.util.Optional; @@ -12,7 +22,7 @@ import io.smallrye.config.ConfigMapping; * */ @ConfigMapping(prefix = "eclipse.mailer") -public interface EclipseMailerConfig { +public interface MailerConfig { public RevalidationAlert revalidationAlert(); diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java index 5e378285..6c2a10d5 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java +++ b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java @@ -10,6 +10,7 @@ */ package org.eclipsefoundation.git.eca.service.impl; +import org.eclipsefoundation.git.eca.config.MailerConfig; import org.eclipsefoundation.git.eca.dto.GithubWebhookTracking; import org.eclipsefoundation.git.eca.service.MailerService; import org.slf4j.Logger; @@ -24,13 +25,13 @@ import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class DefaultMailerService implements MailerService { public static final Logger LOGGER = LoggerFactory.getLogger(DefaultMailerService.class); - private final EclipseMailerConfig config; + private final MailerConfig config; private final Mailer mailer; @Location("emails/revalidation_alert") Template revalidationAlertTemplate; - public DefaultMailerService(EclipseMailerConfig config, Mailer mailer) { + public DefaultMailerService(MailerConfig config, Mailer mailer) { this.config = config; this.mailer = mailer; } -- GitLab From 530e453a9e35440178778ace5499d19e24c7f69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20G=C3=B3mez?= <jordi.gomez@eclipse-foundation.org> Date: Thu, 24 Apr 2025 11:13:55 +0200 Subject: [PATCH 09/10] chore: fix formatting --- .../git/eca/config/MailerConfig.java | 26 +- .../git/eca/service/MailerService.java | 14 +- .../service/impl/DefaultMailerService.java | 65 ++-- .../eca/tasks/GithubRevalidationQueue.java | 314 +++++++++--------- 4 files changed, 202 insertions(+), 217 deletions(-) diff --git a/src/main/java/org/eclipsefoundation/git/eca/config/MailerConfig.java b/src/main/java/org/eclipsefoundation/git/eca/config/MailerConfig.java index 4b9d7192..abf66ffb 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/config/MailerConfig.java +++ b/src/main/java/org/eclipsefoundation/git/eca/config/MailerConfig.java @@ -24,21 +24,21 @@ import io.smallrye.config.ConfigMapping; @ConfigMapping(prefix = "eclipse.mailer") public interface MailerConfig { - public RevalidationAlert revalidationAlert(); + public RevalidationAlert revalidationAlert(); - /** - * This interface defines the contract for specifying recipients and message configuration when - * sending revalidation alerts within the ECA validation process. - */ - public interface RevalidationAlert { - public List<String> to(); + /** + * This interface defines the contract for specifying recipients and message configuration when sending revalidation alerts within the + * ECA validation process. + */ + public interface RevalidationAlert { + public List<String> to(); - public MessageConfiguration authorMessage(); - } + public MessageConfiguration authorMessage(); + } - public interface MessageConfiguration { - public Optional<String> replyTo(); + public interface MessageConfiguration { + public Optional<String> replyTo(); - public Optional<List<String>> bcc(); - } + public Optional<List<String>> bcc(); + } } diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java b/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java index a2dde623..1e307f69 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java +++ b/src/main/java/org/eclipsefoundation/git/eca/service/MailerService.java @@ -14,11 +14,11 @@ import org.eclipsefoundation.git.eca.dto.GithubWebhookTracking; * Service responsible for sending email notifications. */ public interface MailerService { - /** - * Notifies a configured recipient about an stuck revalidation request. - * - * @param tracking the GithubWebhookTracking object containing information about the request - * @param threshold the used threshold for the revalidation alert - */ - void sendRevalidationAlert(GithubWebhookTracking tracking, Integer threshold); + /** + * Notifies a configured recipient about an stuck revalidation request. + * + * @param tracking the GithubWebhookTracking object containing information about the request + * @param threshold the used threshold for the revalidation alert + */ + void sendRevalidationAlert(GithubWebhookTracking tracking, Integer threshold); } diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java index 6c2a10d5..5452c6a0 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java +++ b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultMailerService.java @@ -24,45 +24,48 @@ import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class DefaultMailerService implements MailerService { - public static final Logger LOGGER = LoggerFactory.getLogger(DefaultMailerService.class); - private final MailerConfig config; - private final Mailer mailer; + public static final Logger LOGGER = LoggerFactory.getLogger(DefaultMailerService.class); + private final MailerConfig config; + private final Mailer mailer; - @Location("emails/revalidation_alert") - Template revalidationAlertTemplate; + @Location("emails/revalidation_alert") + Template revalidationAlertTemplate; - public DefaultMailerService(MailerConfig config, Mailer mailer) { - this.config = config; - this.mailer = mailer; - } + public DefaultMailerService(MailerConfig config, Mailer mailer) { + this.config = config; + this.mailer = mailer; + } - @Override - public void sendRevalidationAlert(GithubWebhookTracking tracking, Integer threshold) { - var revalidationAlertConfig = config.revalidationAlert(); + @Override + public void sendRevalidationAlert(GithubWebhookTracking tracking, Integer threshold) { + var revalidationAlertConfig = config.revalidationAlert(); - if (revalidationAlertConfig.to().isEmpty()) { - LOGGER.warn("No recipients configured for revalidation alert. Skipping email notification."); - return; - } + if (revalidationAlertConfig.to().isEmpty()) { + LOGGER.warn("No recipients configured for revalidation alert. Skipping email notification."); + return; + } - String subject = "GitHub Webhook Revalidation Alert"; + String subject = "GitHub Webhook Revalidation Alert"; - Mail messageBuilder = new Mail(); + Mail messageBuilder = new Mail(); - messageBuilder.setSubject(subject); - messageBuilder.setText(revalidationAlertTemplate.data("attempts", threshold) - .data("requestId", tracking.getId()).data("repository", tracking.getRepositoryFullName()) - .data("pullRequest", tracking.getPullRequestNumber()) - .data("lastState", tracking.getLastKnownState()) - .data("lastUpdated", tracking.getLastUpdated().toString()).render()); + messageBuilder.setSubject(subject); + messageBuilder + .setText(revalidationAlertTemplate + .data("attempts", threshold) + .data("requestId", tracking.getId()) + .data("repository", tracking.getRepositoryFullName()) + .data("pullRequest", tracking.getPullRequestNumber()) + .data("lastState", tracking.getLastKnownState()) + .data("lastUpdated", tracking.getLastUpdated().toString()) + .render()); - messageBuilder.addTo(revalidationAlertConfig.to().toArray(String[]::new)); - revalidationAlertConfig.authorMessage().replyTo().ifPresent(messageBuilder::addReplyTo); - revalidationAlertConfig.authorMessage().bcc() - .ifPresent(bcc -> messageBuilder.addBcc(bcc.toArray(String[]::new))); + messageBuilder.addTo(revalidationAlertConfig.to().toArray(String[]::new)); + revalidationAlertConfig.authorMessage().replyTo().ifPresent(messageBuilder::addReplyTo); + revalidationAlertConfig.authorMessage().bcc().ifPresent(bcc -> messageBuilder.addBcc(bcc.toArray(String[]::new))); - mailer.send(messageBuilder); - LOGGER.info("Revalidation alert sent to: {}", revalidationAlertConfig.to()); - } + mailer.send(messageBuilder); + LOGGER.info("Revalidation alert sent to: {}", revalidationAlertConfig.to()); + } } diff --git a/src/main/java/org/eclipsefoundation/git/eca/tasks/GithubRevalidationQueue.java b/src/main/java/org/eclipsefoundation/git/eca/tasks/GithubRevalidationQueue.java index 2c3b3b2a..7c638ce0 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/tasks/GithubRevalidationQueue.java +++ b/src/main/java/org/eclipsefoundation/git/eca/tasks/GithubRevalidationQueue.java @@ -41,180 +41,162 @@ import jakarta.ws.rs.core.MultivaluedHashMap; import jakarta.ws.rs.core.MultivaluedMap; /** - * Scheduled regular task that will interact with the backend persistence to look for requests that - * are in a failed/unvalidated state after an error while processing that could not be recovered. - * These requests will be reprocessed using the same logic as the standard validation, updating the - * timestamp on completion and either setting the revalidation flag to false or incrementing the - * number of repeated revalidations needed for the request for tracking, depending on the succcess - * of the revalidation. + * Scheduled regular task that will interact with the backend persistence to look for requests that are in a failed/unvalidated state after + * an error while processing that could not be recovered. These requests will be reprocessed using the same logic as the standard + * validation, updating the timestamp on completion and either setting the revalidation flag to false or incrementing the number of repeated + * revalidations needed for the request for tracking, depending on the succcess of the revalidation. */ @ApplicationScoped public class GithubRevalidationQueue { - private static final Logger LOGGER = LoggerFactory.getLogger(GithubRevalidationQueue.class); - - // full repo name should be 2 parts, org and actual repo name - private static final int FULL_REPO_NAME_PARTS = 2; - - @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.enabled", defaultValue = "true") - Instance<Boolean> isEnabled; - - @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.notification-enabled", - defaultValue = "true") - Instance<Boolean> isRevalidationAlertEnabled; - - @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.notification-threshold", - defaultValue = "100") - Instance<Integer> revalidationThreshold; - - @Inject - PersistenceDao dao; - @Inject - FilterService filters; - @Inject - GithubHelper validationHelper; - @Inject - MailerService mailerService; - - @PostConstruct - void init() { - // indicate to log whether enabled to reduce log spam - LOGGER.info("Github revalidation queue task is{} enabled.", - Boolean.TRUE.equals(isEnabled.get()) ? "" : " not"); - } - - /** - * Every 5s, this method will attempt to load a Github webhook validation request that has the - * needs revalidation flag set to true. This will retrieve the oldest request in queue and will - * attempt to revalidate it. - */ - @Scheduled(every = "${eclipse.git-eca.tasks.gh-revalidation.frequency:60s}") - @ActivateRequestContext - public void revalidate() { - // if not enabled, don't process any potentially OOD records - if (!Boolean.TRUE.equals(isEnabled.get())) { - return; - } + private static final Logger LOGGER = LoggerFactory.getLogger(GithubRevalidationQueue.class); + + // full repo name should be 2 parts, org and actual repo name + private static final int FULL_REPO_NAME_PARTS = 2; + + @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.enabled", defaultValue = "true") + Instance<Boolean> isEnabled; + + @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.notification-enabled", defaultValue = "true") + Instance<Boolean> isRevalidationAlertEnabled; + + @ConfigProperty(name = "eclipse.git-eca.tasks.gh-revalidation.notification-threshold", defaultValue = "100") + Instance<Integer> revalidationThreshold; - // set up params for looking up the top of the revalidation queue - MultivaluedMap<String, String> params = new MultivaluedHashMap<>(); - params.add(GitEcaParameterNames.NEEDS_REVALIDATION_RAW, "true"); - params.add(PersistenceUrlParameterNames.SORT.getName(), "lastUpdated"); - params.add(DefaultUrlParameterNames.PAGESIZE.getName(), "1"); - - // build the request and query to lookup the longest standing request that needs - // revalidation - RequestWrapper wrap = - new FlatRequestWrapper(URI.create("https://api.eclipse.org/git/eca/revalidation-queue")); - RDBMSQuery<GithubWebhookTracking> trackingQuery = - new RDBMSQuery<>(wrap, filters.get(GithubWebhookTracking.class), params); - - List<GithubWebhookTracking> oldestRevalidation = dao.get(trackingQuery); - if (oldestRevalidation.isEmpty()) { - LOGGER.debug("No queued revalidation requests found"); - } else { - reprocessRequest(oldestRevalidation.get(0), wrap); + @Inject + PersistenceDao dao; + @Inject + FilterService filters; + @Inject + GithubHelper validationHelper; + @Inject + MailerService mailerService; + + @PostConstruct + void init() { + // indicate to log whether enabled to reduce log spam + LOGGER.info("Github revalidation queue task is{} enabled.", Boolean.TRUE.equals(isEnabled.get()) ? "" : " not"); } - } - - /** - * Reprocess the given record, attempting to run the ECA validation logic again. If it passes, the - * revalidation flag is set to false and the time code is updated. If the processing fails again, - * the failure count gets incremented and the updated time is set so that another entry can be - * updated, as to not block on potentially broken records. - * - * @param requestToRevalidate the webhook tracking request to attempt to revalidate - * @param wrap the current stubbed request wrapper used for queries. - */ - private void reprocessRequest(GithubWebhookTracking requestToRevalidate, RequestWrapper wrap) { - LOGGER.debug("Attempting revalidation of request w/ ID {}, in repo {}#{}", - requestToRevalidate.getId(), requestToRevalidate.getRepositoryFullName(), - requestToRevalidate.getPullRequestNumber()); - - // update the number of times this status has revalidated (tracking) - requestToRevalidate - .setManualRevalidationCount(requestToRevalidate.getManualRevalidationCount() == null ? 1 - : requestToRevalidate.getManualRevalidationCount() + 1); - - // Check if notification threshold is reached and send email if needed - checkRevalidationThreshold(requestToRevalidate); - - // wrap in try-catch to avoid errors from stopping the record updates - try { - // split the full repo name into the org and repo name - String[] repoFullNameParts = requestToRevalidate.getRepositoryFullName().split("/"); - if (repoFullNameParts.length != FULL_REPO_NAME_PARTS) { - throw new IllegalStateException( - "Record with ID '" + Long.toString(requestToRevalidate.getId()) - + "' is in an invalid state (repository full name is not valid)"); - } - - // run the validation and then check if it succeeded. Use the forced flag since - // we want to try even if there are no - // changes - validationHelper.validateIncomingRequest(wrap, repoFullNameParts[0], repoFullNameParts[1], - requestToRevalidate.getPullRequestNumber(), true); - // if we have gotten here, then the validation has completed and can be removed - // from queue - requestToRevalidate.setNeedsRevalidation(false); - LOGGER.debug("Sucessfully revalidated request w/ ID {}", requestToRevalidate.getId()); - } catch (RuntimeException e) { - // log the message so we can see what happened - LOGGER.error("Error while revalidating request w/ ID {}", requestToRevalidate.getId(), e); - } finally { - // whether successful or failed, update the updated time field - requestToRevalidate.setLastUpdated(DateTimeHelper.now()); - - // if in a closed state, we shouldn't try to revalidate again as it will never - // be valid - // if a PR is reopened, it should create a new event and validate anyways - if ("closed".equalsIgnoreCase(requestToRevalidate.getLastKnownState())) { - LOGGER.debug("Tracking request {} set to not revalidate as it was closed", - requestToRevalidate.getId()); - requestToRevalidate.setNeedsRevalidation(false); - } - // push the update with the potentially updated validation flag or error count - dao.add(new RDBMSQuery<>(wrap, filters.get(GithubWebhookTracking.class)), - Arrays.asList(requestToRevalidate)); + + /** + * Every 5s, this method will attempt to load a Github webhook validation request that has the needs revalidation flag set to true. This + * will retrieve the oldest request in queue and will attempt to revalidate it. + */ + @Scheduled(every = "${eclipse.git-eca.tasks.gh-revalidation.frequency:60s}") + @ActivateRequestContext + public void revalidate() { + // if not enabled, don't process any potentially OOD records + if (!Boolean.TRUE.equals(isEnabled.get())) { + return; + } + + // set up params for looking up the top of the revalidation queue + MultivaluedMap<String, String> params = new MultivaluedHashMap<>(); + params.add(GitEcaParameterNames.NEEDS_REVALIDATION_RAW, "true"); + params.add(PersistenceUrlParameterNames.SORT.getName(), "lastUpdated"); + params.add(DefaultUrlParameterNames.PAGESIZE.getName(), "1"); + + // build the request and query to lookup the longest standing request that needs revalidation + RequestWrapper wrap = new FlatRequestWrapper(URI.create("https://api.eclipse.org/git/eca/revalidation-queue")); + RDBMSQuery<GithubWebhookTracking> trackingQuery = new RDBMSQuery<>(wrap, filters.get(GithubWebhookTracking.class), params); + + List<GithubWebhookTracking> oldestRevalidation = dao.get(trackingQuery); + if (oldestRevalidation.isEmpty()) { + LOGGER.debug("No queued revalidation requests found"); + } else { + reprocessRequest(oldestRevalidation.get(0), wrap); + } } - } - - /** - * Checks if the manual revalidation count has reached the configured threshold and sends an email - * notification if it has and the notification alert is enabled. - * - * @param tracking the webhook tracking object - */ - private void checkRevalidationThreshold(GithubWebhookTracking tracking) { - // If revalidation alert is not enabled, do nothing - if (!Boolean.TRUE.equals(isRevalidationAlertEnabled.get())) - return; - - Integer threshold = revalidationThreshold.get(); - - // If manual revalidation count is null or less than threshold, do nothing - if (Objects.isNull(tracking.getManualRevalidationCount()) - || tracking.getManualRevalidationCount() < threshold) { - return; + + /** + * Reprocess the given record, attempting to run the ECA validation logic again. If it passes, the revalidation flag is set to false and + * the time code is updated. If the processing fails again, the failure count gets incremented and the updated time is set so that + * another entry can be updated, as to not block on potentially broken records. + * + * @param requestToRevalidate the webhook tracking request to attempt to revalidate + * @param wrap the current stubbed request wrapper used for queries. + */ + private void reprocessRequest(GithubWebhookTracking requestToRevalidate, RequestWrapper wrap) { + LOGGER + .debug("Attempting revalidation of request w/ ID {}, in repo {}#{}", requestToRevalidate.getId(), + requestToRevalidate.getRepositoryFullName(), requestToRevalidate.getPullRequestNumber()); + + // update the number of times this status has revalidated (tracking) + requestToRevalidate + .setManualRevalidationCount(requestToRevalidate.getManualRevalidationCount() == null ? 1 + : requestToRevalidate.getManualRevalidationCount() + 1); + + // Check if notification threshold is reached and send email if needed + checkRevalidationThreshold(requestToRevalidate); + + // wrap in try-catch to avoid errors from stopping the record updates + try { + // split the full repo name into the org and repo name + String[] repoFullNameParts = requestToRevalidate.getRepositoryFullName().split("/"); + if (repoFullNameParts.length != FULL_REPO_NAME_PARTS) { + throw new IllegalStateException("Record with ID '" + Long.toString(requestToRevalidate.getId()) + + "' is in an invalid state (repository full name is not valid)"); + } + + // run the validation and then check if it succeeded. Use the forced flag since we want to try even if there are no changes + validationHelper + .validateIncomingRequest(wrap, repoFullNameParts[0], repoFullNameParts[1], requestToRevalidate.getPullRequestNumber(), + true); + // if we have gotten here, then the validation has completed and can be removed from queue + requestToRevalidate.setNeedsRevalidation(false); + LOGGER.debug("Sucessfully revalidated request w/ ID {}", requestToRevalidate.getId()); + } catch (RuntimeException e) { + // log the message so we can see what happened + LOGGER.error("Error while revalidating request w/ ID {}", requestToRevalidate.getId(), e); + } finally { + // whether successful or failed, update the updated time field + requestToRevalidate.setLastUpdated(DateTimeHelper.now()); + + // if in a closed state, we shouldn't try to revalidate again as it will never be valid + // if a PR is reopened, it should create a new event and validate anyways + if ("closed".equalsIgnoreCase(requestToRevalidate.getLastKnownState())) { + LOGGER.debug("Tracking request {} set to not revalidate as it was closed", requestToRevalidate.getId()); + requestToRevalidate.setNeedsRevalidation(false); + } + // push the update with the potentially updated validation flag or error count + dao.add(new RDBMSQuery<>(wrap, filters.get(GithubWebhookTracking.class)), Arrays.asList(requestToRevalidate)); + } } - // Check if count equals threshold (to send notification only once when threshold is reached) - if (tracking.getManualRevalidationCount() == threshold) { - sendRevalidationAlert(tracking); + /** + * Checks if the manual revalidation count has reached the configured threshold and sends an email notification if it has and the + * notification alert is enabled. + * + * @param tracking the webhook tracking object + */ + private void checkRevalidationThreshold(GithubWebhookTracking tracking) { + // If revalidation alert is not enabled, do nothing + if (!Boolean.TRUE.equals(isRevalidationAlertEnabled.get())) + return; + + Integer threshold = revalidationThreshold.get(); + + // If manual revalidation count is null or less than threshold, do nothing + if (Objects.isNull(tracking.getManualRevalidationCount()) || tracking.getManualRevalidationCount() < threshold) { + return; + } + + // Check if count equals threshold (to send notification only once when threshold is reached) + if (tracking.getManualRevalidationCount() == threshold) { + sendRevalidationAlert(tracking); + } } - } - - /** - * Sends an email alert about a webhook that has reached the revalidation threshold. - * - * @param tracking the webhook tracking object - */ - private void sendRevalidationAlert(GithubWebhookTracking tracking) { - try { - mailerService.sendRevalidationAlert(tracking, revalidationThreshold.get()); - LOGGER.info("Sent revalidation alert email for request ID {}", tracking.getId()); - } catch (RuntimeException e) { - LOGGER.error("Failed to send revalidation alert email for request ID {}", tracking.getId(), - e); + + /** + * Sends an email alert about a webhook that has reached the revalidation threshold. + * + * @param tracking the webhook tracking object + */ + private void sendRevalidationAlert(GithubWebhookTracking tracking) { + try { + mailerService.sendRevalidationAlert(tracking, revalidationThreshold.get()); + LOGGER.info("Sent revalidation alert email for request ID {}", tracking.getId()); + } catch (RuntimeException e) { + LOGGER.error("Failed to send revalidation alert email for request ID {}", tracking.getId(), e); + } } - } } -- GitLab From 92d5e711aa4cceedcc0e87f80d4ed43ec78b96c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20G=C3=B3mez?= <jordi.gomez@eclipse-foundation.org> Date: Mon, 28 Apr 2025 11:13:54 +0200 Subject: [PATCH 10/10] chore(config): updating mailer config & secrets sample --- config/application/secret.properties.sample | 6 +++++- src/main/resources/application.properties | 12 ++++++++++++ src/test/resources/application.properties | 11 +---------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/config/application/secret.properties.sample b/config/application/secret.properties.sample index 4de58a1f..99f4d517 100644 --- a/config/application/secret.properties.sample +++ b/config/application/secret.properties.sample @@ -12,4 +12,8 @@ quarkus.datasource.password= quarkus.datasource.jdbc.url=jdbc:mariadb://mariadb/dev_eclipse_eca %dev.quarkus.datasource.jdbc.url=jdbc:mariadb://${eclipse.internal-host}:10101/dev_eclipse_eca -eclipse.gitlab.access-token= \ No newline at end of file +eclipse.gitlab.access-token= + +## Used to send mail through the EclipseFdn smtp connection +quarkus.mailer.password=YOURGENERATEDAPPLICATIONPASSWORD +quarkus.mailer.username=YOUREMAIL@gmail.com \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3f208c28..c4402971 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -65,3 +65,15 @@ eclipse.git-eca.reports.allowed-users=mbarbaro,webdev ## Misc eclipse.system-hook.pool-size=5 + +## Revalidation alert email config +eclipse.git-eca.tasks.gh-revalidation.notification-threshold=100 +eclipse.mailer.revalidation-alert.to=webdev@eclipse-foundation.org + +# Quarkus Mailer +quarkus.mailer.auth-methods=DIGEST-MD5 CRAM-SHA256 CRAM-SHA1 CRAM-MD5 PLAIN LOGIN +quarkus.mailer.from=no-reply@eclipse-foundation.org +# Uses gmail by default, can be overridden +quarkus.mailer.host=smtp.gmail.com +quarkus.mailer.port=465 +quarkus.mailer.ssl=true diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index 205ea9ab..bd6e17d8 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -24,12 +24,7 @@ quarkus.oidc-client.enabled=false smallrye.jwt.sign.key.location=test.pem # Quarkus Mailer -quarkus.mailer.auth-methods=DIGEST-MD5 CRAM-SHA256 CRAM-SHA1 CRAM-MD5 PLAIN LOGIN -quarkus.mailer.from=membership.coordination@eclipse-foundation.org -# Uses gmail by default, can be overridden -quarkus.mailer.host=smtp.gmail.com -quarkus.mailer.port=465 -quarkus.mailer.ssl=true +quarkus.mailer.mock=true # hCaptcha test key and secret eclipse.hcaptcha.site-key=20000000-ffff-ffff-ffff-000000000002 @@ -43,10 +38,6 @@ eclipse.git-eca.mail.allow-list=noreply@github.com eclipse.git-eca.reports.access-key=samplekey eclipse.git-eca.tasks.gh-revalidation.enabled=false eclipse.git-eca.tasks.gh-installation.enabled=false -eclipse.git-eca.tasks.gh-revalidation.notification-threshold=100 - -## Revalidation alert email config -eclipse.mailer.revalidation-alert.to=webdev@eclipse-foundation.org ## Misc eclipse.gitlab.access-token=token_val -- GitLab