mirror of
https://github.com/discourse/discourse.git
synced 2025-05-25 00:32:52 +08:00
DEV: Drop ember-cli-based SCSS and locale compilation (#31407)
This totally separate SCSS and i18n compilation pipelines only existed so that we could run `ember exam` in CI without starting Rails. Now that our CI has such heavy caching of Ruby dependencies and database migrations, the speed benefit of this is not worth the cost of maintaining these separate pipelines. Therefore, this commit removes that system, and updates CI to use `bin/rake qunit:test`. That will start up a Rails server and proxy stylesheet/locale requests to it. This strategy was already used for our theme and plugin qunit test runs.
This commit is contained in:
75
.github/workflows/tests.yml
vendored
75
.github/workflows/tests.yml
vendored
@ -28,7 +28,7 @@ permissions:
|
||||
jobs:
|
||||
build:
|
||||
if: github.event_name == 'pull_request' || github.repository != 'discourse/discourse-private-mirror'
|
||||
name: ${{ matrix.target }} ${{ matrix.build_type }} # Update fetch-job-id step if changing this
|
||||
name: ${{ matrix.target }} ${{ matrix.build_type }}${{ (matrix.target == 'core' && matrix.build_type == 'frontend' && format(' ({0})', matrix.browser)) || '' }} # Update fetch-job-id step if changing this
|
||||
runs-on: ${{ (github.repository_owner == 'discourse' && 'debian-12') || 'ubuntu-latest' }}
|
||||
container: discourse/discourse_test:release
|
||||
timeout-minutes: 20
|
||||
@ -42,8 +42,9 @@ jobs:
|
||||
MINIO_RUNNER_LOG_LEVEL: DEBUG
|
||||
DISCOURSE_TURBO_RSPEC_RETRY_AND_LOG_FLAKY_TESTS: ${{ (matrix.build_type == 'system' || matrix.build_type == 'backend') && '1' }}
|
||||
CHEAP_SOURCE_MAPS: "1"
|
||||
TESTEM_DEFAULT_BROWSER: Chrome
|
||||
MINIO_RUNNER_INSTALL_DIR: /home/discourse/.minio_runner
|
||||
TESTEM_BROWSER: ${{ (startsWith(matrix.browser, 'Firefox') && 'Firefox') || matrix.browser }}
|
||||
TESTEM_FIREFOX_PATH: ${{ (matrix.browser == 'Firefox Evergreen') && '/opt/firefox-evergreen/firefox' }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@ -51,6 +52,7 @@ jobs:
|
||||
matrix:
|
||||
build_type: [backend, frontend, system, annotations]
|
||||
target: [core, plugins, themes]
|
||||
browser: [Chrome]
|
||||
exclude:
|
||||
- build_type: annotations
|
||||
target: plugins
|
||||
@ -58,11 +60,15 @@ jobs:
|
||||
target: themes
|
||||
- build_type: backend
|
||||
target: themes
|
||||
- build_type: frontend
|
||||
target: core # Handled by core_frontend_tests job (below)
|
||||
include:
|
||||
- build_type: system
|
||||
target: chat
|
||||
- build_type: frontend
|
||||
target: core
|
||||
browser: Firefox Evergreen
|
||||
- build_type: frontend
|
||||
target: core
|
||||
browser: Firefox ESR
|
||||
|
||||
steps:
|
||||
- name: Set working directory owner
|
||||
@ -233,6 +239,11 @@ jobs:
|
||||
if: matrix.build_type == 'backend' && matrix.target == 'plugins'
|
||||
run: bin/rake plugin:turbo_spec['*','--verbose --format=documentation --use-runtime-info --profile=50']
|
||||
|
||||
- name: Core QUnit
|
||||
if: matrix.build_type == 'frontend' && matrix.target == 'core'
|
||||
run: QUNIT_WRITE_EXECUTION_FILE=1 bin/rake qunit:test
|
||||
timeout-minutes: 30
|
||||
|
||||
- name: Plugin QUnit
|
||||
if: matrix.build_type == 'frontend' && matrix.target == 'plugins'
|
||||
run: QUNIT_WRITE_EXECUTION_FILE=1 bin/rake plugin:qunit['*']
|
||||
@ -244,9 +255,9 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always() && matrix.build_type == 'frontend' && matrix.target == 'plugins'
|
||||
if: always() && matrix.build_type == 'frontend'
|
||||
with:
|
||||
name: ember-exam-execution-plugins-frontend-${{ hashFiles('./app/assets/javascripts/discourse/test-execution-*.json') }}
|
||||
name: ember-exam-execution-${{ matrix.target }}-${{ matrix.browser }}-frontend-${{ hashFiles('./app/assets/javascripts/discourse/test-execution-*.json') }}
|
||||
path: ./app/assets/javascripts/discourse/test-execution-*.json
|
||||
|
||||
- name: Ember Build for System Tests
|
||||
@ -322,7 +333,7 @@ jobs:
|
||||
id: fetch-job-id
|
||||
if: steps.check-flaky-spec-report.outputs.exists == 'true'
|
||||
run: |
|
||||
job_id=$(ruby script/get_github_workflow_run_job_id.rb ${{ github.run_id }} ${{ github.run_attempt }} '${{ matrix.target }} ${{ matrix.build_type }}')
|
||||
job_id=$(ruby script/get_github_workflow_run_job_id.rb ${{ github.run_id }} ${{ github.run_attempt }} '${{ matrix.target }} ${{ matrix.build_type }}${{ (matrix.target == 'core' && matrix.build_type == 'frontend' && format(' ({0})', matrix.browser)) || '' }}')
|
||||
echo "job_id=$job_id" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create flaky tests report artifact
|
||||
@ -353,56 +364,6 @@ jobs:
|
||||
fi
|
||||
timeout-minutes: 30
|
||||
|
||||
core_frontend_tests:
|
||||
if: github.event_name == 'pull_request' || github.repository != 'discourse/discourse-private-mirror'
|
||||
name: core frontend (${{ matrix.browser }})
|
||||
runs-on: ${{ (github.repository_owner == 'discourse' && 'debian-12') || 'ubuntu-latest' }}
|
||||
container:
|
||||
image: discourse/discourse_test:release
|
||||
options: --user discourse
|
||||
|
||||
timeout-minutes: 35
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
browser: ["Chrome", "Firefox ESR", "Firefox Evergreen"]
|
||||
|
||||
env:
|
||||
TESTEM_BROWSER: ${{ (startsWith(matrix.browser, 'Firefox') && 'Firefox') || matrix.browser }}
|
||||
TESTEM_FIREFOX_PATH: ${{ (matrix.browser == 'Firefox Evergreen') && '/opt/firefox-evergreen/firefox' }}
|
||||
CHEAP_SOURCE_MAPS: "1"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup Git
|
||||
run: |
|
||||
git config --global user.email "ci@ci.invalid"
|
||||
git config --global user.name "Discourse CI"
|
||||
|
||||
- name: pnpm install
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Ember Build
|
||||
working-directory: ./app/assets/javascripts/discourse
|
||||
run: |
|
||||
mkdir /tmp/emberbuild
|
||||
pnpm ember build --environment=test -o /tmp/emberbuild
|
||||
|
||||
- name: Core QUnit
|
||||
working-directory: ./app/assets/javascripts/discourse
|
||||
run: |
|
||||
pnpm ember exam --path /tmp/emberbuild --load-balance --parallel=$(($(nproc) / 2)) --launch "${{ env.TESTEM_BROWSER }}" --write-execution-file --random
|
||||
timeout-minutes: 15
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: ember-exam-execution-${{ matrix.browser }}-${{ hashFiles('./app/assets/javascripts/discourse/test-execution-*.json') }}
|
||||
path: ./app/assets/javascripts/discourse/test-execution-*.json
|
||||
|
||||
merge:
|
||||
if: github.repository == 'discourse/discourse' && github.ref == 'refs/heads/main'
|
||||
|
@ -4,9 +4,7 @@ const EmberApp = require("ember-cli/lib/broccoli/ember-app");
|
||||
const path = require("path");
|
||||
const mergeTrees = require("broccoli-merge-trees");
|
||||
const concat = require("broccoli-concat");
|
||||
const { createI18nTree } = require("./lib/translation-plugin");
|
||||
const { parsePluginClientSettings } = require("./lib/site-settings-plugin");
|
||||
const discourseScss = require("./lib/discourse-scss");
|
||||
const generateScriptsTree = require("./lib/scripts");
|
||||
const funnel = require("broccoli-funnel");
|
||||
const DeprecationSilencer = require("deprecation-silencer");
|
||||
@ -96,20 +94,12 @@ module.exports = function (defaults) {
|
||||
|
||||
const adminTree = app.project.findAddonByName("admin").treeForAddonBundle();
|
||||
|
||||
const testStylesheetTree = mergeTrees([
|
||||
discourseScss(`${discourseRoot}/app/assets/stylesheets`, "qunit.scss"),
|
||||
discourseScss(
|
||||
`${discourseRoot}/app/assets/stylesheets`,
|
||||
"qunit-custom.scss"
|
||||
),
|
||||
]);
|
||||
app.project.liveReloadFilterPatterns = [/.*\.scss/];
|
||||
|
||||
const terserPlugin = app.project.findAddonByName("ember-cli-terser");
|
||||
const applyTerser = (tree) => terserPlugin.postprocessTree("all", tree);
|
||||
|
||||
let extraPublicTrees = [
|
||||
createI18nTree(discourseRoot, vendorJs),
|
||||
parsePluginClientSettings(discourseRoot, vendorJs, app),
|
||||
funnel(`${discourseRoot}/public/javascripts`, { destDir: "javascripts" }),
|
||||
applyTerser(
|
||||
@ -120,7 +110,6 @@ module.exports = function (defaults) {
|
||||
),
|
||||
applyTerser(generateScriptsTree(app)),
|
||||
applyTerser(discoursePluginsTree),
|
||||
testStylesheetTree,
|
||||
];
|
||||
|
||||
const assetCachebuster = process.env["DISCOURSE_ASSET_URL_SALT"] || "";
|
||||
|
@ -1,64 +0,0 @@
|
||||
const Plugin = require("broccoli-plugin");
|
||||
const sass = require("sass");
|
||||
const fs = require("fs");
|
||||
const concat = require("broccoli-concat");
|
||||
|
||||
let builtSet = new Set();
|
||||
|
||||
class DiscourseScss extends Plugin {
|
||||
constructor(inputNodes, inputFile, options) {
|
||||
super(inputNodes, {
|
||||
...options,
|
||||
persistentOutput: true,
|
||||
});
|
||||
|
||||
this.inputFile = inputFile;
|
||||
}
|
||||
|
||||
build() {
|
||||
let file = this.inputPaths[0] + "/" + this.inputFile;
|
||||
|
||||
// We could get fancy eventually and do this based on whether the css changes
|
||||
// but this is just used for tests right now.
|
||||
if (builtSet.has(file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let deprecationCount = 0;
|
||||
let result = sass.renderSync({
|
||||
file,
|
||||
includePaths: this.inputPaths,
|
||||
silenceDeprecations: ["color-functions", "import", "global-builtin"],
|
||||
verbose: true, // call warn() for all deprecations
|
||||
logger: {
|
||||
warn(message, options) {
|
||||
if (options.deprecation) {
|
||||
deprecationCount += 1;
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`\nWARNING: ${message}`);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
if (deprecationCount > 0) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
`\nWARNING: ${deprecationCount} deprecations encountered while compiling scss. (we cannot correct these until the Ruby SCSS pipeline is updated)`
|
||||
);
|
||||
}
|
||||
|
||||
fs.writeFileSync(
|
||||
`${this.outputPath}/` + this.inputFile.replace(".scss", ".css"),
|
||||
result.css
|
||||
);
|
||||
|
||||
builtSet.add(file);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function scss(path, file) {
|
||||
return concat(new DiscourseScss([path], file), {
|
||||
outputFile: `assets/${file.replace(".scss", ".css")}`,
|
||||
});
|
||||
};
|
@ -1,137 +0,0 @@
|
||||
const Plugin = require("broccoli-plugin");
|
||||
const Yaml = require("js-yaml");
|
||||
const fs = require("fs");
|
||||
const concat = require("broccoli-concat");
|
||||
const mergeTrees = require("broccoli-merge-trees");
|
||||
const MessageFormat = require("@messageformat/core");
|
||||
const deepmerge = require("deepmerge");
|
||||
const glob = require("glob");
|
||||
const { shouldLoadPlugins } = require("discourse-plugins");
|
||||
|
||||
let built = false;
|
||||
|
||||
class TranslationPlugin extends Plugin {
|
||||
constructor(inputNodes, inputFile, options) {
|
||||
super(inputNodes, {
|
||||
...options,
|
||||
persistentOutput: true,
|
||||
});
|
||||
|
||||
this.inputFile = inputFile;
|
||||
}
|
||||
|
||||
replaceMF(formats, input, path = []) {
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object.keys(input).forEach((key) => {
|
||||
let value = input[key];
|
||||
|
||||
let subpath = path.concat(key);
|
||||
if (typeof value === "object") {
|
||||
this.replaceMF(formats, value, subpath);
|
||||
} else if (key.endsWith("_MF")) {
|
||||
// omit locale.js
|
||||
let mfPath = subpath.slice(2).join(".");
|
||||
formats[mfPath] = this.mf.compile(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
build() {
|
||||
// We could get fancy eventually and do this based on whether the yaml
|
||||
// or vendor files change but in practice we shouldn't need exact up to date
|
||||
// translations in admin.
|
||||
if (built) {
|
||||
return;
|
||||
}
|
||||
|
||||
let parsed = {};
|
||||
|
||||
this.inputPaths.forEach((path) => {
|
||||
let file = path + "/" + this.inputFile;
|
||||
let yaml = fs.readFileSync(file, { encoding: "UTF-8" });
|
||||
let loaded = Yaml.load(yaml, { json: true });
|
||||
parsed = deepmerge(parsed, loaded);
|
||||
});
|
||||
|
||||
let extras = {
|
||||
en: {
|
||||
admin: parsed.en.admin_js.admin,
|
||||
wizard: parsed.en.wizard_js.wizard,
|
||||
},
|
||||
};
|
||||
|
||||
delete parsed.en.admin_js;
|
||||
delete parsed.en.wizard_js;
|
||||
|
||||
let formats = {};
|
||||
this.mf = new MessageFormat("en");
|
||||
this.replaceMF(formats, parsed);
|
||||
this.replaceMF(formats, extras);
|
||||
|
||||
formats = Object.entries(formats).map(([k, v]) => `"${k}": ${v}`);
|
||||
|
||||
let contents = `
|
||||
(function() {
|
||||
I18n.locale = 'en';
|
||||
I18n.translations = ${JSON.stringify(parsed)};
|
||||
I18n.extras = ${JSON.stringify(extras)};
|
||||
|
||||
const Messages = require("@messageformat/runtime/messages").default;
|
||||
const { number, plural, select } = require("@messageformat/runtime");
|
||||
const { en } = require("@messageformat/runtime/lib/cardinals");
|
||||
const msgData = { en: { ${formats.join(",\n")} } };
|
||||
const messages = new Messages(msgData, "en");
|
||||
messages.defaultLocale = "en";
|
||||
I18n._mfMessages = messages;
|
||||
})()
|
||||
`;
|
||||
|
||||
fs.writeFileSync(
|
||||
`${this.outputPath}/` + this.inputFile.replace(".yml", ".js"),
|
||||
contents
|
||||
);
|
||||
built = true;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function translatePlugin(...params) {
|
||||
return new TranslationPlugin(...params);
|
||||
};
|
||||
|
||||
module.exports.createI18nTree = function (discourseRoot, vendorJs) {
|
||||
let translations = [discourseRoot + "/config/locales"];
|
||||
|
||||
if (shouldLoadPlugins()) {
|
||||
translations = translations.concat(
|
||||
glob
|
||||
.sync(discourseRoot + "/plugins/*/config/locales/client.en.yml")
|
||||
.map((f) => f.replace(/\/client\.en\.yml$/, ""))
|
||||
);
|
||||
}
|
||||
|
||||
let en = new TranslationPlugin(translations, "client.en.yml");
|
||||
|
||||
return concat(
|
||||
mergeTrees([
|
||||
vendorJs,
|
||||
discourseRoot + "/app/assets/javascripts/locales",
|
||||
en,
|
||||
]),
|
||||
{
|
||||
inputFiles: [
|
||||
"i18n.js",
|
||||
"moment.js",
|
||||
"moment-timezone-with-data.js",
|
||||
"client.en.js",
|
||||
],
|
||||
headerFiles: ["i18n.js", "moment.js", "moment-timezone-with-data.js"],
|
||||
footerFiles: ["client.en.js"],
|
||||
outputFile: `assets/test-i18n.js`,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
module.exports.TranslationPlugin = TranslationPlugin;
|
@ -127,7 +127,6 @@
|
||||
"pretender": "^3.4.7",
|
||||
"qunit": "^2.24.1",
|
||||
"qunit-dom": "^3.4.0",
|
||||
"sass": "^1.85.0",
|
||||
"select-kit": "workspace:1.0.0",
|
||||
"sinon": "^19.0.2",
|
||||
"source-map": "^0.7.4",
|
||||
|
@ -1,5 +1,4 @@
|
||||
const TapReporter = require("testem/lib/reporters/tap_reporter");
|
||||
const { shouldLoadPlugins } = require("discourse-plugins");
|
||||
const fs = require("fs");
|
||||
const displayUtils = require("testem/lib/utils/displayutils");
|
||||
const colors = require("@colors/colors/safe");
|
||||
@ -177,6 +176,16 @@ if (process.env.TESTEM_FIREFOX_PATH) {
|
||||
}
|
||||
|
||||
const target = `http://127.0.0.1:${process.env.UNICORN_PORT || "3000"}`;
|
||||
|
||||
fetch(`${target}/about.json`).catch(() => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(
|
||||
colors.red(
|
||||
`Error connecting to Rails server on ${target}. Is it running? Use 'bin/rake qunit:test' or 'plugin:qunit' to start automatically.`
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
const themeTestPages = process.env.THEME_TEST_PAGES;
|
||||
|
||||
if (themeTestPages) {
|
||||
@ -204,20 +213,26 @@ if (themeTestPages) {
|
||||
});
|
||||
},
|
||||
];
|
||||
} else if (shouldLoadPlugins()) {
|
||||
} else {
|
||||
// Running with ember cli, but we want to pass through plugin request to Rails
|
||||
module.exports.proxies = {
|
||||
"/assets/locales/*.js": {
|
||||
target,
|
||||
},
|
||||
"/assets/plugins/*_extra.js": {
|
||||
target,
|
||||
},
|
||||
"/plugins/": {
|
||||
target,
|
||||
},
|
||||
"/bootstrap/plugin-css-for-tests.css": {
|
||||
"/bootstrap/": {
|
||||
target,
|
||||
},
|
||||
"/stylesheets/": {
|
||||
target,
|
||||
},
|
||||
"/extra-locales/": {
|
||||
target,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/vendor.css" />
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/discourse.css">
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/test-support.css" />
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/qunit.css" data-embroider-ignore />
|
||||
<link rel="stylesheet" href="{{rootURL}}bootstrap/core-css-for-tests.css" data-embroider-ignore />
|
||||
|
||||
{{content-for "head-footer"}} {{content-for "test-head-footer"}}
|
||||
|
||||
@ -53,7 +53,10 @@
|
||||
|
||||
<script src="{{rootURL}}assets/discourse.js"></script>
|
||||
|
||||
<script src="{{rootURL}}assets/test-i18n.js" data-embroider-ignore></script>
|
||||
<script src="{{rootURL}}assets/locales/en.js" data-embroider-ignore></script>
|
||||
<script src="{{rootURL}}extra-locales/mf" data-embroider-ignore></script>
|
||||
<script src="{{rootURL}}extra-locales/admin" data-embroider-ignore></script>
|
||||
<script src="{{rootURL}}extra-locales/wizard" data-embroider-ignore></script>
|
||||
<script src="{{rootURL}}assets/test-site-settings.js" data-embroider-ignore></script>
|
||||
<script src="{{rootURL}}assets/admin.js" data-embroider-ignore></script>
|
||||
|
||||
@ -72,6 +75,6 @@
|
||||
<!-- This script takes the <template>, filters plugin assets as required, then appends to discourse-dynamic-test-js -->
|
||||
<script src="{{rootURL}}assets/scripts/discourse-test-load-dynamic-js.js" data-embroider-ignore></script>
|
||||
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/qunit-custom.css" data-embroider-ignore />
|
||||
<link rel="stylesheet" href="{{rootURL}}stylesheets/qunit-custom.css" data-embroider-ignore />
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,11 +0,0 @@
|
||||
// Styles for Ember CLI test environment
|
||||
:root {
|
||||
--font-family: "Arial";
|
||||
}
|
||||
|
||||
@import "common/foundation/colors";
|
||||
@import "common/foundation/variables";
|
||||
@import "common/foundation/mixins";
|
||||
@import "desktop";
|
||||
@import "color_definitions";
|
||||
@import "admin";
|
@ -4,16 +4,26 @@ class BootstrapController < ApplicationController
|
||||
skip_before_action :redirect_to_login_if_required, :check_xhr
|
||||
|
||||
def plugin_css_for_tests
|
||||
targets = Discourse.find_plugin_css_assets(include_disabled: true, desktop_view: true)
|
||||
render_css_for_tests(targets)
|
||||
end
|
||||
|
||||
def core_css_for_tests
|
||||
targets = %w[color_definitions desktop admin]
|
||||
render_css_for_tests(targets)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_css_for_tests(targets)
|
||||
urls =
|
||||
Discourse
|
||||
.find_plugin_css_assets(include_disabled: true, desktop_view: true)
|
||||
.map do |target|
|
||||
details = Stylesheet::Manager.new().stylesheet_details(target, "all")
|
||||
details[0][:new_href]
|
||||
end
|
||||
targets.map do |target|
|
||||
details = Stylesheet::Manager.new().stylesheet_details(target, "all")
|
||||
details[0][:new_href]
|
||||
end
|
||||
|
||||
stylesheet = <<~CSS
|
||||
/* For use in tests only - `@import`s all plugin stylesheets */
|
||||
/* For use in tests only */
|
||||
#{urls.map { |url| "@import \"#{url}\";" }.join("\n")}
|
||||
CSS
|
||||
|
||||
|
@ -85,6 +85,7 @@ class ExtraLocalesController < ApplicationController
|
||||
private
|
||||
|
||||
def valid_bundle?(bundle)
|
||||
bundle.in?(BUNDLES) || (bundle =~ /\A(admin|wizard)\z/ && current_user&.staff?)
|
||||
return true if bundle.in?(BUNDLES)
|
||||
bundle =~ /\A(admin|wizard)\z/ && (current_user&.staff? || Rails.env.local?)
|
||||
end
|
||||
end
|
||||
|
@ -29,6 +29,7 @@ Discourse::Application.routes.draw do
|
||||
|
||||
if Rails.env.test? || Rails.env.development?
|
||||
get "/bootstrap/plugin-css-for-tests.css" => "bootstrap#plugin_css_for_tests"
|
||||
get "/bootstrap/core-css-for-tests.css" => "bootstrap#core_css_for_tests"
|
||||
end
|
||||
|
||||
# This is not a valid production route and is causing routing errors to be raised in
|
||||
|
@ -300,10 +300,7 @@ task "docker:test" do
|
||||
|
||||
unless ENV["RUBY_ONLY"]
|
||||
unless ENV["SKIP_CORE"]
|
||||
@good &&=
|
||||
run_or_fail(
|
||||
"cd app/assets/javascripts/discourse && CI=1 pnpm ember exam --load-balance --parallel=#{qunit_concurrency} --random",
|
||||
)
|
||||
@good &&= run_or_fail("CI=1 QUNIT_PARALLEL=#{qunit_concurrency} bin/rake qunit:test")
|
||||
end
|
||||
|
||||
unless ENV["SKIP_PLUGINS"]
|
||||
|
192
pnpm-lock.yaml
generated
192
pnpm-lock.yaml
generated
@ -597,9 +597,6 @@ importers:
|
||||
qunit-dom:
|
||||
specifier: ^3.4.0
|
||||
version: 3.4.0
|
||||
sass:
|
||||
specifier: ^1.85.0
|
||||
version: 1.85.0
|
||||
select-kit:
|
||||
specifier: workspace:1.0.0
|
||||
version: link:../select-kit
|
||||
@ -2423,88 +2420,6 @@ packages:
|
||||
resolution: {integrity: sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==}
|
||||
engines: {node: ^16.14.0 || >=18.0.0}
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@parcel/watcher-darwin-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@parcel/watcher-darwin-x64@2.5.1':
|
||||
resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@parcel/watcher-freebsd-x64@2.5.1':
|
||||
resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@parcel/watcher-linux-arm-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@parcel/watcher-win32-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@parcel/watcher-win32-ia32@2.5.1':
|
||||
resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@parcel/watcher-win32-x64@2.5.1':
|
||||
resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@parcel/watcher@2.5.1':
|
||||
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
engines: {node: '>=14'}
|
||||
@ -3612,10 +3527,6 @@ packages:
|
||||
peerDependencies:
|
||||
chart.js: '>=3.0.0'
|
||||
|
||||
chokidar@4.0.3:
|
||||
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
|
||||
engines: {node: '>= 14.16.0'}
|
||||
|
||||
chownr@2.0.0:
|
||||
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
|
||||
engines: {node: '>=10'}
|
||||
@ -4238,11 +4149,6 @@ packages:
|
||||
resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==}
|
||||
engines: {node: '>=12.20'}
|
||||
|
||||
detect-libc@1.0.3:
|
||||
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
|
||||
engines: {node: '>=0.10'}
|
||||
hasBin: true
|
||||
|
||||
detect-newline@4.0.1:
|
||||
resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
@ -5515,9 +5421,6 @@ packages:
|
||||
immer@10.1.1:
|
||||
resolution: {integrity: sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==}
|
||||
|
||||
immutable@5.0.3:
|
||||
resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==}
|
||||
|
||||
import-cwd@3.0.0:
|
||||
resolution: {integrity: sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==}
|
||||
engines: {node: '>=8'}
|
||||
@ -6594,9 +6497,6 @@ packages:
|
||||
no-case@3.0.4:
|
||||
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
|
||||
|
||||
node-addon-api@7.1.1:
|
||||
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
||||
|
||||
node-domexception@1.0.0:
|
||||
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||
engines: {node: '>=10.5.0'}
|
||||
@ -7325,10 +7225,6 @@ packages:
|
||||
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
readdirp@4.1.2:
|
||||
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
||||
engines: {node: '>= 14.18.0'}
|
||||
|
||||
recast@0.18.10:
|
||||
resolution: {integrity: sha512-XNvYvkfdAN9QewbrxeTOjgINkdY/odTgTS56ZNEWL9Ml0weT4T3sFtvnTuF+Gxyu46ANcRm1ntrF6F5LAJPAaQ==}
|
||||
engines: {node: '>= 4'}
|
||||
@ -7592,11 +7488,6 @@ packages:
|
||||
engines: {node: 10.* || >= 12.*}
|
||||
hasBin: true
|
||||
|
||||
sass@1.85.0:
|
||||
resolution: {integrity: sha512-3ToiC1xZ1Y8aU7+CkgCI/tqyuPXEmYGJXO7H4uqp0xkLXUqp88rQQ4j1HmP37xSJLbCJPaIiv+cT1y+grssrww==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
hasBin: true
|
||||
|
||||
saxes@6.0.0:
|
||||
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
|
||||
engines: {node: '>=v12.22.7'}
|
||||
@ -10598,67 +10489,6 @@ snapshots:
|
||||
- bluebird
|
||||
- supports-color
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-darwin-arm64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-darwin-x64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-freebsd-x64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-arm-glibc@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-win32-arm64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-win32-ia32@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-win32-x64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher@2.5.1':
|
||||
dependencies:
|
||||
detect-libc: 1.0.3
|
||||
is-glob: 4.0.3
|
||||
micromatch: 4.0.8
|
||||
node-addon-api: 7.1.1
|
||||
optionalDependencies:
|
||||
'@parcel/watcher-android-arm64': 2.5.1
|
||||
'@parcel/watcher-darwin-arm64': 2.5.1
|
||||
'@parcel/watcher-darwin-x64': 2.5.1
|
||||
'@parcel/watcher-freebsd-x64': 2.5.1
|
||||
'@parcel/watcher-linux-arm-glibc': 2.5.1
|
||||
'@parcel/watcher-linux-arm-musl': 2.5.1
|
||||
'@parcel/watcher-linux-arm64-glibc': 2.5.1
|
||||
'@parcel/watcher-linux-arm64-musl': 2.5.1
|
||||
'@parcel/watcher-linux-x64-glibc': 2.5.1
|
||||
'@parcel/watcher-linux-x64-musl': 2.5.1
|
||||
'@parcel/watcher-win32-arm64': 2.5.1
|
||||
'@parcel/watcher-win32-ia32': 2.5.1
|
||||
'@parcel/watcher-win32-x64': 2.5.1
|
||||
optional: true
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
optional: true
|
||||
|
||||
@ -12139,10 +11969,6 @@ snapshots:
|
||||
dependencies:
|
||||
chart.js: 3.5.1
|
||||
|
||||
chokidar@4.0.3:
|
||||
dependencies:
|
||||
readdirp: 4.1.2
|
||||
|
||||
chownr@2.0.0: {}
|
||||
|
||||
chrome-launcher@1.1.2:
|
||||
@ -12580,9 +12406,6 @@ snapshots:
|
||||
|
||||
detect-indent@7.0.1: {}
|
||||
|
||||
detect-libc@1.0.3:
|
||||
optional: true
|
||||
|
||||
detect-newline@4.0.1: {}
|
||||
|
||||
devtools-protocol@0.0.1402036: {}
|
||||
@ -14665,8 +14488,6 @@ snapshots:
|
||||
|
||||
immer@10.1.1: {}
|
||||
|
||||
immutable@5.0.3: {}
|
||||
|
||||
import-cwd@3.0.0:
|
||||
dependencies:
|
||||
import-from: 3.0.0
|
||||
@ -15768,9 +15589,6 @@ snapshots:
|
||||
lower-case: 2.0.2
|
||||
tslib: 2.8.1
|
||||
|
||||
node-addon-api@7.1.1:
|
||||
optional: true
|
||||
|
||||
node-domexception@1.0.0: {}
|
||||
|
||||
node-fetch@2.7.0(encoding@0.1.13):
|
||||
@ -16566,8 +16384,6 @@ snapshots:
|
||||
string_decoder: 1.3.0
|
||||
util-deprecate: 1.0.2
|
||||
|
||||
readdirp@4.1.2: {}
|
||||
|
||||
recast@0.18.10:
|
||||
dependencies:
|
||||
ast-types: 0.13.3
|
||||
@ -16838,14 +16654,6 @@ snapshots:
|
||||
minimist: 1.2.8
|
||||
walker: 1.0.8
|
||||
|
||||
sass@1.85.0:
|
||||
dependencies:
|
||||
chokidar: 4.0.3
|
||||
immutable: 5.0.3
|
||||
source-map-js: 1.2.1
|
||||
optionalDependencies:
|
||||
'@parcel/watcher': 2.5.1
|
||||
|
||||
saxes@6.0.0:
|
||||
dependencies:
|
||||
xmlchars: 2.2.0
|
||||
|
@ -14,7 +14,8 @@ RSpec.describe ExtraLocalesController do
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "requires staff access" do
|
||||
it "requires staff access in production" do
|
||||
Rails.env.stubs(:local?).returns(false)
|
||||
get "/extra-locales/admin"
|
||||
expect(response.status).to eq(403)
|
||||
|
||||
|
Reference in New Issue
Block a user