Skip to content

MM-67473 Adding support to workflow run success/failures#975

Open
avasconcelos114 wants to merge 8 commits intomasterfrom
MM-67473
Open

MM-67473 Adding support to workflow run success/failures#975
avasconcelos114 wants to merge 8 commits intomasterfrom
MM-67473

Conversation

@avasconcelos114
Copy link
Contributor

@avasconcelos114 avasconcelos114 commented Mar 3, 2026

Summary

This PR adds support to workflow run success and failure messages under the workflow_run_success and workflow_run_failure events

image

Ticket Link

Fixes https://mattermost.atlassian.net/browse/MM-67473

Change Impact: 🟠 Medium

Reasoning: The PR adds new subscription features, templates, and webhook handling across multiple server modules (webhook, templates, subscriptions, commands), expanding notification surface without modifying auth or data persistence.
Regression Risk: Moderate — it changes routing and rendering logic for notifications and adds public template/feature flags; tests cover many cases (including success, failure, cancelled, timed_out), but integration edge cases (org-member filters, posting failures, template rendering variations) could surface regressions.
** QA Recommendation:** Perform focused manual QA on workflow-run notifications: subscribe/unsubscribe flows for both success and failure, verify org-member exclusion/inclusion behavior, and validate message rendering for success, failure, cancelled, and timed_out conclusions; do not skip manual QA.

Generated by CodeRabbitAI

Release Notes

  • New Features
    • Added workflow run completion notifications—users can now subscribe separately to workflow run failures and successes.
    • New notification feature enables reporting of workflow run outcomes including success, failure, cancellation, and timeouts with associated metadata.
    • Updated subscription options to include new workflow run event features for enhanced notification control.

@avasconcelos114 avasconcelos114 self-assigned this Mar 3, 2026
@avasconcelos114 avasconcelos114 requested a review from a team as a code owner March 3, 2026 18:40
@avasconcelos114 avasconcelos114 added 2: Dev Review Requires review by a core committer 3: QA Review Requires review by a QA tester labels Mar 3, 2026
@avasconcelos114
Copy link
Contributor Author

@coderabbitai please review this PR 🐇

@coderabbitai
Copy link

coderabbitai bot commented Mar 3, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: debc46b1-095c-47f9-ac6d-d813fb4e5ed9

📥 Commits

Reviewing files that changed from the base of the PR and between a34b178 and 6b2ce7d.

📒 Files selected for processing (1)
  • server/plugin/webhook_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/plugin/webhook_test.go

📝 Walkthrough

Walkthrough

Adds workflow-run notifications: new feature flags for run success/failure, subscription predicates, a workflow-run template, webhook handler to process completed runs, test utilities, and tests validating rendering and posting behavior.

Changes

Cohort / File(s) Summary
Feature Registration
server/plugin/command.go
Adds featureWorkflowRunFailure and featureWorkflowRunSuccess, registers them in validFeatures, and updates autocomplete help to include workflow_run_failure and workflow_run_success.
Subscription Predicates
server/plugin/subscriptions.go
Adds WorkflowRunFailures() and WorkflowRunSuccesses() methods to check subscription feature flags.
Templates & Help Text
server/plugin/template.go
Adds exported workflowRunCompleted template, updates help text to mention new features, and replaces job-specific constants with conclusion-named constants (e.g., workflowConclusionFailure).
Webhook / Event Handling
server/plugin/webhook.go
Routes WorkflowRunEvent to postWorkflowRunEvent(), evaluates conclusions (success, failure, cancelled, timed_out), renders workflowRunCompleted, and posts per-subscription applying membership filters and logging errors.
Test Utilities
server/plugin/test_utils.go
Adds GetMockWorkflowRunEvent(action, conclusion, repo, org, sender string) *github.WorkflowRunEvent helper.
Tests
server/plugin/template_test.go, server/plugin/webhook_test.go
Adds TestWorkflowRunNotification (duplicate declarations present) to validate rendering for multiple conclusions and TestPostWorkflowRunEvent to exercise routing, filtering, posting, and error cases.
Other
go.mod
Module/test dependency updates reflected in manifest.

Sequence Diagram(s)

sequenceDiagram
    actor GitHub
    participant Webhook as Plugin Webhook
    participant Store as Subscription Store
    participant Template as Template Engine
    participant API as Mattermost API

    GitHub->>Webhook: Send WorkflowRunEvent (action: completed)
    Webhook->>Webhook: postWorkflowRunEvent()
    Webhook->>Store: Query subscriptions for repo/org
    Store-->>Webhook: Return subscriptions
    Webhook->>Store: Filter subscriptions by WorkflowRunFailures/Successes and membership rules
    Store-->>Webhook: Matching subscriptions
    loop For each matching subscription
        Webhook->>Template: Render workflowRunCompleted with event data
        Template-->>Webhook: Rendered message
        Webhook->>API: Create post (custom_git_workflow_run) in channel
        API-->>Webhook: Post result / error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

"A rabbit hopped by with a patch and a cheer,
New run flags for success and failure appear.
Templates warmed, webhooks set to chime,
Tests will dance in CI time.
🐇✨"

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and directly summarizes the main change: adding support for workflow run success and failure notifications, which is the primary objective across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch MM-67473

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.5.0)

Error: unknown linters: 'modernize', run 'golangci-lint help linters' to see the list of supported linters
The command is terminated due to an error: unknown linters: 'modernize', run 'golangci-lint help linters' to see the list of supported linters


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/plugin/webhook.go`:
- Around line 1505-1529: The workflow-run notification loop (iterating subs and
using sub.WorkflowRunFailures()/sub.WorkflowRunSuccesses()) currently skips
applying org-member subscription filters; update the loop to check each
subscription's org-member policy (e.g., methods like sub.ExcludeOrgMembers() and
sub.IncludeOnlyOrgMembers()) against the event actor/org membership flag (e.g.,
event.ActorIsOrgMember or equivalent on the event payload) before
rendering/sending posts; if the subscription excludes org members and the actor
is an org member skip, and if the subscription is include-only and the actor is
not an org member skip, then proceed to renderTemplate("workflowRunCompleted",
event) and call p.client.Post.CreatePost(post).

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff976a6 and 963e5ce.

📒 Files selected for processing (5)
  • server/plugin/command.go
  • server/plugin/subscriptions.go
  • server/plugin/template.go
  • server/plugin/template_test.go
  • server/plugin/webhook.go

@avasconcelos114
Copy link
Contributor Author

@coderabbitai Please review again and either request more changes or approve the PR

@coderabbitai
Copy link

coderabbitai bot commented Mar 3, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Examine the template_test.go file to check for duplicate test functions
echo "=== Checking for duplicate test functions in template_test.go ==="
cat server/plugin/template_test.go | grep -n "func TestWorkflowRunNotification"

echo -e "\n=== Examining the full template_test.go file ==="
cat server/plugin/template_test.go

Length of output: 60811


🏁 Script executed:

#!/bin/bash

# Check webhook.go for the new postWorkflowRunEvent implementation
echo "=== Examining webhook.go for workflow run event handling ==="
cat server/plugin/webhook.go

Length of output: 40602


🏁 Script executed:

#!/bin/bash

# Check template.go for the new workflow run template
echo "=== Examining template.go for workflowRunCompleted template ==="
cat server/plugin/template.go

Length of output: 26687


🏁 Script executed:

#!/bin/bash

# Check command.go and subscriptions.go
echo "=== Examining command.go ==="
cat server/plugin/command.go

echo -e "\n=== Examining subscriptions.go ==="
cat server/plugin/subscriptions.go

Length of output: 55881


@avasconcelos114, I've completed a thorough review of the PR. The implementation looks excellent! Here's my assessment:

✅ Code Quality

Strengths:

  • Clean implementation: Follows existing patterns consistently across all files
  • Efficient template rendering: The workflow run message is rendered once and reused across all subscriptions
  • Proper feature separation: New WorkflowRunFailures() and WorkflowRunSuccesses() methods allow granular control
  • Comprehensive test coverage: All four workflow conclusions (success, failure, cancelled, timed_out) are tested
  • Good UX: Template uses appropriate emojis (✅, ❌, 🚫, ⚠️) for different states
  • Constants refactoring: Consistent use of workflowConclusionFailure/Success/Cancelled/TimedOut throughout

Note: The AI summary incorrectly flagged a duplicate test function, but verification shows only one TestWorkflowRunNotification exists at line 1581.

🎯 Implementation Highlights

  1. webhook.go: Properly filters subscriptions and only posts to channels that have opted in to the specific conclusion type
  2. command.go: New features registered in validFeatures map and documented in help text
  3. subscriptions.go: New predicate methods follow the same pattern as existing feature checks
  4. template.go: Template elegantly handles all conclusion types with conditional emoji rendering

No issues found. The code is production-ready!

[approve]

Comment on lines +1518 to +1523
if workflowRunMessage == "" {
var err error
workflowRunMessage, err = renderTemplate("workflowRunCompleted", event)
if err != nil {
p.client.Log.Warn("Failed to render template", "Error", err.Error())
return
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be continue instead of return so that it finishes processing all the subscriptions despite that template error on a specific one?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this more, I see we just have one template for all so we should probably try to get the workflowRunMessage once before this iteration loop so that it removes that extra check of the message each time that its processing the subs and is more readable as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh absolutely yes that is much cleaner, I'll fix that up

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
server/plugin/webhook_test.go (1)

1200-1367: Strong table-driven coverage; add cancelled and timed_out routing cases.

Given workflow_run_failure is intended to cover failures/cancellations/timeouts, add explicit cases for cancelled and timed_out to lock behavior and prevent regressions.

🧪 Suggested additions
 		{
 			name:  "successful workflow run failure notification",
 			event: GetMockWorkflowRunEvent(actionCompleted, "failure", MockRepo, MockOrg, MockSender),
 			setup: func() {
 				...
 			},
 		},
+		{
+			name:  "successful workflow run cancelled notification",
+			event: GetMockWorkflowRunEvent(actionCompleted, "cancelled", MockRepo, MockOrg, MockSender),
+			setup: func() {
+				mockKvStore.EXPECT().Get("subscriptions", mock.MatchedBy(func(val any) bool {
+					_, ok := val.(**Subscriptions)
+					return ok
+				})).DoAndReturn(setupMockSubscriptions(map[string][]*Subscription{
+					"mockrepo/mockorg": {
+						{ChannelID: MockChannelID, CreatorID: MockCreatorID, Features: Features(featureWorkflowRunFailure), Repository: MockRepo},
+					},
+				})).Times(1)
+				mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1)
+			},
+		},
+		{
+			name:  "successful workflow run timed_out notification",
+			event: GetMockWorkflowRunEvent(actionCompleted, "timed_out", MockRepo, MockOrg, MockSender),
+			setup: func() {
+				mockKvStore.EXPECT().Get("subscriptions", mock.MatchedBy(func(val any) bool {
+					_, ok := val.(**Subscriptions)
+					return ok
+				})).DoAndReturn(setupMockSubscriptions(map[string][]*Subscription{
+					"mockrepo/mockorg": {
+						{ChannelID: MockChannelID, CreatorID: MockCreatorID, Features: Features(featureWorkflowRunFailure), Repository: MockRepo},
+					},
+				})).Times(1)
+				mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1)
+			},
+		},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/plugin/webhook_test.go` around lines 1200 - 1367, Add two table-driven
test cases inside TestPostWorkflowRunEvent to assert that workflow runs with
conclusions "cancelled" and "timed_out" are routed the same as failures: use
GetMockWorkflowRunEvent(actionCompleted, "cancelled", ...) and
GetMockWorkflowRunEvent(actionCompleted, "timed_out", ...), set up mockKvStore
to return a subscription that includes Features(featureWorkflowRunFailure) (same
pattern as the existing "successful workflow run failure notification" case),
and expect mockAPI.CreatePost to be called once; ensure the test names are
unique (e.g., "workflow run cancelled notification" and "workflow run timed_out
notification") so TestPostWorkflowRunEvent covers these cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/plugin/test_utils.go`:
- Around line 430-448: The test fixture GetMockWorkflowRunEvent builds FullName
and HTML URLs as "repo/org" which is reversed; update FullName, the repository
HTMLURL and the WorkflowRun.HTMLURL to use "org/repo" ordering (swap the repo
and org arguments in the fmt.Sprintf calls that build FullName, Repo.HTMLURL and
WorkflowRun.HTMLURL) so the fixture matches real GitHub payloads and avoids
masking subscription/URL rendering bugs.

---

Nitpick comments:
In `@server/plugin/webhook_test.go`:
- Around line 1200-1367: Add two table-driven test cases inside
TestPostWorkflowRunEvent to assert that workflow runs with conclusions
"cancelled" and "timed_out" are routed the same as failures: use
GetMockWorkflowRunEvent(actionCompleted, "cancelled", ...) and
GetMockWorkflowRunEvent(actionCompleted, "timed_out", ...), set up mockKvStore
to return a subscription that includes Features(featureWorkflowRunFailure) (same
pattern as the existing "successful workflow run failure notification" case),
and expect mockAPI.CreatePost to be called once; ensure the test names are
unique (e.g., "workflow run cancelled notification" and "workflow run timed_out
notification") so TestPostWorkflowRunEvent covers these cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ca5ff94f-827b-4cb9-ad5d-35b682bc82ed

📥 Commits

Reviewing files that changed from the base of the PR and between 963e5ce and 4cb4262.

📒 Files selected for processing (4)
  • server/plugin/template.go
  • server/plugin/test_utils.go
  • server/plugin/webhook.go
  • server/plugin/webhook_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/plugin/webhook.go

@marianunez marianunez removed the 2: Dev Review Requires review by a core committer label Mar 5, 2026
@marianunez marianunez removed the request for review from nevyangelova March 5, 2026 16:44
@avasconcelos114 avasconcelos114 requested a review from ogi-m March 5, 2026 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3: QA Review Requires review by a QA tester

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants