diff --git a/Gemfile.lock b/Gemfile.lock index 900e1a2e..8697be97 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - dsu (2.4.4) + dsu (3.0.0.alpha.4) activemodel (>= 7.0.8, < 8.0) activesupport (>= 7.0.8, < 8.0) colorize (>= 1.1, < 2.0) diff --git a/Rakefile b/Rakefile index cca71754..dc93e767 100644 --- a/Rakefile +++ b/Rakefile @@ -10,3 +10,9 @@ require "rubocop/rake_task" RuboCop::RakeTask.new task default: %i[spec rubocop] + +desc 'Generate a migration timestamp' +task :timestamp do + puts 'The below migration timestamp should be placed in the "lib/dsu/migration/version.rb" file.' + puts Time.now.strftime('%Y%m%d%H%M%S') +end diff --git a/current_project.bak b/current_project.bak deleted file mode 100644 index b33cfdd7..00000000 --- a/current_project.bak +++ /dev/null @@ -1,4 +0,0 @@ -{ - "version": 20230613121411, - "project_name": "default" -} diff --git a/lib/dsu.rb b/lib/dsu.rb index a6844d1d..8eb84bcd 100644 --- a/lib/dsu.rb +++ b/lib/dsu.rb @@ -33,14 +33,6 @@ exit 1 end end - # TODO: Hack. Integrate this into the migration service - # so that this runs only if the migration version changes. - %w[light.json christmas.json].each do |theme_file| - destination_theme_file_path = File.join(Dsu::Support::Fileable.themes_folder, theme_file) - next if File.exist?(destination_theme_file_path) - - source_theme_file_path = File.join(Dsu::Support::Fileable.seed_data_folder, 'themes', theme_file) - FileUtils.cp(source_theme_file_path, destination_theme_file_path) - puts I18n.t('migrations.information.theme_copied', from: source_theme_file_path, to: destination_theme_file_path) - end + + Dsu::Migration::Factory.migrate_if! end diff --git a/lib/dsu/migration/factory.rb b/lib/dsu/migration/factory.rb new file mode 100644 index 00000000..ffc5b639 --- /dev/null +++ b/lib/dsu/migration/factory.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require_relative '../models/migration_version' +require_relative 'service_20230613121411' +require_relative 'version' + +module Dsu + module Migration + class Factory + class << self + def migrate_if!(options: {}) + version = options.fetch(:version, migration_version) + if version == 20230613121411 # rubocop:disable Style/NumericLiterals + Service20230613121411.new(options: options).migrate! + end + end + + private + + def migration_version + @migration_version ||= Models::MigrationVersion.new.version + end + end + end + end +end diff --git a/lib/dsu/migration/service.rb b/lib/dsu/migration/service.rb index d9ddbe28..7aeefb60 100644 --- a/lib/dsu/migration/service.rb +++ b/lib/dsu/migration/service.rb @@ -31,7 +31,7 @@ def call class << self def run_migrations? - Models::MigrationVersion.new.version < Dsu::Migration::VERSION + Models::MigrationVersion.new.version < 20230613121411 # rubocop:disable Style/NumericLiterals end end diff --git a/lib/dsu/migration/service_20230613121411.rb b/lib/dsu/migration/service_20230613121411.rb new file mode 100644 index 00000000..f3345d77 --- /dev/null +++ b/lib/dsu/migration/service_20230613121411.rb @@ -0,0 +1,171 @@ +# frozen_string_literal: true + +require_relative '../support/fileable' +require_relative 'version' + +# TODO: Read raw configuration .json file +# If default_project is not set... +# - Add default_project to configuration .json file and write it out. +# - Reload the configuration file. +# - Create a Models::Project object for the default project and initialize/save it. +# - Move the old entries folder into the default project folder. +# TODO: Add default_project to configuration .json file +module Dsu + module Migration + class Service20230613121411 + include Support::Fileable + + def initialize(options: {}) + @options = options || {} + end + + def migrate! + puts 'Running migrations...' + puts + + puts "options[:pretend] is true\n" if pretend? + + raise_wrong_migration_version_error_if! + + puts "Migrating from: #{target_migration_version} to version: #{Migration::VERSION}" + puts + + add_new_color_themes + backup + create_default_project + update_configuration + update_entry_groups + update_color_themes + delete_old_entry_folder + delete_old_theme_folder + + puts 'Migration completed successfully.' + end + + private + + attr_reader :options + + def pretend? + options.fetch(:pretend, true) + end + + def add_new_color_themes + puts 'Copying new color themes...' + puts + + %w[light.json christmas.json].each do |theme_file| + destination_theme_file_path = File.join(Dsu::Support::Fileable.themes_folder, theme_file) + next if File.exist?(destination_theme_file_path) + + source_theme_file_path = File.join(Dsu::Support::Fileable.seed_data_folder, 'themes', theme_file) + FileUtils.cp(source_theme_file_path, destination_theme_file_path) unless pretend? + puts I18n.t('migrations.information.theme_copied', from: source_theme_file_path, to: destination_theme_file_path) + end + end + + def backup + return if Dir.exist?(backup_folder) + + puts 'Creating backup...' + puts + + FileUtils.cp_r(dsu_folder, backup_folder) unless pretend? + end + + def create_default_project + default_project = Models::Configuration::DEFAULT_CONFIGURATION[:default_project] + return if Models::Project.project_initialized?(project_name: default_project) + + puts "Creating default project \"#{default_project}\"..." + puts + + Models::Project.create(project_name: default_project, options: options) unless pretend? + end + + def update_configuration + puts 'Updating configuration...' + puts + + Models::Configuration.new.write! unless pretend? + end + + def update_entry_groups + puts 'Updating entry groups...' + puts + + return if Dir.exist?(entries_folder) || pretend? + + puts 'Copying entries to default project...' + puts + + FileUtils.mkdir_p(entries_folder) + FileUtils.cp_r(File.join(backup_folder, 'entries', '.'), entries_folder) + + puts 'Updating entry group version...' + puts + + Models::EntryGroup.all.each do |entry_group| + puts "Updating entry group version: #{entry_group.time_yyyy_mm_dd}..." + entry_group.version = Dsu::Migration::VERSION + entry_group.save! unless pretend? + end + end + + def update_color_themes + puts 'Updating color themes...' + puts + + return if Dir.exist?(themes_folder) || pretend? + + puts 'Copying color themes...' + puts + + FileUtils.mkdir_p(themes_folder) + FileUtils.cp_r(File.join(backup_folder, 'themes', '.'), themes_folder) + + puts 'Updating color theme version...' + puts + + Models::ColorTheme.all.each do |color_theme| + puts "Updating color theme version: #{color_theme.theme_name}..." + color_theme.version = Dsu::Migration::VERSION + color_theme.save! unless pretend? + end + end + + def delete_old_entry_folder + puts 'Cleaning up old entries...' + puts + + FileUtils.rm_rf(File.join(dsu_folder, 'entries')) unless pretend? + end + + def delete_old_theme_folder + puts 'Cleaning up old themes...' + puts + + FileUtils.rm_rf(File.join(dsu_folder, 'themes')) unless pretend? + end + + def backup_folder + @backup_folder ||= File.join(dsu_folder, target_migration_version.to_s) + end + + def target_migration_version + 20230613121411 # rubocop:disable Style/NumericLiterals + end + + def raise_wrong_migration_version_error_if! + return if migration_version == target_migration_version + + raise "Actual migration version #{migration_version} " \ + "is not the expected migration version #{target_migration_version}." + end + + def migration_version + @migration_version ||= Models::MigrationVersion.new.version + end + end + end +end diff --git a/lib/dsu/migration/version.rb b/lib/dsu/migration/version.rb index 4bc6a3fd..c3415d63 100644 --- a/lib/dsu/migration/version.rb +++ b/lib/dsu/migration/version.rb @@ -2,6 +2,6 @@ module Dsu module Migration - VERSION = 20230613121411 # rubocop:disable Style/NumericLiterals + VERSION = 20240210161248 # rubocop:disable Style/NumericLiterals end end diff --git a/lib/dsu/models/migration_version.rb b/lib/dsu/models/migration_version.rb index 6fcc9451..0164e2e8 100644 --- a/lib/dsu/models/migration_version.rb +++ b/lib/dsu/models/migration_version.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require 'active_model' require_relative '../crud/json_file' require_relative '../services/migration_version/hydrator_service' require_relative '../validators/version_validator' diff --git a/lib/dsu/version.rb b/lib/dsu/version.rb index a9922d1b..391337f7 100644 --- a/lib/dsu/version.rb +++ b/lib/dsu/version.rb @@ -2,5 +2,5 @@ module Dsu VERSION_REGEX = /\A\d+\.\d+\.\d+(\.(alpha|rc)\.\d+)?\z/ - VERSION = '2.4.4' + VERSION = '3.0.0.alpha.5' end diff --git a/spec/dsu/migration/service_spec.rb b/spec/dsu/migration/service_spec.rb index 98f5ac56..708999dd 100644 --- a/spec/dsu/migration/service_spec.rb +++ b/spec/dsu/migration/service_spec.rb @@ -47,9 +47,9 @@ end end - context 'when the migration version less than the current version' do + context 'when the migration version less than 20230613121411' do before do - create(:migration_version, version: Dsu::Migration::VERSION - 1) + create(:migration_version, version: 20230613121411 - 1) # rubocop:disable Style/NumericLiterals end it 'returns true' do diff --git a/spec/dsu/models/color_theme_spec.rb b/spec/dsu/models/color_theme_spec.rb index 0547994d..025c2fc1 100644 --- a/spec/dsu/models/color_theme_spec.rb +++ b/spec/dsu/models/color_theme_spec.rb @@ -75,7 +75,7 @@ describe 'constants' do it 'defines VERSION' do - expect(described_class::VERSION).to eq 20230613121411 # rubocop:disable Style/NumericLiterals + expect(described_class::VERSION).to eq 20240210161248 # rubocop:disable Style/NumericLiterals end it_behaves_like 'the version is a valid version' diff --git a/spec/fixtures/files/current_project.json b/spec/fixtures/files/current_project.json index b33cfdd7..a8ca6e5c 100644 --- a/spec/fixtures/files/current_project.json +++ b/spec/fixtures/files/current_project.json @@ -1,4 +1,4 @@ { - "version": 20230613121411, + "version": 20240210161248, "project_name": "default" } diff --git a/spec/fixtures/files/entries/2023-06-15.json b/spec/fixtures/files/entries/2023-06-15.json index a1c07a67..56dfa5e7 100644 --- a/spec/fixtures/files/entries/2023-06-15.json +++ b/spec/fixtures/files/entries/2023-06-15.json @@ -1,6 +1,6 @@ { "time": "2023-06-15 20:34:09 -0400", - "version": 20230613121411, + "version": 20240210161248, "entries": [ { "description": "20230615 description 0" diff --git a/spec/fixtures/files/entries/2023-06-16.json b/spec/fixtures/files/entries/2023-06-16.json index c3cf4bbb..a49318eb 100644 --- a/spec/fixtures/files/entries/2023-06-16.json +++ b/spec/fixtures/files/entries/2023-06-16.json @@ -1,6 +1,6 @@ { "time": "2023-06-16 20:33:40 -0400", - "version": 20230613121411, + "version": 20240210161248, "entries": [ { "description": "20230616 description 0" diff --git a/spec/fixtures/files/entries/2023-06-17.json b/spec/fixtures/files/entries/2023-06-17.json index 042f23b1..e1174c19 100644 --- a/spec/fixtures/files/entries/2023-06-17.json +++ b/spec/fixtures/files/entries/2023-06-17.json @@ -1,6 +1,6 @@ { "time": "2023-06-17 20:34:26 -0400", - "version": 20230613121411, + "version": 20240210161248, "entries": [ { "description": "20230617 description 0" diff --git a/spec/fixtures/files/import-with-duplicate-errors.csv b/spec/fixtures/files/import-with-duplicate-errors.csv index 69f57c9b..af64dbdf 100644 --- a/spec/fixtures/files/import-with-duplicate-errors.csv +++ b/spec/fixtures/files/import-with-duplicate-errors.csv @@ -1,5 +1,5 @@ project_name,version,entry_group,entry_no,total_entries,entry_group_entry -default,20230613121411,2023-12-31,1,2,Entry 2023-12-31 duplicate -default,20230613121411,2023-12-31,2,2,Entry 2023-12-31 duplicate -default,20230613121411,2024-01-01,1,1,Entry 2024-01-01 1 of 2 -default,20230613121411,2024-01-02,1,1,Entry 2024-01-02 2 of 2 +default,20240210161248,2023-12-31,1,2,Entry 2023-12-31 duplicate +default,20240210161248,2023-12-31,2,2,Entry 2023-12-31 duplicate +default,20240210161248,2024-01-01,1,1,Entry 2024-01-01 1 of 2 +default,20240210161248,2024-01-02,1,1,Entry 2024-01-02 2 of 2 diff --git a/spec/fixtures/files/import-with-errors.csv b/spec/fixtures/files/import-with-errors.csv index 84cf9270..f40bda56 100644 --- a/spec/fixtures/files/import-with-errors.csv +++ b/spec/fixtures/files/import-with-errors.csv @@ -1,5 +1,5 @@ project_name,version,entry_group,entry_no,total_entries,entry_group_entry -default,20230613121411,2023-12-31,1,2, -default,20230613121411,2023-12-31,2,2, -default,20230613121411,2024-01-01,1,1, -default,20230613121411,2024-01-02,1,1, +default,20240210161248,2023-12-31,1,2, +default,20240210161248,2023-12-31,2,2, +default,20240210161248,2024-01-01,1,1, +default,20240210161248,2024-01-02,1,1, diff --git a/spec/fixtures/files/import.csv b/spec/fixtures/files/import.csv index a5a89d0c..0ad85cb6 100644 --- a/spec/fixtures/files/import.csv +++ b/spec/fixtures/files/import.csv @@ -1,5 +1,5 @@ project_name,version,entry_group,entry_no,total_entries,entry_group_entry -default,20230613121411,2023-12-31,1,2,Entry 2023-12-31 1 of 2 -default,20230613121411,2023-12-31,2,2,Entry 2023-12-31 2 of 2 -default,20230613121411,2024-01-01,1,1,Entry 2024-01-01 1 of 1 -default,20230613121411,2024-01-02,1,1,Entry 2024-01-02 1 of 1 +default,20240210161248,2023-12-31,1,2,Entry 2023-12-31 1 of 2 +default,20240210161248,2023-12-31,2,2,Entry 2023-12-31 2 of 2 +default,20240210161248,2024-01-01,1,1,Entry 2024-01-01 1 of 1 +default,20240210161248,2024-01-02,1,1,Entry 2024-01-02 1 of 1 diff --git a/spec/fixtures/files/nothing-to-import.csv b/spec/fixtures/files/nothing-to-import.csv index 617ec05d..d537f7f5 100644 --- a/spec/fixtures/files/nothing-to-import.csv +++ b/spec/fixtures/files/nothing-to-import.csv @@ -1,5 +1,5 @@ project_name,version,entry_group,entry_no,total_entries,entry_group_entry -bad-project,20230613121411,2023-12-31,1,2,Entry 2023-12-31 1 of 2 -bad-project,20230613121411,2023-12-31,2,2,Entry 2023-12-31 2 of 2 -bad-project,20230613121411,2024-01-01,1,1,Entry 2024-01-01 1 of 1 -bad-project,20230613121411,2024-01-02,1,1,Entry 2024-01-02 1 of 1 +bad-project,20240210161248,2023-12-31,1,2,Entry 2023-12-31 1 of 2 +bad-project,20240210161248,2023-12-31,2,2,Entry 2023-12-31 2 of 2 +bad-project,20240210161248,2024-01-01,1,1,Entry 2024-01-01 1 of 1 +bad-project,20240210161248,2024-01-02,1,1,Entry 2024-01-02 1 of 1 diff --git a/spec/fixtures/files/project.json b/spec/fixtures/files/project.json index e10263cd..c3bbf09b 100644 --- a/spec/fixtures/files/project.json +++ b/spec/fixtures/files/project.json @@ -1,5 +1,5 @@ { - "version": 20230613121411, + "version": 20240210161248, "project_name": "default", "description": "Default project" }