app/lib/slack/DeployReporter.scala (52 lines of code) (raw):

package lib.slack import cats.data.NonEmptySeq import com.madgag.scalagithub.model.{PullRequest, User} import io.lemonlabs.uri.Url import lib.labels.Seen import lib._ import play.api.Logging import play.api.libs.json.{JsValue, Json} import play.api.libs.ws.WSClient import scala.concurrent.{ExecutionContext, Future} class DeployReporter( ws: WSClient, bot: Bot )(implicit ec: ExecutionContext ) extends Logging with UpdateReporter { override def report( repoSnapshot: RepoSnapshot, pr: PullRequest, checkpointsChangeSummary: PullRequestCheckpointsStateChangeSummary ): Unit = slackHooksFrom(repoSnapshot.repoLevelDetails).flatMap { slackHooks => report(checkpointsChangeSummary, slackHooks) }.getOrElse(Future.successful(())) private def slackHooksFrom(repoLevelDetails: RepoLevelDetails): Option[NonEmptySeq[Url]] = NonEmptySeq.fromSeq(repoLevelDetails.hooks.filter(_.hostOption.exists(_.value == "hooks.slack.com"))) private def report(checkpointChangeSummary: PullRequestCheckpointsStateChangeSummary, slackHooks: NonEmptySeq[Url]): Option[Future[Unit]] = { val pr = checkpointChangeSummary.prCheckpointDetails.pr for (changedSnapshots <- checkpointChangeSummary.changedByState.get(Seen)) yield { val json = messageJsonFor(pr, changedSnapshots) Future.traverse(slackHooks.toSeq) { hook => val responseF = ws.url(hook.toString).post(json) responseF.onComplete { r => logger.debug(s"Response from Slack: ${r.map(_.body)}") } responseF }.map(_ => ()) } } private def messageJsonFor(pr: PullRequest, changedSnapshots: Set[EverythingYouWantToKnowAboutACheckpoint]): JsValue = { val checkpointsWherePRIsNewlySeen = changedSnapshots.map(_.snapshot.checkpoint) Json.toJson( Message( s"*Deployed to ${checkpointsWherePRIsNewlySeen.map(slackLinkFor).mkString(", ")}: ${pr.title}*", Some(bot.user.login), pr.merged_by.map(_.avatar_url), attachments = Seq(Attachment(s"PR #${pr.number} deployed to ${checkpointsWherePRIsNewlySeen.map(_.name).mkString(", ")}", Seq( Attachment.Field("PR", s"<${pr.html_url}|#${pr.number}>", short = true), ) ++ pr.merged_by.map(mergedBy => Attachment.Field("Merged by", slackLinkFor(mergedBy), short = true)))) ) ) } private def slackLinkFor(c: Config.Checkpoint) = s"<${c.details.url}|${c.name}>" private def slackLinkFor(user: User) = s"<${user.html_url}|${user.atLogin}>" }