Skip to content
Snippets Groups Projects

Fix incorrect renaming migrations

Merged Bob Van Landuyt :neckbeard: requested to merge bvl-fix-already-renamed-paths into master
All threads resolved!
3 files
+ 170
1
Compare changes
  • Side-by-side
  • Inline
Files
3
 
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
 
# for more information on how to write migrations for GitLab.
 
 
class FixWronglyRenamedRoutes < ActiveRecord::Migration
 
include Gitlab::Database::RenameReservedPathsMigration::V1
 
 
DOWNTIME = false
 
 
disable_ddl_transaction!
 
 
DISALLOWED_ROOT_PATHS = %w[
 
-
 
abuse_reports
 
api
 
autocomplete
 
explore
 
health_check
 
import
 
invites
 
jwt
 
koding
 
member
 
notification_settings
 
oauth
 
sent_notifications
 
unicorn_test
 
uploads
 
users
 
]
 
 
FIXED_PATHS = DISALLOWED_ROOT_PATHS.map { |p| "#{p}0" }
 
 
class Route < Gitlab::Database::RenameReservedPathsMigration::V1::MigrationClasses::Route
 
self.table_name = 'routes'
 
end
 
 
def routes
 
@routes ||= Route.arel_table
 
end
 
 
def namespaces
 
@namespaces ||= Arel::Table.new(:namespaces)
 
end
 
 
def wildcard_collection(collection)
 
collection.map { |word| "#{word}%" }
 
end
 
 
# The routes that got incorrectly renamed before, still have a namespace that
 
# contains the correct path.
 
# This query fetches all rows from the `routes` table that meet the following
 
# conditions using `api` as an example:
 
# - route.path ILIKE `api0%`
 
# - route.source_type = `Namespace`
 
# - namespace.parent_id IS NULL
 
# - namespace.path ILIKE `api%`
 
# - NOT(namespace.path ILIKE `api0%`)
 
# This gives us all root-routes, that were renamed, but their namespace was not.
 
#
 
def wrongly_renamed
 
Route.joins("INNER JOIN namespaces ON routes.source_id = namespaces.id")
 
.where(
 
routes[:source_type].eq('Namespace')
 
.and(namespaces[:parent_id].eq(nil))
 
)
 
.where(namespaces[:path].matches_any(wildcard_collection(DISALLOWED_ROOT_PATHS)))
 
.where.not(namespaces[:path].matches_any(wildcard_collection(FIXED_PATHS)))
 
.where(routes[:path].matches_any(wildcard_collection(FIXED_PATHS)))
 
end
 
 
# Using the query above, we just fetch the `route.path` & the `namespace.path`
 
# `route.path` is the part of the route that is now incorrect
 
# `namespace.path` is what it should be
 
# We can use `route.path` to find all the namespaces that need to be fixed
 
# And we can use `namespace.path` to apply the correct name.
 
#
 
def paths_and_corrections
 
connection.select_all(
 
wrongly_renamed.select(routes[:path], namespaces[:path].as('namespace_path')).to_sql
 
)
 
end
 
 
# This can be used to limit the `update_in_batches` call to all routes for a
 
# single namespace, note the `/` that's what went wrong in the initial migration.
 
#
 
def routes_in_namespace_query(namespace)
 
routes[:path].matches_any([namespace, "#{namespace}/%"])
 
end
 
 
def up
 
paths_and_corrections.each do |root_namespace|
 
wrong_path = root_namespace['path']
 
correct_path = root_namespace['namespace_path']
 
replace_statement = replace_sql(Route.arel_table[:path], wrong_path, correct_path)
 
 
update_column_in_batches(:routes, :path, replace_statement) do |table, query|
 
query.where(routes_in_namespace_query(wrong_path))
 
end
 
end
 
end
 
 
def down
 
end
 
end
Loading