actual_db_schema 0.7.9 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/Gemfile.lock +3 -2
- data/README.md +78 -2
- data/Rakefile +2 -0
- data/actual_db_schema.gemspec +13 -1
- data/docker/mysql-init/create_secondary_db.sql +1 -0
- data/docker/postgres-init/create_secondary_db.sql +1 -0
- data/docker-compose.yml +23 -0
- data/gemfiles/rails.6.0.gemfile +2 -0
- data/gemfiles/rails.6.1.gemfile +2 -0
- data/gemfiles/rails.7.0.gemfile +2 -0
- data/gemfiles/rails.7.1.gemfile +2 -0
- data/gemfiles/rails.edge.gemfile +2 -0
- data/lib/actual_db_schema/commands/rollback.rb +43 -34
- data/lib/actual_db_schema/configuration.rb +32 -0
- data/lib/actual_db_schema/failed_migration.rb +1 -1
- data/lib/actual_db_schema/git_hooks.rb +194 -0
- data/lib/actual_db_schema/multi_tenant.rb +63 -0
- data/lib/actual_db_schema/output_formatter.rb +18 -0
- data/lib/actual_db_schema/patches/migration_context.rb +97 -11
- data/lib/actual_db_schema/version.rb +1 -1
- data/lib/actual_db_schema.rb +9 -5
- data/lib/generators/actual_db_schema/templates/actual_db_schema.rb +23 -0
- data/lib/tasks/actual_db_schema.rake +56 -0
- data/lib/tasks/test.rake +69 -0
- metadata +24 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9197558d7b71582d339535933b2186c9ce3db7d0c4dd492759db5a226931ddf8
|
4
|
+
data.tar.gz: ccd05c4164478a54130c6bee32a234abbb2f193292438b8d35b6d7edd313802c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b12528875d4b7d5b12739b1a37877d979bccc6d66f7a0006454ae260b1215eb69bb5baa2aae332e68bc4f1fa29859e4b00a427591cf78acf2aebc57264889a46
|
7
|
+
data.tar.gz: ae2baeaae67451740cc6773abbc79e4d0896baf96b99e7c2baebe027c1b7b05bbbbb75da5717be47c43d240835810a1681408e79c3d44449f7f44c3d4e8830a6
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## [0.8.1] - 2025-01-15
|
2
|
+
|
3
|
+
- Support for multiple database schemas, ensuring compatibility with multi-tenant applications using the apartment gem or similar solutions
|
4
|
+
- DSL for configuring the gem, simplifying setup and customization
|
5
|
+
- Rake task added to initialize the gem
|
6
|
+
- Improved the post-checkout git hook to run only when switching branches, reducing unnecessary executions during file checkouts
|
7
|
+
- Fixed the changelog link in the gemspec, ensuring Rubygems points to the correct file and the link works
|
8
|
+
|
9
|
+
## [0.8.0] - 2024-12-30
|
10
|
+
- Enhanced Console Visibility: Automatically rolled-back phantom migrations now provide clearer and more visible logs in the console
|
11
|
+
- Git Hooks for Branch Management: Introduced hooks that automatically rollback phantom migrations after checking out a branch. Additionally, the schema migration rake task can now be executed automatically upon branch checkout
|
12
|
+
- Temporary Folder Cleanup: Rolled-back phantom migrations are now automatically deleted from the temporary folder after rollback
|
13
|
+
- Acronym Support in Phantom Migration Names: Resolved an issue where phantom migrations with acronyms in their names, defined in other branches, couldn't be rolled back automatically. These are now handled seamlessly
|
14
|
+
|
1
15
|
## [0.7.9] - 2024-09-07
|
2
16
|
- Don't stop if a phantom migration rollback fails
|
3
17
|
- Improve failed rollback of phantom migrations report
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
actual_db_schema (0.
|
4
|
+
actual_db_schema (0.8.1)
|
5
5
|
activerecord
|
6
6
|
activesupport
|
7
7
|
csv
|
@@ -93,7 +93,7 @@ GEM
|
|
93
93
|
concurrent-ruby (1.2.2)
|
94
94
|
connection_pool (2.4.1)
|
95
95
|
crass (1.0.6)
|
96
|
-
csv (3.3.
|
96
|
+
csv (3.3.2)
|
97
97
|
date (3.3.3)
|
98
98
|
debug (1.8.0)
|
99
99
|
irb (>= 1.5.0)
|
@@ -222,6 +222,7 @@ GEM
|
|
222
222
|
zeitwerk (2.6.12)
|
223
223
|
|
224
224
|
PLATFORMS
|
225
|
+
arm64-darwin-22
|
225
226
|
arm64-darwin-23
|
226
227
|
x86_64-darwin-20
|
227
228
|
x86_64-darwin-22
|
data/README.md
CHANGED
@@ -50,6 +50,16 @@ And then execute:
|
|
50
50
|
|
51
51
|
If you cannot commit changes to the repo or Gemfile, consider the local Gemfile installation described in [this post](https://blog.widefix.com/personal-gemfile-for-development/).
|
52
52
|
|
53
|
+
Next, generate your ActualDbSchema initializer file by running:
|
54
|
+
|
55
|
+
```sh
|
56
|
+
rake actual_db_schema:install
|
57
|
+
```
|
58
|
+
|
59
|
+
This will create a `config/initializers/actual_db_schema.rb` file with all the available configuration options so you can adjust them as needed. It will also prompt you to install the post-checkout Git hook for automatic phantom migration rollback when switching branches.
|
60
|
+
|
61
|
+
For more details on the available configuration options, see the sections below.
|
62
|
+
|
53
63
|
## Usage
|
54
64
|
|
55
65
|
Just run `rails db:migrate` inside the current branch. It will roll back all phantom migrations for all configured databases in your `database.yml.`
|
@@ -86,7 +96,7 @@ export ACTUAL_DB_SCHEMA_UI_ENABLED=true
|
|
86
96
|
Add the following line to your initializer file (`config/initializers/actual_db_schema.rb`):
|
87
97
|
|
88
98
|
```ruby
|
89
|
-
|
99
|
+
config.ui_enabled = true
|
90
100
|
```
|
91
101
|
|
92
102
|
> With this option, the UI can be disabled for all environments or be enabled in specific ones.
|
@@ -107,7 +117,55 @@ export ACTUAL_DB_SCHEMA_AUTO_ROLLBACK_DISABLED=true
|
|
107
117
|
Add the following line to your initializer file (`config/initializers/actual_db_schema.rb`):
|
108
118
|
|
109
119
|
```ruby
|
110
|
-
|
120
|
+
config.auto_rollback_disabled = true
|
121
|
+
```
|
122
|
+
|
123
|
+
## Automatic Phantom Migration Rollback On Branch Switch
|
124
|
+
|
125
|
+
By default, the automatic rollback of migrations on branch switch is disabled. If you prefer to automatically rollback phantom migrations whenever you switch branches with `git checkout`, you can enable it in two ways:
|
126
|
+
|
127
|
+
### 1. Using Environment Variable
|
128
|
+
|
129
|
+
Set the environment variable `ACTUAL_DB_SCHEMA_GIT_HOOKS_ENABLED` to `true`:
|
130
|
+
|
131
|
+
```sh
|
132
|
+
export ACTUAL_DB_SCHEMA_GIT_HOOKS_ENABLED=true
|
133
|
+
```
|
134
|
+
|
135
|
+
### 2. Using Initializer
|
136
|
+
Add the following line to your initializer file (`config/initializers/actual_db_schema.rb`):
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
config.git_hooks_enabled = true
|
140
|
+
```
|
141
|
+
|
142
|
+
### Installing the Post-Checkout Hook
|
143
|
+
After enabling Git hooks in your configuration, run the rake task to install the post-checkout hook:
|
144
|
+
|
145
|
+
```sh
|
146
|
+
rake actual_db_schema:install_git_hooks
|
147
|
+
```
|
148
|
+
|
149
|
+
This task will prompt you to choose one of the three options:
|
150
|
+
|
151
|
+
1. Rollback phantom migrations with `db:rollback_branches`
|
152
|
+
2. Migrate up to the latest schema with `db:migrate`
|
153
|
+
3. Skip installing git hook
|
154
|
+
|
155
|
+
Based on your selection, a post-checkout hook will be installed or updated in your `.git/hooks` folder.
|
156
|
+
|
157
|
+
## Multi-Tenancy Support
|
158
|
+
|
159
|
+
If your application leverages multiple schemas for multi-tenancy — such as those implemented by the [apartment](https://github.com/influitive/apartment) gem or similar solutions — you can configure ActualDbSchema to handle migrations across all schemas. To do so, add the following configuration to your initializer file (`config/initializers/actual_db_schema.rb`):
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
config.multi_tenant_schemas = -> { # list of all active schemas }
|
163
|
+
```
|
164
|
+
|
165
|
+
### Example:
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
config.multi_tenant_schemas = -> { ["public", "tenant1", "tenant2"] }
|
111
169
|
```
|
112
170
|
|
113
171
|
## Development
|
@@ -148,6 +206,24 @@ To run tests with a specific version of Rails using Appraisal:
|
|
148
206
|
bundle exec appraisal rails.6.0 rake test TEST=test/rake_task_test.rb TESTOPTS="--name=/db::db:rollback_branches#test_0003_keeps/"
|
149
207
|
```
|
150
208
|
|
209
|
+
By default, `rake test` runs tests using `SQLite3`. To explicitly run tests with `SQLite3`, `PostgreSQL`, or `MySQL`, you can use the following tasks:
|
210
|
+
- Run tests with `SQLite3`:
|
211
|
+
```sh
|
212
|
+
bundle exec rake test:sqlite3
|
213
|
+
```
|
214
|
+
- Run tests with `PostgreSQL` (requires Docker):
|
215
|
+
```sh
|
216
|
+
bundle exec rake test:postgresql
|
217
|
+
```
|
218
|
+
- Run tests with `MySQL` (requires Docker):
|
219
|
+
```sh
|
220
|
+
bundle exec rake test:mysql2
|
221
|
+
```
|
222
|
+
- Run tests for all supported adapters:
|
223
|
+
```sh
|
224
|
+
bundle exec rake test:all
|
225
|
+
```
|
226
|
+
|
151
227
|
## Contributing
|
152
228
|
|
153
229
|
Bug reports and pull requests are welcome on GitHub at https://github.com/widefix/actual_db_schema. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/widefix/actual_db_schema/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
CHANGED
data/actual_db_schema.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
|
22
22
|
spec.metadata["homepage_uri"] = spec.homepage
|
23
23
|
spec.metadata["source_code_uri"] = "https://github.com/widefix/actual_db_schema"
|
24
|
-
spec.metadata["changelog_uri"] = "
|
24
|
+
spec.metadata["changelog_uri"] = "https://github.com/widefix/actual_db_schema/blob/main/CHANGELOG.md"
|
25
25
|
|
26
26
|
# Specify which files should be added to the gem when it is released.
|
27
27
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
@@ -44,6 +44,18 @@ Gem::Specification.new do |spec|
|
|
44
44
|
spec.add_development_dependency "rails"
|
45
45
|
spec.add_development_dependency "sqlite3"
|
46
46
|
|
47
|
+
spec.post_install_message = <<~MSG
|
48
|
+
Thank you for installing ActualDbSchema!
|
49
|
+
|
50
|
+
Next steps:
|
51
|
+
1. Run `rake actual_db_schema:install` to generate the initializer file and install
|
52
|
+
the post-checkout Git hook for automatic phantom migration rollback when switching branches.
|
53
|
+
2. Or, if you prefer environment variables, skip this step.
|
54
|
+
|
55
|
+
For more information, see the README.
|
56
|
+
|
57
|
+
MSG
|
58
|
+
|
47
59
|
# For more information and examples about making a new gem, check out our
|
48
60
|
# guide at: https://bundler.io/guides/creating_gem.html
|
49
61
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
CREATE DATABASE actual_db_schema_test_secondary;
|
@@ -0,0 +1 @@
|
|
1
|
+
CREATE DATABASE actual_db_schema_test_secondary;
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
version: '3.8'
|
2
|
+
|
3
|
+
services:
|
4
|
+
postgres:
|
5
|
+
image: postgres:14
|
6
|
+
environment:
|
7
|
+
POSTGRES_USER: postgres
|
8
|
+
POSTGRES_PASSWORD: password
|
9
|
+
POSTGRES_DB: actual_db_schema_test
|
10
|
+
ports:
|
11
|
+
- "5432:5432"
|
12
|
+
volumes:
|
13
|
+
- ./docker/postgres-init:/docker-entrypoint-initdb.d
|
14
|
+
|
15
|
+
mysql:
|
16
|
+
image: mysql:8.0
|
17
|
+
environment:
|
18
|
+
MYSQL_ROOT_PASSWORD: password
|
19
|
+
MYSQL_DATABASE: actual_db_schema_test
|
20
|
+
ports:
|
21
|
+
- "3306:3306"
|
22
|
+
volumes:
|
23
|
+
- ./docker/mysql-init:/docker-entrypoint-initdb.d
|
data/gemfiles/rails.6.0.gemfile
CHANGED
data/gemfiles/rails.6.1.gemfile
CHANGED
data/gemfiles/rails.7.0.gemfile
CHANGED
data/gemfiles/rails.7.1.gemfile
CHANGED
data/gemfiles/rails.edge.gemfile
CHANGED
@@ -4,11 +4,8 @@ module ActualDbSchema
|
|
4
4
|
module Commands
|
5
5
|
# Rolls back all phantom migrations
|
6
6
|
class Rollback < Base
|
7
|
-
|
8
|
-
|
9
|
-
green: 32,
|
10
|
-
yellow: 33
|
11
|
-
}.freeze
|
7
|
+
include ActualDbSchema::OutputFormatter
|
8
|
+
include ActionView::Helpers::TextHelper
|
12
9
|
|
13
10
|
def initialize(context, manual_mode: false)
|
14
11
|
@manual_mode = manual_mode || manual_mode_default?
|
@@ -18,50 +15,62 @@ module ActualDbSchema
|
|
18
15
|
private
|
19
16
|
|
20
17
|
def call_impl
|
21
|
-
context.rollback_branches(manual_mode: @manual_mode)
|
18
|
+
rolled_back = context.rollback_branches(manual_mode: @manual_mode)
|
22
19
|
|
23
|
-
return
|
20
|
+
return unless rolled_back || ActualDbSchema.failed.any?
|
24
21
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
ActualDbSchema.failed.empty? ? print_success : print_error
|
23
|
+
end
|
24
|
+
|
25
|
+
def print_success
|
26
|
+
puts colorize("[ActualDbSchema] All phantom migrations rolled back successfully! 🎉", :green)
|
27
|
+
end
|
28
|
+
|
29
|
+
def print_error
|
30
|
+
header_message = <<~HEADER
|
31
|
+
#{ActualDbSchema.failed.count} phantom migration(s) could not be rolled back automatically.
|
32
|
+
|
33
|
+
Try these steps to fix and move forward:
|
34
|
+
1. Ensure the migrations are reversible (define #up and #down methods or use #reversible).
|
35
|
+
2. If the migration references code or tables from another branch, restore or remove them.
|
36
|
+
3. Once fixed, run `rails db:migrate` again.
|
37
|
+
|
38
|
+
Below are the details of the problematic migrations:
|
39
|
+
HEADER
|
40
|
+
|
41
|
+
print_error_summary("#{header_message}\n#{failed_migrations_list}")
|
30
42
|
end
|
31
43
|
|
32
44
|
def failed_migrations_list
|
33
45
|
ActualDbSchema.failed.map.with_index(1) do |failed, index|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
\t\t#{exception.inspect.gsub("\n", "\n\t ")}
|
41
|
-
MSG
|
42
|
-
end
|
46
|
+
migration_details = colorize("Migration ##{index}:\n", :yellow)
|
47
|
+
migration_details += " File: #{failed.short_filename}\n"
|
48
|
+
migration_details += " Schema: #{failed.schema}\n" if failed.schema
|
49
|
+
migration_details + " Branch: #{failed.branch}\n"
|
50
|
+
end.join("\n")
|
43
51
|
end
|
44
52
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
53
|
+
def print_error_summary(content)
|
54
|
+
width = 100
|
55
|
+
indent = 4
|
56
|
+
gem_name = "ActualDbSchema"
|
57
|
+
|
58
|
+
puts colorize("╔═ [#{gem_name}] #{"═" * (width - gem_name.length - 5)}╗", :red)
|
59
|
+
print_wrapped_content(content, width, indent)
|
60
|
+
puts colorize("╚#{"═" * width}╝", :red)
|
49
61
|
end
|
50
62
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
63
|
+
def print_wrapped_content(content, width, indent)
|
64
|
+
usable_width = width - indent - 4
|
65
|
+
wrapped_content = word_wrap(content, line_width: usable_width)
|
66
|
+
wrapped_content.each_line do |line|
|
67
|
+
puts "#{" " * indent}#{line.chomp}"
|
68
|
+
end
|
55
69
|
end
|
56
70
|
|
57
71
|
def manual_mode_default?
|
58
72
|
ActualDbSchema.config[:auto_rollback_disabled]
|
59
73
|
end
|
60
|
-
|
61
|
-
def colorize(text, color)
|
62
|
-
code = UNICODE_COLORS.fetch(color, 37)
|
63
|
-
"\e[#{code}m#{text}\e[0m"
|
64
|
-
end
|
65
74
|
end
|
66
75
|
end
|
67
76
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActualDbSchema
|
4
|
+
# Manages the configuration settings for the gem.
|
5
|
+
class Configuration
|
6
|
+
attr_accessor :enabled, :auto_rollback_disabled, :ui_enabled, :git_hooks_enabled, :multi_tenant_schemas
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@enabled = Rails.env.development?
|
10
|
+
@auto_rollback_disabled = ENV["ACTUAL_DB_SCHEMA_AUTO_ROLLBACK_DISABLED"].present?
|
11
|
+
@ui_enabled = Rails.env.development? || ENV["ACTUAL_DB_SCHEMA_UI_ENABLED"].present?
|
12
|
+
@git_hooks_enabled = ENV["ACTUAL_DB_SCHEMA_GIT_HOOKS_ENABLED"].present?
|
13
|
+
@multi_tenant_schemas = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](key)
|
17
|
+
public_send(key)
|
18
|
+
end
|
19
|
+
|
20
|
+
def []=(key, value)
|
21
|
+
public_send("#{key}=", value)
|
22
|
+
end
|
23
|
+
|
24
|
+
def fetch(key, default = nil)
|
25
|
+
if respond_to?(key)
|
26
|
+
public_send(key)
|
27
|
+
else
|
28
|
+
default
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActualDbSchema
|
4
|
-
FailedMigration = Struct.new(:migration, :exception, keyword_init: true) do
|
4
|
+
FailedMigration = Struct.new(:migration, :exception, :branch, :schema, keyword_init: true) do
|
5
5
|
def filename
|
6
6
|
migration.filename
|
7
7
|
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
|
5
|
+
module ActualDbSchema
|
6
|
+
# Handles the installation of a git post-checkout hook that rolls back phantom migrations when switching branches
|
7
|
+
class GitHooks # rubocop:disable Metrics/ClassLength
|
8
|
+
include ActualDbSchema::OutputFormatter
|
9
|
+
|
10
|
+
POST_CHECKOUT_MARKER_START = "# >>> BEGIN ACTUAL_DB_SCHEMA"
|
11
|
+
POST_CHECKOUT_MARKER_END = "# <<< END ACTUAL_DB_SCHEMA"
|
12
|
+
|
13
|
+
POST_CHECKOUT_HOOK_ROLLBACK = <<~BASH
|
14
|
+
#{POST_CHECKOUT_MARKER_START}
|
15
|
+
# ActualDbSchema post-checkout hook (ROLLBACK)
|
16
|
+
# Runs db:rollback_branches on branch checkout.
|
17
|
+
|
18
|
+
# Check if this is a file checkout or creating a new branch
|
19
|
+
if [ "$3" == "0" ] || [ "$1" == "$2" ]; then
|
20
|
+
exit 0
|
21
|
+
fi
|
22
|
+
|
23
|
+
if [ -f ./bin/rails ]; then
|
24
|
+
if [ -n "$ACTUAL_DB_SCHEMA_GIT_HOOKS_ENABLED" ]; then
|
25
|
+
GIT_HOOKS_ENABLED="$ACTUAL_DB_SCHEMA_GIT_HOOKS_ENABLED"
|
26
|
+
else
|
27
|
+
GIT_HOOKS_ENABLED=$(./bin/rails runner "puts ActualDbSchema.config[:git_hooks_enabled]" 2>/dev/null)
|
28
|
+
fi
|
29
|
+
|
30
|
+
if [ "$GIT_HOOKS_ENABLED" == "true" ]; then
|
31
|
+
./bin/rails db:rollback_branches
|
32
|
+
fi
|
33
|
+
fi
|
34
|
+
#{POST_CHECKOUT_MARKER_END}
|
35
|
+
BASH
|
36
|
+
|
37
|
+
POST_CHECKOUT_HOOK_MIGRATE = <<~BASH
|
38
|
+
#{POST_CHECKOUT_MARKER_START}
|
39
|
+
# ActualDbSchema post-checkout hook (MIGRATE)
|
40
|
+
# Runs db:migrate on branch checkout.
|
41
|
+
|
42
|
+
# Check if this is a file checkout or creating a new branch
|
43
|
+
if [ "$3" == "0" ] || [ "$1" == "$2" ]; then
|
44
|
+
exit 0
|
45
|
+
fi
|
46
|
+
|
47
|
+
if [ -f ./bin/rails ]; then
|
48
|
+
if [ -n "$ACTUAL_DB_SCHEMA_GIT_HOOKS_ENABLED" ]; then
|
49
|
+
GIT_HOOKS_ENABLED="$ACTUAL_DB_SCHEMA_GIT_HOOKS_ENABLED"
|
50
|
+
else
|
51
|
+
GIT_HOOKS_ENABLED=$(./bin/rails runner "puts ActualDbSchema.config[:git_hooks_enabled]" 2>/dev/null)
|
52
|
+
fi
|
53
|
+
|
54
|
+
if [ "$GIT_HOOKS_ENABLED" == "true" ]; then
|
55
|
+
./bin/rails db:migrate
|
56
|
+
fi
|
57
|
+
fi
|
58
|
+
#{POST_CHECKOUT_MARKER_END}
|
59
|
+
BASH
|
60
|
+
|
61
|
+
def initialize(strategy: :rollback)
|
62
|
+
@strategy = strategy
|
63
|
+
end
|
64
|
+
|
65
|
+
def install_post_checkout_hook
|
66
|
+
return unless git_hooks_enabled?
|
67
|
+
return unless hooks_directory_present?
|
68
|
+
|
69
|
+
if File.exist?(hook_path)
|
70
|
+
handle_existing_hook
|
71
|
+
else
|
72
|
+
create_new_hook
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def hook_code
|
79
|
+
@strategy == :migrate ? POST_CHECKOUT_HOOK_MIGRATE : POST_CHECKOUT_HOOK_ROLLBACK
|
80
|
+
end
|
81
|
+
|
82
|
+
def hooks_dir
|
83
|
+
@hooks_dir ||= Rails.root.join(".git", "hooks")
|
84
|
+
end
|
85
|
+
|
86
|
+
def hook_path
|
87
|
+
@hook_path ||= hooks_dir.join("post-checkout")
|
88
|
+
end
|
89
|
+
|
90
|
+
def git_hooks_enabled?
|
91
|
+
return true if ActualDbSchema.config[:git_hooks_enabled]
|
92
|
+
|
93
|
+
puts colorize("[ActualDbSchema] Git hooks are disabled in configuration. Skipping installation.", :gray)
|
94
|
+
end
|
95
|
+
|
96
|
+
def hooks_directory_present?
|
97
|
+
return true if Dir.exist?(hooks_dir)
|
98
|
+
|
99
|
+
puts colorize("[ActualDbSchema] .git/hooks directory not found. Please ensure this is a Git repository.", :gray)
|
100
|
+
end
|
101
|
+
|
102
|
+
def handle_existing_hook
|
103
|
+
return update_hook if markers_exist?
|
104
|
+
return install_hook if safe_install?
|
105
|
+
|
106
|
+
show_manual_install_instructions
|
107
|
+
end
|
108
|
+
|
109
|
+
def create_new_hook
|
110
|
+
contents = <<~BASH
|
111
|
+
#!/usr/bin/env bash
|
112
|
+
|
113
|
+
#{hook_code}
|
114
|
+
BASH
|
115
|
+
|
116
|
+
write_hook_file(contents)
|
117
|
+
print_success
|
118
|
+
end
|
119
|
+
|
120
|
+
def markers_exist?
|
121
|
+
contents = File.read(hook_path)
|
122
|
+
contents.include?(POST_CHECKOUT_MARKER_START) && contents.include?(POST_CHECKOUT_MARKER_END)
|
123
|
+
end
|
124
|
+
|
125
|
+
def update_hook
|
126
|
+
contents = File.read(hook_path)
|
127
|
+
new_contents = replace_marker_contents(contents)
|
128
|
+
|
129
|
+
if new_contents == contents
|
130
|
+
message = "[ActualDbSchema] post-checkout git hook already contains the necessary code. Nothing to update."
|
131
|
+
puts colorize(message, :gray)
|
132
|
+
else
|
133
|
+
write_hook_file(new_contents)
|
134
|
+
puts colorize("[ActualDbSchema] post-checkout git hook updated successfully at #{hook_path}", :green)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def replace_marker_contents(contents)
|
139
|
+
contents.gsub(
|
140
|
+
/#{Regexp.quote(POST_CHECKOUT_MARKER_START)}.*#{Regexp.quote(POST_CHECKOUT_MARKER_END)}/m,
|
141
|
+
hook_code.strip
|
142
|
+
)
|
143
|
+
end
|
144
|
+
|
145
|
+
def safe_install?
|
146
|
+
puts colorize("[ActualDbSchema] A post-checkout hook already exists at #{hook_path}.", :gray)
|
147
|
+
puts "Overwrite the existing hook at #{hook_path}? [y,n] "
|
148
|
+
|
149
|
+
answer = $stdin.gets.chomp.downcase
|
150
|
+
answer.start_with?("y")
|
151
|
+
end
|
152
|
+
|
153
|
+
def install_hook
|
154
|
+
contents = File.read(hook_path)
|
155
|
+
new_contents = <<~BASH
|
156
|
+
#{contents.rstrip}
|
157
|
+
|
158
|
+
#{hook_code}
|
159
|
+
BASH
|
160
|
+
|
161
|
+
write_hook_file(new_contents)
|
162
|
+
print_success
|
163
|
+
end
|
164
|
+
|
165
|
+
def show_manual_install_instructions
|
166
|
+
puts colorize("[ActualDbSchema] You can follow these steps to manually install the hook:", :yellow)
|
167
|
+
puts <<~MSG
|
168
|
+
|
169
|
+
1. Open the existing post-checkout hook at:
|
170
|
+
#{hook_path}
|
171
|
+
|
172
|
+
2. Insert the following lines into that file (preferably at the end or in a relevant section).
|
173
|
+
Make sure you include the #{POST_CHECKOUT_MARKER_START} and #{POST_CHECKOUT_MARKER_END} lines:
|
174
|
+
|
175
|
+
#{hook_code}
|
176
|
+
|
177
|
+
3. Ensure the post-checkout file is executable:
|
178
|
+
chmod +x #{hook_path}
|
179
|
+
|
180
|
+
4. Done! Now when you switch branches, phantom migrations will be rolled back automatically (if enabled).
|
181
|
+
|
182
|
+
MSG
|
183
|
+
end
|
184
|
+
|
185
|
+
def write_hook_file(contents)
|
186
|
+
File.open(hook_path, "w") { |file| file.write(contents) }
|
187
|
+
FileUtils.chmod("+x", hook_path)
|
188
|
+
end
|
189
|
+
|
190
|
+
def print_success
|
191
|
+
puts colorize("[ActualDbSchema] post-checkout git hook installed successfully at #{hook_path}", :green)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActualDbSchema
|
4
|
+
# Handles multi-tenancy support by switching schemas for supported databases
|
5
|
+
module MultiTenant
|
6
|
+
include ActualDbSchema::OutputFormatter
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def with_schema(schema_name)
|
10
|
+
context = switch_schema(schema_name)
|
11
|
+
yield
|
12
|
+
ensure
|
13
|
+
restore_context(context)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def adapter_name
|
19
|
+
ActiveRecord::Base.connection.adapter_name
|
20
|
+
end
|
21
|
+
|
22
|
+
def switch_schema(schema_name)
|
23
|
+
case adapter_name
|
24
|
+
when /postgresql/i
|
25
|
+
switch_postgresql_schema(schema_name)
|
26
|
+
when /mysql/i
|
27
|
+
switch_mysql_schema(schema_name)
|
28
|
+
else
|
29
|
+
message = "[ActualDbSchema] Multi-tenancy not supported for adapter: #{adapter_name}. " \
|
30
|
+
"Proceeding without schema switching."
|
31
|
+
puts colorize(message, :gray)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def switch_postgresql_schema(schema_name)
|
36
|
+
old_search_path = ActiveRecord::Base.connection.schema_search_path
|
37
|
+
ActiveRecord::Base.connection.schema_search_path = schema_name
|
38
|
+
{ type: :postgresql, old_context: old_search_path }
|
39
|
+
end
|
40
|
+
|
41
|
+
def switch_mysql_schema(schema_name)
|
42
|
+
old_db = ActiveRecord::Base.connection.current_database
|
43
|
+
ActiveRecord::Base.connection.execute("USE #{ActiveRecord::Base.connection.quote_table_name(schema_name)}")
|
44
|
+
{ type: :mysql, old_context: old_db }
|
45
|
+
end
|
46
|
+
|
47
|
+
def restore_context(context)
|
48
|
+
return unless context
|
49
|
+
|
50
|
+
case context[:type]
|
51
|
+
when :postgresql
|
52
|
+
ActiveRecord::Base.connection.schema_search_path = context[:old_context] if context[:old_context]
|
53
|
+
when :mysql
|
54
|
+
return unless context[:old_context]
|
55
|
+
|
56
|
+
ActiveRecord::Base.connection.execute(
|
57
|
+
"USE #{ActiveRecord::Base.connection.quote_table_name(context[:old_context])}"
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActualDbSchema
|
4
|
+
# Provides functionality for formatting terminal output with colors
|
5
|
+
module OutputFormatter
|
6
|
+
UNICODE_COLORS = {
|
7
|
+
red: 31,
|
8
|
+
green: 32,
|
9
|
+
yellow: 33,
|
10
|
+
gray: 90
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
def colorize(text, color)
|
14
|
+
code = UNICODE_COLORS.fetch(color, 37)
|
15
|
+
"\e[#{code}m#{text}\e[0m"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -3,16 +3,21 @@
|
|
3
3
|
module ActualDbSchema
|
4
4
|
module Patches
|
5
5
|
# Add new command to roll back the phantom migrations
|
6
|
-
module MigrationContext
|
6
|
+
module MigrationContext # rubocop:disable Metrics/ModuleLength
|
7
|
+
include ActualDbSchema::OutputFormatter
|
8
|
+
|
7
9
|
def rollback_branches(manual_mode: false)
|
8
|
-
|
9
|
-
|
10
|
+
schemas = multi_tenant_schemas&.call || []
|
11
|
+
schema_count = schemas.any? ? schemas.size : 1
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
rolled_back_migrations = if schemas.any?
|
14
|
+
rollback_multi_tenant(schemas, manual_mode: manual_mode)
|
15
|
+
else
|
16
|
+
rollback_branches_for_schema(manual_mode: manual_mode)
|
17
|
+
end
|
18
|
+
|
19
|
+
delete_migrations(rolled_back_migrations, schema_count)
|
20
|
+
rolled_back_migrations.any?
|
16
21
|
end
|
17
22
|
|
18
23
|
def phantom_migrations
|
@@ -27,6 +32,32 @@ module ActualDbSchema
|
|
27
32
|
|
28
33
|
private
|
29
34
|
|
35
|
+
def rollback_branches_for_schema(manual_mode: false, schema_name: nil, rolled_back_migrations: [])
|
36
|
+
phantom_migrations.reverse_each do |migration|
|
37
|
+
next unless status_up?(migration)
|
38
|
+
|
39
|
+
show_info_for(migration, schema_name) if manual_mode
|
40
|
+
migrate(migration, rolled_back_migrations, schema_name) if !manual_mode || user_wants_rollback?
|
41
|
+
rescue StandardError => e
|
42
|
+
handle_rollback_error(migration, e, schema_name)
|
43
|
+
end
|
44
|
+
|
45
|
+
rolled_back_migrations
|
46
|
+
end
|
47
|
+
|
48
|
+
def rollback_multi_tenant(schemas, manual_mode: false)
|
49
|
+
all_rolled_back_migrations = []
|
50
|
+
|
51
|
+
schemas.each do |schema_name|
|
52
|
+
ActualDbSchema::MultiTenant.with_schema(schema_name) do
|
53
|
+
rollback_branches_for_schema(manual_mode: manual_mode, schema_name: schema_name,
|
54
|
+
rolled_back_migrations: all_rolled_back_migrations)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
all_rolled_back_migrations
|
59
|
+
end
|
60
|
+
|
30
61
|
def down_migrator_for(migration)
|
31
62
|
if ActiveRecord::Migration.current_version < 6
|
32
63
|
ActiveRecord::Migrator.new(:down, [migration], migration.version)
|
@@ -62,19 +93,34 @@ module ActualDbSchema
|
|
62
93
|
answer[0] == "y"
|
63
94
|
end
|
64
95
|
|
65
|
-
def show_info_for(migration)
|
66
|
-
puts "\n[ActualDbSchema] A phantom migration was found and is about to be rolled back."
|
96
|
+
def show_info_for(migration, schema_name = nil)
|
97
|
+
puts colorize("\n[ActualDbSchema] A phantom migration was found and is about to be rolled back.", :gray)
|
67
98
|
puts "Please make a decision from the options below to proceed.\n\n"
|
99
|
+
puts "Schema: #{schema_name}" if schema_name
|
68
100
|
puts "Branch: #{branch_for(migration.version.to_s)}"
|
69
101
|
puts "Database: #{ActualDbSchema.db_config[:database]}"
|
70
102
|
puts "Version: #{migration.version}\n\n"
|
71
103
|
puts File.read(migration.filename)
|
72
104
|
end
|
73
105
|
|
74
|
-
def migrate(migration)
|
106
|
+
def migrate(migration, rolled_back_migrations, schema_name = nil)
|
107
|
+
migration.name = extract_class_name(migration.filename)
|
108
|
+
|
109
|
+
message = "[ActualDbSchema]"
|
110
|
+
message += " #{schema_name}:" if schema_name
|
111
|
+
message += " Rolling back phantom migration #{migration.version} #{migration.name} " \
|
112
|
+
"(from branch: #{branch_for(migration.version.to_s)})"
|
113
|
+
puts colorize(message, :gray)
|
114
|
+
|
75
115
|
migrator = down_migrator_for(migration)
|
76
116
|
migrator.extend(ActualDbSchema::Patches::Migrator)
|
77
117
|
migrator.migrate
|
118
|
+
rolled_back_migrations << migration
|
119
|
+
end
|
120
|
+
|
121
|
+
def extract_class_name(filename)
|
122
|
+
content = File.read(filename)
|
123
|
+
content.match(/^class\s+([A-Za-z0-9_]+)\s+</)[1]
|
78
124
|
end
|
79
125
|
|
80
126
|
def branch_for(version)
|
@@ -84,6 +130,46 @@ module ActualDbSchema
|
|
84
130
|
def metadata
|
85
131
|
@metadata ||= ActualDbSchema::Store.instance.read
|
86
132
|
end
|
133
|
+
|
134
|
+
def handle_rollback_error(migration, exception, schema_name = nil)
|
135
|
+
error_message = <<~ERROR
|
136
|
+
Error encountered during rollback:
|
137
|
+
|
138
|
+
#{cleaned_exception_message(exception.message)}
|
139
|
+
ERROR
|
140
|
+
|
141
|
+
puts colorize(error_message, :red)
|
142
|
+
ActualDbSchema.failed << FailedMigration.new(
|
143
|
+
migration: migration,
|
144
|
+
exception: exception,
|
145
|
+
branch: branch_for(migration.version.to_s),
|
146
|
+
schema: schema_name
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
150
|
+
def cleaned_exception_message(message)
|
151
|
+
patterns_to_remove = [
|
152
|
+
/^An error has occurred, all later migrations canceled:\s*/,
|
153
|
+
/^An error has occurred, this and all later migrations canceled:\s*/
|
154
|
+
]
|
155
|
+
|
156
|
+
patterns_to_remove.reduce(message.strip) { |msg, pattern| msg.gsub(pattern, "").strip }
|
157
|
+
end
|
158
|
+
|
159
|
+
def delete_migrations(migrations, schema_count)
|
160
|
+
migration_counts = migrations.each_with_object(Hash.new(0)) do |migration, hash|
|
161
|
+
hash[migration.filename] += 1
|
162
|
+
end
|
163
|
+
|
164
|
+
migrations.uniq.each do |migration|
|
165
|
+
count = migration_counts[migration.filename]
|
166
|
+
File.delete(migration.filename) if count == schema_count && File.exist?(migration.filename)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def multi_tenant_schemas
|
171
|
+
ActualDbSchema.config[:multi_tenant_schemas]
|
172
|
+
end
|
87
173
|
end
|
88
174
|
end
|
89
175
|
end
|
data/lib/actual_db_schema.rb
CHANGED
@@ -4,14 +4,18 @@ require "actual_db_schema/engine"
|
|
4
4
|
require "active_record/migration"
|
5
5
|
require "csv"
|
6
6
|
require_relative "actual_db_schema/git"
|
7
|
+
require_relative "actual_db_schema/configuration"
|
7
8
|
require_relative "actual_db_schema/store"
|
8
9
|
require_relative "actual_db_schema/version"
|
9
10
|
require_relative "actual_db_schema/migration"
|
10
11
|
require_relative "actual_db_schema/failed_migration"
|
11
12
|
require_relative "actual_db_schema/migration_context"
|
13
|
+
require_relative "actual_db_schema/output_formatter"
|
12
14
|
require_relative "actual_db_schema/patches/migration_proxy"
|
13
15
|
require_relative "actual_db_schema/patches/migrator"
|
14
16
|
require_relative "actual_db_schema/patches/migration_context"
|
17
|
+
require_relative "actual_db_schema/git_hooks"
|
18
|
+
require_relative "actual_db_schema/multi_tenant"
|
15
19
|
|
16
20
|
require_relative "actual_db_schema/commands/base"
|
17
21
|
require_relative "actual_db_schema/commands/rollback"
|
@@ -26,11 +30,11 @@ module ActualDbSchema
|
|
26
30
|
end
|
27
31
|
|
28
32
|
self.failed = []
|
29
|
-
self.config =
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
33
|
+
self.config = Configuration.new
|
34
|
+
|
35
|
+
def self.configure
|
36
|
+
yield(config)
|
37
|
+
end
|
34
38
|
|
35
39
|
def self.migrated_folder
|
36
40
|
migrated_folders.first
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# ActualDbSchema initializer
|
4
|
+
# Adjust the configuration as needed.
|
5
|
+
|
6
|
+
ActualDbSchema.configure do |config|
|
7
|
+
# Enable the gem.
|
8
|
+
config.enabled = Rails.env.development?
|
9
|
+
|
10
|
+
# Disable automatic rollback of phantom migrations.
|
11
|
+
# config.auto_rollback_disabled = true
|
12
|
+
config.auto_rollback_disabled = ENV["ACTUAL_DB_SCHEMA_AUTO_ROLLBACK_DISABLED"].present?
|
13
|
+
|
14
|
+
# Enable the UI for managing migrations.
|
15
|
+
config.ui_enabled = Rails.env.development? || ENV["ACTUAL_DB_SCHEMA_UI_ENABLED"].present?
|
16
|
+
|
17
|
+
# Enable automatic phantom migration rollback on branch switch,
|
18
|
+
# config.git_hooks_enabled = true
|
19
|
+
config.git_hooks_enabled = ENV["ACTUAL_DB_SCHEMA_GIT_HOOKS_ENABLED"].present?
|
20
|
+
|
21
|
+
# If your application leverages multiple schemas for multi-tenancy, define the active schemas.
|
22
|
+
# config.multi_tenant_schemas = -> { ["public", "tenant1", "tenant2"] }
|
23
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :actual_db_schema do # rubocop:disable Metrics/BlockLength
|
4
|
+
desc "Install ActualDbSchema initializer and post-checkout git hook."
|
5
|
+
task :install do
|
6
|
+
extend ActualDbSchema::OutputFormatter
|
7
|
+
|
8
|
+
initializer_path = Rails.root.join("config", "initializers", "actual_db_schema.rb")
|
9
|
+
initializer_content = File.read(
|
10
|
+
File.expand_path("../../lib/generators/actual_db_schema/templates/actual_db_schema.rb", __dir__)
|
11
|
+
)
|
12
|
+
|
13
|
+
if File.exist?(initializer_path)
|
14
|
+
puts colorize("[ActualDbSchema] An initializer already exists at #{initializer_path}.", :gray)
|
15
|
+
puts "Overwrite the existing file at #{initializer_path}? [y,n] "
|
16
|
+
answer = $stdin.gets.chomp.downcase
|
17
|
+
|
18
|
+
if answer.start_with?("y")
|
19
|
+
File.write(initializer_path, initializer_content)
|
20
|
+
puts colorize("[ActualDbSchema] Initializer updated successfully at #{initializer_path}", :green)
|
21
|
+
else
|
22
|
+
puts colorize("[ActualDbSchema] Skipped overwriting the initializer.", :yellow)
|
23
|
+
end
|
24
|
+
else
|
25
|
+
File.write(initializer_path, initializer_content)
|
26
|
+
puts colorize("[ActualDbSchema] Initializer created successfully at #{initializer_path}", :green)
|
27
|
+
end
|
28
|
+
|
29
|
+
Rake::Task["actual_db_schema:install_git_hooks"].invoke
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Install ActualDbSchema post-checkout git hook that rolls back phantom migrations when switching branches."
|
33
|
+
task :install_git_hooks do
|
34
|
+
extend ActualDbSchema::OutputFormatter
|
35
|
+
|
36
|
+
puts "Which Git hook strategy would you like to install? [1, 2, 3]"
|
37
|
+
puts " 1) Rollback phantom migrations (db:rollback_branches)"
|
38
|
+
puts " 2) Migrate up to latest (db:migrate)"
|
39
|
+
puts " 3) No hook installation (skip)"
|
40
|
+
answer = $stdin.gets.chomp
|
41
|
+
|
42
|
+
strategy =
|
43
|
+
case answer
|
44
|
+
when "1" then :rollback
|
45
|
+
when "2" then :migrate
|
46
|
+
else
|
47
|
+
:none
|
48
|
+
end
|
49
|
+
|
50
|
+
if strategy == :none
|
51
|
+
puts colorize("[ActualDbSchema] Skipping git hook installation.", :gray)
|
52
|
+
else
|
53
|
+
ActualDbSchema::GitHooks.new(strategy: strategy).install_post_checkout_hook
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/tasks/test.rake
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :test do # rubocop:disable Metrics/BlockLength
|
4
|
+
desc "Run tests with SQLite3"
|
5
|
+
task :sqlite3 do
|
6
|
+
ENV["DB_ADAPTER"] = "sqlite3"
|
7
|
+
Rake::Task["test"].invoke
|
8
|
+
Rake::Task["test"].reenable
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Run tests with PostgreSQL"
|
12
|
+
task :postgresql do
|
13
|
+
sh "docker-compose up -d postgres"
|
14
|
+
wait_for_postgres
|
15
|
+
|
16
|
+
begin
|
17
|
+
ENV["DB_ADAPTER"] = "postgresql"
|
18
|
+
Rake::Task["test"].invoke
|
19
|
+
Rake::Task["test"].reenable
|
20
|
+
ensure
|
21
|
+
sh "docker-compose down"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Run tests with MySQL"
|
26
|
+
task :mysql2 do
|
27
|
+
sh "docker-compose up -d mysql"
|
28
|
+
wait_for_mysql
|
29
|
+
|
30
|
+
begin
|
31
|
+
ENV["DB_ADAPTER"] = "mysql2"
|
32
|
+
Rake::Task["test"].invoke
|
33
|
+
Rake::Task["test"].reenable
|
34
|
+
ensure
|
35
|
+
sh "docker-compose down"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Run tests with all adapters (SQLite3, PostgreSQL, MySQL)"
|
40
|
+
task all: %i[sqlite3 postgresql mysql2]
|
41
|
+
|
42
|
+
def wait_for_postgres
|
43
|
+
retries = 10
|
44
|
+
begin
|
45
|
+
sh "docker-compose exec -T postgres pg_isready -U postgres"
|
46
|
+
rescue StandardError
|
47
|
+
retries -= 1
|
48
|
+
|
49
|
+
raise "PostgreSQL is not ready after several attempts." if retries < 1
|
50
|
+
|
51
|
+
sleep 2
|
52
|
+
retry
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def wait_for_mysql
|
57
|
+
retries = 10
|
58
|
+
begin
|
59
|
+
sh "docker-compose exec -T mysql mysqladmin ping -h 127.0.0.1 --silent"
|
60
|
+
rescue StandardError
|
61
|
+
retries -= 1
|
62
|
+
|
63
|
+
raise "MySQL is not ready after several attempts." if retries < 1
|
64
|
+
|
65
|
+
sleep 2
|
66
|
+
retry
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actual_db_schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrei Kaleshka
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -136,6 +136,9 @@ files:
|
|
136
136
|
- app/views/actual_db_schema/shared/_js.html
|
137
137
|
- app/views/actual_db_schema/shared/_style.html
|
138
138
|
- config/routes.rb
|
139
|
+
- docker-compose.yml
|
140
|
+
- docker/mysql-init/create_secondary_db.sql
|
141
|
+
- docker/postgres-init/create_secondary_db.sql
|
139
142
|
- gemfiles/rails.6.0.gemfile
|
140
143
|
- gemfiles/rails.6.1.gemfile
|
141
144
|
- gemfiles/rails.7.0.gemfile
|
@@ -145,17 +148,24 @@ files:
|
|
145
148
|
- lib/actual_db_schema/commands/base.rb
|
146
149
|
- lib/actual_db_schema/commands/list.rb
|
147
150
|
- lib/actual_db_schema/commands/rollback.rb
|
151
|
+
- lib/actual_db_schema/configuration.rb
|
148
152
|
- lib/actual_db_schema/engine.rb
|
149
153
|
- lib/actual_db_schema/failed_migration.rb
|
150
154
|
- lib/actual_db_schema/git.rb
|
155
|
+
- lib/actual_db_schema/git_hooks.rb
|
151
156
|
- lib/actual_db_schema/migration.rb
|
152
157
|
- lib/actual_db_schema/migration_context.rb
|
158
|
+
- lib/actual_db_schema/multi_tenant.rb
|
159
|
+
- lib/actual_db_schema/output_formatter.rb
|
153
160
|
- lib/actual_db_schema/patches/migration_context.rb
|
154
161
|
- lib/actual_db_schema/patches/migration_proxy.rb
|
155
162
|
- lib/actual_db_schema/patches/migrator.rb
|
156
163
|
- lib/actual_db_schema/store.rb
|
157
164
|
- lib/actual_db_schema/version.rb
|
165
|
+
- lib/generators/actual_db_schema/templates/actual_db_schema.rb
|
166
|
+
- lib/tasks/actual_db_schema.rake
|
158
167
|
- lib/tasks/db.rake
|
168
|
+
- lib/tasks/test.rake
|
159
169
|
- sig/actual_db_schema.rbs
|
160
170
|
homepage: https://blog.widefix.com/actual-db-schema/
|
161
171
|
licenses:
|
@@ -163,8 +173,17 @@ licenses:
|
|
163
173
|
metadata:
|
164
174
|
homepage_uri: https://blog.widefix.com/actual-db-schema/
|
165
175
|
source_code_uri: https://github.com/widefix/actual_db_schema
|
166
|
-
changelog_uri: https://
|
167
|
-
post_install_message:
|
176
|
+
changelog_uri: https://github.com/widefix/actual_db_schema/blob/main/CHANGELOG.md
|
177
|
+
post_install_message: |+
|
178
|
+
Thank you for installing ActualDbSchema!
|
179
|
+
|
180
|
+
Next steps:
|
181
|
+
1. Run `rake actual_db_schema:install` to generate the initializer file and install
|
182
|
+
the post-checkout Git hook for automatic phantom migration rollback when switching branches.
|
183
|
+
2. Or, if you prefer environment variables, skip this step.
|
184
|
+
|
185
|
+
For more information, see the README.
|
186
|
+
|
168
187
|
rdoc_options: []
|
169
188
|
require_paths:
|
170
189
|
- lib
|
@@ -184,3 +203,4 @@ signing_key:
|
|
184
203
|
specification_version: 4
|
185
204
|
summary: Keep your DB and schema.rb consistent in dev branches.
|
186
205
|
test_files: []
|
206
|
+
...
|