From 9656c6a3da566cbba565ae02b77992b2d68937e1 Mon Sep 17 00:00:00 2001 From: aakash137 Date: Mon, 29 Jun 2020 03:01:51 +0530 Subject: [PATCH 1/4] Added email support. Removed parent pom. --- .../BuildResultDto.java} | 4 +- .../{execution => }/dto/ExecutionInfo.java | 0 .../com/miqdigital/dto/NotificationDto.java | 19 +++++ .../{scenario => }/dto/ScenarioInfo.java | 0 .../{scenario => }/dto/ScenarioStep.java | 0 .../AfterSuite.java | 0 .../BeforeSuite.java | 0 .../ExtendedCucumberRunner.java | 0 .../ExecutionInfoGenerator.java | 2 +- .../HeimdallReporting.java | 76 ++++++++++++------- .../{slack => services}/MessageGenerator.java | 18 ++--- .../slack/dto/SlackChannelInfo.java | 10 --- .../AmazonS3Connector.java | 0 .../java/com/miqdigital/utils/EmailUtil.java | 76 +++++++++++++++++++ .../{utility => utils}/ReadProperties.java | 51 ++++++++++++- .../{slack => utils}/SlackUtils.java | 40 +++++----- heimdall.sample-client/CucumberREADME.md | 19 +++-- heimdall.sample-client/KarateREADME.md | 25 ++++-- heimdall.sample-client/pom.xml | 45 +++++++---- .../javasample/CucumberTestRunner.java | 11 ++- .../javasample/KarateTestRunner.java | 20 +++-- .../kotlinesample/KarateTestRunner.kt | 8 +- .../resources/features/Karate/Test.feature | 4 +- .../resources/properties/runner.properties | 19 +++-- pom.xml | 15 ---- 25 files changed, 322 insertions(+), 140 deletions(-) rename heimdall.application/src/main/java/com/miqdigital/{slack/dto/SlackMessageInfo.java => dto/BuildResultDto.java} (70%) rename heimdall.application/src/main/java/com/miqdigital/{execution => }/dto/ExecutionInfo.java (100%) create mode 100644 heimdall.application/src/main/java/com/miqdigital/dto/NotificationDto.java rename heimdall.application/src/main/java/com/miqdigital/{scenario => }/dto/ScenarioInfo.java (100%) rename heimdall.application/src/main/java/com/miqdigital/{scenario => }/dto/ScenarioStep.java (100%) rename heimdall.application/src/main/java/com/miqdigital/{cucumber_runner => runner}/AfterSuite.java (100%) rename heimdall.application/src/main/java/com/miqdigital/{cucumber_runner => runner}/BeforeSuite.java (100%) rename heimdall.application/src/main/java/com/miqdigital/{cucumber_runner => runner}/ExtendedCucumberRunner.java (100%) rename heimdall.application/src/main/java/com/miqdigital/{execution => services}/ExecutionInfoGenerator.java (99%) rename heimdall.application/src/main/java/com/miqdigital/{reporting => services}/HeimdallReporting.java (60%) rename heimdall.application/src/main/java/com/miqdigital/{slack => services}/MessageGenerator.java (86%) delete mode 100644 heimdall.application/src/main/java/com/miqdigital/slack/dto/SlackChannelInfo.java rename heimdall.application/src/main/java/com/miqdigital/{connector => utils}/AmazonS3Connector.java (100%) create mode 100644 heimdall.application/src/main/java/com/miqdigital/utils/EmailUtil.java rename heimdall.application/src/main/java/com/miqdigital/{utility => utils}/ReadProperties.java (52%) rename heimdall.application/src/main/java/com/miqdigital/{slack => utils}/SlackUtils.java (56%) rename heimdall.sample-client/src/test/java/com/miqdigital/{cucumber_runner => runner}/javasample/CucumberTestRunner.java (80%) rename heimdall.sample-client/src/test/java/com/miqdigital/{cucumber_runner => runner}/javasample/KarateTestRunner.java (60%) rename heimdall.sample-client/src/test/java/com/miqdigital/{cucumber_runner => runner}/kotlinesample/KarateTestRunner.kt (79%) delete mode 100644 pom.xml diff --git a/heimdall.application/src/main/java/com/miqdigital/slack/dto/SlackMessageInfo.java b/heimdall.application/src/main/java/com/miqdigital/dto/BuildResultDto.java similarity index 70% rename from heimdall.application/src/main/java/com/miqdigital/slack/dto/SlackMessageInfo.java rename to heimdall.application/src/main/java/com/miqdigital/dto/BuildResultDto.java index 2ec1657..47fa0d3 100644 --- a/heimdall.application/src/main/java/com/miqdigital/slack/dto/SlackMessageInfo.java +++ b/heimdall.application/src/main/java/com/miqdigital/dto/BuildResultDto.java @@ -1,9 +1,9 @@ -package com.miqdigital.slack.dto; +package com.miqdigital.dto; import lombok.Builder; @Builder -public class SlackMessageInfo { +public class ResultDto { public StringBuilder testExecutionInfo; public StringBuilder failedTestDescription; public long failedTestCount; diff --git a/heimdall.application/src/main/java/com/miqdigital/execution/dto/ExecutionInfo.java b/heimdall.application/src/main/java/com/miqdigital/dto/ExecutionInfo.java similarity index 100% rename from heimdall.application/src/main/java/com/miqdigital/execution/dto/ExecutionInfo.java rename to heimdall.application/src/main/java/com/miqdigital/dto/ExecutionInfo.java diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/NotificationDto.java b/heimdall.application/src/main/java/com/miqdigital/dto/NotificationDto.java new file mode 100644 index 0000000..6dccb56 --- /dev/null +++ b/heimdall.application/src/main/java/com/miqdigital/dto/NotificationDto.java @@ -0,0 +1,19 @@ +package com.miqdigital.dto; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class EmailDto { + private final String emailHost; + private final String smtpUsername; + private final String smtpPassword; + private final boolean notifySlack; + private final boolean notifyEmail; + private final String emailTo; + private final String emailFrom; + private final String subject; + private final String jenkinsDomain; + +} diff --git a/heimdall.application/src/main/java/com/miqdigital/scenario/dto/ScenarioInfo.java b/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfo.java similarity index 100% rename from heimdall.application/src/main/java/com/miqdigital/scenario/dto/ScenarioInfo.java rename to heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfo.java diff --git a/heimdall.application/src/main/java/com/miqdigital/scenario/dto/ScenarioStep.java b/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStep.java similarity index 100% rename from heimdall.application/src/main/java/com/miqdigital/scenario/dto/ScenarioStep.java rename to heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStep.java diff --git a/heimdall.application/src/main/java/com/miqdigital/cucumber_runner/AfterSuite.java b/heimdall.application/src/main/java/com/miqdigital/runner/AfterSuite.java similarity index 100% rename from heimdall.application/src/main/java/com/miqdigital/cucumber_runner/AfterSuite.java rename to heimdall.application/src/main/java/com/miqdigital/runner/AfterSuite.java diff --git a/heimdall.application/src/main/java/com/miqdigital/cucumber_runner/BeforeSuite.java b/heimdall.application/src/main/java/com/miqdigital/runner/BeforeSuite.java similarity index 100% rename from heimdall.application/src/main/java/com/miqdigital/cucumber_runner/BeforeSuite.java rename to heimdall.application/src/main/java/com/miqdigital/runner/BeforeSuite.java diff --git a/heimdall.application/src/main/java/com/miqdigital/cucumber_runner/ExtendedCucumberRunner.java b/heimdall.application/src/main/java/com/miqdigital/runner/ExtendedCucumberRunner.java similarity index 100% rename from heimdall.application/src/main/java/com/miqdigital/cucumber_runner/ExtendedCucumberRunner.java rename to heimdall.application/src/main/java/com/miqdigital/runner/ExtendedCucumberRunner.java diff --git a/heimdall.application/src/main/java/com/miqdigital/execution/ExecutionInfoGenerator.java b/heimdall.application/src/main/java/com/miqdigital/services/ExecutionInfoGenerator.java similarity index 99% rename from heimdall.application/src/main/java/com/miqdigital/execution/ExecutionInfoGenerator.java rename to heimdall.application/src/main/java/com/miqdigital/services/ExecutionInfoGenerator.java index 99dc091..e6ab96d 100644 --- a/heimdall.application/src/main/java/com/miqdigital/execution/ExecutionInfoGenerator.java +++ b/heimdall.application/src/main/java/com/miqdigital/services/ExecutionInfoGenerator.java @@ -17,7 +17,7 @@ import com.miqdigital.execution.dto.ExecutionInfo; import com.miqdigital.scenario.dto.ScenarioInfo; import com.miqdigital.scenario.dto.ScenarioStep; -import com.miqdigital.utility.ReadProperties; +import com.miqdigital.utils.ReadProperties; import net.masterthought.cucumber.Configuration; import net.masterthought.cucumber.ReportBuilder; diff --git a/heimdall.application/src/main/java/com/miqdigital/reporting/HeimdallReporting.java b/heimdall.application/src/main/java/com/miqdigital/services/HeimdallReporting.java similarity index 60% rename from heimdall.application/src/main/java/com/miqdigital/reporting/HeimdallReporting.java rename to heimdall.application/src/main/java/com/miqdigital/services/HeimdallReporting.java index e3a37c2..4e0d907 100644 --- a/heimdall.application/src/main/java/com/miqdigital/reporting/HeimdallReporting.java +++ b/heimdall.application/src/main/java/com/miqdigital/services/HeimdallReporting.java @@ -5,19 +5,22 @@ import java.io.IOException; import java.util.Objects; +import javax.mail.MessagingException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.amazonaws.util.StringUtils; import com.google.gson.Gson; -import com.miqdigital.connector.AmazonS3Connector; +import com.miqdigital.utils.AmazonS3Connector; +import com.miqdigital.dto.NotificationDto; import com.miqdigital.execution.ExecutionInfoGenerator; import com.miqdigital.execution.dto.ExecutionInfo; import com.miqdigital.slack.MessageGenerator; import com.miqdigital.slack.SlackUtils; -import com.miqdigital.slack.dto.SlackChannelInfo; -import com.miqdigital.slack.dto.SlackMessageInfo; -import com.miqdigital.utility.ReadProperties; +import com.miqdigital.dto.ResultDto; +import com.miqdigital.utils.EmailUtil; +import com.miqdigital.utils.ReadProperties; import cucumber.runtime.CucumberException; @@ -27,7 +30,7 @@ public class HeimdallReporting { private static final Logger LOGGER = LoggerFactory.getLogger(HeimdallReporting.class); - private ReadProperties readProperties; + private ReadProperties properties; private String executionOutputPath; public HeimdallReporting(final String pathOfRunnerPropertiesFile, @@ -37,23 +40,34 @@ public HeimdallReporting(final String pathOfRunnerPropertiesFile, } else if (StringUtils.isNullOrEmpty(executionOutputPath)) { throw new CucumberException("Please specify cucumber output path"); } else { - this.readProperties = new ReadProperties(pathOfRunnerPropertiesFile); + this.properties = new ReadProperties(pathOfRunnerPropertiesFile); this.executionOutputPath = executionOutputPath; } } /** * Sends the notification on the Slack channel. - * - * @param executionInfo Jenkins build execution info - * @param slackChannelInfo slack channel info from client + * @param executionInfo Jenkins build execution info + * @param notificationDto slack channel info from client */ private static void sendSlackNotification(final ExecutionInfo executionInfo, - final SlackChannelInfo slackChannelInfo) throws IOException { - final SlackMessageInfo slackMessageInfo = MessageGenerator.getMessage(executionInfo); + final NotificationDto notificationDto) throws IOException { + final ResultDto resultDto = MessageGenerator.getBuildResult(executionInfo,notificationDto); SlackUtils slackUtils = new SlackUtils(); - slackUtils.slackNotification(slackChannelInfo, slackMessageInfo); + slackUtils.sendSlackNotification(notificationDto, resultDto); + } + + /** + * Sends Email notification. + * @param executionInfo + * @param notificationDto + */ + private static void sendEmailNotification(ExecutionInfo executionInfo, + NotificationDto notificationDto) throws MessagingException, IOException { + final ResultDto resultDto = MessageGenerator.getBuildResult(executionInfo, notificationDto); + + EmailUtil.sendEmail(notificationDto, resultDto); } /** @@ -94,9 +108,9 @@ public void updateStatusInS3() throws IllegalAccessException, NoSuchFieldException, IOException, InterruptedException { ExecutionInfoGenerator executionInfoGenerator = new ExecutionInfoGenerator(); ExecutionInfo executionInfo = - executionInfoGenerator.getBuildExecutionDetails(readProperties, executionOutputPath); + executionInfoGenerator.getBuildExecutionDetails(properties, executionOutputPath); - pushResultToS3(readProperties.getS3BucketName(), executionInfo); + pushResultToS3(properties.getS3BucketName(), executionInfo); } /** @@ -105,27 +119,37 @@ public void updateStatusInS3() * @throws NoSuchFieldException noSuchFieldException * @throws IllegalAccessException illegalAccessException */ - public void updateStatusInS3AndNotifySlack() - throws NoSuchFieldException, IllegalAccessException, IOException, InterruptedException { + public void updateStatusInS3AndNotify() + throws NoSuchFieldException, IllegalAccessException, IOException, InterruptedException, + MessagingException { ExecutionInfoGenerator executionInfoGenerator = new ExecutionInfoGenerator(); ExecutionInfo executionInfo = - executionInfoGenerator.getBuildExecutionDetails(readProperties, executionOutputPath); + executionInfoGenerator.getBuildExecutionDetails(properties, executionOutputPath); - if (StringUtils.isNullOrEmpty(readProperties.getChannelName()) || StringUtils - .isNullOrEmpty(readProperties.getHeimdallBotToken())) { + if (StringUtils.isNullOrEmpty(properties.getChannelName()) || StringUtils + .isNullOrEmpty(properties.getHeimdallBotToken())) { throw new NullPointerException( "Please specify Channel name and Slack bot token in runner properties file"); } - final SlackChannelInfo slackChannelInfo = - SlackChannelInfo.builder().channelName(readProperties.getChannelName()) - .token(readProperties.getHeimdallBotToken()) - .isNotifySlack(readProperties.isNotifySlack()).build(); + final NotificationDto notificationDto = NotificationDto.builder().emailHost(properties.getEmailHost()) + .slackChannel(properties.getChannelName()) + .slackToken(properties.getHeimdallBotToken()) + .notifySlack(properties.isNotifySlack()) + .smtpUsername(properties.getSmtpUsername()) + .smtpPassword(properties.getSmtpPassword()) + .notifyEmail(properties.isNotifyEmail()) + .emailFrom(properties.getEmailFrom()) + .emailTo(properties.getEmailTo()) + .jenkinsDomain(properties.getJenkinsDomain()).build(); LOGGER.info("Execution info generated Successfully"); - if (slackChannelInfo.isNotifySlack) { - sendSlackNotification(executionInfo, slackChannelInfo); + if (notificationDto.isNotifySlack()) { + sendSlackNotification(executionInfo, notificationDto); + } + if(notificationDto.isNotifyEmail()){ + sendEmailNotification(executionInfo, notificationDto); } - pushResultToS3(readProperties.getS3BucketName(), executionInfo); + pushResultToS3(properties.getS3BucketName(), executionInfo); } } \ No newline at end of file diff --git a/heimdall.application/src/main/java/com/miqdigital/slack/MessageGenerator.java b/heimdall.application/src/main/java/com/miqdigital/services/MessageGenerator.java similarity index 86% rename from heimdall.application/src/main/java/com/miqdigital/slack/MessageGenerator.java rename to heimdall.application/src/main/java/com/miqdigital/services/MessageGenerator.java index ca273d6..ca1273d 100644 --- a/heimdall.application/src/main/java/com/miqdigital/slack/MessageGenerator.java +++ b/heimdall.application/src/main/java/com/miqdigital/services/MessageGenerator.java @@ -4,9 +4,10 @@ import java.util.Objects; import java.util.stream.Collectors; +import com.miqdigital.dto.NotificationDto; import com.miqdigital.execution.dto.ExecutionInfo; import com.miqdigital.scenario.dto.ScenarioInfo; -import com.miqdigital.slack.dto.SlackMessageInfo; +import com.miqdigital.dto.ResultDto; /** * This class builds the Slack message and the failed test scenarios report, if any. @@ -14,20 +15,15 @@ public class MessageGenerator { - private MessageGenerator() { - } - - public static SlackMessageInfo getMessage(final ExecutionInfo executionInfo) { - return sendSlackNotification(executionInfo); - } - /** * Sends the build notification to the Slack channel. * * @param executionInfo test execution info + * @param notificationDto * @return slack notification info */ - private static SlackMessageInfo sendSlackNotification(final ExecutionInfo executionInfo) { + public static ResultDto getBuildResult(final ExecutionInfo executionInfo, + NotificationDto notificationDto) { final StringBuilder testExecutionInfo = new StringBuilder(); StringBuilder failedTestsInfo = new StringBuilder(); @@ -46,11 +42,11 @@ private static SlackMessageInfo sendSlackNotification(final ExecutionInfo execut if (Objects.nonNull(executionInfo.BuildNumber) && Objects .nonNull(System.getProperty("viewName"))) { testExecutionInfo.append("\n").append("*Console out:* ").append(String - .format("https://builds-corp.mediaiqdigital.com/view/%s/job/%s/%s/console", + .format(notificationDto.getJenkinsDomain() + "/view/%s/job/%s/%s/console", System.getProperty("viewName"), executionInfo.BuildName, executionInfo.BuildNumber)); } - return SlackMessageInfo.builder().testExecutionInfo(testExecutionInfo) + return ResultDto.builder().testExecutionInfo(testExecutionInfo) .failedTestDescription(failedTestsInfo).failedTestCount(executionInfo.failTestCount) .build(); } diff --git a/heimdall.application/src/main/java/com/miqdigital/slack/dto/SlackChannelInfo.java b/heimdall.application/src/main/java/com/miqdigital/slack/dto/SlackChannelInfo.java deleted file mode 100644 index 413ab0c..0000000 --- a/heimdall.application/src/main/java/com/miqdigital/slack/dto/SlackChannelInfo.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.miqdigital.slack.dto; - -import lombok.Builder; - -@Builder -public class SlackChannelInfo { - public String channelName; - public String token; - public boolean isNotifySlack; -} \ No newline at end of file diff --git a/heimdall.application/src/main/java/com/miqdigital/connector/AmazonS3Connector.java b/heimdall.application/src/main/java/com/miqdigital/utils/AmazonS3Connector.java similarity index 100% rename from heimdall.application/src/main/java/com/miqdigital/connector/AmazonS3Connector.java rename to heimdall.application/src/main/java/com/miqdigital/utils/AmazonS3Connector.java diff --git a/heimdall.application/src/main/java/com/miqdigital/utils/EmailUtil.java b/heimdall.application/src/main/java/com/miqdigital/utils/EmailUtil.java new file mode 100644 index 0000000..d9854d3 --- /dev/null +++ b/heimdall.application/src/main/java/com/miqdigital/utils/EmailUtil.java @@ -0,0 +1,76 @@ +package com.miqdigital.utility; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Properties; + +import javax.mail.Authenticator; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.Multipart; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; + +import com.miqdigital.dto.EmailDto; +import com.miqdigital.dto.ResultDto; + +public class EmailUtil { + + private static final String ATTACHMENT_FILE_NAME = "./target/FailedTestsInfo.txt"; + + /** + * Creating an email body and sending the email. + * @param emailDto + * @param resultDto + * @throws MessagingException + * @throws IOException + */ + public static void sendEmail(EmailDto emailDto, ResultDto resultDto) + throws MessagingException, IOException { + String msg = resultDto.testExecutionInfo.toString(); + + Properties prop = new Properties(); + prop.put("mail.smtp.auth", true); + prop.put("mail.smtp.starttls.enable", "true"); + prop.put("mail.smtp.host", emailDto.getEmailHost()); + prop.put("mail.smtp.port", emailDto.getEmailHost()); + prop.put("mail.smtp.ssl.trust", "smtp.mailtrap.io"); + + Session session = Session.getInstance(prop, new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(emailDto.getSmtpUsername(), emailDto.getSmtpPassword()); + } + }); + final String generatedFileName = Files.write(Paths.get(ATTACHMENT_FILE_NAME), + resultDto.failedTestDescription.toString().getBytes()).normalize().toAbsolutePath() + .toString(); + Message message = new MimeMessage(session); + message.setFrom(new InternetAddress(emailDto.getEmailFrom())); + message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(emailDto.getEmailTo())); + message.setSubject(emailDto.getSubject()); + + + MimeBodyPart attachmentBodyPart = new MimeBodyPart(); + attachmentBodyPart.attachFile(new File(generatedFileName)); + MimeBodyPart mimeBodyPart = new MimeBodyPart(); + mimeBodyPart.setContent(msg, "text/html"); + + Multipart multipart = new MimeMultipart(); + multipart.addBodyPart(mimeBodyPart); + multipart.addBodyPart(attachmentBodyPart); + + message.setContent(multipart); + + Transport.send(message); + + } + +} diff --git a/heimdall.application/src/main/java/com/miqdigital/utility/ReadProperties.java b/heimdall.application/src/main/java/com/miqdigital/utils/ReadProperties.java similarity index 52% rename from heimdall.application/src/main/java/com/miqdigital/utility/ReadProperties.java rename to heimdall.application/src/main/java/com/miqdigital/utils/ReadProperties.java index 29de33a..badc242 100644 --- a/heimdall.application/src/main/java/com/miqdigital/utility/ReadProperties.java +++ b/heimdall.application/src/main/java/com/miqdigital/utils/ReadProperties.java @@ -30,9 +30,29 @@ public class ReadProperties { */ private String channelName; /** - * The constant isNotifySlack. + * The constant notifySlack. */ - private boolean isNotifySlack; + private boolean notifySlack; + /** + * The constant notifyEmail. + */ + private boolean notifyEmail; + /** + * The constant emailTo. + */ + private String emailTo; + /** + * The constant emailFrom. + */ + private String emailFrom; + /** + * The constant emailPort. + */ + private String emailPort; + /** + * The constant emailSubject. + */ + private String emailSubject; /** * The constant jiraPrefix. */ @@ -42,6 +62,22 @@ public class ReadProperties { * The constant s3BucketFolderName e.g. ABCCompanyAutomationTestReport */ private String s3BucketName; + /** + * The host to use while sending email. + */ + private String emailHost; + /** + * The SMTP username. + */ + private String smtpUsername; + /** + * The SMTP password. + */ + private String smtpPassword; + /** + * The company's Jenkins domain + */ + private String jenkinsDomain; private Properties properties; @@ -61,10 +97,19 @@ public ReadProperties(final String filepath) throws IOException { */ private void initFields() { channelName = properties.getProperty("CHANNEL_NAME"); - isNotifySlack = Boolean.parseBoolean(properties.getProperty("ISNOTIFYSLACK")); + notifySlack = Boolean.parseBoolean(properties.getProperty("NOTIFY_SLACK")); heimdallBotToken = properties.getProperty("HEIMDALL_BOT_TOKEN"); jiraPrefix = properties.getProperty("JIRA_PREFIX"); s3BucketName = properties.getProperty("S3_BUCKETNAME"); + emailHost = properties.getProperty("EMAIL_HOST"); + smtpUsername = properties.getProperty("SMTP_USERNAME"); + smtpPassword = properties.getProperty("SMTP_PASSWORD"); + notifyEmail = Boolean.parseBoolean(properties.getProperty("NOTIFY_EMAIL")); + emailTo = properties.getProperty("EMAIL_TO"); + emailFrom = properties.getProperty("EMAIL_FROM"); + emailPort = properties.getProperty("EMAIL_PORT"); + emailSubject = properties.getProperty("EMAIL_SUBJECT"); + jenkinsDomain = properties.getProperty("JENKINS_DOMAIN"); } } \ No newline at end of file diff --git a/heimdall.application/src/main/java/com/miqdigital/slack/SlackUtils.java b/heimdall.application/src/main/java/com/miqdigital/utils/SlackUtils.java similarity index 56% rename from heimdall.application/src/main/java/com/miqdigital/slack/SlackUtils.java rename to heimdall.application/src/main/java/com/miqdigital/utils/SlackUtils.java index b237d5f..924f72f 100644 --- a/heimdall.application/src/main/java/com/miqdigital/slack/SlackUtils.java +++ b/heimdall.application/src/main/java/com/miqdigital/utils/SlackUtils.java @@ -14,8 +14,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.miqdigital.slack.dto.SlackChannelInfo; -import com.miqdigital.slack.dto.SlackMessageInfo; +import com.miqdigital.dto.NotificationDto; +import com.miqdigital.dto.ResultDto; /** * This class is used to post Slack notification on provided channel. @@ -31,17 +31,17 @@ public class SlackUtils { /** * Makes Http post request to Slack to send the notification and upload the failed scenarios file. * - * @param slackChannelInfo slack channel details and token - * @param slackMessageInfo slack notification + * @param notificationDto slack channel details and token + * @param resultDto slack notification */ - public void slackNotification(final SlackChannelInfo slackChannelInfo, - final SlackMessageInfo slackMessageInfo) throws IOException { + public void sendSlackNotification(final NotificationDto notificationDto, + final ResultDto resultDto) throws IOException { final HttpClient httpclient = HttpClientBuilder.create().disableContentCompression().build(); - final HttpPost httpPost = slackMessageInfo.failedTestCount == 0 ? + final HttpPost httpPost = resultDto.failedTestCount == 0 ? new HttpPost(CHAT_POST_URL) : new HttpPost(FILE_UPLOAD_URL); - final HttpEntity httpEntity = getHttpRequestEntity(slackChannelInfo, slackMessageInfo).build(); + final HttpEntity httpEntity = getHttpRequestEntity(notificationDto, resultDto).build(); httpPost.setEntity(httpEntity); final HttpResponse execute = httpclient.execute(httpPost); logger.info(execute.getStatusLine().getReasonPhrase()); @@ -50,28 +50,28 @@ public void slackNotification(final SlackChannelInfo slackChannelInfo, /** * Configures the Http request for Slack. * - * @param slackChannelInfo - * @param slackMessageInfo + * @param notificationDto + * @param resultDto * @return * @throws IOException */ - private MultipartEntityBuilder getHttpRequestEntity(final SlackChannelInfo slackChannelInfo, - final SlackMessageInfo slackMessageInfo) throws IOException { + public MultipartEntityBuilder getHttpRequestEntity(final NotificationDto notificationDto, + final ResultDto resultDto) throws IOException { final MultipartEntityBuilder reqEntity = - MultipartEntityBuilder.create().addTextBody("token", slackChannelInfo.token); - if (slackMessageInfo.failedTestCount == 0) { + MultipartEntityBuilder.create().addTextBody("token", notificationDto.getSlackToken()); + if (resultDto.failedTestCount == 0) { //soft slack notification - reqEntity.addTextBody("channel", slackChannelInfo.channelName).addTextBody("as_user", "true") - .addTextBody("text", slackMessageInfo.testExecutionInfo.toString()); + reqEntity.addTextBody("channel", notificationDto.getSlackChannel()) + .addTextBody("as_user", "true") + .addTextBody("text", resultDto.testExecutionInfo.toString()); } else { //slack notification with @here final String generatedFileName = Files.write(Paths.get(ATTACHMENT_FILE_NAME), - slackMessageInfo.failedTestDescription.toString().getBytes()).normalize().toAbsolutePath() + resultDto.failedTestDescription.toString().getBytes()).normalize().toAbsolutePath() .toString(); reqEntity.addBinaryBody("file", new File(generatedFileName)) - .addTextBody("channels", slackChannelInfo.channelName).addTextBody("media", "file") - .addTextBody("initial_comment", - " " + slackMessageInfo.testExecutionInfo.toString()); + .addTextBody("channels", notificationDto.getSlackChannel()).addTextBody("media", "file") + .addTextBody("initial_comment", " " + resultDto.testExecutionInfo.toString()); } return reqEntity; } diff --git a/heimdall.sample-client/CucumberREADME.md b/heimdall.sample-client/CucumberREADME.md index 2398c1c..78329c5 100644 --- a/heimdall.sample-client/CucumberREADME.md +++ b/heimdall.sample-client/CucumberREADME.md @@ -13,11 +13,20 @@ - Create a Slack channel to receive build notifications of the projects. - Create a properties file for the automation module. It should contain the following fields. - 1. HEIMDALL_BOT_TOKEN - the the Slack token for BOT or user. - 2. CHANNEL_NAME - the channel for the build notifications. - 3. ISNOTIFYSLACK - this field can be true or false, accordingly. - 4. JIRA_PREFIX - the JIRA ticket prefix assigned to the team. - 5. S3_BUCKETNAME - the S3 bucket where the build results are pushed. + 1. HEIMDALL_BOT_TOKEN - the the Slack token for BOT or user. + 2. CHANNEL_NAME - the channel for the build notifications. + 3. NOTIFY_SLACK - this field can be true or false, accordingly. + 4. JIRA_PREFIX - the JIRA ticket prefix assigned to the team. + 5. S3_BUCKETNAME - the S3 bucket where the build results are pushed. + 6. NOTIFY_EMAIL - this field can be true or false, accordingly. + 7. EMAIL_HOST - your email host. For example - smtp.gmail.com + 8. SMTP_USERNAME - the email by which report is to be sent. + 9. SMTP_PASSWORD - the app password. This is not the account password. + 10. EMAIL_TO - the email recipient. + 11. EMAIL_FROM - the email sender. + 12. EMAIL_PORT - the smtp port. For gmail, it's 587. + 13. EMAIL_SUBJECT - the email subject. + 14. JENKINS_DOMAIN - the jenkins domain of the jobs. An example of properties file is given under heimdall.sample-client/src/test/resources/properties, named runner.properties. diff --git a/heimdall.sample-client/KarateREADME.md b/heimdall.sample-client/KarateREADME.md index f9a085a..71cdcae 100644 --- a/heimdall.sample-client/KarateREADME.md +++ b/heimdall.sample-client/KarateREADME.md @@ -13,11 +13,20 @@ - Create a Slack channel to receive build notifications of the projects. - Create a properties file for the automation module. It should contain the following fields. - 1. HEIMDALL_BOT_TOKEN - the the Slack token for BOT or user. - 2. CHANNEL_NAME - the channel for the build notifications. - 3. ISNOTIFYSLACK - this field can be true or false, accordingly. - 4. JIRA_PREFIX - the JIRA ticket prefix assigned to the team. - 5. S3_BUCKETNAME - the S3 bucket where the build results are pushed. + 1. HEIMDALL_BOT_TOKEN - the the Slack token for BOT or user. + 2. CHANNEL_NAME - the channel for the build notifications. + 3. NOTIFY_SLACK - this field can be true or false, accordingly. + 4. JIRA_PREFIX - the JIRA ticket prefix assigned to the team. + 5. S3_BUCKETNAME - the S3 bucket where the build results are pushed. + 6. NOTIFY_EMAIL - this field can be true or false, accordingly. + 7. EMAIL_HOST - your email host. For example - smtp.gmail.com + 8. SMTP_USERNAME - the email by which report is to be sent. + 9. SMTP_PASSWORD - the app password. This is not the account password. + 10. EMAIL_TO - the email recipient. + 11. EMAIL_FROM - the email sender. + 12. EMAIL_PORT - the smtp port. For gmail, it's 587. + 13. EMAIL_SUBJECT - the email subject. + 14. JENKINS_DOMAIN - the jenkins domain of the jobs. An example of properties file is given under heimdall.sample-client/src/test/resources/properties, named runner.properties. @@ -35,10 +44,10 @@ 4. Heimdall heimdall = new Heimdall(); Generate an instance of the Heimdall class. - 5. heimdall.updateStatusInS3AndNotifySlack(pathOfPropertyFile, karateOutputPath) - Call the updateStatusInS3AndNotifySlack with the Heimdall instance and pass + 5. heimdall.updateStatusInS3AndNotify(pathOfPropertyFile, karateOutputPath) + Call the updateStatusInS3AndNotify with the Heimdall instance and pass pathOfPropertyFile and karateOutputPath as parameters. This method pushes the build - information of tests to S3 and notifies the Slack channel of the same. + information of tests to S3 and notifies the same. ### Steps for writing scenarios: diff --git a/heimdall.sample-client/pom.xml b/heimdall.sample-client/pom.xml index ce05186..370bfb1 100644 --- a/heimdall.sample-client/pom.xml +++ b/heimdall.sample-client/pom.xml @@ -2,34 +2,47 @@ - - - com.miqdigital.automation - heimdall - 1.0.1 - - + com.miqdigital.automation + 1.0-SNAPSHOT 4.0.0 heimdall.sample-client + + + 0.9.5 + 0.9.5 + 4.2.0 + 1.3.72 + 1.0.2 + 3.8.1 + + org.apache.maven.plugins maven-compiler-plugin + ${maven-compiler-plugin.version} - 7 - 7 + 8 + 8 + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + compile + process-sources + + compile + + + + - - 0.9.5 - 0.9.5 - 4.2.0 - 1.3.50 - 1.0.1 - diff --git a/heimdall.sample-client/src/test/java/com/miqdigital/cucumber_runner/javasample/CucumberTestRunner.java b/heimdall.sample-client/src/test/java/com/miqdigital/runner/javasample/CucumberTestRunner.java similarity index 80% rename from heimdall.sample-client/src/test/java/com/miqdigital/cucumber_runner/javasample/CucumberTestRunner.java rename to heimdall.sample-client/src/test/java/com/miqdigital/runner/javasample/CucumberTestRunner.java index 627373d..a142cf6 100644 --- a/heimdall.sample-client/src/test/java/com/miqdigital/cucumber_runner/javasample/CucumberTestRunner.java +++ b/heimdall.sample-client/src/test/java/com/miqdigital/runner/javasample/CucumberTestRunner.java @@ -1,11 +1,13 @@ -package com.miqdigital.cucumber_runner.javasample; +package com.miqdigital.runner.javasample; import java.io.IOException; +import javax.mail.MessagingException; + import org.junit.runner.RunWith; import com.miqdigital.Heimdall; -import com.miqdigital.cucumber_runner.ExtendedCucumberRunner; +import com.miqdigital.runner.ExtendedCucumberRunner; import cucumber.api.CucumberOptions; @@ -34,8 +36,9 @@ public class CucumberTestRunner { * @throws IOException the io exception */ public void heimdallReporting() - throws IllegalAccessException, NoSuchFieldException, InterruptedException, IOException { + throws IllegalAccessException, NoSuchFieldException, InterruptedException, IOException, + MessagingException { final Heimdall heimdall = new Heimdall(); - heimdall.updateStatusInS3AndNotifySlack(pathOfPropertyFile, cucumberOutputPath); + heimdall.updateStatusInS3AndNotify(pathOfPropertyFile, cucumberOutputPath); } } diff --git a/heimdall.sample-client/src/test/java/com/miqdigital/cucumber_runner/javasample/KarateTestRunner.java b/heimdall.sample-client/src/test/java/com/miqdigital/runner/javasample/KarateTestRunner.java similarity index 60% rename from heimdall.sample-client/src/test/java/com/miqdigital/cucumber_runner/javasample/KarateTestRunner.java rename to heimdall.sample-client/src/test/java/com/miqdigital/runner/javasample/KarateTestRunner.java index 0bf6c64..da4f4ac 100644 --- a/heimdall.sample-client/src/test/java/com/miqdigital/cucumber_runner/javasample/KarateTestRunner.java +++ b/heimdall.sample-client/src/test/java/com/miqdigital/runner/javasample/KarateTestRunner.java @@ -1,9 +1,11 @@ -package com.miqdigital.cucumber_runner.javasample; +package com.miqdigital.runner.javasample; import static org.junit.Assert.assertEquals; import java.io.IOException; +import javax.mail.MessagingException; + import org.junit.Test; import com.intuit.karate.KarateOptions; @@ -14,13 +16,12 @@ /** * The type Karate test runner. */ -@KarateOptions(features = {"classpath:features/Karate"}, - tags = {"@regression"}) +@KarateOptions public class KarateTestRunner { - private final String pathOfPropertyFile = ""; - private final String karateOutputPath = ""; + private final String pathOfPropertyFile = "src/test/resources/properties/runner.properties"; + private final String karateOutputPath = "target/cucumber-reports"; /** * Heimdall reporting. @@ -32,12 +33,15 @@ public class KarateTestRunner { */ @Test public void heimdallReporting() - throws InterruptedException, NoSuchFieldException, IllegalAccessException, IOException { + throws InterruptedException, NoSuchFieldException, IllegalAccessException, IOException, + MessagingException { - Results results = Runner.path(karateOutputPath).tags("@regression").parallel(10); + Results results = + Runner.path("classpath:features/Karate").reportDir(karateOutputPath).tags("@regression") + .parallel(10); final Heimdall heimdall = new Heimdall(); - heimdall.updateStatusInS3AndNotifySlack(pathOfPropertyFile, karateOutputPath); + heimdall.updateStatusInS3AndNotify(pathOfPropertyFile, karateOutputPath); assertEquals("There are scenario failures", 0, results.getFailCount()); } } diff --git a/heimdall.sample-client/src/test/java/com/miqdigital/cucumber_runner/kotlinesample/KarateTestRunner.kt b/heimdall.sample-client/src/test/java/com/miqdigital/runner/kotlinesample/KarateTestRunner.kt similarity index 79% rename from heimdall.sample-client/src/test/java/com/miqdigital/cucumber_runner/kotlinesample/KarateTestRunner.kt rename to heimdall.sample-client/src/test/java/com/miqdigital/runner/kotlinesample/KarateTestRunner.kt index a7d06ef..11d3358 100644 --- a/heimdall.sample-client/src/test/java/com/miqdigital/cucumber_runner/kotlinesample/KarateTestRunner.kt +++ b/heimdall.sample-client/src/test/java/com/miqdigital/runner/kotlinesample/KarateTestRunner.kt @@ -1,4 +1,4 @@ -package com.miqdigital.cucumber_runner.kotlinesample +package com.miqdigital.runner.kotlinesample import com.intuit.karate.KarateOptions import com.intuit.karate.Results @@ -15,8 +15,8 @@ import java.io.IOException class KarateTestRunner { - private val pathOfPropertyFile = "" - private val karateOutputPath = "" + private val pathOfPropertyFile = "src/test/resources/properties/runner.properties" + private val karateOutputPath = "target/cucumber-reports" /** * Heimdall reporting. @@ -33,7 +33,7 @@ class KarateTestRunner { val results: Results = Runner.path(karateOutputPath).tags("@regression").parallel(10) val heimdall = Heimdall() - heimdall.updateStatusInS3AndNotifySlack(pathOfPropertyFile, karateOutputPath) + heimdall.updateStatusInS3AndNotify(pathOfPropertyFile, karateOutputPath) assertEquals("There are scenario failures", 0, results.failCount.toLong()) } } \ No newline at end of file diff --git a/heimdall.sample-client/src/test/resources/features/Karate/Test.feature b/heimdall.sample-client/src/test/resources/features/Karate/Test.feature index 8a96792..7e59f44 100644 --- a/heimdall.sample-client/src/test/resources/features/Karate/Test.feature +++ b/heimdall.sample-client/src/test/resources/features/Karate/Test.feature @@ -4,14 +4,14 @@ Feature: Test Client Background: * header Content-Type = 'application/json' - @jira_prefix-124 + @S5-124 Scenario: Making Get call Given url 'http://dummy.restapiexample.com/api/v1/employees' When method Get Then status 200 * print response - @jira_prefix-123 + @S5-123 Scenario: Making Post call Given url 'http://dummy.restapiexample.com/api/v1/create' And request {"name":"test09","salary":"123","age":"25"} diff --git a/heimdall.sample-client/src/test/resources/properties/runner.properties b/heimdall.sample-client/src/test/resources/properties/runner.properties index d7bba98..484f5c6 100644 --- a/heimdall.sample-client/src/test/resources/properties/runner.properties +++ b/heimdall.sample-client/src/test/resources/properties/runner.properties @@ -1,5 +1,14 @@ -HEIMDALL_BOT_TOKEN=add slack token -CHANNEL_NAME=add channel name -ISNOTIFYSLACK=true -JIRA_PREFIX=add Jira prefix -S3_BUCKETNAME=S3 bucket name \ No newline at end of file +HEIMDALL_BOT_TOKEN= +CHANNEL_NAME= +NOTIFY_SLACK= +JIRA_PREFIX= +S3_BUCKETNAME= +NOTIFY_EMAIL= +EMAIL_HOST= +SMTP_USERNAME= +SMTP_PASSWORD= +EMAIL_TO= +EMAIL_FROM= +EMAIL_PORT= +EMAIL_SUBJECT= +JENKINS_DOMAIN= \ No newline at end of file diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 1e40994..0000000 --- a/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - 4.0.0 - - com.miqdigital.automation - heimdall - pom - 1.0.1 - - heimdall.application - - - \ No newline at end of file From 0d76992ed48088b404b3b27e6525793b416179e1 Mon Sep 17 00:00:00 2001 From: aakash137 Date: Mon, 29 Jun 2020 03:02:01 +0530 Subject: [PATCH 2/4] Added email support. Removed parent pom. --- heimdall.application/pom.xml | 43 +++++++---- .../main/java/com/miqdigital/Heimdall.java | 11 ++- .../com/miqdigital/dto/BuildResultDto.java | 2 +- .../com/miqdigital/dto/ExecutionInfo.java | 4 +- .../com/miqdigital/dto/NotificationDto.java | 13 ++-- .../java/com/miqdigital/dto/ScenarioInfo.java | 2 +- .../java/com/miqdigital/dto/ScenarioStep.java | 2 +- .../com/miqdigital/runner/AfterSuite.java | 2 +- .../com/miqdigital/runner/BeforeSuite.java | 2 +- .../runner/ExtendedCucumberRunner.java | 2 +- .../services/ExecutionInfoGenerator.java | 15 ++-- .../services/HeimdallReporting.java | 73 +++++++++++-------- .../miqdigital/services/MessageGenerator.java | 25 +++++-- .../miqdigital/utils/AmazonS3Connector.java | 2 +- .../java/com/miqdigital/utils/EmailUtil.java | 37 +++++----- .../com/miqdigital/utils/ReadProperties.java | 17 ++--- .../java/com/miqdigital/utils/SlackUtils.java | 35 +++++---- 17 files changed, 159 insertions(+), 128 deletions(-) diff --git a/heimdall.application/pom.xml b/heimdall.application/pom.xml index 9a70b51..96837e9 100644 --- a/heimdall.application/pom.xml +++ b/heimdall.application/pom.xml @@ -2,26 +2,25 @@ - - com.miqdigital.automation - heimdall - 1.0.1 - + com.miqdigital.automation + heimdall.application + 1.0.2 4.0.0 - heimdall.application - 2.8.0 + 1.5.0-b01 1.18.6 4.3.3 1.7.21 - 3.10.0 - 1.11.368 - 1.11.368 + 5.3.0 + 1.11.729 + 1.11.729 4.2.0 4.2.0 4.2.0 + 3.0.0-M4 + 3.8.1 @@ -35,11 +34,6 @@ aws-java-sdk-s3 ${aws-java-sdk-s3.version} - - com.google.code.gson - gson - ${gson.version} - org.apache.httpcomponents httpmime @@ -60,7 +54,11 @@ cucumber-reporting ${cucumber-reporting.version} - + + javax.mail + mail + ${javax-mail.version} + io.cucumber @@ -77,12 +75,24 @@ cucumber-core ${cucumber-core.version} + + com.fasterxml.jackson.core + jackson-core + 2.11.1 + + + com.fasterxml.jackson.core + jackson-databind + 2.11.1 + + org.apache.maven.plugins maven-compiler-plugin + ${maven-compiler-plugin.version} 8 8 @@ -91,6 +101,7 @@ org.apache.maven.plugins maven-surefire-plugin + ${maven-surefire-plugin.version} ${buildNumber} diff --git a/heimdall.application/src/main/java/com/miqdigital/Heimdall.java b/heimdall.application/src/main/java/com/miqdigital/Heimdall.java index 1105170..505049d 100644 --- a/heimdall.application/src/main/java/com/miqdigital/Heimdall.java +++ b/heimdall.application/src/main/java/com/miqdigital/Heimdall.java @@ -2,7 +2,9 @@ import java.io.IOException; -import com.miqdigital.reporting.HeimdallReporting; +import javax.mail.MessagingException; + +import com.miqdigital.services.HeimdallReporting; /** * This class uses the instance of Heimdall Reporting. @@ -19,11 +21,12 @@ public class Heimdall { * @throws NoSuchFieldException noSuchFieldException * @throws IllegalAccessException illegalAccessException */ - public void updateStatusInS3AndNotifySlack(final String pathOfRunnerPropertiesFile, + public void updateStatusInS3AndNotify(final String pathOfRunnerPropertiesFile, final String executionOutputPath) - throws InterruptedException, IOException, IllegalAccessException, NoSuchFieldException { + throws InterruptedException, IOException, IllegalAccessException, NoSuchFieldException, + MessagingException { this.heimdallReporting = new HeimdallReporting(pathOfRunnerPropertiesFile, executionOutputPath); - heimdallReporting.updateStatusInS3AndNotifySlack(); + heimdallReporting.updateStatusInS3AndNotify(); } /** diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/BuildResultDto.java b/heimdall.application/src/main/java/com/miqdigital/dto/BuildResultDto.java index 47fa0d3..639e3e4 100644 --- a/heimdall.application/src/main/java/com/miqdigital/dto/BuildResultDto.java +++ b/heimdall.application/src/main/java/com/miqdigital/dto/BuildResultDto.java @@ -3,7 +3,7 @@ import lombok.Builder; @Builder -public class ResultDto { +public class BuildResultDto { public StringBuilder testExecutionInfo; public StringBuilder failedTestDescription; public long failedTestCount; diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/ExecutionInfo.java b/heimdall.application/src/main/java/com/miqdigital/dto/ExecutionInfo.java index ecc579a..4c926bb 100644 --- a/heimdall.application/src/main/java/com/miqdigital/dto/ExecutionInfo.java +++ b/heimdall.application/src/main/java/com/miqdigital/dto/ExecutionInfo.java @@ -1,10 +1,8 @@ -package com.miqdigital.execution.dto; +package com.miqdigital.dto; import java.util.Arrays; import java.util.List; -import com.miqdigital.scenario.dto.ScenarioInfo; - import lombok.Builder; @Builder diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/NotificationDto.java b/heimdall.application/src/main/java/com/miqdigital/dto/NotificationDto.java index 6dccb56..6a9012a 100644 --- a/heimdall.application/src/main/java/com/miqdigital/dto/NotificationDto.java +++ b/heimdall.application/src/main/java/com/miqdigital/dto/NotificationDto.java @@ -5,15 +5,18 @@ @Builder @Getter -public class EmailDto { - private final String emailHost; - private final String smtpUsername; - private final String smtpPassword; +public class NotificationDto { + private final String slackChannel; + private final String heimdallBotToken; private final boolean notifySlack; private final boolean notifyEmail; private final String emailTo; private final String emailFrom; - private final String subject; + private final String smtpHost; + private final String smtpPort; + private final String smtpUsername; + private final String smtpPassword; + private final String emailSubject; private final String jenkinsDomain; } diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfo.java b/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfo.java index 87f9dba..068de39 100644 --- a/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfo.java +++ b/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfo.java @@ -1,4 +1,4 @@ -package com.miqdigital.scenario.dto; +package com.miqdigital.dto; import lombok.Builder; import lombok.Getter; diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStep.java b/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStep.java index 52d7a6b..12d0230 100644 --- a/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStep.java +++ b/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStep.java @@ -1,4 +1,4 @@ -package com.miqdigital.scenario.dto; +package com.miqdigital.dto; import lombok.Builder; diff --git a/heimdall.application/src/main/java/com/miqdigital/runner/AfterSuite.java b/heimdall.application/src/main/java/com/miqdigital/runner/AfterSuite.java index ac97c58..5f4d8b1 100644 --- a/heimdall.application/src/main/java/com/miqdigital/runner/AfterSuite.java +++ b/heimdall.application/src/main/java/com/miqdigital/runner/AfterSuite.java @@ -1,4 +1,4 @@ -package com.miqdigital.cucumber_runner; +package com.miqdigital.runner; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/heimdall.application/src/main/java/com/miqdigital/runner/BeforeSuite.java b/heimdall.application/src/main/java/com/miqdigital/runner/BeforeSuite.java index 597c723..c23c8df 100644 --- a/heimdall.application/src/main/java/com/miqdigital/runner/BeforeSuite.java +++ b/heimdall.application/src/main/java/com/miqdigital/runner/BeforeSuite.java @@ -1,4 +1,4 @@ -package com.miqdigital.cucumber_runner; +package com.miqdigital.runner; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/heimdall.application/src/main/java/com/miqdigital/runner/ExtendedCucumberRunner.java b/heimdall.application/src/main/java/com/miqdigital/runner/ExtendedCucumberRunner.java index 1341cbc..f3cf4dc 100644 --- a/heimdall.application/src/main/java/com/miqdigital/runner/ExtendedCucumberRunner.java +++ b/heimdall.application/src/main/java/com/miqdigital/runner/ExtendedCucumberRunner.java @@ -1,4 +1,4 @@ -package com.miqdigital.cucumber_runner; +package com.miqdigital.runner; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; diff --git a/heimdall.application/src/main/java/com/miqdigital/services/ExecutionInfoGenerator.java b/heimdall.application/src/main/java/com/miqdigital/services/ExecutionInfoGenerator.java index e6ab96d..b56c50e 100644 --- a/heimdall.application/src/main/java/com/miqdigital/services/ExecutionInfoGenerator.java +++ b/heimdall.application/src/main/java/com/miqdigital/services/ExecutionInfoGenerator.java @@ -1,4 +1,4 @@ -package com.miqdigital.execution; +package com.miqdigital.services; import java.io.File; import java.lang.reflect.Field; @@ -14,9 +14,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.miqdigital.execution.dto.ExecutionInfo; -import com.miqdigital.scenario.dto.ScenarioInfo; -import com.miqdigital.scenario.dto.ScenarioStep; +import com.miqdigital.dto.ExecutionInfo; +import com.miqdigital.dto.ScenarioInfo; +import com.miqdigital.dto.ScenarioStep; import com.miqdigital.utils.ReadProperties; import net.masterthought.cucumber.Configuration; @@ -50,15 +50,15 @@ public ExecutionInfo getBuildExecutionDetails(final ReadProperties readPropertie /** * Gets the list of all scenario tags. * - * @param cucumberOutputPath pass cucumber result output path e.g target/cucumber-html-reports + * @param executionOutputPath pass cucumber result output path e.g target/cucumber-html-reports * @return lis of all cucumber tags * @throws NoSuchFieldException noSuchFieldException * @throws IllegalAccessException illegalAccessException */ - private List getListOfTags(final String cucumberOutputPath) + private List getListOfTags(final String executionOutputPath) throws NoSuchFieldException, IllegalAccessException { final Collection jsonFiles = - FileUtils.listFiles(new File(cucumberOutputPath), new String[] {"json"}, true); + FileUtils.listFiles(new File(executionOutputPath), new String[] {"json"}, true); final List jsonPaths = new ArrayList<>(jsonFiles.size()); jsonFiles.forEach(file -> jsonPaths.add(file.getAbsolutePath())); final Configuration config = new Configuration(new File("target"), "demo"); @@ -82,7 +82,6 @@ private List parseAnnotations(final List alltags, final String projectJiraPrefix) { final List scenarioInfoList = new LinkedList<>(); for (final TagObject tag : alltags) { - LOGGER.info("Parsing tags: {}", tag.getName()); if (tag.getScenarios() >= 1) { final ScenarioInfo.ScenarioInfoBuilder scenarioInfoBuilder = ScenarioInfo.builder().scenarioTagId(tag.getName()).scenarioTotalSteps(tag.getSteps()) diff --git a/heimdall.application/src/main/java/com/miqdigital/services/HeimdallReporting.java b/heimdall.application/src/main/java/com/miqdigital/services/HeimdallReporting.java index 4e0d907..5a95d7a 100644 --- a/heimdall.application/src/main/java/com/miqdigital/services/HeimdallReporting.java +++ b/heimdall.application/src/main/java/com/miqdigital/services/HeimdallReporting.java @@ -1,4 +1,4 @@ -package com.miqdigital.reporting; +package com.miqdigital.services; import java.io.FileNotFoundException; import java.io.FileWriter; @@ -11,14 +11,14 @@ import org.slf4j.LoggerFactory; import com.amazonaws.util.StringUtils; -import com.google.gson.Gson; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import com.miqdigital.utils.AmazonS3Connector; import com.miqdigital.dto.NotificationDto; -import com.miqdigital.execution.ExecutionInfoGenerator; -import com.miqdigital.execution.dto.ExecutionInfo; -import com.miqdigital.slack.MessageGenerator; -import com.miqdigital.slack.SlackUtils; -import com.miqdigital.dto.ResultDto; +import com.miqdigital.dto.ExecutionInfo; +import com.miqdigital.utils.SlackUtils; +import com.miqdigital.dto.BuildResultDto; import com.miqdigital.utils.EmailUtil; import com.miqdigital.utils.ReadProperties; @@ -30,6 +30,7 @@ public class HeimdallReporting { private static final Logger LOGGER = LoggerFactory.getLogger(HeimdallReporting.class); + private ReadProperties properties; private String executionOutputPath; @@ -47,52 +48,61 @@ public HeimdallReporting(final String pathOfRunnerPropertiesFile, /** * Sends the notification on the Slack channel. - * @param executionInfo Jenkins build execution info + * + * @param executionInfo Jenkins build execution info * @param notificationDto slack channel info from client */ private static void sendSlackNotification(final ExecutionInfo executionInfo, final NotificationDto notificationDto) throws IOException { - final ResultDto resultDto = MessageGenerator.getBuildResult(executionInfo,notificationDto); + final BuildResultDto buildResultDto = + MessageGenerator.getBuildResult(executionInfo, notificationDto); SlackUtils slackUtils = new SlackUtils(); - slackUtils.sendSlackNotification(notificationDto, resultDto); + slackUtils.sendSlackNotification(notificationDto, buildResultDto); + LOGGER.info("Slack Notification Sent"); + } /** * Sends Email notification. + * * @param executionInfo * @param notificationDto */ private static void sendEmailNotification(ExecutionInfo executionInfo, NotificationDto notificationDto) throws MessagingException, IOException { - final ResultDto resultDto = MessageGenerator.getBuildResult(executionInfo, notificationDto); + final BuildResultDto buildResultDto = + MessageGenerator.getBuildResult(executionInfo, notificationDto); + + EmailUtil.sendEmail(notificationDto, buildResultDto); + LOGGER.info("Email Sent"); - EmailUtil.sendEmail(notificationDto, resultDto); } /** * Pushes to S3 only if jenkins buildNumber is present. * - * @param bucketName pass the S3 bucketName + * @param bucketName pass the S3 bucketName * @param executionInfo test execution info */ private void pushResultToS3(final String bucketName, final ExecutionInfo executionInfo) throws IOException, InterruptedException { - LOGGER.info("Execution Result {}", executionInfo); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); if (Objects.nonNull(executionInfo.BuildNumber)) { - final Gson gson = new Gson(); final String outputReportPath = System.getProperty("user.dir") + "/target/" + executionInfo.BuildNumber + ".json"; try (final FileWriter writer = new FileWriter(outputReportPath)) { - gson.toJson(executionInfo, writer); + objectMapper.writeValue(writer, executionInfo); } final AmazonS3Connector amazonS3Connector = new AmazonS3Connector.Builder().build(); final String prefix = executionInfo.BuildName + "/" + executionInfo.BuildNumber + ".json"; amazonS3Connector.uploadFile(outputReportPath, bucketName, prefix); } else { - LOGGER.error("Build number is null, not pushing build result to S3"); + LOGGER.info("Build number is null, not pushing build result to S3"); } } @@ -100,9 +110,9 @@ private void pushResultToS3(final String bucketName, final ExecutionInfo executi * Updates the execution result status in S3. * * @throws IllegalAccessException illegalAccessException - * @throws NoSuchFieldException noSuchFieldException - * @throws IOException inputOutputException - * @throws InterruptedException interruptedException + * @throws NoSuchFieldException noSuchFieldException + * @throws IOException inputOutputException + * @throws InterruptedException interruptedException */ public void updateStatusInS3() throws IllegalAccessException, NoSuchFieldException, IOException, InterruptedException { @@ -116,7 +126,7 @@ public void updateStatusInS3() /** * Generates the execution info and pushes the results to S3 and notifies on the Slack channel. * - * @throws NoSuchFieldException noSuchFieldException + * @throws NoSuchFieldException noSuchFieldException * @throws IllegalAccessException illegalAccessException */ public void updateStatusInS3AndNotify() @@ -131,22 +141,21 @@ public void updateStatusInS3AndNotify() throw new NullPointerException( "Please specify Channel name and Slack bot token in runner properties file"); } - final NotificationDto notificationDto = NotificationDto.builder().emailHost(properties.getEmailHost()) - .slackChannel(properties.getChannelName()) - .slackToken(properties.getHeimdallBotToken()) - .notifySlack(properties.isNotifySlack()) - .smtpUsername(properties.getSmtpUsername()) - .smtpPassword(properties.getSmtpPassword()) - .notifyEmail(properties.isNotifyEmail()) - .emailFrom(properties.getEmailFrom()) - .emailTo(properties.getEmailTo()) - .jenkinsDomain(properties.getJenkinsDomain()).build(); + final NotificationDto notificationDto = + NotificationDto.builder().smtpHost(properties.getSmtpHost()) + .slackChannel(properties.getChannelName()) + .heimdallBotToken(properties.getHeimdallBotToken()) + .notifySlack(properties.isNotifySlack()).smtpUsername(properties.getSmtpUsername()) + .smtpPassword(properties.getSmtpPassword()).notifyEmail(properties.isNotifyEmail()) + .emailSubject(properties.getEmailSubject()).emailFrom(properties.getEmailFrom()) + .emailTo(properties.getEmailTo()).smtpPort(properties.getSmtpPort()) + .jenkinsDomain(properties.getJenkinsDomain()).build(); LOGGER.info("Execution info generated Successfully"); if (notificationDto.isNotifySlack()) { sendSlackNotification(executionInfo, notificationDto); } - if(notificationDto.isNotifyEmail()){ + if (notificationDto.isNotifyEmail()) { sendEmailNotification(executionInfo, notificationDto); } pushResultToS3(properties.getS3BucketName(), executionInfo); diff --git a/heimdall.application/src/main/java/com/miqdigital/services/MessageGenerator.java b/heimdall.application/src/main/java/com/miqdigital/services/MessageGenerator.java index ca1273d..068124a 100644 --- a/heimdall.application/src/main/java/com/miqdigital/services/MessageGenerator.java +++ b/heimdall.application/src/main/java/com/miqdigital/services/MessageGenerator.java @@ -1,13 +1,13 @@ -package com.miqdigital.slack; +package com.miqdigital.services; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import com.miqdigital.dto.NotificationDto; -import com.miqdigital.execution.dto.ExecutionInfo; -import com.miqdigital.scenario.dto.ScenarioInfo; -import com.miqdigital.dto.ResultDto; +import com.miqdigital.dto.ExecutionInfo; +import com.miqdigital.dto.ScenarioInfo; +import com.miqdigital.dto.BuildResultDto; /** * This class builds the Slack message and the failed test scenarios report, if any. @@ -15,6 +15,14 @@ public class MessageGenerator { + private MessageGenerator() { + } + + public static BuildResultDto getBuildResult(final ExecutionInfo executionInfo, + NotificationDto notificationDto) { + return getBuildResponse(executionInfo, notificationDto); + } + /** * Sends the build notification to the Slack channel. * @@ -22,7 +30,7 @@ public class MessageGenerator { * @param notificationDto * @return slack notification info */ - public static ResultDto getBuildResult(final ExecutionInfo executionInfo, + private static BuildResultDto getBuildResponse(final ExecutionInfo executionInfo, NotificationDto notificationDto) { final StringBuilder testExecutionInfo = new StringBuilder(); StringBuilder failedTestsInfo = new StringBuilder(); @@ -41,12 +49,13 @@ public static ResultDto getBuildResult(final ExecutionInfo executionInfo, if (Objects.nonNull(executionInfo.BuildNumber) && Objects .nonNull(System.getProperty("viewName"))) { + String jenkinsJobUrl = notificationDto.getJenkinsDomain() + "/view/%s/job/%s/%s/console"; testExecutionInfo.append("\n").append("*Console out:* ").append(String - .format(notificationDto.getJenkinsDomain() + "/view/%s/job/%s/%s/console", - System.getProperty("viewName"), executionInfo.BuildName, executionInfo.BuildNumber)); + .format(jenkinsJobUrl, System.getProperty("viewName"), executionInfo.BuildName, + executionInfo.BuildNumber)); } - return ResultDto.builder().testExecutionInfo(testExecutionInfo) + return BuildResultDto.builder().testExecutionInfo(testExecutionInfo) .failedTestDescription(failedTestsInfo).failedTestCount(executionInfo.failTestCount) .build(); } diff --git a/heimdall.application/src/main/java/com/miqdigital/utils/AmazonS3Connector.java b/heimdall.application/src/main/java/com/miqdigital/utils/AmazonS3Connector.java index aba7233..39ae5ed 100644 --- a/heimdall.application/src/main/java/com/miqdigital/utils/AmazonS3Connector.java +++ b/heimdall.application/src/main/java/com/miqdigital/utils/AmazonS3Connector.java @@ -1,4 +1,4 @@ -package com.miqdigital.connector; +package com.miqdigital.utils; import java.io.File; diff --git a/heimdall.application/src/main/java/com/miqdigital/utils/EmailUtil.java b/heimdall.application/src/main/java/com/miqdigital/utils/EmailUtil.java index d9854d3..acf4d3d 100644 --- a/heimdall.application/src/main/java/com/miqdigital/utils/EmailUtil.java +++ b/heimdall.application/src/main/java/com/miqdigital/utils/EmailUtil.java @@ -1,4 +1,4 @@ -package com.miqdigital.utility; +package com.miqdigital.utils; import java.io.File; import java.io.IOException; @@ -18,50 +18,54 @@ import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; -import com.miqdigital.dto.EmailDto; -import com.miqdigital.dto.ResultDto; +import com.miqdigital.dto.NotificationDto; +import com.miqdigital.dto.BuildResultDto; + public class EmailUtil { + private EmailUtil(){} + private static final String ATTACHMENT_FILE_NAME = "./target/FailedTestsInfo.txt"; /** * Creating an email body and sending the email. - * @param emailDto - * @param resultDto + * @param notificationDto + * @param buildResultDto * @throws MessagingException * @throws IOException */ - public static void sendEmail(EmailDto emailDto, ResultDto resultDto) + public static void sendEmail(NotificationDto notificationDto, BuildResultDto buildResultDto) throws MessagingException, IOException { - String msg = resultDto.testExecutionInfo.toString(); + String msg = buildResultDto.testExecutionInfo.toString(); Properties prop = new Properties(); prop.put("mail.smtp.auth", true); prop.put("mail.smtp.starttls.enable", "true"); - prop.put("mail.smtp.host", emailDto.getEmailHost()); - prop.put("mail.smtp.port", emailDto.getEmailHost()); - prop.put("mail.smtp.ssl.trust", "smtp.mailtrap.io"); + prop.put("mail.smtp.host", notificationDto.getSmtpHost()); + prop.put("mail.smtp.port", notificationDto.getSmtpPort()); + prop.put("mail.smtp.ssl.trust", notificationDto.getSmtpHost()); Session session = Session.getInstance(prop, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(emailDto.getSmtpUsername(), emailDto.getSmtpPassword()); + return new PasswordAuthentication(notificationDto.getSmtpUsername(), notificationDto.getSmtpPassword()); } }); + String failedTestDescription = buildResultDto.failedTestDescription.toString(); final String generatedFileName = Files.write(Paths.get(ATTACHMENT_FILE_NAME), - resultDto.failedTestDescription.toString().getBytes()).normalize().toAbsolutePath() + failedTestDescription.getBytes()).normalize().toAbsolutePath() .toString(); Message message = new MimeMessage(session); - message.setFrom(new InternetAddress(emailDto.getEmailFrom())); - message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(emailDto.getEmailTo())); - message.setSubject(emailDto.getSubject()); + message.setFrom(new InternetAddress(notificationDto.getEmailFrom())); + message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(notificationDto.getEmailTo())); + message.setSubject(notificationDto.getEmailSubject()); MimeBodyPart attachmentBodyPart = new MimeBodyPart(); attachmentBodyPart.attachFile(new File(generatedFileName)); MimeBodyPart mimeBodyPart = new MimeBodyPart(); - mimeBodyPart.setContent(msg, "text/html"); + mimeBodyPart.setContent(msg.replace("\n","
"), "text/html"); Multipart multipart = new MimeMultipart(); multipart.addBodyPart(mimeBodyPart); @@ -70,7 +74,6 @@ protected PasswordAuthentication getPasswordAuthentication() { message.setContent(multipart); Transport.send(message); - } } diff --git a/heimdall.application/src/main/java/com/miqdigital/utils/ReadProperties.java b/heimdall.application/src/main/java/com/miqdigital/utils/ReadProperties.java index badc242..b7878f8 100644 --- a/heimdall.application/src/main/java/com/miqdigital/utils/ReadProperties.java +++ b/heimdall.application/src/main/java/com/miqdigital/utils/ReadProperties.java @@ -1,12 +1,10 @@ -package com.miqdigital.utility; +package com.miqdigital.utils; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import lombok.Getter; @@ -16,11 +14,6 @@ @Getter public class ReadProperties { - /** - * Logger. - */ - private static final Logger LOGGER = LoggerFactory.getLogger(ReadProperties.class); - /** * The constant heimdallBotToken. */ @@ -48,7 +41,7 @@ public class ReadProperties { /** * The constant emailPort. */ - private String emailPort; + private String smtpPort; /** * The constant emailSubject. */ @@ -65,7 +58,7 @@ public class ReadProperties { /** * The host to use while sending email. */ - private String emailHost; + private String smtpHost; /** * The SMTP username. */ @@ -101,13 +94,13 @@ private void initFields() { heimdallBotToken = properties.getProperty("HEIMDALL_BOT_TOKEN"); jiraPrefix = properties.getProperty("JIRA_PREFIX"); s3BucketName = properties.getProperty("S3_BUCKETNAME"); - emailHost = properties.getProperty("EMAIL_HOST"); + smtpHost = properties.getProperty("EMAIL_HOST"); smtpUsername = properties.getProperty("SMTP_USERNAME"); smtpPassword = properties.getProperty("SMTP_PASSWORD"); notifyEmail = Boolean.parseBoolean(properties.getProperty("NOTIFY_EMAIL")); emailTo = properties.getProperty("EMAIL_TO"); emailFrom = properties.getProperty("EMAIL_FROM"); - emailPort = properties.getProperty("EMAIL_PORT"); + smtpPort = properties.getProperty("EMAIL_PORT"); emailSubject = properties.getProperty("EMAIL_SUBJECT"); jenkinsDomain = properties.getProperty("JENKINS_DOMAIN"); } diff --git a/heimdall.application/src/main/java/com/miqdigital/utils/SlackUtils.java b/heimdall.application/src/main/java/com/miqdigital/utils/SlackUtils.java index 924f72f..2bf468c 100644 --- a/heimdall.application/src/main/java/com/miqdigital/utils/SlackUtils.java +++ b/heimdall.application/src/main/java/com/miqdigital/utils/SlackUtils.java @@ -1,4 +1,4 @@ -package com.miqdigital.slack; +package com.miqdigital.utils; import java.io.File; import java.io.IOException; @@ -14,13 +14,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import com.miqdigital.dto.NotificationDto; -import com.miqdigital.dto.ResultDto; +import com.miqdigital.dto.BuildResultDto; /** * This class is used to post Slack notification on provided channel. */ - public class SlackUtils { private static final Logger logger = LoggerFactory.getLogger(SlackUtils.class); @@ -32,16 +32,16 @@ public class SlackUtils { * Makes Http post request to Slack to send the notification and upload the failed scenarios file. * * @param notificationDto slack channel details and token - * @param resultDto slack notification + * @param buildResultDto slack notification */ public void sendSlackNotification(final NotificationDto notificationDto, - final ResultDto resultDto) throws IOException { + final BuildResultDto buildResultDto) throws IOException { final HttpClient httpclient = HttpClientBuilder.create().disableContentCompression().build(); - final HttpPost httpPost = resultDto.failedTestCount == 0 ? + final HttpPost httpPost = buildResultDto.failedTestCount == 0 ? new HttpPost(CHAT_POST_URL) : new HttpPost(FILE_UPLOAD_URL); - final HttpEntity httpEntity = getHttpRequestEntity(notificationDto, resultDto).build(); + final HttpEntity httpEntity = getHttpRequestEntity(notificationDto, buildResultDto).build(); httpPost.setEntity(httpEntity); final HttpResponse execute = httpclient.execute(httpPost); logger.info(execute.getStatusLine().getReasonPhrase()); @@ -51,27 +51,30 @@ public void sendSlackNotification(final NotificationDto notificationDto, * Configures the Http request for Slack. * * @param notificationDto - * @param resultDto + * @param buildResultDto * @return * @throws IOException */ public MultipartEntityBuilder getHttpRequestEntity(final NotificationDto notificationDto, - final ResultDto resultDto) throws IOException { + final BuildResultDto buildResultDto) throws IOException { final MultipartEntityBuilder reqEntity = - MultipartEntityBuilder.create().addTextBody("token", notificationDto.getSlackToken()); - if (resultDto.failedTestCount == 0) { + MultipartEntityBuilder.create().addTextBody("token", notificationDto.getHeimdallBotToken()); + if (buildResultDto.failedTestCount == 0) { //soft slack notification - reqEntity.addTextBody("channel", notificationDto.getSlackChannel()) - .addTextBody("as_user", "true") - .addTextBody("text", resultDto.testExecutionInfo.toString()); + final String generatedFileName = Files.write(Paths.get(ATTACHMENT_FILE_NAME), + buildResultDto.failedTestDescription.toString().getBytes()).normalize().toAbsolutePath() + .toString(); + reqEntity.addBinaryBody("file", new File(generatedFileName)) + .addTextBody("channels", notificationDto.getSlackChannel()).addTextBody("media", "file") + .addTextBody("initial_comment", " " + buildResultDto.testExecutionInfo.toString()); } else { //slack notification with @here final String generatedFileName = Files.write(Paths.get(ATTACHMENT_FILE_NAME), - resultDto.failedTestDescription.toString().getBytes()).normalize().toAbsolutePath() + buildResultDto.failedTestDescription.toString().getBytes()).normalize().toAbsolutePath() .toString(); reqEntity.addBinaryBody("file", new File(generatedFileName)) .addTextBody("channels", notificationDto.getSlackChannel()).addTextBody("media", "file") - .addTextBody("initial_comment", " " + resultDto.testExecutionInfo.toString()); + .addTextBody("initial_comment", " " + buildResultDto.testExecutionInfo.toString()); } return reqEntity; } From cb497f9dccdee2c4e6a1df6644f856d9d88d6a0f Mon Sep 17 00:00:00 2001 From: aakash137 Date: Mon, 29 Jun 2020 03:10:37 +0530 Subject: [PATCH 3/4] Fixed test scenarios. --- .../src/test/resources/features/Karate/Test.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/heimdall.sample-client/src/test/resources/features/Karate/Test.feature b/heimdall.sample-client/src/test/resources/features/Karate/Test.feature index 7e59f44..8a96792 100644 --- a/heimdall.sample-client/src/test/resources/features/Karate/Test.feature +++ b/heimdall.sample-client/src/test/resources/features/Karate/Test.feature @@ -4,14 +4,14 @@ Feature: Test Client Background: * header Content-Type = 'application/json' - @S5-124 + @jira_prefix-124 Scenario: Making Get call Given url 'http://dummy.restapiexample.com/api/v1/employees' When method Get Then status 200 * print response - @S5-123 + @jira_prefix-123 Scenario: Making Post call Given url 'http://dummy.restapiexample.com/api/v1/create' And request {"name":"test09","salary":"123","age":"25"} From a463e6a6b77667a3b95d3d013b1ed85ede83e30d Mon Sep 17 00:00:00 2001 From: aakash137 Date: Sun, 12 Jul 2020 13:54:05 +0530 Subject: [PATCH 4/4] Rearranged packages. --- heimdall.application/pom.xml | 13 +-- .../{NotificationDto.java => EmailDto.java} | 6 +- ...ecutionInfo.java => ExecutionInfoDto.java} | 10 +- .../java/com/miqdigital/dto/ScenarioInfo.java | 17 ---- .../com/miqdigital/dto/ScenarioInfoDto.java | 17 ++++ .../java/com/miqdigital/dto/ScenarioStep.java | 10 -- .../com/miqdigital/dto/ScenarioStepDto.java | 10 ++ .../java/com/miqdigital/dto/SlackDto.java | 12 +++ .../services/ExecutionInfoGenerator.java | 51 +++++----- .../services/HeimdallReporting.java | 93 ++++++++++--------- .../miqdigital/services/MessageGenerator.java | 68 +++++++------- .../java/com/miqdigital/utils/EmailUtil.java | 34 +++---- .../java/com/miqdigital/utils/SlackUtils.java | 31 +++---- 13 files changed, 188 insertions(+), 184 deletions(-) rename heimdall.application/src/main/java/com/miqdigital/dto/{NotificationDto.java => EmailDto.java} (67%) rename heimdall.application/src/main/java/com/miqdigital/dto/{ExecutionInfo.java => ExecutionInfoDto.java} (69%) delete mode 100644 heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfo.java create mode 100644 heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfoDto.java delete mode 100644 heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStep.java create mode 100644 heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStepDto.java create mode 100644 heimdall.application/src/main/java/com/miqdigital/dto/SlackDto.java diff --git a/heimdall.application/pom.xml b/heimdall.application/pom.xml index 96837e9..a67c688 100644 --- a/heimdall.application/pom.xml +++ b/heimdall.application/pom.xml @@ -10,17 +10,18 @@ 1.5.0-b01 - 1.18.6 - 4.3.3 + 1.18.12 + 4.5.12 1.7.21 5.3.0 1.11.729 1.11.729 - 4.2.0 + 6.0.0-RC2 4.2.0 - 4.2.0 + 6.0.0-RC2 3.0.0-M4 3.8.1 + 2.11.1 @@ -78,12 +79,12 @@ com.fasterxml.jackson.core jackson-core - 2.11.1 + ${jackson.version} com.fasterxml.jackson.core jackson-databind - 2.11.1 + ${jackson.version} diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/NotificationDto.java b/heimdall.application/src/main/java/com/miqdigital/dto/EmailDto.java similarity index 67% rename from heimdall.application/src/main/java/com/miqdigital/dto/NotificationDto.java rename to heimdall.application/src/main/java/com/miqdigital/dto/EmailDto.java index 6a9012a..d21b2b3 100644 --- a/heimdall.application/src/main/java/com/miqdigital/dto/NotificationDto.java +++ b/heimdall.application/src/main/java/com/miqdigital/dto/EmailDto.java @@ -5,10 +5,7 @@ @Builder @Getter -public class NotificationDto { - private final String slackChannel; - private final String heimdallBotToken; - private final boolean notifySlack; +public class EmailDto { private final boolean notifyEmail; private final String emailTo; private final String emailFrom; @@ -17,6 +14,5 @@ public class NotificationDto { private final String smtpUsername; private final String smtpPassword; private final String emailSubject; - private final String jenkinsDomain; } diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/ExecutionInfo.java b/heimdall.application/src/main/java/com/miqdigital/dto/ExecutionInfoDto.java similarity index 69% rename from heimdall.application/src/main/java/com/miqdigital/dto/ExecutionInfo.java rename to heimdall.application/src/main/java/com/miqdigital/dto/ExecutionInfoDto.java index 4c926bb..ab2b564 100644 --- a/heimdall.application/src/main/java/com/miqdigital/dto/ExecutionInfo.java +++ b/heimdall.application/src/main/java/com/miqdigital/dto/ExecutionInfoDto.java @@ -6,7 +6,7 @@ import lombok.Builder; @Builder -public class ExecutionInfo { +public class ExecutionInfoDto { public String environment; public String testType; public String dateTime; @@ -15,14 +15,14 @@ public class ExecutionInfo { public long failTestCount; public String BuildName; public String BuildNumber; - public List scenarioInfoList; + public List scenarioInfoDtoList; @Override public String toString() { - return "ExecutionInfo{" + "environment='" + environment + '\'' + ", testType='" + testType + return "ExecutionInfoDto{" + "environment='" + environment + '\'' + ", testType='" + testType + '\'' + ", dateTime='" + dateTime + '\'' + ", totalTests=" + totalTests + ", passTestCount=" + passTestCount + ", failTestCount=" + failTestCount + ", BuildName='" - + BuildName + '\'' + ", BuildNumber='" + BuildNumber + '\'' + ", scenarioInfoList=" + Arrays - .toString(scenarioInfoList.toArray()) + '}'; + + BuildName + '\'' + ", BuildNumber='" + BuildNumber + '\'' + ", scenarioInfoDtoList=" + + Arrays.toString(scenarioInfoDtoList.toArray()) + '}'; } } diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfo.java b/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfo.java deleted file mode 100644 index 068de39..0000000 --- a/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfo.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.miqdigital.dto; - -import lombok.Builder; -import lombok.Getter; - -@Builder -@Getter -public class ScenarioInfo { - private String scenarioTagId; - private String scenarioName; - private String scenarioStatus; - private String scenarioTotalDuration; - private int scenarioTotalSteps; - private String featureDescription; - private String featureFile; - private ScenarioStep scenarioStep; -} \ No newline at end of file diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfoDto.java b/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfoDto.java new file mode 100644 index 0000000..60a2324 --- /dev/null +++ b/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioInfoDto.java @@ -0,0 +1,17 @@ +package com.miqdigital.dto; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class ScenarioInfoDto { + private final String scenarioTagId; + private final String scenarioName; + private final String scenarioStatus; + private final String scenarioTotalDuration; + private final int scenarioTotalSteps; + private final String featureDescription; + private final String featureFile; + private final ScenarioStepDto scenarioStepDto; +} \ No newline at end of file diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStep.java b/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStep.java deleted file mode 100644 index 12d0230..0000000 --- a/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStep.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.miqdigital.dto; - -import lombok.Builder; - -@Builder -public class ScenarioStep { - private String errMessage; - private String stepDuration; - private String scenarioLine; -} \ No newline at end of file diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStepDto.java b/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStepDto.java new file mode 100644 index 0000000..3af19a9 --- /dev/null +++ b/heimdall.application/src/main/java/com/miqdigital/dto/ScenarioStepDto.java @@ -0,0 +1,10 @@ +package com.miqdigital.dto; + +import lombok.Builder; + +@Builder +public class ScenarioStepDto { + private final String errMessage; + private final String stepDuration; + private final String scenarioLine; +} \ No newline at end of file diff --git a/heimdall.application/src/main/java/com/miqdigital/dto/SlackDto.java b/heimdall.application/src/main/java/com/miqdigital/dto/SlackDto.java new file mode 100644 index 0000000..9f48ea6 --- /dev/null +++ b/heimdall.application/src/main/java/com/miqdigital/dto/SlackDto.java @@ -0,0 +1,12 @@ +package com.miqdigital.dto; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class SlackDto { + private final String slackChannel; + private final String heimdallBotToken; + private final boolean notifySlack; +} diff --git a/heimdall.application/src/main/java/com/miqdigital/services/ExecutionInfoGenerator.java b/heimdall.application/src/main/java/com/miqdigital/services/ExecutionInfoGenerator.java index b56c50e..b5e694e 100644 --- a/heimdall.application/src/main/java/com/miqdigital/services/ExecutionInfoGenerator.java +++ b/heimdall.application/src/main/java/com/miqdigital/services/ExecutionInfoGenerator.java @@ -14,9 +14,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.miqdigital.dto.ExecutionInfo; -import com.miqdigital.dto.ScenarioInfo; -import com.miqdigital.dto.ScenarioStep; +import com.miqdigital.dto.ExecutionInfoDto; +import com.miqdigital.dto.ScenarioInfoDto; +import com.miqdigital.dto.ScenarioStepDto; import com.miqdigital.utils.ReadProperties; import net.masterthought.cucumber.Configuration; @@ -40,7 +40,7 @@ public class ExecutionInfoGenerator { * @throws IllegalAccessException * @throws NoSuchFieldException */ - public ExecutionInfo getBuildExecutionDetails(final ReadProperties readProperties, + public ExecutionInfoDto getBuildExecutionDetails(final ReadProperties readProperties, final String executionOutputPath) throws IllegalAccessException, NoSuchFieldException { final List listOfTags = getListOfTags(executionOutputPath); LOGGER.info("Tags generated Successfully"); @@ -74,17 +74,18 @@ private List getListOfTags(final String executionOutputPath) /** * Method to parse cucumber annotation no project level. * - * @param alltags list of all cucumber tags + * @param alltags list of all cucumber tags * @param projectJiraPrefix project jira prifix JA, JC * @return list of scenation info */ - private List parseAnnotations(final List alltags, + private List parseAnnotations(final List alltags, final String projectJiraPrefix) { - final List scenarioInfoList = new LinkedList<>(); + final List scenarioInfoDtoList = new LinkedList<>(); for (final TagObject tag : alltags) { if (tag.getScenarios() >= 1) { - final ScenarioInfo.ScenarioInfoBuilder scenarioInfoBuilder = - ScenarioInfo.builder().scenarioTagId(tag.getName()).scenarioTotalSteps(tag.getSteps()) + final ScenarioInfoDto.ScenarioInfoDtoBuilder scenarioInfoBuilder = + ScenarioInfoDto.builder().scenarioTagId(tag.getName()) + .scenarioTotalSteps(tag.getSteps()) .scenarioTotalDuration(tag.getFormattedDuration()); final net.masterthought.cucumber.json.Element element = tag.getElements().get(0); @@ -93,25 +94,25 @@ private List parseAnnotations(final List alltags, .featureFile(element.getFeature().getReportFileName()) .scenarioStatus(tag.getStatus().toString()); if (!tag.getStatus().isPassed()) { - final ScenarioStep scenarioStep = parseFailedTag(tag); - scenarioInfoBuilder.scenarioStep(scenarioStep); + final ScenarioStepDto scenarioStepDto = parseFailedTag(tag); + scenarioInfoBuilder.scenarioStepDto(scenarioStepDto); } - final ScenarioInfo scenarioInfo = scenarioInfoBuilder.build(); - scenarioInfoList.add(scenarioInfo); + final ScenarioInfoDto scenarioInfoDto = scenarioInfoBuilder.build(); + scenarioInfoDtoList.add(scenarioInfoDto); } } - return scenarioInfoList.stream().filter(f -> f.getScenarioTagId().contains(projectJiraPrefix)) - .collect(Collectors.toList()); + return scenarioInfoDtoList.stream() + .filter(f -> f.getScenarioTagId().contains(projectJiraPrefix)).collect(Collectors.toList()); } /** - * Method to create ScenarioStep in case of scenario failure. + * Method to create ScenarioStepDto in case of scenario failure. * * @param tag Tagobject for which scenario failed * @return Scenario Step */ - private ScenarioStep parseFailedTag(final TagObject tag) { - final ScenarioStep.ScenarioStepBuilder scenarioStepBuilder = ScenarioStep.builder(); + private ScenarioStepDto parseFailedTag(final TagObject tag) { + final ScenarioStepDto.ScenarioStepDtoBuilder scenarioStepBuilder = ScenarioStepDto.builder(); Arrays.stream(tag.getElements().get(0).getSteps()) .filter(s -> !s.getResult().getStatus().isPassed()).peek( f -> scenarioStepBuilder.errMessage(f.getResult().getErrorMessage()) @@ -126,19 +127,19 @@ private ScenarioStep parseFailedTag(final TagObject tag) { * @param alltags List of all the tags present in a feature file * @param readProperties readProperties */ - private ExecutionInfo getBuildDetails(final List alltags, + private ExecutionInfoDto getBuildDetails(final List alltags, final ReadProperties readProperties) { - final List scenarioInfoList = + final List scenarioInfoDtoList = parseAnnotations(alltags, readProperties.getJiraPrefix()); final long passedTestCount = - scenarioInfoList.stream().filter(r -> r.getScenarioStatus().equals("PASSED")).count(); + scenarioInfoDtoList.stream().filter(r -> r.getScenarioStatus().equals("PASSED")).count(); final long failedTestCount = - scenarioInfoList.stream().filter(r -> r.getScenarioStatus().equals("FAILED")).count(); + scenarioInfoDtoList.stream().filter(r -> r.getScenarioStatus().equals("FAILED")).count(); - return ExecutionInfo.builder().environment(System.getProperty("environment")) + return ExecutionInfoDto.builder().environment(System.getProperty("environment")) .testType(System.getProperty("tags")).dateTime(LocalDateTime.now().toString()) - .scenarioInfoList(scenarioInfoList).passTestCount(passedTestCount) - .failTestCount(failedTestCount).totalTests(scenarioInfoList.size()) + .scenarioInfoDtoList(scenarioInfoDtoList).passTestCount(passedTestCount) + .failTestCount(failedTestCount).totalTests(scenarioInfoDtoList.size()) .BuildName(System.getProperty("JOB_NAME")).BuildNumber(System.getProperty("BUILD_NUMBER")) .build(); } diff --git a/heimdall.application/src/main/java/com/miqdigital/services/HeimdallReporting.java b/heimdall.application/src/main/java/com/miqdigital/services/HeimdallReporting.java index 5a95d7a..588753c 100644 --- a/heimdall.application/src/main/java/com/miqdigital/services/HeimdallReporting.java +++ b/heimdall.application/src/main/java/com/miqdigital/services/HeimdallReporting.java @@ -14,15 +14,16 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; -import com.miqdigital.utils.AmazonS3Connector; -import com.miqdigital.dto.NotificationDto; -import com.miqdigital.dto.ExecutionInfo; -import com.miqdigital.utils.SlackUtils; import com.miqdigital.dto.BuildResultDto; +import com.miqdigital.dto.EmailDto; +import com.miqdigital.dto.ExecutionInfoDto; +import com.miqdigital.dto.SlackDto; +import com.miqdigital.utils.AmazonS3Connector; import com.miqdigital.utils.EmailUtil; import com.miqdigital.utils.ReadProperties; +import com.miqdigital.utils.SlackUtils; -import cucumber.runtime.CucumberException; +import io.cucumber.core.exception.CucumberException; /** * This class uploads the build status to S3 and notifies the Slack channel. @@ -31,8 +32,8 @@ public class HeimdallReporting { private static final Logger LOGGER = LoggerFactory.getLogger(HeimdallReporting.class); - private ReadProperties properties; - private String executionOutputPath; + private final ReadProperties properties; + private final String executionOutputPath; public HeimdallReporting(final String pathOfRunnerPropertiesFile, final String executionOutputPath) throws IOException { @@ -49,57 +50,52 @@ public HeimdallReporting(final String pathOfRunnerPropertiesFile, /** * Sends the notification on the Slack channel. * - * @param executionInfo Jenkins build execution info - * @param notificationDto slack channel info from client + * @param buildResultDto Jenkins build execution info + * @param slackDto slack channel info from client */ - private static void sendSlackNotification(final ExecutionInfo executionInfo, - final NotificationDto notificationDto) throws IOException { - final BuildResultDto buildResultDto = - MessageGenerator.getBuildResult(executionInfo, notificationDto); + private static void sendSlackNotification(final BuildResultDto buildResultDto, + final SlackDto slackDto) throws IOException { SlackUtils slackUtils = new SlackUtils(); - slackUtils.sendSlackNotification(notificationDto, buildResultDto); + slackUtils.sendSlackNotification(slackDto, buildResultDto); LOGGER.info("Slack Notification Sent"); - } /** * Sends Email notification. * - * @param executionInfo - * @param notificationDto + * @param buildResultDto + * @param emailDto */ - private static void sendEmailNotification(ExecutionInfo executionInfo, - NotificationDto notificationDto) throws MessagingException, IOException { - final BuildResultDto buildResultDto = - MessageGenerator.getBuildResult(executionInfo, notificationDto); + private static void sendEmailNotification(final BuildResultDto buildResultDto, EmailDto emailDto) + throws MessagingException, IOException { - EmailUtil.sendEmail(notificationDto, buildResultDto); + EmailUtil.sendEmail(emailDto, buildResultDto); LOGGER.info("Email Sent"); - } /** * Pushes to S3 only if jenkins buildNumber is present. * * @param bucketName pass the S3 bucketName - * @param executionInfo test execution info + * @param executionInfoDto test execution info */ - private void pushResultToS3(final String bucketName, final ExecutionInfo executionInfo) + private void pushResultToS3(final String bucketName, final ExecutionInfoDto executionInfoDto) throws IOException, InterruptedException { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.enable(SerializationFeature.INDENT_OUTPUT); objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - if (Objects.nonNull(executionInfo.BuildNumber)) { + if (Objects.nonNull(executionInfoDto.BuildNumber)) { final String outputReportPath = - System.getProperty("user.dir") + "/target/" + executionInfo.BuildNumber + ".json"; + System.getProperty("user.dir") + "/target/" + executionInfoDto.BuildNumber + ".json"; try (final FileWriter writer = new FileWriter(outputReportPath)) { - objectMapper.writeValue(writer, executionInfo); + objectMapper.writeValue(writer, executionInfoDto); } final AmazonS3Connector amazonS3Connector = new AmazonS3Connector.Builder().build(); - final String prefix = executionInfo.BuildName + "/" + executionInfo.BuildNumber + ".json"; + final String prefix = + executionInfoDto.BuildName + "/" + executionInfoDto.BuildNumber + ".json"; amazonS3Connector.uploadFile(outputReportPath, bucketName, prefix); } else { LOGGER.info("Build number is null, not pushing build result to S3"); @@ -117,10 +113,10 @@ private void pushResultToS3(final String bucketName, final ExecutionInfo executi public void updateStatusInS3() throws IllegalAccessException, NoSuchFieldException, IOException, InterruptedException { ExecutionInfoGenerator executionInfoGenerator = new ExecutionInfoGenerator(); - ExecutionInfo executionInfo = + ExecutionInfoDto executionInfoDto = executionInfoGenerator.getBuildExecutionDetails(properties, executionOutputPath); - pushResultToS3(properties.getS3BucketName(), executionInfo); + pushResultToS3(properties.getS3BucketName(), executionInfoDto); } /** @@ -133,7 +129,7 @@ public void updateStatusInS3AndNotify() throws NoSuchFieldException, IllegalAccessException, IOException, InterruptedException, MessagingException { ExecutionInfoGenerator executionInfoGenerator = new ExecutionInfoGenerator(); - ExecutionInfo executionInfo = + ExecutionInfoDto executionInfoDto = executionInfoGenerator.getBuildExecutionDetails(properties, executionOutputPath); if (StringUtils.isNullOrEmpty(properties.getChannelName()) || StringUtils @@ -141,24 +137,29 @@ public void updateStatusInS3AndNotify() throw new NullPointerException( "Please specify Channel name and Slack bot token in runner properties file"); } - final NotificationDto notificationDto = - NotificationDto.builder().smtpHost(properties.getSmtpHost()) - .slackChannel(properties.getChannelName()) - .heimdallBotToken(properties.getHeimdallBotToken()) - .notifySlack(properties.isNotifySlack()).smtpUsername(properties.getSmtpUsername()) - .smtpPassword(properties.getSmtpPassword()).notifyEmail(properties.isNotifyEmail()) - .emailSubject(properties.getEmailSubject()).emailFrom(properties.getEmailFrom()) - .emailTo(properties.getEmailTo()).smtpPort(properties.getSmtpPort()) - .jenkinsDomain(properties.getJenkinsDomain()).build(); + + SlackDto slackDto = SlackDto.builder().slackChannel(properties.getChannelName()) + .heimdallBotToken(properties.getHeimdallBotToken()).notifySlack(properties.isNotifySlack()) + .build(); + + final EmailDto emailDto = EmailDto.builder().smtpHost(properties.getSmtpHost()) + .smtpUsername(properties.getSmtpUsername()).smtpPassword(properties.getSmtpPassword()) + .notifyEmail(properties.isNotifyEmail()).emailSubject(properties.getEmailSubject()) + .emailFrom(properties.getEmailFrom()).emailTo(properties.getEmailTo()) + .smtpPort(properties.getSmtpPort()).build(); LOGGER.info("Execution info generated Successfully"); - if (notificationDto.isNotifySlack()) { - sendSlackNotification(executionInfo, notificationDto); + + final BuildResultDto buildResultDto = + MessageGenerator.getBuildResult(executionInfoDto, properties.getJenkinsDomain()); + + if (slackDto.isNotifySlack()) { + sendSlackNotification(buildResultDto, slackDto); } - if (notificationDto.isNotifyEmail()) { - sendEmailNotification(executionInfo, notificationDto); + if (emailDto.isNotifyEmail()) { + sendEmailNotification(buildResultDto, emailDto); } - pushResultToS3(properties.getS3BucketName(), executionInfo); + pushResultToS3(properties.getS3BucketName(), executionInfoDto); } } \ No newline at end of file diff --git a/heimdall.application/src/main/java/com/miqdigital/services/MessageGenerator.java b/heimdall.application/src/main/java/com/miqdigital/services/MessageGenerator.java index 068124a..cd742dc 100644 --- a/heimdall.application/src/main/java/com/miqdigital/services/MessageGenerator.java +++ b/heimdall.application/src/main/java/com/miqdigital/services/MessageGenerator.java @@ -4,10 +4,9 @@ import java.util.Objects; import java.util.stream.Collectors; -import com.miqdigital.dto.NotificationDto; -import com.miqdigital.dto.ExecutionInfo; -import com.miqdigital.dto.ScenarioInfo; import com.miqdigital.dto.BuildResultDto; +import com.miqdigital.dto.ExecutionInfoDto; +import com.miqdigital.dto.ScenarioInfoDto; /** * This class builds the Slack message and the failed test scenarios report, if any. @@ -18,75 +17,76 @@ public class MessageGenerator { private MessageGenerator() { } - public static BuildResultDto getBuildResult(final ExecutionInfo executionInfo, - NotificationDto notificationDto) { - return getBuildResponse(executionInfo, notificationDto); + public static BuildResultDto getBuildResult(final ExecutionInfoDto executionInfoDto, + String jenkinsDomain) { + return getBuildResponse(executionInfoDto, jenkinsDomain); } /** * Sends the build notification to the Slack channel. * - * @param executionInfo test execution info - * @param notificationDto + * @param executionInfoDto test execution info + * @param jenkinsDomain * @return slack notification info */ - private static BuildResultDto getBuildResponse(final ExecutionInfo executionInfo, - NotificationDto notificationDto) { + private static BuildResultDto getBuildResponse(final ExecutionInfoDto executionInfoDto, + String jenkinsDomain) { final StringBuilder testExecutionInfo = new StringBuilder(); StringBuilder failedTestsInfo = new StringBuilder(); - final StringBuilder jenkinsBuildInfo = getBuildInfo(executionInfo); + final StringBuilder jenkinsBuildInfo = getBuildInfo(executionInfoDto); - if (executionInfo.failTestCount > 0) { + if (executionInfoDto.failTestCount > 0) { testExecutionInfo.append("*BUILD FAILED ").append(jenkinsBuildInfo) - .append("\n*Tests Failed:* ").append(executionInfo.failTestCount) + .append("\n*Tests Failed:* ").append(executionInfoDto.failTestCount) .append("\n*List of failed tests:* "); - failedTestsInfo = getFailedTestInfo(executionInfo); + failedTestsInfo = getFailedTestInfo(executionInfoDto); } else { testExecutionInfo.append("*BUILD PASSED ").append(jenkinsBuildInfo); } - if (Objects.nonNull(executionInfo.BuildNumber) && Objects + if (Objects.nonNull(executionInfoDto.BuildNumber) && Objects .nonNull(System.getProperty("viewName"))) { - String jenkinsJobUrl = notificationDto.getJenkinsDomain() + "/view/%s/job/%s/%s/console"; + String jenkinsJobUrl = jenkinsDomain + "/view/%s/job/%s/%s/console"; testExecutionInfo.append("\n").append("*Console out:* ").append(String - .format(jenkinsJobUrl, System.getProperty("viewName"), executionInfo.BuildName, - executionInfo.BuildNumber)); + .format(jenkinsJobUrl, System.getProperty("viewName"), executionInfoDto.BuildName, + executionInfoDto.BuildNumber)); } return BuildResultDto.builder().testExecutionInfo(testExecutionInfo) - .failedTestDescription(failedTestsInfo).failedTestCount(executionInfo.failTestCount) + .failedTestDescription(failedTestsInfo).failedTestCount(executionInfoDto.failTestCount) .build(); } /** - * @param executionInfo test execution info + * @param executionInfoDto test execution info * @return get failed test information */ - private static StringBuilder getFailedTestInfo(final ExecutionInfo executionInfo) { + private static StringBuilder getFailedTestInfo(final ExecutionInfoDto executionInfoDto) { final StringBuilder failedTestsInfo = new StringBuilder(); - final List scenarioInfoList = executionInfo.scenarioInfoList; - final List failedTests = - scenarioInfoList.stream().filter(r -> r.getScenarioStatus().equals("FAILED")) + final List scenarioInfoDtoList = executionInfoDto.scenarioInfoDtoList; + final List failedTests = + scenarioInfoDtoList.stream().filter(r -> r.getScenarioStatus().equals("FAILED")) .collect(Collectors.toList()); - for (final ScenarioInfo scenarioInfo : failedTests) { - failedTestsInfo.append(scenarioInfo.getScenarioTagId()).append(" "); - failedTestsInfo.append(scenarioInfo.getScenarioName()).append("\n"); + for (final ScenarioInfoDto scenarioInfoDto : failedTests) { + failedTestsInfo.append(scenarioInfoDto.getScenarioTagId()).append(" "); + failedTestsInfo.append(scenarioInfoDto.getScenarioName()).append("\n"); } failedTestsInfo.setLength(failedTestsInfo.length() - 1); return failedTestsInfo; } /** - * @param executionInfo test execution info + * @param executionInfoDto test execution info * @return jenkins build info */ - private static StringBuilder getBuildInfo(final ExecutionInfo executionInfo) { - return new StringBuilder().append("for job:* ").append(executionInfo.BuildName) - .append("\n*BuildNo.:* ").append(executionInfo.BuildNumber).append("\n*Environment:* ") - .append(executionInfo.environment).append("\n*Test type:* ").append(executionInfo.testType) - .append("\n*Total tests executed:* ").append(executionInfo.totalTests) - .append("\n*Tests Passed:* ").append(executionInfo.passTestCount); + private static StringBuilder getBuildInfo(final ExecutionInfoDto executionInfoDto) { + return new StringBuilder().append("for job:* ").append(executionInfoDto.BuildName) + .append("\n*BuildNo.:* ").append(executionInfoDto.BuildNumber).append("\n*Environment:* ") + .append(executionInfoDto.environment).append("\n*Test type:* ") + .append(executionInfoDto.testType).append("\n*Total tests executed:* ") + .append(executionInfoDto.totalTests).append("\n*Tests Passed:* ") + .append(executionInfoDto.passTestCount); } } \ No newline at end of file diff --git a/heimdall.application/src/main/java/com/miqdigital/utils/EmailUtil.java b/heimdall.application/src/main/java/com/miqdigital/utils/EmailUtil.java index acf4d3d..26211ab 100644 --- a/heimdall.application/src/main/java/com/miqdigital/utils/EmailUtil.java +++ b/heimdall.application/src/main/java/com/miqdigital/utils/EmailUtil.java @@ -18,61 +18,61 @@ import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; -import com.miqdigital.dto.NotificationDto; import com.miqdigital.dto.BuildResultDto; +import com.miqdigital.dto.EmailDto; public class EmailUtil { - private EmailUtil(){} + private EmailUtil() { + } private static final String ATTACHMENT_FILE_NAME = "./target/FailedTestsInfo.txt"; /** * Creating an email body and sending the email. - * @param notificationDto + * + * @param emailDto * @param buildResultDto * @throws MessagingException * @throws IOException */ - public static void sendEmail(NotificationDto notificationDto, BuildResultDto buildResultDto) + public static void sendEmail(EmailDto emailDto, BuildResultDto buildResultDto) throws MessagingException, IOException { String msg = buildResultDto.testExecutionInfo.toString(); Properties prop = new Properties(); prop.put("mail.smtp.auth", true); prop.put("mail.smtp.starttls.enable", "true"); - prop.put("mail.smtp.host", notificationDto.getSmtpHost()); - prop.put("mail.smtp.port", notificationDto.getSmtpPort()); - prop.put("mail.smtp.ssl.trust", notificationDto.getSmtpHost()); + prop.put("mail.smtp.host", emailDto.getSmtpHost()); + prop.put("mail.smtp.port", emailDto.getSmtpPort()); + prop.put("mail.smtp.ssl.trust", emailDto.getSmtpHost()); Session session = Session.getInstance(prop, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(notificationDto.getSmtpUsername(), notificationDto.getSmtpPassword()); + return new PasswordAuthentication(emailDto.getSmtpUsername(), emailDto.getSmtpPassword()); } }); String failedTestDescription = buildResultDto.failedTestDescription.toString(); - final String generatedFileName = Files.write(Paths.get(ATTACHMENT_FILE_NAME), - failedTestDescription.getBytes()).normalize().toAbsolutePath() - .toString(); + final String generatedFileName = + Files.write(Paths.get(ATTACHMENT_FILE_NAME), failedTestDescription.getBytes()).normalize() + .toAbsolutePath().toString(); Message message = new MimeMessage(session); - message.setFrom(new InternetAddress(notificationDto.getEmailFrom())); - message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(notificationDto.getEmailTo())); - message.setSubject(notificationDto.getEmailSubject()); - + message.setFrom(new InternetAddress(emailDto.getEmailFrom())); + message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(emailDto.getEmailTo())); + message.setSubject(emailDto.getEmailSubject()); MimeBodyPart attachmentBodyPart = new MimeBodyPart(); attachmentBodyPart.attachFile(new File(generatedFileName)); MimeBodyPart mimeBodyPart = new MimeBodyPart(); - mimeBodyPart.setContent(msg.replace("\n","
"), "text/html"); + mimeBodyPart.setContent(msg.replace("\n", "
"), "text/html"); Multipart multipart = new MimeMultipart(); multipart.addBodyPart(mimeBodyPart); multipart.addBodyPart(attachmentBodyPart); message.setContent(multipart); - Transport.send(message); } diff --git a/heimdall.application/src/main/java/com/miqdigital/utils/SlackUtils.java b/heimdall.application/src/main/java/com/miqdigital/utils/SlackUtils.java index 2bf468c..eaa2758 100644 --- a/heimdall.application/src/main/java/com/miqdigital/utils/SlackUtils.java +++ b/heimdall.application/src/main/java/com/miqdigital/utils/SlackUtils.java @@ -6,7 +6,6 @@ import java.nio.file.Paths; import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.mime.MultipartEntityBuilder; @@ -14,9 +13,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import com.miqdigital.dto.NotificationDto; import com.miqdigital.dto.BuildResultDto; +import com.miqdigital.dto.SlackDto; /** * This class is used to post Slack notification on provided channel. @@ -31,49 +29,44 @@ public class SlackUtils { /** * Makes Http post request to Slack to send the notification and upload the failed scenarios file. * - * @param notificationDto slack channel details and token + * @param slackDto slack channel details and token * @param buildResultDto slack notification */ - public void sendSlackNotification(final NotificationDto notificationDto, - final BuildResultDto buildResultDto) throws IOException { + public void sendSlackNotification(final SlackDto slackDto, final BuildResultDto buildResultDto) + throws IOException { final HttpClient httpclient = HttpClientBuilder.create().disableContentCompression().build(); final HttpPost httpPost = buildResultDto.failedTestCount == 0 ? new HttpPost(CHAT_POST_URL) : new HttpPost(FILE_UPLOAD_URL); - final HttpEntity httpEntity = getHttpRequestEntity(notificationDto, buildResultDto).build(); + final HttpEntity httpEntity = getHttpRequestEntity(slackDto, buildResultDto).build(); httpPost.setEntity(httpEntity); - final HttpResponse execute = httpclient.execute(httpPost); - logger.info(execute.getStatusLine().getReasonPhrase()); + httpclient.execute(httpPost); } /** * Configures the Http request for Slack. * - * @param notificationDto + * @param slackDto * @param buildResultDto * @return * @throws IOException */ - public MultipartEntityBuilder getHttpRequestEntity(final NotificationDto notificationDto, + public MultipartEntityBuilder getHttpRequestEntity(final SlackDto slackDto, final BuildResultDto buildResultDto) throws IOException { final MultipartEntityBuilder reqEntity = - MultipartEntityBuilder.create().addTextBody("token", notificationDto.getHeimdallBotToken()); + MultipartEntityBuilder.create().addTextBody("token", slackDto.getHeimdallBotToken()); if (buildResultDto.failedTestCount == 0) { //soft slack notification - final String generatedFileName = Files.write(Paths.get(ATTACHMENT_FILE_NAME), - buildResultDto.failedTestDescription.toString().getBytes()).normalize().toAbsolutePath() - .toString(); - reqEntity.addBinaryBody("file", new File(generatedFileName)) - .addTextBody("channels", notificationDto.getSlackChannel()).addTextBody("media", "file") - .addTextBody("initial_comment", " " + buildResultDto.testExecutionInfo.toString()); + reqEntity.addTextBody("channel", slackDto.getSlackChannel()).addTextBody("as_user", "true") + .addTextBody("text", buildResultDto.testExecutionInfo.toString()); } else { //slack notification with @here final String generatedFileName = Files.write(Paths.get(ATTACHMENT_FILE_NAME), buildResultDto.failedTestDescription.toString().getBytes()).normalize().toAbsolutePath() .toString(); reqEntity.addBinaryBody("file", new File(generatedFileName)) - .addTextBody("channels", notificationDto.getSlackChannel()).addTextBody("media", "file") + .addTextBody("channels", slackDto.getSlackChannel()).addTextBody("media", "file") .addTextBody("initial_comment", " " + buildResultDto.testExecutionInfo.toString()); } return reqEntity;