From 3fc217a9c5ff0b17b531b10c9b2161297d33b4f1 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Thu, 18 Jun 2026 14:02:07 +0200 Subject: [PATCH 1/8] feat: track PR additions, deletions --- src/main/kotlin/com/wire/github/response/model/PullRequest.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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..ebb756e 100644 --- a/src/main/kotlin/com/wire/github/response/model/PullRequest.kt +++ b/src/main/kotlin/com/wire/github/response/model/PullRequest.kt @@ -11,5 +11,7 @@ data class PullRequest( val body: String, val user: User, val merged: Boolean, - val number: Int + val number: Int, + val additions: Int = 0, + val deletions: Int = 0 ) From 4158978b736075bc4d9b4d8452007520c8ba2923 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Thu, 18 Jun 2026 14:02:54 +0200 Subject: [PATCH 2/8] chore: simplify PR opened template --- .../resources/templates/en/pull_request.opened.template | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/resources/templates/en/pull_request.opened.template b/src/main/resources/templates/en/pull_request.opened.template index 58e1704..a327798 100644 --- a/src/main/resources/templates/en/pull_request.opened.template +++ b/src/main/resources/templates/en/pull_request.opened.template @@ -1,5 +1,3 @@ -🟢 **New Pull Request Opened!** by **{{pullRequest.user.login}}** +[**{{pullRequest.title}}**]({{pullRequest.htmlUrl}}) (+{{pullRequest.additions}}/-{{pullRequest.deletions}}) by **@{{pullRequest.user.login}}** -📦 **Repository:** {{repository.fullName}} -🔖 **Title:** {{pullRequest.title}} -🔗 **PR Link:** [#{{pullRequest.number}}]({{pullRequest.htmlUrl}}) +{{{pullRequest.body}}} From 40eb67602db385423eaec64043d71d2dab02a850 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Thu, 18 Jun 2026 14:23:59 +0200 Subject: [PATCH 3/8] chore: rm noisy review commit template This template would have been fired on every individual line comment in a PR--too much. --- .../templates/en/pull_request_review_comment.created.template | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 src/main/resources/templates/en/pull_request_review_comment.created.template 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 deleted file mode 100644 index 835bab4..0000000 --- a/src/main/resources/templates/en/pull_request_review_comment.created.template +++ /dev/null @@ -1,4 +0,0 @@ -**{{pullRequest.title}}** -**@{{comment.user.login}}** [commented]({{comment.htmlUrl}}): - -{{{comment.body}}} From 44665c7455ce4962938aa8cc8f63ee8a4e6a06f6 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Thu, 18 Jun 2026 14:37:16 +0200 Subject: [PATCH 4/8] docs: annotate in each template when precisely it fires --- .../resources/templates/en/commit_comment.created.template | 1 + .../resources/templates/en/issue_comment.created.template | 4 +++- src/main/resources/templates/en/issues.closed.template | 2 ++ src/main/resources/templates/en/issues.opened.template | 1 + src/main/resources/templates/en/issues.reopened.template | 1 + src/main/resources/templates/en/pull_request.closed.template | 2 ++ src/main/resources/templates/en/pull_request.opened.template | 1 + .../templates/en/pull_request_review.submitted.template | 3 +++ src/main/resources/templates/en/push.template | 3 +++ 9 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/resources/templates/en/commit_comment.created.template b/src/main/resources/templates/en/commit_comment.created.template index 1573964..01c0290 100644 --- a/src/main/resources/templates/en/commit_comment.created.template +++ b/src/main/resources/templates/en/commit_comment.created.template @@ -1,3 +1,4 @@ +{{! Fired on the "commit_comment" event (action=created): a comment left directly on a commit via GitHub's commit view. This is NOT a PR review comment and NOT an issue/PR conversation comment. }} **[{{repository.fullName}}]** New comment on commit {{comment.id}} **Comment on line {{comment.line}} by {{comment.user.login}}** diff --git a/src/main/resources/templates/en/issue_comment.created.template b/src/main/resources/templates/en/issue_comment.created.template index 419547a..18f5916 100644 --- a/src/main/resources/templates/en/issue_comment.created.template +++ b/src/main/resources/templates/en/issue_comment.created.template @@ -1,6 +1,8 @@ +{{! Fired on the "issue_comment" event (action=created). }} +{{! This also fires for top-level comments on Pull Requests, because GitHub models a PR's conversation timeline as an issue. }} +{{! It does not fire for inline diff-line review comments — those are pull_request_review_comment events, which we intentionally do not notify on. }} **[{{repository.fullName}}]** New comment by **{{sender.login}}** on issue **{{{issue.title}}}** {{{comment.body}}} [comment]({{comment.htmlUrl}}) -— diff --git a/src/main/resources/templates/en/issues.closed.template b/src/main/resources/templates/en/issues.closed.template index b97d57d..e10a739 100644 --- a/src/main/resources/templates/en/issues.closed.template +++ b/src/main/resources/templates/en/issues.closed.template @@ -1,3 +1,5 @@ +{{! Fired on the "issues" event (action=closed): an issue — never a pull request — was closed. }} +{{! Closing or merging a PR comes through pull_request.closed instead. }} **[{{repository.fullName}}]** Issue **{{{issue.title}}}** {{action}} by **{{sender.login}}** [issue]({{issue.htmlUrl}}) diff --git a/src/main/resources/templates/en/issues.opened.template b/src/main/resources/templates/en/issues.opened.template index 06a67dd..c087b49 100644 --- a/src/main/resources/templates/en/issues.opened.template +++ b/src/main/resources/templates/en/issues.opened.template @@ -1,3 +1,4 @@ +{{! Fired on the "issues" event (action=opened): a new issue (never a pull request) was created. }} **[{{repository.fullName}}]** Issue **{{{issue.title}}}** {{action}} by **{{issue.user.login}}** {{{issue.body}}} diff --git a/src/main/resources/templates/en/issues.reopened.template b/src/main/resources/templates/en/issues.reopened.template index c1b041f..5084c54 100644 --- a/src/main/resources/templates/en/issues.reopened.template +++ b/src/main/resources/templates/en/issues.reopened.template @@ -1,3 +1,4 @@ +{{! Fired on the "issues" event (action=reopened): a previously closed issue (never a pull request) was reopened. }} **[{{repository.fullName}}]** Issue **{{{issue.title}}}** {{action}} by **{{sender.login}}** {{{issue.body}}} diff --git a/src/main/resources/templates/en/pull_request.closed.template b/src/main/resources/templates/en/pull_request.closed.template index c0219e6..2fa40e3 100644 --- a/src/main/resources/templates/en/pull_request.closed.template +++ b/src/main/resources/templates/en/pull_request.closed.template @@ -1,3 +1,5 @@ +{{! Fired on the "pull_request" event (action=closed). }} +{{! GitHub uses action=closed for BOTH merged and merely-closed PRs, so this template branches on pullRequest.merged to tell them apart. }} {{#pullRequest.merged}} 🚀 **Pull Request Merged!** by **{{ pullRequest.user.login }}** {{/pullRequest.merged}} diff --git a/src/main/resources/templates/en/pull_request.opened.template b/src/main/resources/templates/en/pull_request.opened.template index a327798..e1c427c 100644 --- a/src/main/resources/templates/en/pull_request.opened.template +++ b/src/main/resources/templates/en/pull_request.opened.template @@ -1,3 +1,4 @@ +{{! Fired on the "pull_request" event (action=opened): a PR was newly opened. SURPRISE: this does NOT fire when a PR is reopened (action=reopened) or marked ready from draft (action=ready_for_review); those actions have no template and are therefore silent. }} [**{{pullRequest.title}}**]({{pullRequest.htmlUrl}}) (+{{pullRequest.additions}}/-{{pullRequest.deletions}}) by **@{{pullRequest.user.login}}** {{{pullRequest.body}}} 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..8ca5fbe 100644 --- a/src/main/resources/templates/en/pull_request_review.submitted.template +++ b/src/main/resources/templates/en/pull_request_review.submitted.template @@ -1,3 +1,6 @@ +{{! Fired on the "pull_request_review" event: a reviewer finished a review via "Review changes". }} +{{! SURPRISE: a bare Approve carries no body, so only the prefix line renders. }} +{{! Any inline diff-line comments made in the same review arrive as separate pull_request_review_comment events, which we intentionally do not notify on. }} {{#review.body}}**[{{repository.fullName}}]** Pull request review **{{pullRequest.title}}** was {{action}} by **{{review.user.login}}** {{{review.body}}} diff --git a/src/main/resources/templates/en/push.template b/src/main/resources/templates/en/push.template index 51b2108..e29fbf6 100644 --- a/src/main/resources/templates/en/push.template +++ b/src/main/resources/templates/en/push.template @@ -1,3 +1,6 @@ +{{! Fired on the "push" event (no action segment): commits pushed to any branch or tag. }} +{{! Also fires for force-pushes and for branch/tag deletions. }} +{{! A deletion carries no commits, so the commits-empty guard below renders nothing for it. }} {{^commits.isEmpty}} **[{{repository.fullName}}]** Push by **{{sender.login}}** From 563d893e60fb30e611ba956f9d784e8be83316b6 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Thu, 18 Jun 2026 14:38:51 +0200 Subject: [PATCH 5/8] feat: simplify issue comment created template --- .../resources/templates/en/issue_comment.created.template | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/resources/templates/en/issue_comment.created.template b/src/main/resources/templates/en/issue_comment.created.template index 18f5916..06030e4 100644 --- a/src/main/resources/templates/en/issue_comment.created.template +++ b/src/main/resources/templates/en/issue_comment.created.template @@ -1,8 +1,7 @@ {{! Fired on the "issue_comment" event (action=created). }} {{! This also fires for top-level comments on Pull Requests, because GitHub models a PR's conversation timeline as an issue. }} {{! It does not fire for inline diff-line review comments — those are pull_request_review_comment events, which we intentionally do not notify on. }} -**[{{repository.fullName}}]** New comment by **{{sender.login}}** on issue **{{{issue.title}}}** +**{{{issue.title}}}** +**@{{comment.user.login}}** [commented]({{comment.htmlUrl}}): {{{comment.body}}} - -[comment]({{comment.htmlUrl}}) From acd235a7eb1c6d3626e93f328666cff56eaf5b05 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Thu, 18 Jun 2026 14:43:08 +0200 Subject: [PATCH 6/8] feat: simplify pull request review submitted template --- src/main/kotlin/com/wire/github/response/model/Review.kt | 8 ++++++-- .../templates/en/pull_request_review.submitted.template | 8 +++----- 2 files changed, 9 insertions(+), 7 deletions(-) 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..4376be1 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,11 @@ import kotlinx.serialization.Serializable @Serializable data class Review( - val body: String, + val body: String? = null, val user: User, val state: String -) +) { + val approved: Boolean get() = state.equals("approved", ignoreCase = true) + val changesRequested: Boolean get() = state.equals("changes_requested", ignoreCase = true) + val commented: Boolean get() = state.equals("commented", ignoreCase = true) +} 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 8ca5fbe..7247e9c 100644 --- a/src/main/resources/templates/en/pull_request_review.submitted.template +++ b/src/main/resources/templates/en/pull_request_review.submitted.template @@ -1,9 +1,7 @@ {{! Fired on the "pull_request_review" event: a reviewer finished a review via "Review changes". }} {{! SURPRISE: a bare Approve carries no body, so only the prefix line renders. }} {{! Any inline diff-line comments made in the same review arrive as separate pull_request_review_comment events, which we intentionally do not notify on. }} -{{#review.body}}**[{{repository.fullName}}]** Pull request review **{{pullRequest.title}}** was {{action}} by **{{review.user.login}}** - +[**{{{pullRequest.title}}}**]({{pullRequest.htmlUrl}}): {{#review.approved}}✅ **Approved** by {{/review.approved}}{{#review.changesRequested}}🔴 **Changes requested** by {{/review.changesRequested}} **@{{review.user.login}}** {{#review.commented}}Commented{{/review.commented}} +{{#review.body}} {{{review.body}}} - -[pull request]({{pullRequest.htmlUrl}}) -—{{/review.body}} +{{/review.body}} From 1ab6d7447d1ad4b1be51a40b06c9f9a77d667c94 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Thu, 18 Jun 2026 14:48:51 +0200 Subject: [PATCH 7/8] feat: handle draft PRs --- .../kotlin/com/wire/github/response/model/PullRequest.kt | 3 ++- src/main/kotlin/com/wire/github/util/TemplateHandler.kt | 2 +- .../resources/templates/en/pull_request.opened.template | 6 +++++- .../templates/en/pull_request.ready_for_review.template | 5 +++++ 4 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 src/main/resources/templates/en/pull_request.ready_for_review.template 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 ebb756e..26af81a 100644 --- a/src/main/kotlin/com/wire/github/response/model/PullRequest.kt +++ b/src/main/kotlin/com/wire/github/response/model/PullRequest.kt @@ -13,5 +13,6 @@ data class PullRequest( val merged: Boolean, val number: Int, val additions: Int = 0, - val deletions: Int = 0 + val deletions: Int = 0, + val draft: Boolean = false ) diff --git a/src/main/kotlin/com/wire/github/util/TemplateHandler.kt b/src/main/kotlin/com/wire/github/util/TemplateHandler.kt index 2b63bcd..66a21a6 100644 --- a/src/main/kotlin/com/wire/github/util/TemplateHandler.kt +++ b/src/main/kotlin/com/wire/github/util/TemplateHandler.kt @@ -26,7 +26,7 @@ class TemplateHandler { populateTemplate( mustache = template, model = response - ) + )?.takeIf { it.isNotBlank() } } catch (exception: MustacheNotFoundException) { logger.error("MustacheNotFoundException: $exception") null diff --git a/src/main/resources/templates/en/pull_request.opened.template b/src/main/resources/templates/en/pull_request.opened.template index e1c427c..6b24a4b 100644 --- a/src/main/resources/templates/en/pull_request.opened.template +++ b/src/main/resources/templates/en/pull_request.opened.template @@ -1,4 +1,8 @@ -{{! Fired on the "pull_request" event (action=opened): a PR was newly opened. SURPRISE: this does NOT fire when a PR is reopened (action=reopened) or marked ready from draft (action=ready_for_review); those actions have no template and are therefore silent. }} +{{! Fired on the "pull_request" event (action=opened): a PR was newly opened. }} +{{! Gated on NOT draft: a PR opened directly as a draft renders nothing and sends no notification. It is announced later by pull_request.ready_for_review.template when the draft is marked ready. }} +{{! The reopened action (action=reopened) has no template and is intentionally silent. }} +{{^pullRequest.draft}} [**{{pullRequest.title}}**]({{pullRequest.htmlUrl}}) (+{{pullRequest.additions}}/-{{pullRequest.deletions}}) by **@{{pullRequest.user.login}}** {{{pullRequest.body}}} +{{/pullRequest.draft}} 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..00ceab4 --- /dev/null +++ b/src/main/resources/templates/en/pull_request.ready_for_review.template @@ -0,0 +1,5 @@ +{{! Fired on the "pull_request" event (action=ready_for_review): a draft PR was marked ready for review. }} +{{! Mirrors pull_request.opened so a PR that started as a draft is still announced once — at the moment it becomes ready, rather than when it was first opened as a draft. }} +[**{{pullRequest.title}}**]({{pullRequest.htmlUrl}}) (+{{pullRequest.additions}}/-{{pullRequest.deletions}}) by **@{{pullRequest.user.login}}** + +{{{pullRequest.body}}} From a511109fca1492698b7dcfdf4e14a2197c8d5a38 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Thu, 18 Jun 2026 14:57:30 +0200 Subject: [PATCH 8/8] feat: adjust the rest of the templates to compact style Let's keep it lightweight and easy to read; these are likely to be frequent. --- .../templates/en/commit_comment.created.template | 6 +----- .../resources/templates/en/issues.closed.template | 5 +---- .../resources/templates/en/issues.opened.template | 5 +---- .../resources/templates/en/issues.reopened.template | 5 +---- .../templates/en/pull_request.closed.template | 11 +---------- src/main/resources/templates/en/push.template | 8 +++----- 6 files changed, 8 insertions(+), 32 deletions(-) diff --git a/src/main/resources/templates/en/commit_comment.created.template b/src/main/resources/templates/en/commit_comment.created.template index 01c0290..6299079 100644 --- a/src/main/resources/templates/en/commit_comment.created.template +++ b/src/main/resources/templates/en/commit_comment.created.template @@ -1,8 +1,4 @@ {{! Fired on the "commit_comment" event (action=created): a comment left directly on a commit via GitHub's commit view. This is NOT a PR review comment and NOT an issue/PR conversation comment. }} -**[{{repository.fullName}}]** New comment on commit {{comment.id}} +**@{{comment.user.login}}** [commented on a commit]({{comment.htmlUrl}}): -**Comment on line {{comment.line}} by {{comment.user.login}}** {{{comment.body}}} - -[comment]({{comment.htmlUrl}}) -— diff --git a/src/main/resources/templates/en/issues.closed.template b/src/main/resources/templates/en/issues.closed.template index e10a739..f5f47eb 100644 --- a/src/main/resources/templates/en/issues.closed.template +++ b/src/main/resources/templates/en/issues.closed.template @@ -1,6 +1,3 @@ {{! Fired on the "issues" event (action=closed): an issue — never a pull request — was closed. }} {{! Closing or merging a PR comes through pull_request.closed instead. }} -**[{{repository.fullName}}]** Issue **{{{issue.title}}}** {{action}} by **{{sender.login}}** - -[issue]({{issue.htmlUrl}}) -— +[**{{{issue.title}}}**]({{issue.htmlUrl}}) {{action}} by **@{{sender.login}}** diff --git a/src/main/resources/templates/en/issues.opened.template b/src/main/resources/templates/en/issues.opened.template index c087b49..63ad527 100644 --- a/src/main/resources/templates/en/issues.opened.template +++ b/src/main/resources/templates/en/issues.opened.template @@ -1,7 +1,4 @@ {{! Fired on the "issues" event (action=opened): a new issue (never a pull request) was created. }} -**[{{repository.fullName}}]** Issue **{{{issue.title}}}** {{action}} by **{{issue.user.login}}** +[**{{{issue.title}}}**]({{issue.htmlUrl}}) {{action}} by **@{{issue.user.login}}** {{{issue.body}}} - -[issue]({{issue.htmlUrl}}) -— diff --git a/src/main/resources/templates/en/issues.reopened.template b/src/main/resources/templates/en/issues.reopened.template index 5084c54..0b76f6c 100644 --- a/src/main/resources/templates/en/issues.reopened.template +++ b/src/main/resources/templates/en/issues.reopened.template @@ -1,7 +1,4 @@ {{! Fired on the "issues" event (action=reopened): a previously closed issue (never a pull request) was reopened. }} -**[{{repository.fullName}}]** Issue **{{{issue.title}}}** {{action}} by **{{sender.login}}** +[**{{{issue.title}}}**]({{issue.htmlUrl}}) {{action}} by **@{{sender.login}}** {{{issue.body}}} - -{{issue.htmlUrl}} -— diff --git a/src/main/resources/templates/en/pull_request.closed.template b/src/main/resources/templates/en/pull_request.closed.template index 2fa40e3..d66da7c 100644 --- a/src/main/resources/templates/en/pull_request.closed.template +++ b/src/main/resources/templates/en/pull_request.closed.template @@ -1,12 +1,3 @@ {{! Fired on the "pull_request" event (action=closed). }} {{! GitHub uses action=closed for BOTH merged and merely-closed PRs, so this template branches on pullRequest.merged to tell them apart. }} -{{#pullRequest.merged}} -🚀 **Pull Request Merged!** by **{{ pullRequest.user.login }}** -{{/pullRequest.merged}} -{{^pullRequest.merged}} -❌ **Pull Request Closed!** by **{{ pullRequest.user.login }}** -{{/pullRequest.merged}} - -📦 **Repository:** {{repository.fullName}} -🔖 **Title:** {{pullRequest.title}} -🔗 **PR Link:** [#{{pullRequest.number}}]({{pullRequest.htmlUrl}}) +[**{{{pullRequest.title}}}**]({{pullRequest.htmlUrl}}): {{#pullRequest.merged}}🚀 **Merged**{{/pullRequest.merged}}{{^pullRequest.merged}}❌ **Closed**{{/pullRequest.merged}} by **@{{sender.login}}** diff --git a/src/main/resources/templates/en/push.template b/src/main/resources/templates/en/push.template index e29fbf6..18b37d0 100644 --- a/src/main/resources/templates/en/push.template +++ b/src/main/resources/templates/en/push.template @@ -2,11 +2,9 @@ {{! Also fires for force-pushes and for branch/tag deletions. }} {{! A deletion carries no commits, so the commits-empty guard below renders nothing for it. }} {{^commits.isEmpty}} -**[{{repository.fullName}}]** Push by **{{sender.login}}** +**@{{sender.login}}** [pushed]({{compare}}) to **{{repository.fullName}}**: {{#commits}} - - {{{message}}} +- {{{message}}} {{/commits}} - -[compare]({{compare}}) -—{{/commits.isEmpty}} +{{/commits.isEmpty}}