mirror of
https://github.com/discourse/discourse.git
synced 2024-12-02 11:53:40 +08:00
5f119c57e8
Before this change, if the "Plugins backend" task on GitHub CI failed, we would get a huge amount of extra output at the end just to show the command that rake ran which failed (the bin/turbo_rspec command). This is useless and just makes it hard to see the failing specs. If you need the full command, it's already output at the top of the "Plugins backend" task in the GitHub CI.
293 lines
8.8 KiB
Ruby
293 lines
8.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
directory "plugins"
|
|
|
|
desc "install all official plugins (use GIT_WRITE=1 to pull with write access)"
|
|
task "plugin:install_all_official" do
|
|
skip = Set.new(%w[customer-flair poll])
|
|
|
|
STDERR.puts "Allowing write to all repos!" if ENV["GIT_WRITE"]
|
|
|
|
promises = []
|
|
failures = []
|
|
|
|
Plugin::Metadata::OFFICIAL_PLUGINS.each do |name|
|
|
next if skip.include? name
|
|
|
|
repo = "https://github.com/discourse/#{name}"
|
|
dir = repo.split("/").last
|
|
path = File.expand_path("plugins/" + dir)
|
|
|
|
if Dir.exist? path
|
|
STDOUT.puts "Skipping #{dir} cause it already exists!"
|
|
next
|
|
end
|
|
|
|
if ENV["GIT_WRITE"]
|
|
repo = repo.gsub("https://github.com/", "git@github.com:")
|
|
repo += ".git"
|
|
end
|
|
|
|
promises << Concurrent::Promise.execute do
|
|
attempts ||= 1
|
|
STDOUT.puts("Cloning '#{repo}' to '#{path}'...")
|
|
system("git clone --quiet #{repo} #{path}", exception: true)
|
|
rescue StandardError
|
|
if attempts == 3
|
|
failures << repo
|
|
abort
|
|
end
|
|
|
|
STDOUT.puts "Failed to clone #{repo}... trying again..."
|
|
attempts += 1
|
|
retry
|
|
end
|
|
end
|
|
|
|
Concurrent::Promise.zip(*promises).value!
|
|
failures.each { |repo| STDOUT.puts "Failed to clone #{repo}" } if failures.present?
|
|
end
|
|
|
|
desc "install plugin"
|
|
task "plugin:install", :repo do |t, args|
|
|
repo = ENV["REPO"] || ENV["repo"] || args[:repo]
|
|
name = ENV["NAME"] || ENV["name"] || File.basename(repo, ".git")
|
|
|
|
plugin_path = File.expand_path("plugins/" + name)
|
|
if File.directory?(File.expand_path(plugin_path))
|
|
abort("Plugin directory, " + plugin_path + ", already exists.")
|
|
end
|
|
|
|
clone_status = system("git clone " + repo + " " + plugin_path)
|
|
unless clone_status
|
|
FileUtils.rm_rf(plugin_path)
|
|
abort("Unable to clone plugin")
|
|
end
|
|
end
|
|
|
|
def update_plugin(plugin)
|
|
plugin = ENV["PLUGIN"] || ENV["plugin"] || plugin
|
|
plugin_path = plugin
|
|
plugin = File.basename(plugin)
|
|
|
|
unless File.directory?(plugin_path)
|
|
if File.directory?("plugins/" + plugin)
|
|
plugin_path = File.expand_path("plugins/" + plugin)
|
|
else
|
|
abort("Plugin " + plugin + " not found")
|
|
end
|
|
end
|
|
|
|
`git -C '#{plugin_path}' fetch origin --tags --force`
|
|
|
|
upstream_branch =
|
|
`git -C '#{plugin_path}' for-each-ref --format='%(upstream:short)' $(git -C '#{plugin_path}' symbolic-ref -q HEAD)`.strip
|
|
has_origin_main = `git -C '#{plugin_path}' branch -a`.match?(%r{remotes/origin/main\z})
|
|
has_local_main = `git -C '#{plugin_path}' show-ref refs/heads/main`.present?
|
|
|
|
if upstream_branch == "origin/master" && has_origin_main
|
|
puts "Branch has changed to `origin/main`"
|
|
|
|
if has_local_main
|
|
update_status = system("git -C '#{plugin_path}' checkout main")
|
|
abort("Unable to pull latest version of plugin #{plugin_path}") unless update_status
|
|
else
|
|
`git -C '#{plugin_path}' branch -m master main`
|
|
end
|
|
|
|
`git -C '#{plugin_path}' branch -u origin/main main`
|
|
end
|
|
|
|
update_status = system("git -C '#{plugin_path}' pull --quiet --no-rebase")
|
|
abort("Unable to pull latest version of plugin #{plugin_path}") unless update_status
|
|
end
|
|
|
|
desc "update all plugins"
|
|
task "plugin:update_all" do |t|
|
|
# Loop through each directory
|
|
plugins =
|
|
Dir
|
|
.glob(File.expand_path("plugins/*"))
|
|
.select { |f| File.directory?(f) && File.directory?("#{f}/.git") }
|
|
|
|
# run plugin:update
|
|
promises = plugins.map { |plugin| Concurrent::Promise.execute { update_plugin(plugin) } }
|
|
Concurrent::Promise.zip(*promises).value!
|
|
|
|
Rake::Task["plugin:versions"].invoke
|
|
end
|
|
|
|
desc "update a plugin"
|
|
task "plugin:update", :plugin do |t, args|
|
|
update_plugin(args[:plugin])
|
|
end
|
|
|
|
desc "pull compatible plugin versions for all plugins"
|
|
task "plugin:pull_compatible_all" do |t|
|
|
STDERR.puts <<~TEXT if GlobalSetting.load_plugins?
|
|
WARNING: Plugins were activated before running `rake plugin:pull_compatible_all`
|
|
You should prefix this command with LOAD_PLUGINS=0
|
|
TEXT
|
|
|
|
# Loop through each directory
|
|
plugins = Dir.glob(File.expand_path("plugins/*")).select { |f| File.directory? f }
|
|
# run plugin:pull_compatible
|
|
plugins.each do |plugin|
|
|
next unless File.directory?(plugin + "/.git")
|
|
Rake::Task["plugin:pull_compatible"].invoke(plugin)
|
|
Rake::Task["plugin:pull_compatible"].reenable
|
|
end
|
|
end
|
|
|
|
desc "pull a compatible plugin version"
|
|
task "plugin:pull_compatible", :plugin do |t, args|
|
|
plugin = ENV["PLUGIN"] || ENV["plugin"] || args[:plugin]
|
|
plugin_path = plugin
|
|
plugin = File.basename(plugin)
|
|
|
|
unless File.directory?(plugin_path)
|
|
if File.directory?("plugins/" + plugin)
|
|
plugin_path = File.expand_path("plugins/" + plugin)
|
|
else
|
|
abort("Plugin " + plugin + " not found")
|
|
end
|
|
end
|
|
|
|
checkout_version = Discourse.find_compatible_git_resource(plugin_path)
|
|
|
|
# Checkout value of the version compat
|
|
if checkout_version
|
|
puts "checking out compatible #{plugin} version: #{checkout_version}"
|
|
update_status =
|
|
system(
|
|
"git -C '#{plugin_path}' cat-file -e #{checkout_version} || git -C '#{plugin_path}' fetch --depth 1 $(git -C '#{plugin_path}' rev-parse --symbolic-full-name @{upstream} | awk -F '/' '{print $3}') #{checkout_version}; git -C '#{plugin_path}' reset --hard #{checkout_version}",
|
|
)
|
|
abort("Unable to checkout a compatible plugin version") unless update_status
|
|
else
|
|
puts "#{plugin} is already at latest compatible version"
|
|
end
|
|
end
|
|
|
|
desc "install all plugin gems"
|
|
task "plugin:install_all_gems" do |t|
|
|
# Left intentionally blank.
|
|
# When the app is being loaded, all missing gems are installed
|
|
# See: lib/plugin_gem.rb
|
|
puts "Done"
|
|
end
|
|
|
|
desc "install plugin gems"
|
|
task "plugin:install_gems", :plugin do |t, args|
|
|
# Left intentionally blank.
|
|
# When the app is being loaded, all missing gems are installed
|
|
# See: lib/plugin_gem.rb
|
|
puts "Done"
|
|
end
|
|
|
|
def spec(plugin, parallel: false, argv: nil)
|
|
params = []
|
|
params << "--profile" if !parallel
|
|
params << "--fail-fast" if ENV["RSPEC_FAILFAST"]
|
|
params << "--seed #{ENV["RSPEC_SEED"]}" if Integer(ENV["RSPEC_SEED"], exception: false)
|
|
params << argv if argv
|
|
|
|
# reject system specs as they are slow and need dedicated setup
|
|
files =
|
|
Dir.glob("./plugins/#{plugin}/spec/**/*_spec.rb").reject { |f| f.include?("spec/system/") }.sort
|
|
|
|
if files.length > 0
|
|
cmd = parallel ? "bin/turbo_rspec" : "bin/rspec"
|
|
|
|
Rake::FileUtilsExt.verbose(!parallel) do
|
|
sh("LOAD_PLUGINS=1 #{cmd} #{files.join(" ")} #{params.join(" ")}") do |ok, status|
|
|
fail "Spec command failed with status (#{status.exitstatus})" if !ok
|
|
end
|
|
end
|
|
else
|
|
abort "No specs found."
|
|
end
|
|
end
|
|
|
|
desc "run plugin specs"
|
|
task "plugin:spec", %i[plugin argv] do |_, args|
|
|
args.with_defaults(plugin: "*")
|
|
spec(args[:plugin], argv: args[:argv])
|
|
end
|
|
|
|
desc "run plugin specs in parallel"
|
|
task "plugin:turbo_spec", %i[plugin argv] do |_, args|
|
|
args.with_defaults(plugin: "*")
|
|
spec(args[:plugin], parallel: true, argv: args[:argv])
|
|
end
|
|
|
|
desc "run plugin qunit tests"
|
|
task "plugin:qunit", %i[plugin timeout] do |t, args|
|
|
args.with_defaults(plugin: "*")
|
|
|
|
rake = "#{Rails.root}/bin/rake"
|
|
|
|
cmd = "LOAD_PLUGINS=1 "
|
|
|
|
target =
|
|
if args[:plugin] == "*"
|
|
puts "Running qunit tests for all plugins"
|
|
"plugins"
|
|
else
|
|
puts "Running qunit tests for #{args[:plugin]}"
|
|
args[:plugin]
|
|
end
|
|
|
|
cmd += "TARGET='#{target}' "
|
|
|
|
cmd += "#{rake} qunit:test"
|
|
cmd += "[#{args[:timeout]}]" if args[:timeout]
|
|
|
|
system cmd
|
|
exit $?.exitstatus
|
|
end
|
|
|
|
desc "run all migrations of a plugin"
|
|
namespace "plugin:migrate" do
|
|
def list_migrations(plugin_name)
|
|
plugin_root = File.join(Rails.root, "plugins", plugin_name)
|
|
migrations_root = File.join(plugin_root, "db", "{post_migrate,migrate}", "*.rb")
|
|
Dir[migrations_root]
|
|
.map { |migration_filename| File.basename(migration_filename)[/(^.*?)_/, 1].to_i }
|
|
.sort
|
|
end
|
|
|
|
def cmd(operation, migration_number)
|
|
"rails db:migrate:#{operation} LOAD_PLUGINS=1 VERSION=#{migration_number}"
|
|
end
|
|
|
|
task :down, [:plugin] do |t, args|
|
|
list_migrations(args[:plugin]).reverse.each do |migration_number|
|
|
sh cmd(:down, migration_number)
|
|
end
|
|
end
|
|
|
|
task :up, [:plugin] do |t, args|
|
|
list_migrations(args[:plugin]).each { |migration_number| sh cmd(:up, migration_number) }
|
|
end
|
|
end
|
|
|
|
desc "display all plugin versions"
|
|
task "plugin:versions" do |t, args|
|
|
versions =
|
|
Dir
|
|
.glob("*", base: "plugins")
|
|
.map { |plugin| [plugin, "plugins/#{plugin}", "plugins/#{plugin}/.git"] }
|
|
.select do |plugin, plugin_dir, plugin_git_dir|
|
|
File.directory?(plugin_dir) && File.exist?(plugin_git_dir)
|
|
end
|
|
.sort_by { |plugin, _, _| plugin }
|
|
.map do |plugin, _, plugin_git_dir|
|
|
version = `git --git-dir \"#{plugin_git_dir}\" rev-parse HEAD`
|
|
abort("unable to get #{plugin} version") unless version
|
|
[plugin, version.strip[0...8]]
|
|
end
|
|
.to_h
|
|
|
|
puts JSON.pretty_generate(versions)
|
|
end
|