Skip to content

Commit

Permalink
Fix decidim db migrate rake task (#50)
Browse files Browse the repository at this point in the history
* refactor: Remove deprecated files

* fix(rake): Decidim db migrate

* chore(db): Update schema.rb

* lint(rubocop): Fix offenses

* test: Remove deprecated test

* test: Remove deprecated test
  • Loading branch information
Quentinchampenois authored Jul 22, 2024
1 parent d420571 commit aea711b
Show file tree
Hide file tree
Showing 13 changed files with 486 additions and 378 deletions.
5 changes: 0 additions & 5 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
require "action_cable/engine"
# require "action_mailbox/engine"
# require "action_text/engine"
require_relative "../lib/active_storage/downloadable"

# TODO : add missing dep to decidim-initiatives/lib/decidim/initiatives/engine.rb
# require "wicked_pdf"
Expand Down Expand Up @@ -41,10 +40,6 @@ class Application < Rails::Application
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.

config.to_prepare do
ActiveStorage::Blob.include ActiveStorage::Downloadable
end

config.after_initialize do
Decidim::GraphiQL::Rails.config.tap do |config|
config.initial_query = "{\n deployment {\n version\n branch\n remote\n upToDate\n currentCommit\n latestCommit\n locallyModified\n }\n}".html_safe
Expand Down
200 changes: 165 additions & 35 deletions db/schema.rb

Large diffs are not rendered by default.

9 changes: 0 additions & 9 deletions lib/active_storage/downloadable.rb

This file was deleted.

46 changes: 0 additions & 46 deletions lib/active_storage/migrator.rb

This file was deleted.

76 changes: 76 additions & 0 deletions lib/migrations_fixer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# frozen_string_literal: true

# MigrationsFixer allows to ensure rake task has needed information to success.
class MigrationsFixer
attr_accessor :migrations_path, :logger

def initialize(logger)
@logger = logger
@migrations_path = Rails.root.join(migrations_folder)
validate!
@osp_app_path = osp_app_path
end

# Validate configuration before executing task
def validate!
raise "Undefined logger" if @logger.blank?

validate_migration_path
validate_osp_app_path
end

# Build osp-app path and returns osp-app path ending with '/*'
def osp_app_path
osp_app_path ||= File.expand_path(ENV.fetch("MIGRATIONS_PATH", "db/migrate"))
if osp_app_path.end_with?("/")
osp_app_path
else
"#{osp_app_path}/"
end
end

private

# Ensure osp_app path exists
def validate_osp_app_path
unless File.directory?(osp_app_path)
@logger.fatal("Directory '#{osp_app_path}' not found, aborting task...")
validation_failed
end
end

# Ensure migrations path exists
def validate_migration_path
unless File.directory? @migrations_path
@logger.error("Directory '#{@migrations_path}' not found, aborting task...")
@logger.error("Please see absolute path '#{File.expand_path(@migrations_path)}'")

@logger.fatal("Please ensure the migration path is correctly defined.")
validation_failed
end
end

# Returns path to DB migrations (default: "db/migrate")
def migrations_folder
ActiveRecord::Base.connection.migration_context.migrations_paths.first
end

# Display helper
def helper
"Manual : decidim:db:migrate
Fix migrations issue when switching from osp-app to decidim-app. Rake task will automatically save already passed migrations from current project that are marked as 'down'.
Then it will try to migrate each 'down' version, if it fails, it automatically note as 'up'
Parameters:
* MIGRATIONS_PATH - String [Relative or absolute path] : Pass to previous decidim project
Example: bundle exec rake decidim:db:migrate MIGRATIONS_PATH='../osp-app/db/migrate'
or
bundle exec rake decidim:db:migrate MIGRATIONS_PATH='/Users/toto/osp-app/db/migrate'
"
end

def validation_failed
raise "Invalid configuration, aborting"
end
end
83 changes: 83 additions & 0 deletions lib/rails_migrations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# frozen_string_literal: true

# RailsMigrations deals with migrations of the project
class RailsMigrations
attr_accessor :fetch_all

def initialize(migration_fixer)
@fetch_all = migration_status
@migration_fixer = migration_fixer
end

# Reload down migrations according to the new migration status
def reload_down!
@down = nil
reload_migrations!
down
end

# Return all migrations marked as 'down'
def down
@down ||= @fetch_all&.map do |migration_ary|
migration_ary if migration_ary&.first == "down"
end&.compact
end

# Refresh all migrations according to DB
def reload_migrations!
@fetch_all = migration_status
end

# Print migrations status
def display_status!
@fetch_all&.each do |status, version, name|
@migration_fixer.logger.info("#{status.center(8)} #{version.ljust(14)} #{name}")
end
end

# Returns all migration present in DB but with no migration files defined
def not_found
@not_found ||= @fetch_all&.map { |_, version, name| version if name.include?("NO FILE") }&.compact
end

# returns all versions marked as 'down' but already passed in past
# This methods is based on migration filenames from osp-app folder, then compare with current migration folder and retrieve duplicated migration with another version number
# Returns array of 'down' versions
def versions_down_but_already_passed
needed_migrations = already_accepted_migrations&.map do |migration|
Dir.glob("#{@migration_fixer.migrations_path}/*#{migration_name_for(migration)}")
end&.flatten!

needed_migrations&.map { |filename| migration_version_for(filename) }
end

private

# returns the migration name based on migration version
# Example for migration : 11111_add_item_in_class
# @return : add_item_in_class
def migration_name_for(migration)
migration.split("/")[-1].split("_")[1..-1].join("_")
end

# Returns the migration version based on migration filename
# Example for migration : 11111_add_item_in_class
# @return : 11111
def migration_version_for(migration)
migration.split("/")[-1].split("_")[0]
end

# returns migrations filename from old osp-app folder, based on versions present in database with no file related
def already_accepted_migrations
@already_accepted_migrations ||= not_found&.map do |migration|
osp_app = Dir.glob("#{@migration_fixer.osp_app_path}*")&.select { |path| path if path.include?(migration) }

osp_app.first if osp_app.present?
end&.compact
end

# Fetch all migrations statuses
def migration_status
ActiveRecord::Base.connection.migration_context.migrations_status
end
end
4 changes: 4 additions & 0 deletions lib/tasks/decidim_app.rake
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ namespace :decidim_app do
task upgrade: :environment do
puts "Running db:migrate"
Rake::Task["db:migrate"].invoke
rescue StandardError => e
puts "Ignoring error: #{e.message}"
puts "Running decidim:db:migrate"
Rake::Task["decidim:db:migrate"].invoke
end

desc "usage: bundle exec rails k8s:dump_db"
Expand Down
Loading

0 comments on commit aea711b

Please sign in to comment.