mirror of
https://github.com/discourse/discourse.git
synced 2024-12-11 17:23:42 +08:00
4f88f2eb15
This commit allows site admins to run theme tests in production via a new `/theme-qunit` route. When you visit `/theme-qunit`, you'll see a list of the themes/components installed on your site that have tests, and from there you can select a theme or component that you run its tests. We also have a new rake task `themes:install_and_test` that can be used to install a list of themes/components on a temporary database and run the tests of the themes/components that are installed. This rake task can be useful when upgrading/deploying a Discourse instance to make sure that the installed themes/components are compatible with the new Discourse version being deployed, and if the tests fail you can abort the build/deploy process so you don't end up with a broken site.
98 lines
2.7 KiB
Ruby
98 lines
2.7 KiB
Ruby
# frozen_string_literal: true
|
|
class ThemeJavascriptsController < ApplicationController
|
|
DISK_CACHE_PATH = "#{Rails.root}/tmp/javascript-cache"
|
|
TESTS_DISK_CACHE_PATH = "#{Rails.root}/tmp/javascript-cache/tests"
|
|
|
|
skip_before_action(
|
|
:check_xhr,
|
|
:handle_theme,
|
|
:preload_json,
|
|
:redirect_to_login_if_required,
|
|
:verify_authenticity_token,
|
|
only: [:show, :show_tests]
|
|
)
|
|
|
|
before_action :is_asset_path, :no_cookies, :apply_cdn_headers, only: [:show, :show_tests]
|
|
|
|
def show
|
|
raise Discourse::NotFound unless last_modified.present?
|
|
return render body: nil, status: 304 if not_modified?
|
|
|
|
# Security: safe due to route constraint
|
|
cache_file = "#{DISK_CACHE_PATH}/#{params[:digest]}.js"
|
|
|
|
unless File.exist?(cache_file)
|
|
content = query.pluck_first(:content)
|
|
raise Discourse::NotFound if content.nil?
|
|
|
|
FileUtils.mkdir_p(DISK_CACHE_PATH)
|
|
File.write(cache_file, content)
|
|
end
|
|
|
|
# this is only required for NGINX X-SendFile it seems
|
|
response.headers["Content-Length"] = File.size(cache_file).to_s
|
|
set_cache_control_headers
|
|
send_file(cache_file, disposition: :inline)
|
|
end
|
|
|
|
def show_tests
|
|
digest = params[:digest]
|
|
raise Discourse::NotFound if !digest.match?(/^\h{40}$/)
|
|
|
|
theme = Theme.find_by(id: params[:theme_id])
|
|
raise Discourse::NotFound if theme.blank?
|
|
|
|
content, content_digest = theme.baked_js_tests_with_digest
|
|
raise Discourse::NotFound if content.blank? || content_digest != digest
|
|
|
|
@cache_file = "#{TESTS_DISK_CACHE_PATH}/#{digest}.js"
|
|
return render body: nil, status: 304 if not_modified?
|
|
|
|
if !File.exist?(@cache_file)
|
|
FileUtils.mkdir_p(TESTS_DISK_CACHE_PATH)
|
|
File.write(@cache_file, content)
|
|
end
|
|
|
|
response.headers["Content-Length"] = File.size(@cache_file).to_s
|
|
set_cache_control_headers
|
|
send_file(@cache_file, disposition: :inline)
|
|
end
|
|
|
|
private
|
|
|
|
def query
|
|
@query ||= JavascriptCache.where(digest: params[:digest]).limit(1)
|
|
end
|
|
|
|
def last_modified
|
|
@last_modified ||= begin
|
|
if params[:action].to_s == "show_tests"
|
|
File.exist?(@cache_file) ? File.ctime(@cache_file) : nil
|
|
else
|
|
query.pluck_first(:updated_at)
|
|
end
|
|
end
|
|
end
|
|
|
|
def not_modified?
|
|
cache_time =
|
|
begin
|
|
Time.rfc2822(request.env["HTTP_IF_MODIFIED_SINCE"])
|
|
rescue ArgumentError
|
|
nil
|
|
end
|
|
|
|
cache_time && last_modified && last_modified <= cache_time
|
|
end
|
|
|
|
def set_cache_control_headers
|
|
if Rails.env.development?
|
|
response.headers['Last-Modified'] = Time.zone.now.httpdate
|
|
immutable_for(1.second)
|
|
else
|
|
response.headers['Last-Modified'] = last_modified.httpdate if last_modified
|
|
immutable_for(1.year)
|
|
end
|
|
end
|
|
end
|