Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ dependencies {
implementation(libs.underscore)
implementation(libs.okio.jvm)
implementation(libs.spring.beans)
// Slack notification packages
implementation("com.slack.api:slack-api-client:1.38.1")
implementation("com.slack.api:slack-api-model-kotlin-extension:1.38.1")
implementation("com.slack.api:slack-api-client-kotlin-extension:1.38.1")
kapt(libs.immutables.value)
compileOnly(libs.immutables.builder)
compileOnly(libs.immutables.value.annotations)
Expand Down
22 changes: 20 additions & 2 deletions src/main/kotlin/com/salesforce/revoman/ReVoman.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,16 @@ import com.salesforce.revoman.internal.postman.RegexReplacer
import com.salesforce.revoman.internal.postman.initPmEnvironment
import com.salesforce.revoman.internal.postman.pm
import com.salesforce.revoman.internal.postman.template.Template
import com.salesforce.revoman.notification.NotificationFactory
import com.salesforce.revoman.notification.NotifierTypes
import com.salesforce.revoman.notification.reports.StepExecutionsResult
import com.salesforce.revoman.notification.PayloadBuilder.slackSummaryReportPayloadBuilder
import com.salesforce.revoman.output.Rundown
import com.salesforce.revoman.output.report.Step
import com.salesforce.revoman.output.report.StepReport
import com.salesforce.revoman.output.report.StepReport.Companion.toVavr
import com.salesforce.revoman.output.report.TxnInfo
import com.slack.api.webhook.Payload
import com.squareup.moshi.Moshi
import com.squareup.moshi.adapter
import io.github.oshai.kotlinlogging.KotlinLogging
Expand Down Expand Up @@ -65,12 +70,25 @@ object ReVoman {
initMoshi(
kick.customAdaptersForMarshalling(),
kick.customAdaptersFromRequestConfig() + kick.customAdaptersFromResponseConfig(),
kick.typesToIgnoreForMarshalling()
)
kick.typesToIgnoreForMarshalling(),
),
)

val stepExecutionsResult = getStepReportDetails(stepNameToReport)
notifyUsers(stepExecutionsResult)
return Rundown(stepNameToReport, pm.environment, kick.haltOnFailureOfTypeExcept())
}

private fun getStepReportDetails(stepNameToReport: List<StepReport>): StepExecutionsResult {
val summaryResult = StepExecutionsResult(stepNameToReport.size, stepNameToReport.count { it.isSuccessful }, stepNameToReport.count { !it.isSuccessful }, "https://www.google.com")
return summaryResult
}

private fun notifyUsers(stepExecutionsResult: StepExecutionsResult) {
val notifier = NotificationFactory().createNotifier<Payload>(NotifierTypes.SLACK)
notifier.notifyUser(slackSummaryReportPayloadBuilder(stepExecutionsResult))
}

private fun executeStepsSerially(
pmStepsFlattened: List<Step>,
kick: Kick,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.salesforce.revoman.notification

interface Notification<T> {
fun notifyUser(message: T)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.salesforce.revoman.notification

import com.salesforce.revoman.notification.slack.SlackNotifier

class NotificationFactory {
fun <T> createNotifier(type: NotifierTypes): Notification<T> {
return when (type) {
NotifierTypes.SLACK -> SlackNotifier()
else -> throw IllegalArgumentException("Notification type $type not supported")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.salesforce.revoman.notification

enum class NotifierTypes {
SLACK
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.salesforce.revoman.notification

import com.salesforce.revoman.notification.reports.StepExecutionsResult
import com.slack.api.model.block.Blocks
import com.slack.api.model.block.HeaderBlock
import com.slack.api.model.block.SectionBlock
import com.slack.api.model.block.composition.MarkdownTextObject
import com.slack.api.model.block.composition.PlainTextObject
import com.slack.api.webhook.Payload

object PayloadBuilder {
fun slackSummaryReportPayloadBuilder(stepExecutionsResult: StepExecutionsResult): Payload {
val blocks = listOf(
HeaderBlock.builder()
.text(
PlainTextObject.builder()
.text(":clipboard: Steps execution report")
.emoji(true)
.build()
)
.build(),
Blocks.divider(),
SectionBlock.builder()
.text(
MarkdownTextObject.builder()
.text("``` ---------------------- ---------- ---------- \n| Total Steps Executed | Success | Failure |\n ====================== ========== ========== \n| ${stepExecutionsResult.totalSteps} | ${stepExecutionsResult.successStepsCount} | ${stepExecutionsResult.failedStepsCount} |\n ---------------------- ---------- ---------- ```")
.build()
)
.build(),
SectionBlock.builder()
.text(
MarkdownTextObject.builder()
.text("For detailed report please click <${stepExecutionsResult.detailedReportUrl}|*here*>.")
.build()
)
.build()
)

return Payload.builder()
.blocks(blocks)
.build()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.salesforce.revoman.notification.reports

data class StepExecutionsResult(val totalSteps: Int, val successStepsCount: Int, val failedStepsCount: Int, val detailedReportUrl: String)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.salesforce.revoman.notification.slack

import com.salesforce.revoman.notification.Notification
import com.slack.api.Slack
import com.slack.api.webhook.Payload
import io.github.oshai.kotlinlogging.KotlinLogging

class SlackNotifier<T> : Notification<T> {
companion object {
val SLACK_WEBHOOK_URL: String = System.getenv("SLACK_WEBHOOK_URL");
}

override fun notifyUser(message: T) {
logger.info { "Sending message: ${message.toString()}" }
val slack = Slack.getInstance()
if (SLACK_WEBHOOK_URL.isBlank()) {
logger.error { "Failed to send message to Slack webhook $SLACK_WEBHOOK_URL" }
return
}

val response = slack.send(SLACK_WEBHOOK_URL, message as Payload);
logger.info { "Got response: ${response.body}" }
}

private val logger = KotlinLogging.logger {}
}