Skip to content

feat(bitbucket-server): Add gated webhook repair task - #128330

Merged
giovanni-guidini merged 4 commits into
masterfrom
gio/feat/bitbucket-webhook-repair-task
Oct 22, 2026
Merged

giovanni-guidini merged 4 commits into
masterfrom
gio/feat/bitbucket-webhook-repair-task

Conversation

@giovanni-guidini

@giovanni-guidini giovanni-guidini commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Adds a cell-side Bitbucket Data Center webhook reconciliation task behind the default-off bitbucket_server.webhook.secret-repair.enabled option. The task validates repository identity, persists a stable local secret before remote mutation, updates the stored hook or creates a replacement only when its ID is absent or confirmed missing, classifies retryable and terminal API failures, and uses conditional config writes plus best-effort cleanup to handle concurrent repairs safely.


This is 3 of 4 PRs aimed at self-healing webhook config for BB data center.
For more details please see SCM-134.

Why do I want this?

Well, this is the meaty part of the change. The task that actually takes a webhook that is missing config and reconciles it.

Note

Dear reviewer, there are files with the full plans in the ticket. I'm not saying "read them first" but maybe ask your clanker to do it. A lot of the reasoning and several questions and answers can be found there, and then you can ask the clanker.

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Oct 21, 2026
@giovanni-guidini
giovanni-guidini force-pushed the gio/feat/bitbucket-webhook-repair-task branch from c7a08ea to 4be3c4f Compare October 21, 2026 09:33
@giovanni-guidini
giovanni-guidini marked this pull request as ready for review October 21, 2026 09:37
@giovanni-guidini
giovanni-guidini requested review from a team as code owners October 21, 2026 09:38
@giovanni-guidini
giovanni-guidini added this pull request to stack #128331 October 21, 2026 09:52
else:
outcome = WebhookRepairOutcome.UPDATED

if needs_create:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This task only runs because a delivery reached us, so when webhook_id is missing or the stored hook 404s, some hook we don't track is already delivering (e.g. an orphan from a lost create race whose cleanup failed, or a hook an admin added by hand). Creating here adds a second one: every push is processed twice, the old hook keeps sending unsigned payloads so the missing signature result never drains, and once enforcement is on the customer sees that hook failing in Bitbucket's admin.

The same happens on retry: if create_hook times out or gets a 5xx after Bitbucket already created the hook, the next attempt creates another.

Could we list the repo's hooks (GET .../webhooks) before creating, and adopt the one whose URL matches build_webhook_data(...)["url"] (set the secret on it and store its id), creating only when nothing matches? That also makes the retry idempotent. GitLab's ensure_project_webhook has the same shape, but it runs as a batch reconcile, so a duplicate there is only possible; here the delivery trigger makes it likely.

@giovanni-guidini giovanni-guidini Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There's something in the plan about this… let me see

Funny:
“Why create a hook instead of discovering and adopting an existing one?”
Follow GitLab’s simpler update-or-create behavior; unknown hooks are not listed or adopted, and duplicate deliveries are an accepted trade-off.

Which the comment already points out 😓

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

But there was a reason for not adopting an existing hook:

A delivery does not include its webhook ID, so listing cannot prove which hook sent it. Adoption would mean selecting a hook based on name and URL, overwriting its secret, and storing its ID even though it may have been manually created or otherwise not managed by us. Multiple matches also require a potentially destructive deduplication policy.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I guess in the end I rather take the chance of double delivery (that will stop working and error out when we turn on the verification) and later delete those as needed than just take whatever is listed pointing at us

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

OK here's the decision: I'll do neither. We only have a very small number of customers in this integration, so if the stored hook ID is absent or 404s we're gonna stop with a specific error code and not reconcile it.

I'll then ask support for help reaching out to customers to manually fix stuff.

Comment thread src/sentry/integrations/bitbucket_server/tasks.py Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a74f0de. Configure here.

Comment thread src/sentry/integrations/bitbucket_server/tasks.py
@giovanni-guidini
giovanni-guidini force-pushed the gio/feat/bitbucket-webhook-repair-task branch from 939d506 to d8d51a0 Compare October 22, 2026 07:41
@sentry

sentry Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Sentry Snapshot Testing

Name Added Removed Changed Renamed Unchanged Skipped Status
sentry-frontend
sentry-frontend
0 0 0 0 760 0 ✅ Unchanged

⚙️ sentry-frontend Snapshot Settings

Base automatically changed from gio/feat/bitbucket-webhook-apis to master October 22, 2026 07:48
@giovanni-guidini
giovanni-guidini force-pushed the gio/feat/bitbucket-webhook-repair-task branch from d8d51a0 to 4daa42b Compare October 22, 2026 07:48
@giovanni-guidini
giovanni-guidini merged commit 0f822e8 into master Oct 22, 2026
89 checks passed
@giovanni-guidini
giovanni-guidini deleted the gio/feat/bitbucket-webhook-repair-task branch October 22, 2026 08:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants