diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index fb1fb70..bafc8f9 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -1,4 +1,4 @@ -name: Build +name: Staging on: workflow_dispatch: diff --git a/docker-compose.yml b/docker-compose.yml index 575d591..9b58b0f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,12 +13,8 @@ services: - WIRE_SDK_API_TOKEN=${WIRE_SDK_API_TOKEN} - WIRE_SDK_APP_ID=${WIRE_SDK_APP_ID} - WIRE_SDK_CRYPTOGRAPHY_STORAGE_PASSWORD=${WIRE_SDK_CRYPTOGRAPHY_STORAGE_PASSWORD} - - WIRE_SDK_USER_ID=${WIRE_SDK_USER_ID} - - WIRE_SDK_EMAIL=${WIRE_SDK_EMAIL} - - WIRE_SDK_PASSWORD=${WIRE_SDK_PASSWORD} - - WIRE_SDK_ENVIRONMENT=${WIRE_SDK_ENVIRONMENT} ports: - - "${GHAPP_SERVER_PORT}:${GHAPP_SERVER_PORT}" + - "${GHAPP_SERVER_PORT:-8083}:${GHAPP_SERVER_PORT:-8083}" volumes: - github-app:/app depends_on: diff --git a/helm/githubapp/templates/NOTES.txt b/helm/githubapp/templates/NOTES.txt index d0d8a69..fbd553b 100644 --- a/helm/githubapp/templates/NOTES.txt +++ b/helm/githubapp/templates/NOTES.txt @@ -37,12 +37,6 @@ MONITORING & DEBUGGING: CONFIGURATION: {{- range .Values.env }} -{{- if eq .name "WIRE_SDK_ENVIRONMENT" }} -- Wire SDK Environment: {{ .value | default "Not configured" }} -{{- end }} -{{- if eq .name "WIRE_ENV" }} -- Wire Environment: {{ .value | default "Not configured" }} -{{- end }} {{- if eq .name "PORT" }} - Application Port: {{ .value | default "8080" }} {{- end }} diff --git a/src/main/kotlin/com/wire/github/Routing.kt b/src/main/kotlin/com/wire/github/Routing.kt index 55fa189..efa1a57 100644 --- a/src/main/kotlin/com/wire/github/Routing.kt +++ b/src/main/kotlin/com/wire/github/Routing.kt @@ -22,6 +22,7 @@ import io.ktor.server.routing.post import io.ktor.server.routing.routing import java.util.UUID import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.SerializationException import org.koin.core.context.GlobalContext @Suppress("LongMethod") @@ -37,7 +38,7 @@ fun Application.configureRouting() { routing { trace { - application.log.info(it.buildText()) + application.log.debug(it.buildText()) } get("/health") { @@ -84,7 +85,12 @@ fun Application.configureRouting() { ) } - val response = KtxSerializer.json.decodeFromString(payload) + val response = try { + KtxSerializer.json.decodeFromString(payload) + } catch (exception: SerializationException) { + application.log.error("Failed to deserialize $event delivery $delivery", exception) + return@post call.response.status(HttpStatusCode.BadRequest) + } // Handle event response and send message val messageTemplate = templateHandler.handleEvent( diff --git a/src/main/kotlin/com/wire/github/response/model/Comment.kt b/src/main/kotlin/com/wire/github/response/model/Comment.kt index 19e1143..6a89097 100644 --- a/src/main/kotlin/com/wire/github/response/model/Comment.kt +++ b/src/main/kotlin/com/wire/github/response/model/Comment.kt @@ -5,7 +5,7 @@ import kotlinx.serialization.Serializable @Serializable data class Comment( - val body: String, + val body: String? = null, val user: User, @SerialName("html_url") val htmlUrl: String, diff --git a/src/main/kotlin/com/wire/github/response/model/Issue.kt b/src/main/kotlin/com/wire/github/response/model/Issue.kt index 3697877..188043e 100644 --- a/src/main/kotlin/com/wire/github/response/model/Issue.kt +++ b/src/main/kotlin/com/wire/github/response/model/Issue.kt @@ -8,7 +8,7 @@ data class Issue( @SerialName("html_url") val htmlUrl: String, val title: String, - val body: String, + val body: String? = null, val user: User, val number: Int ) diff --git a/src/main/kotlin/com/wire/github/response/model/PullRequest.kt b/src/main/kotlin/com/wire/github/response/model/PullRequest.kt index acb5278..b84152b 100644 --- a/src/main/kotlin/com/wire/github/response/model/PullRequest.kt +++ b/src/main/kotlin/com/wire/github/response/model/PullRequest.kt @@ -8,8 +8,8 @@ data class PullRequest( @SerialName("html_url") val htmlUrl: String, val title: String, - val body: String, + val body: String? = null, val user: User, - val merged: Boolean, + val merged: Boolean? = null, val number: Int ) diff --git a/src/main/kotlin/com/wire/github/response/model/Review.kt b/src/main/kotlin/com/wire/github/response/model/Review.kt index b46bb5a..0adf5a1 100644 --- a/src/main/kotlin/com/wire/github/response/model/Review.kt +++ b/src/main/kotlin/com/wire/github/response/model/Review.kt @@ -4,7 +4,14 @@ import kotlinx.serialization.Serializable @Serializable data class Review( - val body: String, - val user: User, + val body: String? = null, + val user: User? = null, val state: String -) +) { + val emoji: String + get() = when (state) { + "approved" -> "✅" + "changes_requested" -> "🔄" + else -> "📝" + } +} diff --git a/src/main/kotlin/com/wire/github/util/TemplateHandler.kt b/src/main/kotlin/com/wire/github/util/TemplateHandler.kt index 2b63bcd..e497ee5 100644 --- a/src/main/kotlin/com/wire/github/util/TemplateHandler.kt +++ b/src/main/kotlin/com/wire/github/util/TemplateHandler.kt @@ -22,13 +22,14 @@ class TemplateHandler { event = event, action = response.action ) + logger.info("Template found for this action: ${template.name}") populateTemplate( mustache = template, model = response ) } catch (exception: MustacheNotFoundException) { - logger.error("MustacheNotFoundException: $exception") + logger.info("MustacheNotFoundException: $exception") null } @@ -62,6 +63,7 @@ class TemplateHandler { .apply { mustache.execute(PrintWriter(this), model).flush() }.toString() + .takeIf { it.isNotBlank() } private companion object { const val LANGUAGE_ENGLISH = "en" diff --git a/src/main/resources/templates/en/commit_comment.created.template b/src/main/resources/templates/en/commit_comment.created.template deleted file mode 100644 index 1573964..0000000 --- a/src/main/resources/templates/en/commit_comment.created.template +++ /dev/null @@ -1,7 +0,0 @@ -**[{{repository.fullName}}]** New comment on commit {{comment.id}} - -**Comment on line {{comment.line}} by {{comment.user.login}}** -{{{comment.body}}} - -[comment]({{comment.htmlUrl}}) -— diff --git a/src/main/resources/templates/en/issue_comment.created.template b/src/main/resources/templates/en/issue_comment.created.template index 419547a..d94903d 100644 --- a/src/main/resources/templates/en/issue_comment.created.template +++ b/src/main/resources/templates/en/issue_comment.created.template @@ -1,6 +1,5 @@ -**[{{repository.fullName}}]** New comment by **{{sender.login}}** on issue **{{{issue.title}}}** - -{{{comment.body}}} - -[comment]({{comment.htmlUrl}}) -— +📝 **New comment** on PR/issue **{{{issue.title}}}** by **{{sender.login}}** +**Repository:** {{repository.fullName}} +**PR/issue:** [#{{issue.number}}]({{issue.htmlUrl}}) - {{issue.title}} +**Comment:** [link]({{comment.htmlUrl}}) +**Text:** {{{comment.body}}} diff --git a/src/main/resources/templates/en/pull_request.ready_for_review.template b/src/main/resources/templates/en/pull_request.ready_for_review.template new file mode 100644 index 0000000..cf776a7 --- /dev/null +++ b/src/main/resources/templates/en/pull_request.ready_for_review.template @@ -0,0 +1,3 @@ +🟢 **New Pull Request Ready for Review!** by **{{sender.login}}** +**Repository:** {{repository.fullName}} +**PR:** [#{{pullRequest.number}}]({{pullRequest.htmlUrl}}) - {{pullRequest.title}} diff --git a/src/main/resources/templates/en/pull_request.reopened.template b/src/main/resources/templates/en/pull_request.reopened.template new file mode 100644 index 0000000..ddb003a --- /dev/null +++ b/src/main/resources/templates/en/pull_request.reopened.template @@ -0,0 +1,3 @@ +🟢 **New Pull Request Reopened!** by **{{sender.login}}** +**Repository:** {{repository.fullName}} +**PR:** [#{{pullRequest.number}}]({{pullRequest.htmlUrl}}) - {{pullRequest.title}} diff --git a/src/main/resources/templates/en/pull_request_review.submitted.template b/src/main/resources/templates/en/pull_request_review.submitted.template index 522a398..37f133e 100644 --- a/src/main/resources/templates/en/pull_request_review.submitted.template +++ b/src/main/resources/templates/en/pull_request_review.submitted.template @@ -1,6 +1,6 @@ -{{#review.body}}**[{{repository.fullName}}]** Pull request review **{{pullRequest.title}}** was {{action}} by **{{review.user.login}}** - -{{{review.body}}} - -[pull request]({{pullRequest.htmlUrl}}) -—{{/review.body}} +{{#review.body}} +{{review.emoji}} **Pull request** update: **{{review.state}}** by **{{review.user.login}}** +**Repository:** {{repository.fullName}} +**PR:** [#{{pullRequest.number}}]({{pullRequest.htmlUrl}}) - {{pullRequest.title}} +**Text:** {{{review.body}}} +{{/review.body}} diff --git a/src/main/resources/templates/en/pull_request_review_comment.created.template b/src/main/resources/templates/en/pull_request_review_comment.created.template index f8d6fd1..e1505dc 100644 --- a/src/main/resources/templates/en/pull_request_review_comment.created.template +++ b/src/main/resources/templates/en/pull_request_review_comment.created.template @@ -1,6 +1,5 @@ -**[{{repository.fullName}}]** Pull request review **{{pullRequest.title}}** was commented by **{{comment.user.login}}** - -{{{comment.body}}} - -[comment]({{comment.htmlUrl}}) -— +📝 **Pull request** was **commented** by **{{comment.user.login}}** +**Repository:** {{repository.fullName}} +**PR:** [#{{pullRequest.number}}]({{pullRequest.htmlUrl}}) - {{pullRequest.title}} +**Comment:** [link]({{comment.htmlUrl}}) +**Text:** {{{comment.body}}} diff --git a/src/main/resources/templates/en/push.template b/src/main/resources/templates/en/push.template index 51b2108..8e02928 100644 --- a/src/main/resources/templates/en/push.template +++ b/src/main/resources/templates/en/push.template @@ -1,9 +1,8 @@ {{^commits.isEmpty}} -**[{{repository.fullName}}]** Push by **{{sender.login}}** - +🫸 **Push** by **{{sender.login}}** +**Repository:** {{repository.fullName}} {{#commits}} - {{{message}}} {{/commits}} - -[compare]({{compare}}) +**Compare:** [link]({{compare}}) —{{/commits.isEmpty}} diff --git a/src/test/kotlin/com/wire/github/util/TemplateHandlerTest.kt b/src/test/kotlin/com/wire/github/util/TemplateHandlerTest.kt new file mode 100644 index 0000000..33609eb --- /dev/null +++ b/src/test/kotlin/com/wire/github/util/TemplateHandlerTest.kt @@ -0,0 +1,127 @@ +package com.wire.github.util + +import com.wire.github.response.model.Commit +import com.wire.github.response.model.GitHubResponse +import com.wire.github.response.model.PullRequest +import com.wire.github.response.model.Repository +import com.wire.github.response.model.Review +import com.wire.github.response.model.User +import kotlin.test.Test +import kotlin.test.assertContains +import kotlin.test.assertNull + +class TemplateHandlerTest { + private val templateHandler = TemplateHandler() + + @Test + fun `does not render a submitted pull request review without a body`() { + val message = templateHandler.handleEvent( + event = "pull_request_review", + response = reviewResponse(body = null) + ) + + assertNull(message) + } + + @Test + fun `does not render a submitted pull request review with a blank body`() { + val message = templateHandler.handleEvent( + event = "pull_request_review", + response = reviewResponse(body = "") + ) + + assertNull(message) + } + + @Test + fun `renders a submitted pull request review with a body`() { + val message = templateHandler.handleEvent( + event = "pull_request_review", + response = reviewResponse(body = "Looks good") + ) + + assertContains(message.orEmpty(), "Looks good") + assertContains(message.orEmpty(), "✅") + } + + @Test + fun `renders a note emoji for a commented pull request review`() { + val message = templateHandler.handleEvent( + event = "pull_request_review", + response = reviewResponse(body = "A comment", state = "commented") + ) + + assertContains(message.orEmpty(), "📝") + } + + @Test + fun `renders a change emoji for a pull request review with requested changes`() { + val message = templateHandler.handleEvent( + event = "pull_request_review", + response = reviewResponse(body = "Please update this", state = "changes_requested") + ) + + assertContains(message.orEmpty(), "🔄") + } + + @Test + fun `does not render a push with no commits`() { + val message = templateHandler.handleEvent( + event = "push", + response = pushResponse(commits = emptyList()) + ) + + assertNull(message) + } + + @Test + fun `renders a push with commits`() { + val message = templateHandler.handleEvent( + event = "push", + response = pushResponse(commits = listOf(Commit(message = "Add feature"))) + ) + + assertContains(message.orEmpty(), "Add feature") + } + + private fun reviewResponse( + body: String?, + state: String = "approved" + ) = GitHubResponse( + action = "submitted", + pullRequest = PullRequest( + htmlUrl = "https://github.com/wire/example/pull/1", + title = "Example pull request", + user = user, + number = 1 + ), + review = Review( + body = body, + user = user, + state = state + ), + sender = user, + repository = Repository( + fullName = "wire/example", + name = "example" + ) + ) + + private fun pushResponse(commits: List) = + GitHubResponse( + commits = commits, + sender = user, + compare = "https://github.com/wire/example/compare/main", + repository = Repository( + fullName = "wire/example", + name = "example" + ) + ) + + private companion object { + val user = User( + avatarUrl = "https://github.com/wire.png", + login = "wire" + ) + } +}