mirror of
https://github.com/discourse/discourse.git
synced 2026-03-05 15:27:34 +08:00
We notify admins both when an upcoming change is available for preview (at promotion status - 1) and when an upcoming change is automatically promoted. There are cases where multiple changes might be deployed at the same time, and we want to avoid sending multiple notifications to admins in a short period of time. This PR consolidates the notifications for both events into a single notification that includes all relevant changes. So for new upcoming changes, admins will receive a single notification that lists all the changes that are now available for preview. For automatic promotions, admins will receive a single notification that lists all the changes that were automatically promoted. In addition, this PR follows up on https://github.com/discourse/discourse/pull/38051 and directly links the notifications to a filtered list of upcoming changes by setting name. <img width="338" alt="image" src="https://github.com/user-attachments/assets/6febc7d7-0122-4f3b-8cbe-04d03721a709" /> <img width="332" alt="image" src="https://github.com/user-attachments/assets/46f2f886-8a6f-46f5-8038-bce3305d788f" /> ### Testing * Start with a fresh DB * Make sure `upcoming_change_verbose_logging` and `enable_upcoming_changes` are true * Choose a couple of upcoming changes and update their statuses in `site_settings.yml` to `beta` * Log in to the site and go to http://localhost:4200/sidekiq/scheduler and find the CheckUpcomingChanges job and run it * You should receive a notification for the changes becoming available, do not read the notification * Change another upcoming change to beta and run the job again * You should not get another notification, the third change should be merged into the first notification * Now update some of the same changes to `stable` status * Run the job again * You should get a new notification saying the changes were automatically enabled * Now update another of the same changes to `stable` status * You should not get another notification, the third change should be merged into the notification for enabled changes --------- Co-authored-by: awesomerobot <kris.aubuchon@discourse.org>
117 lines
4 KiB
Ruby
117 lines
4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Intended to be called from UpcomingChanges::Track service,
|
|
# not standalone.
|
|
#
|
|
# Lookup any previous event_type: status_changed (5) events for the change
|
|
# * If there are none, create one for the current status
|
|
# * Send an appropriate notification to admins
|
|
# * If the change was also added at the same time, and the status is correct (promotion_status - 1),
|
|
# then don't send another notification
|
|
# * If the change was not added, send a notification about the status change if it's the correct
|
|
# status (promotion_status - 1) to indicate it's available to admins
|
|
class UpcomingChanges::Action::TrackStatusChanges < Service::ActionBase
|
|
# Every admin user that are not bots
|
|
option :all_admins
|
|
|
|
# All changes that were added at the same time, we already added events
|
|
# and notified admins for them.
|
|
option :added_changes
|
|
|
|
# All changes that were removed at the same time, we don't care about
|
|
# their statuses anymore.
|
|
option :removed_changes
|
|
|
|
def call
|
|
status_changes = {}
|
|
notified_changes = []
|
|
|
|
SiteSetting.upcoming_change_site_settings.each do |change_name|
|
|
if no_previous_status_event?(change_name)
|
|
UpcomingChangeEvent.create!(
|
|
event_type: :status_changed,
|
|
upcoming_change_name: change_name,
|
|
event_data: {
|
|
previous_value: nil,
|
|
new_value: UpcomingChanges.change_status(change_name),
|
|
},
|
|
)
|
|
status_changes[change_name] = {
|
|
previous_value: "N/A",
|
|
new_value: UpcomingChanges.change_status(change_name),
|
|
}
|
|
next
|
|
end
|
|
|
|
next if added_changes.include?(change_name)
|
|
next if removed_changes.include?(change_name)
|
|
|
|
previous_status = previous_status_for(change_name)
|
|
current_status = UpcomingChanges.change_status(change_name)
|
|
|
|
if status_changed?(previous_status, current_status)
|
|
UpcomingChangeEvent.create!(
|
|
event_type: :status_changed,
|
|
upcoming_change_name: change_name,
|
|
event_data: {
|
|
previous_value: previous_status,
|
|
new_value: current_status,
|
|
},
|
|
)
|
|
status_changes[change_name] = { previous_value: previous_status, new_value: current_status }
|
|
|
|
# If admins were already notified about this change, don't notify them again.
|
|
# This can happen if the change was added and it already met the promotion status
|
|
# minus one (previous status) criteria for notification.
|
|
#
|
|
# However, if the status was later changed and it meets the promotion status
|
|
# minus one (previous status) criteria for notification, then we should notify
|
|
# admins here.
|
|
if should_notify_admins?(change_name) &&
|
|
!UpcomingChanges.meets_or_exceeds_status?(
|
|
change_name,
|
|
SiteSetting.promote_upcoming_changes_on_status.to_sym,
|
|
)
|
|
Rails.logger.info(
|
|
"Notifying admins about available change #{change_name} from TrackStatusChanges",
|
|
)
|
|
notified =
|
|
UpcomingChanges::Action::NotifyAdminsOfAvailableChange.call(change_name:, all_admins:)
|
|
notified_changes << change_name if notified
|
|
end
|
|
end
|
|
end
|
|
|
|
{ status_changes:, notified_changes: }
|
|
end
|
|
|
|
private
|
|
|
|
def previous_status_events
|
|
@previous_status_events ||= UpcomingChangeEvent.status_changed.to_a
|
|
end
|
|
|
|
def no_previous_status_event?(change_name)
|
|
previous_status_events.none? { |event| event.upcoming_change_name == change_name.to_s }
|
|
end
|
|
|
|
def previous_status_for(change_name)
|
|
previous_status_events
|
|
.select { |event| event.upcoming_change_name == change_name.to_s }
|
|
.last
|
|
.event_data[
|
|
"new_value"
|
|
]
|
|
end
|
|
|
|
def status_changed?(previous_status, current_status)
|
|
previous_status&.to_sym != current_status
|
|
end
|
|
|
|
def should_notify_admins?(change_name)
|
|
!UpcomingChangeEvent.exists?(
|
|
upcoming_change_name: change_name,
|
|
event_type: :admins_notified_available_change,
|
|
)
|
|
end
|
|
end
|