mirror of
https://github.com/discourse/discourse.git
synced 2025-01-31 19:23:16 +08:00
FEATURE: Show warning banner for critical JS deprecations to admins (#25091)
Ported from d95706b25a
This is enabled by default, but can be disabled via the `warn_critical_js_deprecations` hidden site setting.
The `warn_critical_js_deprecations_message` site setting can be used by hosting providers to add a sentence to the warning message (e.g. a date when they will be deploying the Ember 5 upgrade).
This commit is contained in:
parent
b9f6e6d637
commit
07caa5bc03
|
@ -1,5 +1,6 @@
|
||||||
export default {
|
export default {
|
||||||
initialize(owner) {
|
initialize(owner) {
|
||||||
owner.lookup("service:client-error-handler");
|
owner.lookup("service:client-error-handler");
|
||||||
|
owner.lookup("service:deprecation-warning-handler");
|
||||||
},
|
},
|
||||||
};
|
};
|
|
@ -0,0 +1,111 @@
|
||||||
|
import { registerDeprecationHandler } from "@ember/debug";
|
||||||
|
import Service, { inject as service } from "@ember/service";
|
||||||
|
import { addGlobalNotice } from "discourse/components/global-notice";
|
||||||
|
import identifySource from "discourse/lib/source-identifier";
|
||||||
|
import { escapeExpression } from "discourse/lib/utilities";
|
||||||
|
import { registerDeprecationHandler as registerDiscourseDeprecationHandler } from "discourse-common/lib/deprecated";
|
||||||
|
import { bind } from "discourse-common/utils/decorators";
|
||||||
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
|
// Deprecations matching patterns on this list will trigger warnings for admins.
|
||||||
|
// To avoid 'crying wolf', we should only add values here when we're sure they're
|
||||||
|
// not being triggered by core or official themes/plugins.
|
||||||
|
export const CRITICAL_DEPRECATIONS = [
|
||||||
|
/^discourse.modal-controllers$/,
|
||||||
|
/^(?!discourse\.)/, // All unsilenced ember deprecations
|
||||||
|
];
|
||||||
|
|
||||||
|
// Deprecation handling APIs don't have any way to unregister handlers, so we set up permenant
|
||||||
|
// handlers and link them up to the application lifecycle using module-local state.
|
||||||
|
let handler;
|
||||||
|
registerDeprecationHandler((message, opts, next) => {
|
||||||
|
handler?.(message, opts);
|
||||||
|
return next(message, opts);
|
||||||
|
});
|
||||||
|
registerDiscourseDeprecationHandler((message, opts) =>
|
||||||
|
handler?.(message, opts)
|
||||||
|
);
|
||||||
|
|
||||||
|
export default class DeprecationWarningHandler extends Service {
|
||||||
|
@service currentUser;
|
||||||
|
@service siteSettings;
|
||||||
|
|
||||||
|
#adminWarned = false;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
handler = this.handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
willDestroy() {
|
||||||
|
handler = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@bind
|
||||||
|
handle(message, opts) {
|
||||||
|
const workflowConfigs = window.deprecationWorkflow?.config?.workflow;
|
||||||
|
const matchingConfig = workflowConfigs.find(
|
||||||
|
(config) => config.matchId === opts.id
|
||||||
|
);
|
||||||
|
|
||||||
|
if (matchingConfig && matchingConfig.handler === "silence") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const source = identifySource();
|
||||||
|
if (source?.type === "browser-extension") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.maybeNotifyAdmin(opts.id, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
maybeNotifyAdmin(id, source) {
|
||||||
|
if (this.#adminWarned) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.currentUser?.admin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.siteSettings.warn_critical_js_deprecations) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CRITICAL_DEPRECATIONS.some((pattern) => pattern.test(id))) {
|
||||||
|
this.notifyAdmin(id, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyAdmin(id, source) {
|
||||||
|
this.#adminWarned = true;
|
||||||
|
|
||||||
|
let notice = I18n.t("critical_deprecation.notice");
|
||||||
|
|
||||||
|
if (this.siteSettings.warn_critical_js_deprecations_message) {
|
||||||
|
notice += " " + this.siteSettings.warn_critical_js_deprecations_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source?.type === "theme") {
|
||||||
|
notice +=
|
||||||
|
" " +
|
||||||
|
I18n.t("critical_deprecation.theme_source", {
|
||||||
|
name: escapeExpression(source.name),
|
||||||
|
path: source.path,
|
||||||
|
});
|
||||||
|
} else if (source?.type === "plugin") {
|
||||||
|
notice +=
|
||||||
|
" " +
|
||||||
|
I18n.t("critical_deprecation.plugin_source", {
|
||||||
|
name: escapeExpression(source.name),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addGlobalNotice(notice, "critical-deprecation", {
|
||||||
|
dismissable: true,
|
||||||
|
dismissDuration: moment.duration(1, "day"),
|
||||||
|
level: "warn",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -225,6 +225,11 @@ en:
|
||||||
|
|
||||||
broken_plugin_alert: "Caused by plugin '%{name}'"
|
broken_plugin_alert: "Caused by plugin '%{name}'"
|
||||||
|
|
||||||
|
critical_deprecation:
|
||||||
|
notice: "<b>[Admin Notice]</b> One of your themes or plugins needs updating for compatibility with upcoming Discourse core changes (<a target='_blank' href='https://meta.discourse.org/t/287211'>more info</a>)."
|
||||||
|
theme_source: "Identified theme: <a target='_blank' href='%{path}'>'%{name}'</a>."
|
||||||
|
plugin_source: "Identified plugin: '%{name}'"
|
||||||
|
|
||||||
s3:
|
s3:
|
||||||
regions:
|
regions:
|
||||||
ap_northeast_1: "Asia Pacific (Tokyo)"
|
ap_northeast_1: "Asia Pacific (Tokyo)"
|
||||||
|
|
|
@ -2308,6 +2308,14 @@ developer:
|
||||||
default: false
|
default: false
|
||||||
client: true
|
client: true
|
||||||
hidden: true
|
hidden: true
|
||||||
|
warn_critical_js_deprecations:
|
||||||
|
default: true
|
||||||
|
client: true
|
||||||
|
hidden: true
|
||||||
|
warn_critical_js_deprecations_message:
|
||||||
|
default: ""
|
||||||
|
client: true
|
||||||
|
hidden: true
|
||||||
|
|
||||||
navigation:
|
navigation:
|
||||||
navigation_menu:
|
navigation_menu:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
describe "Production mode debug shims", type: :system do
|
describe "JS Deprecation Handling", type: :system do
|
||||||
it "can successfully print a deprecation message after applying prod shims" do
|
it "can successfully print a deprecation message after applying production-mode shims" do
|
||||||
visit("/latest")
|
visit("/latest")
|
||||||
expect(find("#main-outlet-wrapper")).to be_visible
|
expect(find("#main-outlet-wrapper")).to be_visible
|
||||||
|
|
||||||
|
@ -31,4 +31,25 @@ describe "Production mode debug shims", type: :system do
|
||||||
expect(call).to eq("DEPRECATION: Some message [deprecation id: some.id]")
|
expect(call).to eq("DEPRECATION: Some message [deprecation id: some.id]")
|
||||||
expect(backtrace).to include("shimLogDeprecationToConsole")
|
expect(backtrace).to include("shimLogDeprecationToConsole")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "shows warnings to admins for critical deprecations" do
|
||||||
|
sign_in Fabricate(:admin)
|
||||||
|
|
||||||
|
SiteSetting.warn_critical_js_deprecations = true
|
||||||
|
SiteSetting.warn_critical_js_deprecations_message =
|
||||||
|
"Discourse core changes will be applied to your site on Jan 15."
|
||||||
|
|
||||||
|
visit("/latest")
|
||||||
|
|
||||||
|
page.execute_script <<~JS
|
||||||
|
const deprecated = require("discourse-common/lib/deprecated").default;
|
||||||
|
deprecated("Fake deprecation message", { id: "fake-deprecation" })
|
||||||
|
JS
|
||||||
|
|
||||||
|
message = find("#global-notice-critical-deprecation")
|
||||||
|
expect(message).to have_text(
|
||||||
|
"One of your themes or plugins needs updating for compatibility with upcoming Discourse core changes",
|
||||||
|
)
|
||||||
|
expect(message).to have_text(SiteSetting.warn_critical_js_deprecations_message)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user