Skip to content

MM-69953 Fixing inconsistent behavior for issue webhook events - #689

Merged
avasconcelos114 merged 5 commits into
masterfrom
MM-69953
Aug 13, 2026
Merged

MM-69953 Fixing inconsistent behavior for issue webhook events#689
avasconcelos114 merged 5 commits into
masterfrom
MM-69953

Conversation

@avasconcelos114

@avasconcelos114 avasconcelos114 commented Jul 30, 2026

Copy link
Copy Markdown
Member

Summary

This PR closes a gap in behaviors that happen across different types of issues and how webhooks handle them

Ticket Link

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

Change Impact: 🟠 Medium

Reasoning: The change updates a shared webhook subscription API across multiple handlers and adds authorization checks for confidential issues. Tests cover confidential and non-confidential notification paths, which reduces regression risk.

Regression Risk: Medium—incorrect confidentiality propagation or permission handling could affect notification delivery across several webhook event types.

QA Recommendation: Perform targeted manual QA for confidential issues, issue comments, and group/project subscriptions. Verify that non-confidential webhook events remain unchanged. Skipping manual QA carries moderate risk.

Generated by CodeRabbitAI

@avasconcelos114 avasconcelos114 self-assigned this Jul 30, 2026
@avasconcelos114
avasconcelos114 requested a review from a team as a code owner July 30, 2026 13:50
@avasconcelos114 avasconcelos114 added the 2: Dev Review Requires review by a core committer label Jul 30, 2026
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

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: 71310333-55c0-4fa1-9fd1-6c554c9fff75

📥 Commits

Reviewing files that changed from the base of the PR and between a2422f6 and 40f7ae6.

📒 Files selected for processing (5)
  • server/command.go
  • server/command_test.go
  • server/webhook.go
  • server/webhook/note.go
  • server/webhook/note_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/command_test.go

📝 Walkthrough

Walkthrough

Confidential issue subscriptions now check group access, apply project and group permission filtering, and propagate confidentiality through issue, note, and other webhook lookups. Tests cover authorization, access evaluation, filtering, channel routing, and flag propagation.

Changes

Confidential issue access and delivery

Layer / File(s) Summary
Group subscription authorization
server/command.go, server/command_test.go
confidential_issues group subscriptions now verify GitLab group access before subscribe. Tests cover allowed, denied, and skipped checks.
Confidential subscription permission filtering
server/webhook/webhook.go, server/webhook.go, server/subscriptions.go, server/webhook_test.go, server/subscriptions_test.go
Subscription lookup now accepts isConfidential. Project filtering uses the higher direct or inherited access level. Confidential public projects require access above guest level. Tests cover the access rules.
Webhook confidentiality propagation
server/webhook/issue.go, server/webhook/note.go, server/webhook/deployment.go, server/webhook/jobs.go, server/webhook/merge_request.go, server/webhook/pipeline.go, server/webhook/push.go, server/webhook/release.go, server/webhook/tag.go, server/webhook/webhook.go, server/webhook/webhook_test.go, server/webhook/constants.go, server/webhook/issue_fixture_test.go
Webhook handlers and the retriever contract now pass confidentiality state into subscription lookup. Issue and note handling derive confidentiality from payload and event type. Non-confidential event handlers pass false.
Confidential webhook validation
server/webhook/issue_test.go, server/webhook/note_test.go
Fixtures and tests verify confidential issue and comment delivery, feature gating, and confidentiality flag propagation.

Estimated code review effort: 4 (Complex) | ~45 minutes

Mergeability Score: ⚪ Minimal · up to 40f7a

The pull request updates issue webhook behavior and related tests; no actionable merge-blocking risk remains based on the supplied evidence.

Sequence Diagram(s)

sequenceDiagram
  participant GitLabWebhook
  participant WebhookHandler
  participant gitlabRetreiver
  participant Plugin
  GitLabWebhook->>WebhookHandler: issue or note event with confidentiality
  WebhookHandler->>gitlabRetreiver: GetSubscribedChannelsForProject with isConfidential
  gitlabRetreiver->>Plugin: GetSubscribedChannelsForProject
  Plugin-->>gitlabRetreiver: filtered subscriptions
  gitlabRetreiver-->>WebhookHandler: subscribed channels
Loading

Poem

A rabbit hops through secret doors,
And checks each flag on hidden shores.
Confident issues take the trail,
While quiet notes and channels sail.
The moonlit tests all pass tonight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the issue webhook event behavior fix, which matches the pull request's primary changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/webhook/issue_test.go`:
- Around line 208-212: Extend the assertions in the result-comparison loop to
compare each expected test.res[index].ToChannels value with
res[index].ToChannels, alongside the existing Message, ToUsers, and From checks,
so confidential-delivery results validate channel recipients.

In `@server/webhook/note.go`:
- Around line 67-71: Update the subscription delivery loop in the note webhook
handler to skip confidential issue comments unless each subscription’s
ConfidentialIssues() opt-in is enabled, matching the existing handleChannelIssue
behavior; add a regression test in note_test.go covering a non-opted-in
subscription.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2489b9ed-5e5c-4b32-b9dd-b2747831188d

📥 Commits

Reviewing files that changed from the base of the PR and between 6673c91 and 3152ce7.

📒 Files selected for processing (19)
  • server/command.go
  • server/command_test.go
  • server/subscriptions.go
  • server/subscriptions_test.go
  • server/webhook.go
  • server/webhook/deployment.go
  • server/webhook/issue.go
  • server/webhook/issue_fixture_test.go
  • server/webhook/issue_test.go
  • server/webhook/jobs.go
  • server/webhook/merge_request.go
  • server/webhook/note.go
  • server/webhook/note_test.go
  • server/webhook/pipeline.go
  • server/webhook/push.go
  • server/webhook/release.go
  • server/webhook/tag.go
  • server/webhook/webhook.go
  • server/webhook/webhook_test.go

Comment thread server/webhook/issue_test.go
Comment thread server/webhook/note.go
@avasconcelos114 avasconcelos114 added the 3: Security Review Review requested from Security Team label Jul 30, 2026
@avasconcelos114

Copy link
Copy Markdown
Member Author

@CodeRabbit approve if the last commit addressed the previously raised concerns

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Tip

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="mattermost/mattermost-plugin-gitlab"
pr="689"

echo "== PR metadata and commits =="
gh pr view "$pr" --repo "$repo" --json url,headRefOid,commits,reviews \
  --jq '{url, headRefOid, commits: [.commits[] | {oid: .oid, messageHeadline: .messageHeadline, committedDate: .committedDate}], reviews: [.reviews[] | {author: .author.login, state: .state, submittedAt: .submittedAt, body: .body}]}'

echo
echo "== CodeRabbit PR review comments =="
gh api --paginate "repos/$repo/pulls/$pr/comments?per_page=100" \
  --jq '.[] | select(.user.login == "coderabbitai") | {id, path, line, original_line, commit_id, created_at, body, html_url}'

echo
echo "== Review threads and resolution status =="
gh api graphql -F owner="mattermost" -F name="mattermost-plugin-gitlab" -F number="$pr" -f query='
query($owner: String!, $name: String!, $number: Int!) {
  repository(owner: $owner, name: $name) {
    pullRequest(number: $number) {
      reviewThreads(first: 100) {
        nodes {
          isResolved
          path
          line
          comments(first: 20) {
            nodes {
              author { login }
              body
              url
              commit { oid }
            }
          }
        }
      }
    }
  }
}' --jq '.data.repository.pullRequest.reviewThreads.nodes[]
  | select(any(.comments.nodes[]; .author.login == "coderabbitai"))
  | {isResolved, path, line, comments: [.comments.nodes[] | {author: .author.login, body, url, commit: .commit.oid}]}'

echo
echo "== Latest commit patch =="
latest=$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq .headRefOid)
git show --format=fuller --stat "$latest"
git show --format= --unified=80 "$latest" -- server/command.go server/subscriptions.go server/webhook/issue.go server/webhook/note.go

Length of output: 17515


🏁 Script executed:

#!/bin/bash
set -euo pipefail

latest="80025be463b3cdcfe852b4f5e15ef74ae14149f4"

echo "== Latest test-only diff =="
git show --format= --unified=100 "$latest" -- \
  server/webhook/issue_test.go \
  server/webhook/note_test.go

echo
echo "== Relevant test declarations =="
ast-grep outline server/webhook/note_test.go --items all --type function --match 'Confidential|IssueComment'
ast-grep outline server/webhook/issue_test.go --items all --type function --match 'ConfidentialIssueWebhook'

Length of output: 13526


@avasconcelos114 The last commit addresses both previously raised concerns:

  • Confidential issue webhook tests now assert ToChannels.
  • Confidential issue comments are gated on the confidential_issues opt-in, with regression coverage for both opted-in and non-opted-in subscriptions.

[approve]

You are interacting with an AI system.

Comment thread server/webhook.go
// Check if the user has guest permission or less for both project and group level
if (userPermission.ProjectAccess != nil && userPermission.ProjectAccess.AccessLevel <= gitlabLib.GuestPermissions) || (userPermission.GroupAccess != nil && userPermission.GroupAccess.AccessLevel <= gitlabLib.GuestPermissions) {
return false
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The core issue seems to still be here, if both ProjectAccess and GroupAccess is nil, you skip the checks. The recommendation is to add a helper to handle this:

func effectiveAccess(perms *gitlabLib.Permissions) gitlabLib.AccessLevelValue {
	if perms == nil {
		return 0
	}
	var level gitlabLib.AccessLevelValue
	if perms.ProjectAccess != nil && perms.ProjectAccess.AccessLevel > level {
		level = perms.ProjectAccess.AccessLevel
	}
	if perms.GroupAccess != nil && perms.GroupAccess.AccessLevel > level {
		level = perms.GroupAccess.AccessLevel
	}
	return level
}

// For confidential content, require > Guest
// return effectiveAccess(result.Permissions) > gitlabLib.GuestPermissions

I definitely think this is more readable and more correct

@jgheithcock
jgheithcock self-requested a review August 3, 2026 22:03
@avasconcelos114

Copy link
Copy Markdown
Member Author

Note: Testing the cherry-pick automation - I'll be closing any PRs prematurely created as part of the tests

Comment thread server/webhook/note.go Outdated
subs := w.gitlabRetreiver.GetSubscribedChannelsForProject(
ctx, namespace, project,
repo.Visibility == gitlab.PublicVisibility,
event.Issue.Confidential,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think CodeRabbit didn't quite go far enough here - sorry I missed it. We should use the same metric for the comments as for handleChannelIssue and add

isConfidential := event.Issue.Confidential || event.EventType == string(gitlab.EventConfidentialNote)
above and use isConfidential in place of the bare event.Issue.Confidential (So we catch it either way.)

We would also want to add a regression test where event_type is confidential_note and issue.confidential is absent/false.

@jgheithcock jgheithcock left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm marking this approved so you don't need a re-review, but I do think we should be consistent here (as well as catching this edge case).

@avasconcelos114 avasconcelos114 removed the 2: Dev Review Requires review by a core committer label Aug 6, 2026

@hmohammed-prodsec hmohammed-prodsec left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for the changes, LGTM 👍

@avasconcelos114
avasconcelos114 merged commit 290d81d into master Aug 13, 2026
17 checks passed
@avasconcelos114
avasconcelos114 deleted the MM-69953 branch August 13, 2026 19:07

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 Starting cherry-pick of #689 onto the following branches:

  • release-1.12
  • release-1.13

Results will be posted here when complete.

Open in Web View Automation 

Sent by Cursor Automation: Plugin Cherry-pick Automation

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 Cherry-pick of #689 complete.

  • ✅ release-1.12: #700
  • ✅ release-1.13: #701
Open in Web View Automation 

Sent by Cursor Automation: Plugin Cherry-pick Automation

avasconcelos114 added a commit that referenced this pull request Aug 13, 2026
* MM-69953 Fixing inconsistent behavior for issue webhook events (#689)

* MM-69953 Fixing inconsistent behavior for issue webhook events

* Applying PR feedback

* Added function to improve readability and type safety

* Making confidential checks more consistent

* Applying PR feedback

* Apply lint fixes

Co-authored-by: Andre Vasconcelos <andre.onogoro@gmail.com>

---------

Co-authored-by: Andre Vasconcelos <a-andre.vasconcelos@mattermost.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Andre Vasconcelos <andre.onogoro@gmail.com>
avasconcelos114 added a commit that referenced this pull request Aug 13, 2026
* MM-69953 Fixing inconsistent behavior for issue webhook events (#689)

* MM-69953 Fixing inconsistent behavior for issue webhook events

* Applying PR feedback

* Added function to improve readability and type safety

* Making confidential checks more consistent

* Applying PR feedback

* Apply lint fixes

Co-authored-by: Andre Vasconcelos <andre.onogoro@gmail.com>

---------

Co-authored-by: Andre Vasconcelos <a-andre.vasconcelos@mattermost.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Andre Vasconcelos <andre.onogoro@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3: Security Review Review requested from Security Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants