Skip to content

Commit

Permalink
Insert schema_migrations rows at end of structure dump (#175)
Browse files Browse the repository at this point in the history
This will make it possible to cleanly run migrations after loading the structure.

Accomplishing this requires more involved database interactions (multiple additional queries to the database after `pg_dump` completes), so switch to testing using a real database. Include a basic `docker-compose.yml` as the beginning of providing a standard environment for local testing too.
  • Loading branch information
timriley authored Jun 16, 2024
1 parent 5906a90 commit f3b7f22
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 109 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ jobs:
- "3.2"
- "3.1"
- "3.0"
env:
POSTGRES_BASE_URL: postgres://postgres:password@localhost:5432/hanami_cli_test
steps:
- uses: actions/checkout@v1
- name: Install package dependencies
Expand All @@ -39,3 +41,18 @@ jobs:
bundler-cache: true
- name: Run all tests
run: bundle exec rake spec
services:
postgres:
# Use postgres:14 for CLI compatibility with ubuntu-latest, currently ubuntu-22.04
# See https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md
image: postgres:14
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ gem "dry-system", github: "dry-rb/dry-system", branch: "main"

gem "rack"

gem "pg"
gem "sqlite3"

gem "hanami-devtools", github: "hanami/devtools", branch: "main"
Expand Down
9 changes: 9 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: "2"
services:
postgres:
image: postgres:latest
ports:
- 5433:5432
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
25 changes: 20 additions & 5 deletions lib/hanami/cli/commands/app/db/structure/dump.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,34 @@ class Dump < DB::Command

# @api private
def call(app: false, slice: nil, **)
exit_codes = []

databases(app: app, slice: slice).each do |database|
slice_root = database.slice.root.relative_path_from(database.slice.app.root)
structure_path = slice_root.join("config", "db", "structure.sql")
structure_path = database.slice.root.join("config", "db", "structure.sql")
relative_structure_path = structure_path.relative_path_from(database.slice.app.root)

measure("#{database.name} structure dumped to #{relative_structure_path}") do
catch :dump_failed do
result = database.exec_dump_command
exit_codes << result.exit_code if result.respond_to?(:exit_code)

measure("#{database.name} structure dumped to #{structure_path}") do
database.exec_dump_command.tap do |result|
unless result.successful?
out.puts result.err
break false
throw :dump_failed, false
end

File.open(structure_path, "a") do |f|
f.puts "#{database.schema_migrations_sql_dump}\n"
end

true
end
end
end

exit_codes.each do |code|
break exit code if code > 0
end
end
end
end
Expand Down
7 changes: 7 additions & 0 deletions lib/hanami/cli/commands/app/db/utils/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ def migrations_path
def migrations_dir?
migrations_path.directory?
end

def schema_migrations_sql_dump
sql = +"INSERT INTO schema_migrations (filename) VALUES\n"
sql << applied_migrations.map { |v| "('#{v}')" }.join(",\n")
sql << ";"
sql
end
end
end
end
Expand Down
10 changes: 9 additions & 1 deletion lib/hanami/cli/commands/app/db/utils/postgres.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def escaped_name

def cli_env_vars
@cli_env_vars ||= {}.tap do |vars|
vars["PGHOST"] = database_uri.hostname.to_s
vars["PGHOST"] = database_uri.host.to_s if database_uri.host
vars["PGPORT"] = database_uri.port.to_s if database_uri.port
vars["PGUSER"] = database_uri.user.to_s if database_uri.user
vars["PGPASSWORD"] = database_uri.password.to_s if database_uri.password
Expand All @@ -59,6 +59,14 @@ def cli_env_vars
def structure_file
slice.root.join("config/db/structure.sql")
end

def schema_migrations_sql_dump
search_path = slice["db.gateway"].connection
.fetch("SHOW search_path").to_a.first
.fetch(:search_path)

+"SET search_path TO #{search_path};\n\n" << super
end
end
end
end
Expand Down
28 changes: 28 additions & 0 deletions spec/support/postgres.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

require "open3"
require "uri"

# Default to a URL that should work with postgres as installed by asdf/mise.
POSTGRES_BASE_URL = ENV.fetch("POSTGRES_BASE_URL", "postgres://postgres@localhost:5432/hanami_cli_test")
POSTGRES_BASE_URI = URI(POSTGRES_BASE_URL)

RSpec.configure do |config|
# Drop all databases with names starting with POSTGRES_URL_BASE
config.after :each, :postgres do
cmd_env = {
"PGHOST" => POSTGRES_BASE_URI.host,
"PGPORT" => POSTGRES_BASE_URI.port.to_s,
"PGUSER" => POSTGRES_BASE_URI.user,
"PGPASSWORD" => POSTGRES_BASE_URI.password
}

db_prefix = POSTGRES_BASE_URI.path.sub(%r{^/}, "")
psql_list, status = Open3.capture2(cmd_env, "psql -t -A -c '\\l #{db_prefix}*'")

test_databases = psql_list.split("\n").map { _1.split("|").first }
test_databases.each do |database|
system(cmd_env, "dropdb --force #{database}")
end
end
end
Loading

0 comments on commit f3b7f22

Please sign in to comment.