mirror of
https://github.com/mastodon/mastodon.git
synced 2026-09-12 14:05:40 -05:00
Add notifications for out-of-support versions of Mastodon (#39734)
This commit is contained in:
@@ -9,7 +9,7 @@ class AdminMailer < ApplicationMailer
|
||||
before_action :process_params
|
||||
before_action :set_instance
|
||||
|
||||
after_action :set_important_headers!, only: :new_critical_software_updates
|
||||
after_action :set_important_headers!, only: [:new_critical_software_updates, :end_of_support_out_of_support_warning]
|
||||
|
||||
around_action :set_locale
|
||||
|
||||
@@ -57,6 +57,24 @@ class AdminMailer < ApplicationMailer
|
||||
mail subject: default_i18n_subject(instance: @instance)
|
||||
end
|
||||
|
||||
def end_of_support_three_months_warning
|
||||
@software_updates = SoftwareUpdate.by_version
|
||||
|
||||
mail subject: default_i18n_subject(instance: @instance, branch: SoftwareDeprecation.current_branch)
|
||||
end
|
||||
|
||||
def end_of_support_two_weeks_warning
|
||||
@software_updates = SoftwareUpdate.by_version
|
||||
|
||||
mail subject: default_i18n_subject(instance: @instance, branch: SoftwareDeprecation.current_branch)
|
||||
end
|
||||
|
||||
def end_of_support_out_of_support_warning
|
||||
@software_updates = SoftwareUpdate.by_version
|
||||
|
||||
mail subject: default_i18n_subject(instance: @instance, branch: SoftwareDeprecation.current_branch)
|
||||
end
|
||||
|
||||
def auto_close_registrations
|
||||
mail subject: default_i18n_subject(instance: @instance)
|
||||
end
|
||||
|
||||
37
app/models/software_deprecation.rb
Normal file
37
app/models/software_deprecation.rb
Normal file
@@ -0,0 +1,37 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: software_deprecations
|
||||
#
|
||||
# id :bigint(8) not null, primary key
|
||||
# branch :string not null
|
||||
# end_of_support :date not null
|
||||
# warning_issued :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
class SoftwareDeprecation < ApplicationRecord
|
||||
enum :warning_issued, {
|
||||
none: 0,
|
||||
three_months_warning: 1,
|
||||
two_weeks_warning: 2,
|
||||
out_of_support_warning: 3,
|
||||
}, validate: true, suffix: :issued
|
||||
|
||||
def unsupported?
|
||||
end_of_support.past?
|
||||
end
|
||||
|
||||
def self.clear_irrelevant_branches!
|
||||
where.not(branch: current_branch).delete_all
|
||||
end
|
||||
|
||||
def self.current
|
||||
find_by(branch: current_branch)
|
||||
end
|
||||
|
||||
def self.current_branch
|
||||
Mastodon::Version.gem_version.segments[...2].join('.')
|
||||
end
|
||||
end
|
||||
@@ -54,6 +54,7 @@ class UserSettings
|
||||
setting :trends, default: true
|
||||
setting :appeal, default: true
|
||||
setting :software_updates, default: 'critical', in: %w(none critical patch all)
|
||||
setting :end_of_support, default: true
|
||||
end
|
||||
|
||||
namespace :interactions do
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
class SoftwareUpdateCheckService < BaseService
|
||||
def call
|
||||
clean_outdated_updates!
|
||||
clean_outdated_deprecations!
|
||||
return unless SoftwareUpdate.check_enabled?
|
||||
|
||||
process_update_notices!(fetch_update_notices)
|
||||
json = fetch_update_notices
|
||||
process_update_notices!(json&.fetch('updatesAvailable', nil))
|
||||
process_deprecation_notice!(json&.fetch('currentVersion', nil))
|
||||
end
|
||||
|
||||
private
|
||||
@@ -18,6 +21,10 @@ class SoftwareUpdateCheckService < BaseService
|
||||
end
|
||||
end
|
||||
|
||||
def clean_outdated_deprecations!
|
||||
SoftwareDeprecation.clear_irrelevant_branches!
|
||||
end
|
||||
|
||||
def fetch_update_notices
|
||||
Request.new(:get, "#{api_url}?version=#{version}").add_headers('Accept' => 'application/json', 'User-Agent' => 'Mastodon update checker').perform do |res|
|
||||
return JSON.parse(res.body_with_limit) if res.code == 200
|
||||
@@ -35,19 +42,17 @@ class SoftwareUpdateCheckService < BaseService
|
||||
end
|
||||
|
||||
def process_update_notices!(update_notices)
|
||||
return if update_notices.blank? || update_notices['updatesAvailable'].nil?
|
||||
return if update_notices.blank?
|
||||
|
||||
# Clear notices that are not listed by the update server anymore
|
||||
SoftwareUpdate.where.not(version: update_notices['updatesAvailable'].pluck('version')).delete_all
|
||||
|
||||
return if update_notices['updatesAvailable'].blank?
|
||||
SoftwareUpdate.where.not(version: update_notices.pluck('version')).delete_all
|
||||
|
||||
# Check if any of the notices is new, and issue notifications
|
||||
known_versions = SoftwareUpdate.where(version: update_notices['updatesAvailable'].pluck('version')).pluck(:version)
|
||||
new_update_notices = update_notices['updatesAvailable'].filter { |notice| known_versions.exclude?(notice['version']) }
|
||||
known_versions = SoftwareUpdate.where(version: update_notices.pluck('version')).pluck(:version)
|
||||
new_update_notices = update_notices.filter { |notice| known_versions.exclude?(notice['version']) }
|
||||
return if new_update_notices.blank?
|
||||
|
||||
SoftwareUpdate.upsert_all(update_notices['updatesAvailable'].map do |notice|
|
||||
SoftwareUpdate.upsert_all(update_notices.map do |notice|
|
||||
{ version: notice['version'], urgent: notice['urgent'], type: notice['type'], release_notes: notice['releaseNotes'], end_of_support: notice['endOfSupport']&.to_date }
|
||||
end, unique_by: :version)
|
||||
|
||||
@@ -56,6 +61,18 @@ class SoftwareUpdateCheckService < BaseService
|
||||
notify_devops!(new_updates)
|
||||
end
|
||||
|
||||
def process_deprecation_notice!(current_version)
|
||||
return if current_version.blank? || current_version['endOfSupport'].blank?
|
||||
|
||||
deprecation_notice = SoftwareDeprecation
|
||||
.create_with(warning_issued: :none, end_of_support: current_version['endOfSupport'].to_date)
|
||||
.find_or_create_by(branch: SoftwareDeprecation.current_branch)
|
||||
|
||||
deprecation_notice.update(end_of_support: current_version['endOfSupport'].to_date)
|
||||
|
||||
notify_of_end_of_support!(deprecation_notice)
|
||||
end
|
||||
|
||||
def should_notify_user?(user, urgent_version, patch_version)
|
||||
case user.settings['notification_emails.software_updates']
|
||||
when 'none'
|
||||
@@ -83,4 +100,30 @@ class SoftwareUpdateCheckService < BaseService
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def should_notify_about_end_of_support?(user)
|
||||
user.settings['notification_emails.end_of_support']
|
||||
end
|
||||
|
||||
def send_notification_for_end_of_support_warning!(deprecation_notice, warning_type)
|
||||
return if deprecation_notice.warning_issued == warning_type
|
||||
|
||||
User.those_who_can(:view_devops).includes(:account).find_each do |user|
|
||||
next unless should_notify_about_end_of_support?(user)
|
||||
|
||||
AdminMailer.with(recipient: user.account).public_send("end_of_support_#{warning_type}").deliver_later
|
||||
end
|
||||
|
||||
deprecation_notice.update!(warning_issued: warning_type)
|
||||
end
|
||||
|
||||
def notify_of_end_of_support!(deprecation_notice)
|
||||
if deprecation_notice.end_of_support.past?
|
||||
send_notification_for_end_of_support_warning!(deprecation_notice, 'out_of_support_warning')
|
||||
elsif deprecation_notice.end_of_support < 2.weeks.from_now
|
||||
send_notification_for_end_of_support_warning!(deprecation_notice, 'two_weeks_warning')
|
||||
elsif deprecation_notice.end_of_support < 3.months.from_now
|
||||
send_notification_for_end_of_support_warning!(deprecation_notice, 'three_months_warning')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
- content_for :page_title do
|
||||
= t('admin.software_updates.title')
|
||||
|
||||
- current_deprecation = SoftwareDeprecation.current
|
||||
- if current_deprecation&.unsupported?
|
||||
.flash-message.alert= t('admin.software_updates.unsupported_branch')
|
||||
- elsif current_deprecation.present?
|
||||
.flash-message.warning= t('admin.software_updates.nearing_eol', date: current_deprecation.end_of_support)
|
||||
|
||||
.simple_form
|
||||
%p.lead
|
||||
= t('admin.software_updates.description')
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<%= raw t('admin_mailer.end_of_support_out_of_support_warning.body') %>
|
||||
|
||||
<% @software_updates.each do |update| %>
|
||||
- Mastodon <%= update.version %>: <%= update.release_notes %>
|
||||
<% end %>
|
||||
|
||||
<%= raw t('application_mailer.view')%> <%= admin_software_updates_url %>
|
||||
@@ -0,0 +1,7 @@
|
||||
<%= raw t('admin_mailer.end_of_support_three_months_warning.body') %>
|
||||
|
||||
<% @software_updates.each do |update| %>
|
||||
- Mastodon <%= update.version %>: <%= update.release_notes %>
|
||||
<% end %>
|
||||
|
||||
<%= raw t('application_mailer.view')%> <%= admin_software_updates_url %>
|
||||
@@ -0,0 +1,7 @@
|
||||
<%= raw t('admin_mailer.end_of_support_two_weeks_warning.body') %>
|
||||
|
||||
<% @software_updates.each do |update| %>
|
||||
- Mastodon <%= update.version %>: <%= update.release_notes %>
|
||||
<% end %>
|
||||
|
||||
<%= raw t('application_mailer.view')%> <%= admin_software_updates_url %>
|
||||
@@ -23,8 +23,8 @@
|
||||
.fields-group
|
||||
= ff.input :always_send_emails, wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_always_send_emails'), hint: I18n.t('simple_form.hints.defaults.setting_always_send_emails')
|
||||
|
||||
- if current_user.can?(:manage_reports, :manage_appeals, :manage_users, :manage_taxonomies) || (SoftwareUpdate.check_enabled? && current_user.can?(:view_devops))
|
||||
%h2= t 'notifications.administration_emails'
|
||||
- if current_user.can?(:manage_reports, :manage_appeals, :manage_users, :manage_taxonomies)
|
||||
%h2= t 'notifications.moderation_emails'
|
||||
|
||||
.fields-group
|
||||
= ff.input :'notification_emails.report', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.report') if current_user.can?(:manage_reports)
|
||||
@@ -32,13 +32,21 @@
|
||||
= ff.input :'notification_emails.pending_account', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.pending_account') if current_user.can?(:manage_users)
|
||||
= ff.input :'notification_emails.trends', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.trending_tag') if current_user.can?(:manage_taxonomies)
|
||||
|
||||
- if SoftwareUpdate.check_enabled? && current_user.can?(:view_devops)
|
||||
.fields-group
|
||||
= ff.input :'notification_emails.software_updates',
|
||||
collection: user_settings_collection('notification_emails.software_updates'),
|
||||
hint: false,
|
||||
include_blank: false,
|
||||
label_method: ->(setting) { I18n.t("simple_form.labels.notification_emails.software_updates.#{setting}") },
|
||||
label: I18n.t('simple_form.labels.notification_emails.software_updates.label'),
|
||||
wrapper: :with_label,
|
||||
required: false
|
||||
- if SoftwareUpdate.check_enabled? && current_user.can?(:view_devops)
|
||||
%h2= t 'notifications.administration_emails'
|
||||
|
||||
.fields-group
|
||||
= ff.input :'notification_emails.end_of_support',
|
||||
wrapper: :with_label,
|
||||
label: I18n.t('simple_form.labels.notification_emails.end_of_support'),
|
||||
recommended: true
|
||||
|
||||
.fields-group
|
||||
= ff.input :'notification_emails.software_updates',
|
||||
collection: user_settings_collection('notification_emails.software_updates'),
|
||||
hint: false,
|
||||
include_blank: false,
|
||||
label_method: ->(setting) { I18n.t("simple_form.labels.notification_emails.software_updates.#{setting}") },
|
||||
label: I18n.t('simple_form.labels.notification_emails.software_updates.label'),
|
||||
wrapper: :with_label,
|
||||
required: false
|
||||
|
||||
@@ -1013,6 +1013,7 @@ en:
|
||||
critical_update: Critical — please update quickly
|
||||
description: It is recommended to keep your Mastodon installation up to date to benefit from the latest fixes and features. Moreover, it is sometimes critical to update Mastodon in a timely manner to avoid security issues. For these reasons, Mastodon checks for updates every 30 minutes, and will notify you according to your email notification preferences.
|
||||
documentation_link: Learn more
|
||||
nearing_eol: Support for the branch you are currently running will stop on %{date}, please consider updating.
|
||||
release_notes: Release notes
|
||||
supported_until: Support ends on %{date}
|
||||
title: Available updates
|
||||
@@ -1021,6 +1022,7 @@ en:
|
||||
major: Major release
|
||||
minor: Minor release
|
||||
patch: Patch release — bugfixes and easy to apply changes
|
||||
unsupported_branch: The branch you are currently running is unsupported, please update as soon as possible.
|
||||
unsupported_since: Unsupported since %{date}
|
||||
version: Version
|
||||
statuses:
|
||||
@@ -1287,6 +1289,15 @@ en:
|
||||
auto_close_registrations:
|
||||
body: Due to a lack of recent moderator activity, registrations on %{instance} have been automatically switched to requiring manual review, to prevent %{instance} from being used as a platform for potential bad actors. You can switch it back to open registrations at any time.
|
||||
subject: Registrations for %{instance} have been automatically switched to requiring approval
|
||||
end_of_support_out_of_support_warning:
|
||||
body: The Mastodon version currently in use on your server is not supported anymore. We recommend you to update as soon as possible!
|
||||
subject: Mastodon %{branch} used on %{instance} is now unsupported!
|
||||
end_of_support_three_months_warning:
|
||||
body: The Mastodon version currently in use on your server will stop being supported in 3 months. You may want to update to a newer branch ahead of time.
|
||||
subject: Support for Mastodon %{branch} used on %{instance} to end in 3 months.
|
||||
end_of_support_two_weeks_warning:
|
||||
body: The Mastodon version currently in use on your server will stop being supported in 2 weeks. We recommend you update to a newer branch ahead of time.
|
||||
subject: Support for Mastodon %{branch} used on %{instance} to end in 2 weeks.
|
||||
new_appeal:
|
||||
actions:
|
||||
delete_statuses: to delete their posts
|
||||
@@ -1922,6 +1933,7 @@ en:
|
||||
administration_emails: Admin email notifications
|
||||
email_events: Events for email notifications
|
||||
email_events_hint: 'Select events that you want to receive notifications for:'
|
||||
moderation_emails: Moderation email notifications
|
||||
number:
|
||||
human:
|
||||
decimal_units:
|
||||
|
||||
@@ -345,6 +345,7 @@ en:
|
||||
notification_emails:
|
||||
appeal: Someone appeals a moderator decision
|
||||
digest: Send digest e-mails
|
||||
end_of_support: The current Mastodon version is nearing end of support
|
||||
favourite: Someone favourited your post
|
||||
follow: Someone followed you
|
||||
follow_request: Someone requested to follow you
|
||||
|
||||
@@ -11,7 +11,7 @@ SimpleNavigation::Configuration.run do |navigation|
|
||||
SoftwareUpdate.urgent_pending? ? [material_symbol('report'), t('admin.critical_update_pending')] : [material_symbol('system_update_alt'), t('admin.update_available')]
|
||||
),
|
||||
admin_software_updates_path,
|
||||
html: { class: SoftwareUpdate.urgent_pending? ? 'warning' : nil },
|
||||
html: { class: SoftwareUpdate.urgent_pending? || SoftwareDeprecation.current&.unsupported? ? 'warning' : nil },
|
||||
if: -> { Rails.configuration.x.mastodon.software_update_url.present? && current_user.can?(:view_devops) && SoftwareUpdate.pending? }
|
||||
|
||||
n.item :profile, safe_join([material_symbol('person'), t('settings.profile')]), settings_profile_path, if: -> { current_user.functional? && !self_destruct }, highlights_on: %r{/settings/profile|/settings/featured_tags|/settings/verification}
|
||||
|
||||
15
db/migrate/20260706143100_create_software_deprecations.rb
Normal file
15
db/migrate/20260706143100_create_software_deprecations.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class CreateSoftwareDeprecations < ActiveRecord::Migration[8.1]
|
||||
def change
|
||||
create_table :software_deprecations do |t|
|
||||
t.string :branch, null: false
|
||||
t.date :end_of_support, null: false
|
||||
t.integer :warning_issued, null: false
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :software_deprecations, :branch, unique: true
|
||||
end
|
||||
end
|
||||
11
db/schema.rb
11
db/schema.rb
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[8.1].define(version: 2026_07_06_122112) do
|
||||
ActiveRecord::Schema[8.1].define(version: 2026_07_06_143100) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_catalog.plpgsql"
|
||||
|
||||
@@ -1157,6 +1157,15 @@ ActiveRecord::Schema[8.1].define(version: 2026_07_06_122112) do
|
||||
t.index ["var"], name: "index_site_uploads_on_var", unique: true
|
||||
end
|
||||
|
||||
create_table "software_deprecations", force: :cascade do |t|
|
||||
t.string "branch", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.date "end_of_support", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "warning_issued", null: false
|
||||
t.index ["branch"], name: "index_software_deprecations_on_branch", unique: true
|
||||
end
|
||||
|
||||
create_table "software_updates", force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.date "end_of_support"
|
||||
|
||||
@@ -66,10 +66,12 @@ RSpec.describe SoftwareUpdateCheckService do
|
||||
end
|
||||
|
||||
context 'when the server returns new versions' do
|
||||
let(:deprecation_date) { nil }
|
||||
|
||||
let(:server_json) do
|
||||
{
|
||||
currentVersion: {
|
||||
endOfSupport: nil,
|
||||
endOfSupport: deprecation_date&.iso8601,
|
||||
},
|
||||
updatesAvailable: [
|
||||
{
|
||||
@@ -104,6 +106,91 @@ RSpec.describe SoftwareUpdateCheckService do
|
||||
expect { subject.call }.to change { SoftwareUpdate.pluck(:version).sort }.from(['3.5.0', '42.13.12', 'Malformed']).to(['4.2.1', '4.3.0', '5.0.0'])
|
||||
end
|
||||
|
||||
context 'when server returns deprecation in the distant future' do
|
||||
let(:deprecation_date) { 5.years.from_now.to_date }
|
||||
|
||||
it 'updates the software deprecation info' do
|
||||
expect { subject.call }
|
||||
.to change { SoftwareDeprecation.pluck(:end_of_support, :warning_issued) }.from([]).to([[deprecation_date, 'none']])
|
||||
end
|
||||
|
||||
context 'when an irrelevant deprecation was stored' do
|
||||
before do
|
||||
SoftwareDeprecation.create!(branch: '4.3', end_of_support: '2026-05-06'.to_date, warning_issued: :out_of_support_warning)
|
||||
end
|
||||
|
||||
it 'updates the software deprecation info' do
|
||||
expect { subject.call }
|
||||
.to change { SoftwareDeprecation.pluck(:end_of_support, :warning_issued) }.from([['2026-05-06'.to_date, 'out_of_support_warning']]).to([[deprecation_date, 'none']])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when server returns deprecation in 2 months' do
|
||||
let(:deprecation_date) { 2.months.from_now.to_date }
|
||||
|
||||
it 'updates the software deprecation info' do
|
||||
expect { subject.call }
|
||||
.to change { SoftwareDeprecation.pluck(:end_of_support, :warning_issued) }.from([]).to([[deprecation_date, 'three_months_warning']])
|
||||
end
|
||||
|
||||
context 'when an irrelevant deprecation was stored' do
|
||||
before do
|
||||
SoftwareDeprecation.create!(branch: '4.3', end_of_support: '2026-05-06'.to_date, warning_issued: :out_of_support_warning)
|
||||
end
|
||||
|
||||
it 'updates the software deprecation info and sends email' do
|
||||
expect { subject.call }
|
||||
.to change { SoftwareDeprecation.pluck(:end_of_support, :warning_issued) }.from([['2026-05-06'.to_date, 'out_of_support_warning']]).to([[deprecation_date, 'three_months_warning']])
|
||||
.and(have_enqueued_mail(AdminMailer, :end_of_support_three_months_warning).with(hash_including(params: { recipient: owner_user.account })).once)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when server returns deprecation in 1 week' do
|
||||
let(:deprecation_date) { 1.week.from_now.to_date }
|
||||
|
||||
it 'updates the software deprecation info' do
|
||||
expect { subject.call }
|
||||
.to change { SoftwareDeprecation.pluck(:end_of_support, :warning_issued) }.from([]).to([[deprecation_date, 'two_weeks_warning']])
|
||||
.and(have_enqueued_mail(AdminMailer, :end_of_support_two_weeks_warning).with(hash_including(params: { recipient: owner_user.account })).once)
|
||||
end
|
||||
|
||||
context 'when an irrelevant deprecation was stored' do
|
||||
before do
|
||||
SoftwareDeprecation.create!(branch: '4.3', end_of_support: '2026-05-06'.to_date, warning_issued: :out_of_support_warning)
|
||||
end
|
||||
|
||||
it 'updates the software deprecation info and sends email' do
|
||||
expect { subject.call }
|
||||
.to change { SoftwareDeprecation.pluck(:end_of_support, :warning_issued) }.from([['2026-05-06'.to_date, 'out_of_support_warning']]).to([[deprecation_date, 'two_weeks_warning']])
|
||||
.and(have_enqueued_mail(AdminMailer, :end_of_support_two_weeks_warning).with(hash_including(params: { recipient: owner_user.account })).once)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when server returns deprecation in the past' do
|
||||
let(:deprecation_date) { 1.week.ago.to_date }
|
||||
|
||||
it 'updates the software deprecation info' do
|
||||
expect { subject.call }
|
||||
.to change { SoftwareDeprecation.pluck(:end_of_support, :warning_issued) }.from([]).to([[deprecation_date, 'out_of_support_warning']])
|
||||
.and(have_enqueued_mail(AdminMailer, :end_of_support_out_of_support_warning).with(hash_including(params: { recipient: owner_user.account })).once)
|
||||
end
|
||||
|
||||
context 'when an irrelevant deprecation was stored' do
|
||||
before do
|
||||
SoftwareDeprecation.create!(branch: '4.3', end_of_support: '2026-05-06'.to_date, warning_issued: :out_of_support_warning)
|
||||
end
|
||||
|
||||
it 'updates the software deprecation info and sends email' do
|
||||
expect { subject.call }
|
||||
.to change { SoftwareDeprecation.pluck(:end_of_support, :warning_issued) }.from([['2026-05-06'.to_date, 'out_of_support_warning']]).to([[deprecation_date, 'out_of_support_warning']])
|
||||
.and(have_enqueued_mail(AdminMailer, :end_of_support_out_of_support_warning).with(hash_including(params: { recipient: owner_user.account })).once)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no update is urgent' do
|
||||
it 'sends e-mail notifications according to settings', :aggregate_failures do
|
||||
expect { subject.call }.to have_enqueued_mail(AdminMailer, :new_software_updates)
|
||||
|
||||
Reference in New Issue
Block a user