Skip to content

feat(bitbucketdatacenter): Added support for pull request events merged, modified, and approved#2749

Open
mluckam wants to merge 3 commits into
tektoncd:mainfrom
mluckam:bitbucket_datacenter_event_pr_merged
Open

feat(bitbucketdatacenter): Added support for pull request events merged, modified, and approved#2749
mluckam wants to merge 3 commits into
tektoncd:mainfrom
mluckam:bitbucket_datacenter_event_pr_merged

Conversation

@mluckam
Copy link
Copy Markdown

@mluckam mluckam commented May 28, 2026

📝 Description of the Change

Adds support for the following pull request events for provider bitbucket datacenter:

  • pr:merged
  • pr:modified
  • pr:reviewer:approved

🔗 Linked GitHub Issue

Fixes #2748

🧪 Testing Strategy

  • Unit tests
  • Integration tests
  • End-to-end tests
  • Manual testing
  • Not Applicable

🤖 AI Assistance

AI assistance can be used for various tasks, such as code generation,
documentation, or testing.

Please indicate whether you have used AI assistance
for this PR and provide details if applicable.

  • I have not used any AI assistance for this PR.
  • I have used AI assistance for this PR.

✅ Submitter Checklist

  • 📝 My commit messages are clear, informative, and follow the project's How to write a git commit message guide. The Gitlint linter ensures in CI it's properly validated
  • ✨ I have ensured my commit message prefix (e.g., fix:, feat:) matches the "Type of Change" I selected above.
  • ♽ I have run make test and make lint locally to check for and fix any
    issues. For an efficient workflow, I have considered installing
    pre-commit and running pre-commit install to
    automate these checks.
  • 📖 I have added or updated documentation for any user-facing changes.
  • 🧪 I have added sufficient unit tests for my code changes.
  • 🎁 I have added end-to-end tests where feasible. See README for more details.
  • 🔎 I have addressed any CI test flakiness or provided a clear reason to bypass it.
  • If adding a provider feature, I have filled in the following and updated the provider documentation:
    • GitHub App
    • GitHub Webhook
    • Gitea/Forgejo
    • GitLab
    • Bitbucket Cloud
    • Bitbucket Data Center

@linux-foundation-easycla
Copy link
Copy Markdown

linux-foundation-easycla Bot commented May 28, 2026

CLA Signed
The committers listed above are authorized under a signed CLA.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request adds support for Bitbucket Data Center webhook events pr:merged, pr:modified, and pr:reviewer:approved to trigger pull request pipelines. However, the reviewer identified a critical issue: mapping these events directly to the standard pull_request event type will cause Pipelines-as-Code to trigger redundant and incorrect pipeline runs (e.g., when a PR is merged, modified for metadata, or approved). The reviewer recommends removing these events from the active triggering and payload parsing logic to prevent wasting CI/CD resources.

Comment on lines +41 to 43
if provider.Valid(event, []string{"pr:from_ref_updated", "pr:opened", "pr:merged", "pr:modified", "pr:reviewer:approved"}) {
return setLoggerAndProceed(true, "", nil)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

⚠️ Critical Triggering Issue

Mapping pr:merged, pr:modified, and pr:reviewer:approved directly to the standard pull_request event type will cause Pipelines-as-Code to trigger and run the full suite of pull_request PipelineRuns every time a PR is merged, modified (e.g., title/description edits), or approved. This is highly inefficient and leads to redundant pipeline runs, wasting significant CI/CD resources.

  • pr:merged: When a PR is merged, a push event (repo:refs_changed) is already triggered and handled to run push pipelines. Running pull_request pipelines again on a merged PR is redundant and incorrect.
  • pr:modified: This event is triggered for metadata changes (like title/description updates). Running the entire CI suite for a title change is usually undesirable.
  • pr:reviewer:approved: Standard Pipelines-as-Code does not trigger new pipeline runs on approval; doing so here would restart the PR pipelines every time a reviewer approves.

If these events are not intended to trigger new PipelineRuns, they should not be included in the active triggering list.

Suggested change
if provider.Valid(event, []string{"pr:from_ref_updated", "pr:opened", "pr:merged", "pr:modified", "pr:reviewer:approved"}) {
return setLoggerAndProceed(true, "", nil)
}
if provider.Valid(event, []string{"pr:from_ref_updated", "pr:opened"}) {
return setLoggerAndProceed(true, "", nil)
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

None of these events trigger a pipeline run unless they are configured to do so in the bitbucket datacenter repository as specified in the PaC documentation. The goal with this PR is to be able to trigger a build on merge without needing to create a second pipeline run (push event (repo:refs_changed)) as suggested by this comment. If the repository maintainer determines that the events merged, modified, or approved are desirable event to trigger a build, why should the maintainer be limited by the provider implementation?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would agree with Gemini's comment here wrt pr:merged, this would introduce confusing behaviour for users who have separate PipelineRuns configured for pull_request and push (on main). When a PR is merged to main, Bitbucket DC fires both pr:merged and repo:refs_changed. With the current mapping, both would trigger pipelines: pr:merged would run all on-event: [pull_request] PipelineRuns, and repo:refs_changed would run all on-event: [push] PipelineRuns. Users end up with multiple, possibly redundant PipelineRuns for a single merge.

This also introduces problems when the source branch is deleted after merge. When the system fetches pipeline definitions from the PR's source branch (which is the normal pull_request code path), those definitions become unreachable after a merge and delete. The system silently does nothing, users won't know why their close-event pipeline never triggered.

pr:merged should be handled in its own block and mapped to triggertype.PullRequestClosed, which is what every other provider does:

  • GitHub: action == "closed" --> PullRequestClosed
  • Bitbucket Cloud: pullrequest:fulfilled --> PullRequestClosed
  • GitLab: action == "close" --> PullRequestClosed
  • Gitea: action == "closed" --> PullRequestClosed

The PullRequestClosed path (pipelineascode.go:L66-L81) skips normal matching entirely, it doesn't create new PipelineRuns, it only cancels in-progress ones for that PR. This is the semantics for a merge (close) event followed by all other providers.

As for pr:modified, I don't fully understand the requirement of supporting it since it looks like a metadata-only change event (title, description, target branch edits). If a PR title is updated while pipelines are running and cancel-in-progress is enabled, the running PipelineRuns would be cancelled and restarted from scratch due to the new pull_request event. Could you elaborate how this event helps in your use case?

pr:reviewer:approved would also have similar cancel-in-progress behaviour, an approval would cancel running CI and restart it, which seems counterproductive.

Comment on lines +110 to 113
if provider.Valid(eventType, []string{"pr:from_ref_updated", "pr:opened", "pr:merged", "pr:modified", "pr:reviewer:approved"}) {
processedEvent.TriggerTarget = triggertype.PullRequest
processedEvent.EventType = triggertype.PullRequest.String()
} else if provider.Valid(eventType, []string{"pr:comment:added", "pr:comment:edited"}) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Similarly to the detection logic, mapping these events to triggertype.PullRequest with EventType = triggertype.PullRequest.String() will cause the controller to execute the pull_request pipelines. They should be excluded from this block to prevent unintended pipeline execution.

		if provider.Valid(eventType, []string{"pr:from_ref_updated", "pr:opened"}) {
			processedEvent.TriggerTarget = triggertype.PullRequest
			processedEvent.EventType = triggertype.PullRequest.String()
		}

Comment on lines 234 to 238
if !provider.Valid(event, []string{
"pr:from_ref_updated", "pr:opened", "pr:comment:added", "pr:comment:edited",
"pr:from_ref_updated", "pr:opened", "pr:comment:added", "pr:comment:edited", "pr:merged", "pr:modified", "pr:reviewer:approved",
}) {
return nil, fmt.Errorf("event \"%s\" is not supported", event)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Since these events should not trigger pipeline runs, they should not be registered as supported pull request payload types here.

Suggested change
if !provider.Valid(event, []string{
"pr:from_ref_updated", "pr:opened", "pr:comment:added", "pr:comment:edited",
"pr:from_ref_updated", "pr:opened", "pr:comment:added", "pr:comment:edited", "pr:merged", "pr:modified", "pr:reviewer:approved",
}) {
return nil, fmt.Errorf("event \"%s\" is not supported", event)
}
if !provider.Valid(event, []string{
"pr:from_ref_updated", "pr:opened", "pr:comment:added", "pr:comment:edited",
}) {
return nil, fmt.Errorf("event \"%s\" is not supported", event)
}

Copy link
Copy Markdown
Member

@theakshaypant theakshaypant left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution @mluckam! Adding pr:merged support is a good idea and fills a real gap for Bitbucket Data Center (it's currently the only provider without a PullRequestClosed mapping). However, the PR has a few questions that need to be addressed before it can be merged.

The core problem is that all three events (pr:merged, pr:modified, pr:reviewer:approved) are mapped to triggertype.PullRequest with EventType = "pull_request". This doesn't match how any other provider handles merge/close events, and it introduces confusing and potentially destructive behaviour, especially around cancel-in-progress.

I would also request @tektoncd/pipelines-as-code-maintainers to weigh in.

Comment on lines +41 to 43
if provider.Valid(event, []string{"pr:from_ref_updated", "pr:opened", "pr:merged", "pr:modified", "pr:reviewer:approved"}) {
return setLoggerAndProceed(true, "", nil)
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would agree with Gemini's comment here wrt pr:merged, this would introduce confusing behaviour for users who have separate PipelineRuns configured for pull_request and push (on main). When a PR is merged to main, Bitbucket DC fires both pr:merged and repo:refs_changed. With the current mapping, both would trigger pipelines: pr:merged would run all on-event: [pull_request] PipelineRuns, and repo:refs_changed would run all on-event: [push] PipelineRuns. Users end up with multiple, possibly redundant PipelineRuns for a single merge.

This also introduces problems when the source branch is deleted after merge. When the system fetches pipeline definitions from the PR's source branch (which is the normal pull_request code path), those definitions become unreachable after a merge and delete. The system silently does nothing, users won't know why their close-event pipeline never triggered.

pr:merged should be handled in its own block and mapped to triggertype.PullRequestClosed, which is what every other provider does:

  • GitHub: action == "closed" --> PullRequestClosed
  • Bitbucket Cloud: pullrequest:fulfilled --> PullRequestClosed
  • GitLab: action == "close" --> PullRequestClosed
  • Gitea: action == "closed" --> PullRequestClosed

The PullRequestClosed path (pipelineascode.go:L66-L81) skips normal matching entirely, it doesn't create new PipelineRuns, it only cancels in-progress ones for that PR. This is the semantics for a merge (close) event followed by all other providers.

As for pr:modified, I don't fully understand the requirement of supporting it since it looks like a metadata-only change event (title, description, target branch edits). If a PR title is updated while pipelines are running and cancel-in-progress is enabled, the running PipelineRuns would be cancelled and restarted from scratch due to the new pull_request event. Could you elaborate how this event helps in your use case?

pr:reviewer:approved would also have similar cancel-in-progress behaviour, an approval would cancel running CI and restart it, which seems counterproductive.

switch e := eventPayload.(type) {
case *types.PullRequestEvent:
if provider.Valid(eventType, []string{"pr:from_ref_updated", "pr:opened"}) {
if provider.Valid(eventType, []string{"pr:from_ref_updated", "pr:opened", "pr:merged", "pr:modified", "pr:reviewer:approved"}) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Semantically speaking, pr:merged should be mapping to PullRequestClosed, following the Bitbucket Cloud pattern (bitbucketcloud/parse_payload.go:L134-L136).
While BitBucket DC is the only provider which does not have a PullRequestClosed mapping at the moment, this would make the provider's behaviour inconsistent with others.

- Pull Request -> Opened
- Pull Request -> Source branch updated
- Pull Request -> Comments added
- Pull Request -> Merged
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If pr:merged is being introduced, docs should note the dual-trigger situation: when a PR is merged, Bitbucket DC fires both pr:merged and repo:refs_changed. Users who enable both webhooks should configure their PipelineRun annotations to match only the event type they need to avoid duplicate execution.

@zakisk
Copy link
Copy Markdown
Member

zakisk commented Jun 1, 2026

we don't support PullRequestClosed in PipelineRun matching so supporting pr:merged is redundant here. pr:modified and pr:reviewer:approved also doesn't make sense to re-trigger PipelineRuns on just metadata changes. @mluckam can you please explain what you're trying to achieve. this PR totally collides with how PaC works!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for bitbucket datacenter pull request event merged

3 participants