feat(broadcasts): Add sync_locked to protect admin edits from changelog sync#113633
feat(broadcasts): Add sync_locked to protect admin edits from changelog sync#113633rahulchhabria merged 5 commits intomasterfrom
Conversation
|
🚨 Warning: This pull request contains Frontend and Backend changes! It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently. Have questions? Please ask in the |
…og sync Broadcasts created by GetSentry's hourly changelog-sync job are rewritten on every run, which overwrites typo fixes and targeting tweaks made by admins. Introduce a `sync_locked` flag on the Broadcast model that the admin PUT endpoint flips automatically whenever a sync-managed field (title, message, link, media_url, category, is_active, date_expires) is edited on a changelog-sourced broadcast. The corresponding GetSentry sync task change teaches the job to skip updates for locked broadcasts while still creating new ones. Also updates the admin UI at /_admin/broadcasts/:id/ to default to a read-only view with an explicit "Edit Broadcast" action, surface the changelog origin and lock state as badges, and expose a "Re-enable changelog sync" action for clearing the lock. Co-Authored-By: Claude <noreply@anthropic.com>
3f16d4a to
6ffe5ce
Compare
|
This PR has a migration; here is the generated SQL for for --
-- Add field sync_locked to broadcast
--
ALTER TABLE "sentry_broadcast" ADD COLUMN "sync_locked" boolean DEFAULT false NOT NULL; |
The admin broadcast edit form stripped every null from the payload to work around URLField validation on an empty mediaUrl. dateExpires uses null to mean "no expiration" and the backend validator declares it allow_null=True, with a sentinel check to distinguish "omitted" from "explicitly null". Stripping it silently reverted the field on save. Keep stripping '' and undefined, but only strip null for fields the backend does not accept null on. Co-Authored-By: Claude <noreply@anthropic.com>
markstory
left a comment
There was a problem hiding this comment.
Looks good. I tested the UI out locally and it behaves well.
| help: fromChangelog | ||
| ? 'Edit broadcast content. Saving will lock this broadcast from future changelog syncs.' | ||
| : 'Edit broadcast content.', | ||
| visible: true, |
There was a problem hiding this comment.
Couldn't this be visible: isAdmin && !isEditing similar to the toggle action?
Replace conditional actions.push() calls with a single array literal where each action controls its own visibility via the `visible` prop. Matches the pattern already used by the toggle-activation action. Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ca6a82f. Configure here.
The activate/deactivate dropdown action remained visible during edit mode, allowing an out-of-band PUT that would be reverted by the edit form's isActive field on save. Match the gating used by the other admin actions. Co-Authored-By: Claude <noreply@anthropic.com>
This reverts commit bacbebd.

Adds a
sync_lockedBooleanField to theBroadcastmodel so admins can edit changelog-sourced broadcasts in/_admin/broadcasts/:id/without the next run of GetSentry's hourly changelog-sync job overwriting their changes.Why: Today, the changelog sync task does
Broadcast.objects.update_or_create(upstream_id=..., defaults=...)every hour, which clobbers any title/message/link/category/is_active/date_expires edits made by an admin within ~59 minutes. Typo fixes and deactivations don't stick.How it works:
sync_lockedfield onBroadcast(defaultFalse, withdb_default=Falsefor zero-downtime deploy).BroadcastDetailsEndpointflipssync_locked=Truewhenever any sync-managed field (title,message,link,media_url,category,is_active,date_expires) is edited on a broadcast that has anupstream_idset. Admins can clear the flag explicitly by passingsyncLocked: false.TargetedBroadcastendpoint override) do not trigger the lock — those fields are already safe from the sync.AdminBroadcastSerializernow exposesupstreamIdandsyncLockedso the UI can render banners/badges.Admin UI revamp at
static/gsAdmin/views/broadcastDetails.tsx:skipConfirmModal: trueso it doesn't route through the admin confirmation dialog.syncLocked: falseto hand control back to the hourly sync.mediaUrl.Companion PR: getsentry/getsentry updates
_process_entryingetsentry/tasks/broadcasts.pyto skip the update branch whensync_locked=True. This sentry PR is backwards compatible — the defaultFalsevalue means existing behavior is unchanged until the getsentry side also merges.Testing: Five new cases in
tests/sentry/api/endpoints/test_broadcast_details.pycover the happy path, the non-changelog case,hasSeen-only updates (shouldn't lock), explicit unlock viasyncLocked: false, and serializer exposure of the new fields.