# 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([ 'customer-flair', 'lazy-yt', 'poll' ]) map = { 'Canned Replies' => 'https://github.com/discourse/discourse-canned-replies' } STDERR.puts "Allowing write to all repos!" if ENV['GIT_WRITE'] Plugin::Metadata::OFFICIAL_PLUGINS.each do |name| next if skip.include? name repo = map[name] || "https://github.com/discourse/#{name}" dir = repo.split('/').last path = File.expand_path('plugins/' + dir) if Dir.exist? path STDERR.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 status = system("git clone #{repo} #{path}") unless status abort("Failed to clone #{repo}") end end 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 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 } # run plugin:update plugins.each do |plugin| next unless File.directory?(plugin + "/.git") Rake::Task['plugin:update'].invoke(plugin) Rake::Task['plugin:update'].reenable end Rake::Task['plugin:versions'].invoke end desc 'update a plugin' task 'plugin:update', :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 `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?(/remotes\/origin\/main$/) 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 --no-rebase") abort("Unable to pull latest version of plugin #{plugin_path}") unless update_status end desc 'pull compatible plugin versions for all plugins' task 'plugin:pull_compatible_all' do |t| if GlobalSetting.load_plugins? STDERR.puts <<~TEXT WARNING: Plugins were activated before running `rake plugin:pull_compatible_all` You should prefix this command with LOAD_PLUGINS=0 TEXT end # 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) params = [] params << '--profile' if !parallel params << '--fail-fast' if ENV['RSPEC_FAILFAST'] params << "--seed #{ENV['RSPEC_SEED']}" if Integer(ENV['RSPEC_SEED'], exception: false) ruby = `which ruby`.strip # 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" sh "LOAD_PLUGINS=1 #{cmd} #{files.join(' ')} #{params.join(' ')}" else abort "No specs found." end end desc 'run plugin specs' task 'plugin:spec', :plugin do |t, args| args.with_defaults(plugin: "*") spec(args[:plugin]) end desc 'run plugin specs in parallel' task 'plugin:turbo_spec', :plugin do |t, args| args.with_defaults(plugin: "*") spec(args[:plugin], parallel: true) end desc 'run plugin qunit tests' task 'plugin:qunit', [:plugin, :timeout] do |t, args| args.with_defaults(plugin: "*") rake = "#{Rails.root}/bin/rake" cmd = 'LOAD_PLUGINS=1 ' cmd += 'QUNIT_SKIP_CORE=1 ' if args[:plugin] == "*" puts "Running qunit tests for all plugins" else puts "Running qunit tests for #{args[:plugin]}" cmd += "QUNIT_SINGLE_PLUGIN='#{args[:plugin]}' " end 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 do |migration_filename| File.basename(migration_filename)[/(^.*?)_/, 1].to_i end .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 do |migration_number| sh cmd(:up, migration_number) end 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 { |plugin, plugin_dir, plugin_git_dir| File.directory?(plugin_dir) && File.exist?(plugin_git_dir) } .sort_by { |plugin, _, _| plugin } .map { |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]] } .to_h puts JSON.pretty_generate(versions) end