This commit adds several pieces of functionality to help keep admins
in the loop about upcoming changes.
First of all, there is a new initializer on boot that will notify admins
about
newly available upcoming changes, as well as log removed changes and
status movement of existing changes.
* When there is a new upcoming change, we only notify admins about
it when the status is the `promote_upcoming_changes_on_status` - 1,
e.g. if `promote_upcoming_changes_on_status` is `beta` then we only
tell admin about the change once it has reached `alpha`. This means
we may log the `added` event in one deploy, but only actually notify
admins in a subsequent deploy.
* We log removed upcoming changes so we can automatically delete old
site setting data in a future job as needed.
We also now notify admins when upcoming changes are automatically
promoted to enabled based on the site's
`promote_upcoming_changes_on_status`:
<img width="378" height="600" alt="image"
src="https://github.com/user-attachments/assets/4200fbee-9990-4bbc-a378-85946e631e77"
/>
In addition, we now show an indicator in the admin sidebar
if there are new upcoming changes that have been added since
they last visited the upcoming change config page. This data
is stored in a user custom field, because Redis is ephemeral,
and storing in the User table is overkill because 99% of users
are not staff:
<img width="248" height="112" alt="image"
src="https://github.com/user-attachments/assets/4c3d3cf7-ac39-45f8-a2c8-a049cb85b8e9"
/>
Finally, this commit moves both the Track and Promote initializer
logic behind a `DistributedMutex`, we don't want multiple processes
running the same logic here, it needs to be only once.
---------
Co-authored-by: Loïc Guitaut <loic@discourse.org>
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
This commit introduces a Rails initializer to inspect
the current status of upcoming changes and compare them
to a hidden `promote_upcoming_changes_on_status` site setting.
If the status of an upcoming change matches or exceeds this setting,
the change is automatically enabled as long as:
* The change has not been manually disabled by an admin.
* The change is not already enabled.
By default for Discourse sites, the `promote_upcoming_changes_on_status`
is set to `Stable`, on our own hosting we will change it depending
on the hosting tier and other considerations.
In a future PR, we will introduce various ways for admins to
be notified when an upcoming change is automatically promoted,
along with new upcoming changes being introduced.
**HOW TO TEST**
This is a little tricky, since it happens on rails init. First, set
`SiteSetting.enable_upcoming_changes = true` and
`SiteSetting.upcoming_change_verbose_logging = true`.
You can also set `SiteSetting.promote_upcoming_changes_on_status =
:alpha`
(by default it's `stable`)
Then, add a change like this to site_settings.yml:
```
fake_upcoming_change:
default: false
hidden: true
client: true
upcoming_change:
status: "alpha"
impact: "other,all_members"
learn_more_url: "https://meta.discourse.org"
```
And then do ` FORCE_RAILS_LOGS_STDOUT=1 brc`. After this, you should see
output like this:
```
I, [2025-11-26T16:46:54.668551 #32662] INFO -- : [Upcoming changes promoter (default)]: Starting promotion check for upcoming changes.
I, [2025-11-26T16:46:54.733353 #32662] INFO -- : [Upcoming changes promoter (default)]: Successfully promoted 'fake_upcoming_change' to enabled.
```
If you want to reset the setting and try some different status
scenarios, do
this `SiteSetting.remove_override!(:fake_upcoming_change)`
This change adds webhook support for the user anonymization event,
allowing external systems to be notified when a user is anonymized in
Discourse.
Changes:
- Add user_anonymized event type (ID: 310) to WebHookEventType
- Wires up DiscourseEvent listener to trigger webhooks on anonymization
- Add translation string for the event in admin UI
- Add database fixture to seed the event type
- Add comprehensive test coverage
The webhook is triggered when UserAnonymizer.make_anonymous is called
and sends the anonymized user data using WebHookUserSerializer.
Nudged along the path by Claude Code
This commit updates our monkey patch of
`ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new_client` to
improve two things:
1. Improve the conditional used to determine if a database does not
exist. Just checking that the error message contains the `database`
name is not sufficient as the value of the database name may be part of
the `host` connection param which can appear in PG error messages as
well.
2. When the PG error messages includes the `user` or `host` connection
param. We append the original PG error message on to the original
error messge so that we don't just end up with a generic error message
that doesn't help us to figure out the actual error.
Currently, if you configure a webhook with reviewable events and apply
categories/tags filtering, no webhook gets fired for reviewable events.
This is because when we schedule the `EmitWebHookEvent` job, we don't
pass to it the reviewable's category or tags, making it seem like the
reviewable doesn't belong to the filtering category/tags that webhook
specifies.
This commit ensures rails will recognise `IST` as a timezone. It will be
mapped to the standard timezone `Asia/Kolkata`.
Its technically not a standard, but it's used by many people so we are
adding it as a timezone in core.
/t/-/150799
The most common thing that we do with fab! is:
fab!(:thing) { Fabricate(:thing) }
This commit adds a shorthand for this which is just simply:
fab!(:thing)
i.e. If you omit the block, then, by default, you'll get a `Fabricate`d object using the fabricator of the same name.
Legal topics, such as the Terms of Service and Privacy Policy topics
do not make sense if the entity creating the community is not a company.
These topics will be created and updated only when the company name is
present and deleted when it is not.
Currently, only user badge grants emit webhook events. This change
extends the `user_badge` webhook to emit user badge revocation events.
A new `user_badge_revoked` event has been introduced instead of relying
on the existing `user_badge_removed` event. `user_badge_removed` emitted
just the `badge_id` and `user_id` which aren't helpful for generating a
meaningful webhook payload for revoked(deleted) user badges.
The new event emits the user badge object.
It's very easy to forget to add `require 'rails_helper'` at the top of every core/plugin spec file, and omissions can cause some very confusing/sporadic errors.
By setting this flag in `.rspec`, we can remove the need for `require 'rails_helper'` entirely.
This filter hides reviewables with a score lower than the "reviewable_low_priority_threshold" setting. We only use reviewables that already met this threshold to calculate the Medium and High priority filters.
* FIX: We need to skip users with associated reviewables when auto-approving them
* Update spec/initializers/track_setting_changes_spec.rb
* Update spec/initializers/track_setting_changes_spec.rb
Co-authored-by: Robin Ward <robin.ward@gmail.com>