diff --git a/.rubocop/default.yml b/.rubocop/default.yml index c130b0916..79198d53a 100644 --- a/.rubocop/default.yml +++ b/.rubocop/default.yml @@ -286,6 +286,10 @@ Rails/EnvironmentVariableAccess: Enabled: true AllowReads: true +Rails/Output: + Exclude: + - "lib/tasks/**/*" + # RSpec tests Style/NumericPredicate: Description: >- diff --git a/app/models/package.rb b/app/models/package.rb index 8fe84021b..8511ff46a 100644 --- a/app/models/package.rb +++ b/app/models/package.rb @@ -151,17 +151,18 @@ execute migration down + unlink files =begin -link files + execute migration up +link files Package.link('/path/to/src/extension') +Migrations will not be executed because the the codebase was modified +in the current process and is therefore inconsistent. This must be done +subsequently in a separate step. + =end def self.link(package_base_dir) - # check if zpm is a package source repo - package = _package_base_dir?(package_base_dir) - # link files Dir.glob("#{package_base_dir}/**/*") do |entry| entry = entry.sub('//', '/') @@ -201,9 +202,6 @@ link files + execute migration up File.symlink(entry.to_s, dest.to_s) end end - - # migration up - Package::Migration.migrate(package) end =begin @@ -220,6 +218,10 @@ returns package # record of newly created package +Migrations will not be executed because the the codebase was modified +in the current process and is therefore inconsistent. This must be done +subsequently in a separate step. + =end def self.install(data) @@ -285,9 +287,6 @@ returns package_db.state = 'installed' package_db.save - # up migrations - Package::Migration.migrate(meta[:name]) - # prebuild assets package_db diff --git a/lib/tasks/zammad/command.rb b/lib/tasks/zammad/command.rb new file mode 100644 index 000000000..7ea31750a --- /dev/null +++ b/lib/tasks/zammad/command.rb @@ -0,0 +1,49 @@ +module Tasks + module Zammad + + # Base class for CLI commands in Zammad. + # Rake is not intended for a real CLI style usage, that is why we need + # to apply some workarounds here. + class Command + + # Infer the rake task name from the class name. + def self.task_name + name.downcase.gsub('::', ':').sub('tasks:', '').to_sym + end + + # Override this if the task needs additional arguments. + # Currently only a fixed number of arguments is supported. + ARGUMENT_COUNT = 0 + + def self.usage + "Usage: bundle exec rails #{task_name}" + end + + def self.register_rake_task + Rake::Task.define_task task_name => :environment do + run_task + end + end + + def self.run_task + validate_comandline + task_handler + rescue => e + # A bit more user friendly than plain Rake. + Rails.logger.error e + abort "Error: #{e.message}" + end + + # Prevent the execution of multiple commands at once (mostly because of codebase + # self-modification in 'zammad:package:install'). + # Enforce the correct number of expected arguments. + def self.validate_comandline + if ARGV.first.eql?(task_name) || ARGV.count != (const_get(:ARGUMENT_COUNT) + 1) + abort "Error: wrong number of arguments given.\n#{usage}" + end + # Rake will try to run additional arguments as tasks, so make sure nothing happens for these. + ARGV[1..].each { |a| Rake::Task.define_task(a.to_sym => :environment) do; end } # rubocop:disable Style/BlockDelimiters + end + end + end +end diff --git a/lib/tasks/zammad/package/install.rake b/lib/tasks/zammad/package/install.rake new file mode 100644 index 000000000..c1041cb58 --- /dev/null +++ b/lib/tasks/zammad/package/install.rake @@ -0,0 +1,2 @@ +require_dependency 'tasks/zammad/package/install.rb' +Tasks::Zammad::Package::Install.register_rake_task diff --git a/lib/tasks/zammad/package/install.rb b/lib/tasks/zammad/package/install.rb new file mode 100644 index 000000000..b6e45bfb1 --- /dev/null +++ b/lib/tasks/zammad/package/install.rb @@ -0,0 +1,31 @@ +require_dependency 'tasks/zammad/command.rb' + +module Tasks + module Zammad + module Package + class Install < Tasks::Zammad::Command + + def self.usage + "#{super} /path/to/package.zpm" + end + + ARGUMENT_COUNT = 1 + + def self.task_handler + filename = ARGV[1] + if filename.blank? + abort "Error: Please provide a valid filename: #{usage}" + end + if !File.exist?(filename) + abort "Could not find file #{filename}." + end + puts "Installing #{filename} (without package migrations)..." + ::Package.install(file: filename) + puts 'done.' + puts "Please run package migrations now via 'zammad:package:migrate'." + end + + end + end + end +end diff --git a/lib/tasks/zammad/package/list.rake b/lib/tasks/zammad/package/list.rake new file mode 100644 index 000000000..576faad94 --- /dev/null +++ b/lib/tasks/zammad/package/list.rake @@ -0,0 +1,2 @@ +require_dependency 'tasks/zammad/package/list.rb' +Tasks::Zammad::Package::List.register_rake_task diff --git a/lib/tasks/zammad/package/list.rb b/lib/tasks/zammad/package/list.rb new file mode 100644 index 000000000..f6fa64470 --- /dev/null +++ b/lib/tasks/zammad/package/list.rb @@ -0,0 +1,17 @@ +require_dependency 'tasks/zammad/command.rb' + +module Tasks + module Zammad + module Package + class List < Tasks::Zammad::Command + + def self.task_handler + ::Package.all.each do |package| + puts package.name.ljust(20) + package.vendor.ljust(20) + package.version + end + end + + end + end + end +end diff --git a/lib/tasks/zammad/package/migrate.rake b/lib/tasks/zammad/package/migrate.rake new file mode 100644 index 000000000..abe73cdd5 --- /dev/null +++ b/lib/tasks/zammad/package/migrate.rake @@ -0,0 +1,2 @@ +require_dependency 'tasks/zammad/package/migrate.rb' +Tasks::Zammad::Package::Migrate.register_rake_task diff --git a/lib/tasks/zammad/package/migrate.rb b/lib/tasks/zammad/package/migrate.rb new file mode 100644 index 000000000..4b60c4ddf --- /dev/null +++ b/lib/tasks/zammad/package/migrate.rb @@ -0,0 +1,20 @@ +require_dependency 'tasks/zammad/command.rb' + +module Tasks + module Zammad + module Package + # Package migrations must not be executed in the same process that also executed + # Package.install or Package.link, as the codebase is in an inconsistent state. + # This is enforced by Tasks:Zammad::Command which prevents command chaining. + class Migrate < Tasks::Zammad::Command + + def self.task_handler + puts 'Executing all pending package migrations...' + ::Package.migration_execute + puts 'done.' + end + + end + end + end +end diff --git a/lib/tasks/zammad/package/uninstall.rake b/lib/tasks/zammad/package/uninstall.rake new file mode 100644 index 000000000..0dba75dd5 --- /dev/null +++ b/lib/tasks/zammad/package/uninstall.rake @@ -0,0 +1,2 @@ +require_dependency 'tasks/zammad/package/uninstall.rb' +Tasks::Zammad::Package::Uninstall.register_rake_task diff --git a/lib/tasks/zammad/package/uninstall.rb b/lib/tasks/zammad/package/uninstall.rb new file mode 100644 index 000000000..50688f13d --- /dev/null +++ b/lib/tasks/zammad/package/uninstall.rb @@ -0,0 +1,32 @@ +require_dependency 'tasks/zammad/command.rb' + +module Tasks + module Zammad + module Package + class Uninstall < Tasks::Zammad::Command + + def self.usage + "#{super} MyPackage" + end + + ARGUMENT_COUNT = 1 + + def self.task_handler + name = ARGV[1] + if name.blank? + abort "Error: please provide a package name: #{ARGV[0]} MyPackage" + end + # Find the package so that we don't need to require the version from the command line. + package = ::Package.find_by( name: name ) + if package.blank? + abort "Error: package #{name} was not found." + end + puts "Uninstalling #{package.name} #{package.version}..." + ::Package.uninstall(name: package.name, version: package.version) + puts 'done.' + end + + end + end + end +end