Skip to content

Instantly share code, notes, and snippets.

@prem-prakash
Last active January 16, 2018 02:06
Show Gist options
  • Save prem-prakash/8582a1c53d69149adf33bb0953be3669 to your computer and use it in GitHub Desktop.
Save prem-prakash/8582a1c53d69149adf33bb0953be3669 to your computer and use it in GitHub Desktop.
Pre commit webhook to check if Ecto structure.sql is updated
PreCommit:
StructureUpToDate:
enabled: true
description: 'Checking for schema changes'
include: 'priv/repo/**/*'
# borrowed from
# https://github.com/brigade/overcommit/blob/master/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb
#
# rubocop:disable
module Overcommit::Hook::PreCommit
# Check to see whether the structure file is in line with the migrations. When a
# structure file is present but a migration file is not, this is usually a
# failure. The exception is if the structure is at version 0 (i.e before any
# migrations have been run). In this case it is OK if there are no migrations.
class StructureUpToDate < Base
def run
if migration_files.any? && structure_files.none?
return :fail, "It looks like you're adding a migration, but did not update "\
"the structure file. Please run 'mix do ecto.migrate, ecto.dump' and stage changes"
elsif migration_files.none? && structure_files.any?
return :fail, "You're trying to change the structure without adding a migration file"
elsif migration_files.any? && structure_files.any?
# Get the latest version from the migration filename. Use
# `File.basename` to prevent finding numbers that could appear in
# directories, such as the home directory of a user with a number in
# their username.
latest_version = migration_files.map do |file|
File.basename(file)[/\d+/]
end.sort.last
up_to_date = structure.include?(latest_version)
unless up_to_date
return :fail, "The latest migration version you're committing is " \
"#{latest_version}, but your structure file " \
"#{structure_files.join(' or ')} is on a different version." \
"Please run 'mix do ecto.migrate, ecto.dump' and stage changes"
end
end
:pass
end
private
def migration_files
@migration_files ||= applicable_files.select do |file|
file.match %r{priv/repo/migrations/.*\.exs}
end
end
def structure_files
@structure_files ||= applicable_files.select do |file|
file.match %r{priv/repo/structure.*\.sql}
end
end
def structure
@structure ||= structure_files.map { |file| File.read(file) }.join
end
def non_zero_structure_version?
structure =~ /\d{14}/
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment