mirror of
https://github.com/discourse/discourse.git
synced 2025-04-02 16:41:10 +08:00
DEV: Introduce TemporaryRedis
and unset DISCOURSE_*
env vars in the themes:isolated_test
rake task (#13401)
The `themes:isolated_test` rake task will now unset all `DISCOURSE_*` env variables if `UNSET_DISCOURSE_ENV_VARS` env var is set and will also spin up a temporary redis server so the unicorn web server that's spun up for the tests doesn't leak into the "main" redis server.
This commit is contained in:
parent
30c7a9b06d
commit
d3a3d1b94c
@ -42,7 +42,10 @@ task "qunit:test", [:timeout, :qunit_path] do |_, args|
|
|||||||
"UNICORN_PID_PATH" => "#{Rails.root}/tmp/pids/unicorn_test_#{port}.pid", # So this can run alongside development
|
"UNICORN_PID_PATH" => "#{Rails.root}/tmp/pids/unicorn_test_#{port}.pid", # So this can run alongside development
|
||||||
"UNICORN_PORT" => port.to_s,
|
"UNICORN_PORT" => port.to_s,
|
||||||
"UNICORN_SIDEKIQS" => "0",
|
"UNICORN_SIDEKIQS" => "0",
|
||||||
"DISCOURSE_SKIP_CSS_WATCHER" => "1"
|
"DISCOURSE_SKIP_CSS_WATCHER" => "1",
|
||||||
|
"UNICORN_LISTENER" => "127.0.0.1:#{port}",
|
||||||
|
"LOGSTASH_UNICORN_URI" => nil,
|
||||||
|
"UNICORN_WORKERS" => "3"
|
||||||
},
|
},
|
||||||
"#{Rails.root}/bin/unicorn -c config/unicorn.conf.rb",
|
"#{Rails.root}/bin/unicorn -c config/unicorn.conf.rb",
|
||||||
pgroup: true
|
pgroup: true
|
||||||
|
@ -120,7 +120,22 @@ task "themes:qunit", :type, :value do |t, args|
|
|||||||
end
|
end
|
||||||
|
|
||||||
desc "Install a theme/component on a temporary DB and run QUnit tests"
|
desc "Install a theme/component on a temporary DB and run QUnit tests"
|
||||||
task "themes:install_and_test" => :environment do |t, args|
|
task "themes:isolated_test" => :environment do |t, args|
|
||||||
|
# This task can be called in a production environment that likely has a bunch
|
||||||
|
# of DISCOURSE_* env vars that we don't want to be picked up by the Unicorn
|
||||||
|
# server that will be spawned for the tests. So we need to unset them all
|
||||||
|
# before we proceed.
|
||||||
|
# Make this behavior opt-in to make it very obvious.
|
||||||
|
if ENV["UNSET_DISCOURSE_ENV_VARS"] == "1"
|
||||||
|
ENV.keys.each do |key|
|
||||||
|
next if !key.start_with?('DISCOURSE_')
|
||||||
|
ENV[key] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
redis = TemporaryRedis.new
|
||||||
|
redis.start
|
||||||
|
$redis = redis.instance # rubocop:disable Style/GlobalVars
|
||||||
db = TemporaryDb.new
|
db = TemporaryDb.new
|
||||||
db.start
|
db.start
|
||||||
db.migrate
|
db.migrate
|
||||||
@ -139,6 +154,7 @@ task "themes:install_and_test" => :environment do |t, args|
|
|||||||
ENV["PGHOST"] = "localhost"
|
ENV["PGHOST"] = "localhost"
|
||||||
ENV["QUNIT_RAILS_ENV"] = "development"
|
ENV["QUNIT_RAILS_ENV"] = "development"
|
||||||
ENV["DISCOURSE_DEV_DB"] = "discourse"
|
ENV["DISCOURSE_DEV_DB"] = "discourse"
|
||||||
|
ENV["DISCOURSE_REDIS_PORT"] = redis.port.to_s
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
themes.each do |(name, id)|
|
themes.each do |(name, id)|
|
||||||
@ -155,4 +171,5 @@ task "themes:install_and_test" => :environment do |t, args|
|
|||||||
ensure
|
ensure
|
||||||
db&.stop
|
db&.stop
|
||||||
db&.remove
|
db&.remove
|
||||||
|
redis&.remove
|
||||||
end
|
end
|
||||||
|
107
lib/temporary_redis.rb
Normal file
107
lib/temporary_redis.rb
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class TemporaryRedis
|
||||||
|
REDIS_TEMP_DIR = "/tmp/discourse_temp_redis"
|
||||||
|
REDIS_LOG_PATH = "#{REDIS_TEMP_DIR}/redis.log"
|
||||||
|
REDIS_PID_PATH = "#{REDIS_TEMP_DIR}/redis.pid"
|
||||||
|
|
||||||
|
attr_reader :instance
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
set_redis_server_bin
|
||||||
|
end
|
||||||
|
|
||||||
|
def port
|
||||||
|
@port ||= find_free_port(11000..11900)
|
||||||
|
end
|
||||||
|
|
||||||
|
def start
|
||||||
|
return if @started
|
||||||
|
FileUtils.rm_rf(REDIS_TEMP_DIR)
|
||||||
|
Dir.mkdir(REDIS_TEMP_DIR)
|
||||||
|
FileUtils.touch(REDIS_LOG_PATH)
|
||||||
|
|
||||||
|
puts "Starting redis on port: #{port}"
|
||||||
|
@thread = Thread.new do
|
||||||
|
system(
|
||||||
|
@redis_server_bin,
|
||||||
|
"--port", port.to_s,
|
||||||
|
"--pidfile", REDIS_PID_PATH,
|
||||||
|
"--logfile", REDIS_LOG_PATH,
|
||||||
|
"--databases", "1",
|
||||||
|
"--save", '""',
|
||||||
|
"--appendonly", "no",
|
||||||
|
"--daemonize", "no",
|
||||||
|
"--maxclients", "100",
|
||||||
|
"--dir", REDIS_TEMP_DIR
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "Waiting for redis server to start..."
|
||||||
|
success = false
|
||||||
|
instance = nil
|
||||||
|
config = {
|
||||||
|
port: port,
|
||||||
|
host: "127.0.0.1",
|
||||||
|
db: 0
|
||||||
|
}
|
||||||
|
start = Time.now
|
||||||
|
while !success
|
||||||
|
begin
|
||||||
|
instance = DiscourseRedis.new(config, namespace: true)
|
||||||
|
success = instance.ping == "PONG"
|
||||||
|
rescue Redis::CannotConnectError
|
||||||
|
ensure
|
||||||
|
if !success && (Time.now - start) >= 5
|
||||||
|
STDERR.puts "ERROR: Could not connect to redis in 5 seconds."
|
||||||
|
self.remove
|
||||||
|
exit(1)
|
||||||
|
elsif !success
|
||||||
|
sleep 0.1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
puts "Redis is ready"
|
||||||
|
@instance = instance
|
||||||
|
@started = true
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove
|
||||||
|
if @instance
|
||||||
|
@instance.shutdown
|
||||||
|
@thread.join
|
||||||
|
puts "Redis has been shutdown."
|
||||||
|
end
|
||||||
|
FileUtils.rm_rf(REDIS_TEMP_DIR)
|
||||||
|
@started = false
|
||||||
|
puts "Redis files have been cleaned up."
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_redis_server_bin
|
||||||
|
path = `which redis-server 2> /dev/null`.strip
|
||||||
|
if path.size < 1
|
||||||
|
STDERR.puts 'ERROR: redis-server is not installed on this machine. Please install it'
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
@redis_server_bin = path
|
||||||
|
rescue => ex
|
||||||
|
STDERR.puts 'ERROR: Failed to find redis-server binary:'
|
||||||
|
STDERR.puts ex.inspect
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_free_port(range)
|
||||||
|
range.each do |port|
|
||||||
|
return port if port_available?(port)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def port_available?(port)
|
||||||
|
TCPServer.open(port).close
|
||||||
|
true
|
||||||
|
rescue Errno::EADDRINUSE
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user