actual_db_schema 0.7.9 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
...
|