planetscale_rails 0.1.4 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +13 -1
- data/Gemfile.lock +77 -75
- data/README.md +14 -24
- data/actions-example.md +1 -1
- data/lib/planetscale_rails/tasks/psdb.rake +153 -112
- data/lib/planetscale_rails/version.rb +1 -1
- data/planetscale_rails.gemspec +1 -1
- metadata +12 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1c96f1384c6bcee4a33e81124384b80ce8cff99823b1d5fc77ad926967087a4
|
4
|
+
data.tar.gz: '0880e54628a3c0b22a98f1883dce8fd6ac4aee57315fffab014d07c9da66e014'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4fabd32053c4456bdd002729f21fd9548905a7fc8472a97dd23fb0f1aed9df5798381cae839fd4495b0acacdc97170c47b92312cc38c78a0a31df3911097765
|
7
|
+
data.tar.gz: 2f50ab3be8305f60c81c11d625f470775678bf311d103c1301d982fb1aa5f6c39ac8b176f21bd8eb4ea511098f22e8a77a3b09cdb459130ea60bdddcee37ae57
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
AllCops:
|
2
2
|
TargetRubyVersion: 3
|
3
3
|
|
4
|
+
Metrics/CyclomaticComplexity:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
Metrics/PerceivedComplexity:
|
8
|
+
Enabled: false
|
9
|
+
|
4
10
|
Style/StringLiterals:
|
5
11
|
Enabled: true
|
6
12
|
EnforcedStyle: double_quotes
|
@@ -10,7 +16,13 @@ Style/StringLiteralsInInterpolation:
|
|
10
16
|
EnforcedStyle: double_quotes
|
11
17
|
|
12
18
|
Layout/LineLength:
|
13
|
-
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
Metrics/MethodLength:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
Metrics/AbcSize:
|
25
|
+
Enabled: false
|
14
26
|
|
15
27
|
Metrics/BlockLength:
|
16
28
|
Enabled: false
|
data/Gemfile.lock
CHANGED
@@ -1,74 +1,74 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
planetscale_rails (0.
|
4
|
+
planetscale_rails (0.2.0)
|
5
5
|
colorize (~> 0.8.1)
|
6
|
-
rails (
|
6
|
+
rails (>= 6.0, < 8)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
actioncable (7.0.
|
12
|
-
actionpack (= 7.0.
|
13
|
-
activesupport (= 7.0.
|
11
|
+
actioncable (7.0.6)
|
12
|
+
actionpack (= 7.0.6)
|
13
|
+
activesupport (= 7.0.6)
|
14
14
|
nio4r (~> 2.0)
|
15
15
|
websocket-driver (>= 0.6.1)
|
16
|
-
actionmailbox (7.0.
|
17
|
-
actionpack (= 7.0.
|
18
|
-
activejob (= 7.0.
|
19
|
-
activerecord (= 7.0.
|
20
|
-
activestorage (= 7.0.
|
21
|
-
activesupport (= 7.0.
|
16
|
+
actionmailbox (7.0.6)
|
17
|
+
actionpack (= 7.0.6)
|
18
|
+
activejob (= 7.0.6)
|
19
|
+
activerecord (= 7.0.6)
|
20
|
+
activestorage (= 7.0.6)
|
21
|
+
activesupport (= 7.0.6)
|
22
22
|
mail (>= 2.7.1)
|
23
23
|
net-imap
|
24
24
|
net-pop
|
25
25
|
net-smtp
|
26
|
-
actionmailer (7.0.
|
27
|
-
actionpack (= 7.0.
|
28
|
-
actionview (= 7.0.
|
29
|
-
activejob (= 7.0.
|
30
|
-
activesupport (= 7.0.
|
26
|
+
actionmailer (7.0.6)
|
27
|
+
actionpack (= 7.0.6)
|
28
|
+
actionview (= 7.0.6)
|
29
|
+
activejob (= 7.0.6)
|
30
|
+
activesupport (= 7.0.6)
|
31
31
|
mail (~> 2.5, >= 2.5.4)
|
32
32
|
net-imap
|
33
33
|
net-pop
|
34
34
|
net-smtp
|
35
35
|
rails-dom-testing (~> 2.0)
|
36
|
-
actionpack (7.0.
|
37
|
-
actionview (= 7.0.
|
38
|
-
activesupport (= 7.0.
|
39
|
-
rack (~> 2.0, >= 2.2.
|
36
|
+
actionpack (7.0.6)
|
37
|
+
actionview (= 7.0.6)
|
38
|
+
activesupport (= 7.0.6)
|
39
|
+
rack (~> 2.0, >= 2.2.4)
|
40
40
|
rack-test (>= 0.6.3)
|
41
41
|
rails-dom-testing (~> 2.0)
|
42
42
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
43
|
-
actiontext (7.0.
|
44
|
-
actionpack (= 7.0.
|
45
|
-
activerecord (= 7.0.
|
46
|
-
activestorage (= 7.0.
|
47
|
-
activesupport (= 7.0.
|
43
|
+
actiontext (7.0.6)
|
44
|
+
actionpack (= 7.0.6)
|
45
|
+
activerecord (= 7.0.6)
|
46
|
+
activestorage (= 7.0.6)
|
47
|
+
activesupport (= 7.0.6)
|
48
48
|
globalid (>= 0.6.0)
|
49
49
|
nokogiri (>= 1.8.5)
|
50
|
-
actionview (7.0.
|
51
|
-
activesupport (= 7.0.
|
50
|
+
actionview (7.0.6)
|
51
|
+
activesupport (= 7.0.6)
|
52
52
|
builder (~> 3.1)
|
53
53
|
erubi (~> 1.4)
|
54
54
|
rails-dom-testing (~> 2.0)
|
55
55
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
56
|
-
activejob (7.0.
|
57
|
-
activesupport (= 7.0.
|
56
|
+
activejob (7.0.6)
|
57
|
+
activesupport (= 7.0.6)
|
58
58
|
globalid (>= 0.3.6)
|
59
|
-
activemodel (7.0.
|
60
|
-
activesupport (= 7.0.
|
61
|
-
activerecord (7.0.
|
62
|
-
activemodel (= 7.0.
|
63
|
-
activesupport (= 7.0.
|
64
|
-
activestorage (7.0.
|
65
|
-
actionpack (= 7.0.
|
66
|
-
activejob (= 7.0.
|
67
|
-
activerecord (= 7.0.
|
68
|
-
activesupport (= 7.0.
|
59
|
+
activemodel (7.0.6)
|
60
|
+
activesupport (= 7.0.6)
|
61
|
+
activerecord (7.0.6)
|
62
|
+
activemodel (= 7.0.6)
|
63
|
+
activesupport (= 7.0.6)
|
64
|
+
activestorage (7.0.6)
|
65
|
+
actionpack (= 7.0.6)
|
66
|
+
activejob (= 7.0.6)
|
67
|
+
activerecord (= 7.0.6)
|
68
|
+
activesupport (= 7.0.6)
|
69
69
|
marcel (~> 1.0)
|
70
70
|
mini_mime (>= 1.1.0)
|
71
|
-
activesupport (7.0.
|
71
|
+
activesupport (7.0.6)
|
72
72
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
73
73
|
i18n (>= 1.6, < 2)
|
74
74
|
minitest (>= 5.1)
|
@@ -83,12 +83,12 @@ GEM
|
|
83
83
|
erubi (1.12.0)
|
84
84
|
globalid (1.1.0)
|
85
85
|
activesupport (>= 5.0)
|
86
|
-
i18n (1.
|
86
|
+
i18n (1.14.1)
|
87
87
|
concurrent-ruby (~> 1.0)
|
88
88
|
json (2.6.3)
|
89
|
-
loofah (2.
|
89
|
+
loofah (2.21.3)
|
90
90
|
crass (~> 1.0.2)
|
91
|
-
nokogiri (>= 1.
|
91
|
+
nokogiri (>= 1.12.0)
|
92
92
|
mail (2.8.1)
|
93
93
|
mini_mime (>= 0.1.1)
|
94
94
|
net-imap
|
@@ -97,8 +97,8 @@ GEM
|
|
97
97
|
marcel (1.0.2)
|
98
98
|
method_source (1.0.0)
|
99
99
|
mini_mime (1.1.2)
|
100
|
-
minitest (5.
|
101
|
-
net-imap (0.3.
|
100
|
+
minitest (5.19.0)
|
101
|
+
net-imap (0.3.7)
|
102
102
|
date
|
103
103
|
net-protocol
|
104
104
|
net-pop (0.1.2)
|
@@ -107,40 +107,42 @@ GEM
|
|
107
107
|
timeout
|
108
108
|
net-smtp (0.3.3)
|
109
109
|
net-protocol
|
110
|
-
nio4r (2.5.
|
111
|
-
nokogiri (1.
|
110
|
+
nio4r (2.5.9)
|
111
|
+
nokogiri (1.15.4-x86_64-darwin)
|
112
112
|
racc (~> 1.4)
|
113
|
-
nokogiri (1.
|
113
|
+
nokogiri (1.15.4-x86_64-linux)
|
114
114
|
racc (~> 1.4)
|
115
115
|
parallel (1.22.1)
|
116
116
|
parser (3.2.1.0)
|
117
117
|
ast (~> 2.4.1)
|
118
|
-
racc (1.
|
119
|
-
rack (2.2.
|
120
|
-
rack-test (2.0
|
118
|
+
racc (1.7.3)
|
119
|
+
rack (2.2.7)
|
120
|
+
rack-test (2.1.0)
|
121
121
|
rack (>= 1.3)
|
122
|
-
rails (7.0.
|
123
|
-
actioncable (= 7.0.
|
124
|
-
actionmailbox (= 7.0.
|
125
|
-
actionmailer (= 7.0.
|
126
|
-
actionpack (= 7.0.
|
127
|
-
actiontext (= 7.0.
|
128
|
-
actionview (= 7.0.
|
129
|
-
activejob (= 7.0.
|
130
|
-
activemodel (= 7.0.
|
131
|
-
activerecord (= 7.0.
|
132
|
-
activestorage (= 7.0.
|
133
|
-
activesupport (= 7.0.
|
122
|
+
rails (7.0.6)
|
123
|
+
actioncable (= 7.0.6)
|
124
|
+
actionmailbox (= 7.0.6)
|
125
|
+
actionmailer (= 7.0.6)
|
126
|
+
actionpack (= 7.0.6)
|
127
|
+
actiontext (= 7.0.6)
|
128
|
+
actionview (= 7.0.6)
|
129
|
+
activejob (= 7.0.6)
|
130
|
+
activemodel (= 7.0.6)
|
131
|
+
activerecord (= 7.0.6)
|
132
|
+
activestorage (= 7.0.6)
|
133
|
+
activesupport (= 7.0.6)
|
134
134
|
bundler (>= 1.15.0)
|
135
|
-
railties (= 7.0.
|
136
|
-
rails-dom-testing (2.
|
137
|
-
activesupport (>=
|
135
|
+
railties (= 7.0.6)
|
136
|
+
rails-dom-testing (2.1.1)
|
137
|
+
activesupport (>= 5.0.0)
|
138
|
+
minitest
|
138
139
|
nokogiri (>= 1.6)
|
139
|
-
rails-html-sanitizer (1.
|
140
|
-
loofah (~> 2.
|
141
|
-
|
142
|
-
|
143
|
-
|
140
|
+
rails-html-sanitizer (1.6.0)
|
141
|
+
loofah (~> 2.21)
|
142
|
+
nokogiri (~> 1.14)
|
143
|
+
railties (7.0.6)
|
144
|
+
actionpack (= 7.0.6)
|
145
|
+
activesupport (= 7.0.6)
|
144
146
|
method_source
|
145
147
|
rake (>= 12.2)
|
146
148
|
thor (~> 1.0)
|
@@ -175,15 +177,15 @@ GEM
|
|
175
177
|
rubocop-ast (1.27.0)
|
176
178
|
parser (>= 3.2.1.0)
|
177
179
|
ruby-progressbar (1.12.0)
|
178
|
-
thor (1.2.
|
179
|
-
timeout (0.
|
180
|
+
thor (1.2.2)
|
181
|
+
timeout (0.4.0)
|
180
182
|
tzinfo (2.0.6)
|
181
183
|
concurrent-ruby (~> 1.0)
|
182
184
|
unicode-display_width (2.4.2)
|
183
|
-
websocket-driver (0.7.
|
185
|
+
websocket-driver (0.7.6)
|
184
186
|
websocket-extensions (>= 0.1.0)
|
185
187
|
websocket-extensions (0.1.5)
|
186
|
-
zeitwerk (2.6.
|
188
|
+
zeitwerk (2.6.9)
|
187
189
|
|
188
190
|
PLATFORMS
|
189
191
|
x86_64-darwin-20
|
data/README.md
CHANGED
@@ -15,7 +15,6 @@ against it. See [usage](#usage) for details.
|
|
15
15
|
rake psdb:migrate # Migrate the database for current environment
|
16
16
|
rake psdb:rollback # Rollback primary database for current environment
|
17
17
|
rake psdb:schema:load # Load the current schema into the database
|
18
|
-
rake psdb:setup_pscale # Setup a proxy to connect to PlanetScale
|
19
18
|
```
|
20
19
|
|
21
20
|
## Installation
|
@@ -34,36 +33,19 @@ And then execute in your terminal:
|
|
34
33
|
bundle install
|
35
34
|
```
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
In your application's `database.yml`, you'll need to make two changes. This will allow the app to run migrations via a connection setup by the pscale CLI.
|
40
|
-
|
41
|
-
1. Swap to port 3305 if `ENV['ENABLE_PSDB']` is true.
|
42
|
-
2. Use production database name if `ENV['ENABLE_PSDB']` is true.
|
43
|
-
|
44
|
-
Here is an example
|
45
|
-
|
46
|
-
```
|
47
|
-
development:
|
48
|
-
<<: *default
|
49
|
-
database: <%= ENV['ENABLE_PSDB'] ? 'your_production_db_name' : 'your_development_db_name' %>
|
50
|
-
port: <%= ENV['ENABLE_PSDB'] ? 3305 : ENV.fetch("DB_PORT", 3306) %>
|
51
|
-
```
|
36
|
+
Make sure you have the [`pscale` CLI installed](https://github.com/planetscale/cli#installation).
|
52
37
|
|
53
38
|
## Usage
|
54
39
|
|
55
|
-
|
56
|
-
|
57
|
-
1. Run this locally, it will create a new branch off of `main`. The `switch` command will update a `.pscale.yml` file to track
|
58
|
-
that this is the branch you want to migrate.
|
40
|
+
1. Using pscale, create a new branch. This command will create a local `.pscale.yml` file. You should add it to your `.gitignore`.
|
59
41
|
|
60
42
|
```
|
61
|
-
pscale branch switch my-new-branch-name --database my-db-name --create
|
43
|
+
pscale branch switch my-new-branch-name --database my-db-name --create --wait
|
62
44
|
```
|
63
45
|
|
64
46
|
**Tip:** In your database settings. Enable "Automatically copy migration data." Select "Rails" as the migration framework. This will auto copy your `schema_migrations` table between branches.
|
65
47
|
|
66
|
-
2.
|
48
|
+
2. Run your schema migrations against the branch.
|
67
49
|
|
68
50
|
```
|
69
51
|
bundle exec rails psdb:migrate
|
@@ -75,8 +57,6 @@ If you run multiple databases in your Rails app, you can specify the DB name.
|
|
75
57
|
bundle exec rails psdb:migrate:primary
|
76
58
|
```
|
77
59
|
|
78
|
-
This will connect to the branch that you created, and run migrations against the branch.
|
79
|
-
|
80
60
|
If you make a mistake, you can use `bundle exec rails psdb:rollback` to rollback the changes on your PlanetScale branch.
|
81
61
|
|
82
62
|
3. Next, you can either open the Deploy Request via the UI. Or the CLI.
|
@@ -88,6 +68,16 @@ pscale deploy-request create database-name my-new-branch-name
|
|
88
68
|
|
89
69
|
4. To get your schema change to production, run the deploy request. Then, once it's complete, you can merge your code changes into your `main` branch in git and deploy your application code.
|
90
70
|
|
71
|
+
## Using PlanetScale deploy requests vs `psdb:migrate` directly in production.
|
72
|
+
|
73
|
+
PlanetScale's deploy requests [solve the schema change problem](https://planetscale.com/docs/learn/how-online-schema-change-tools-work). They make a normally high risk operation, safe. This is done by running your schema change using [Vitess's online schema change](https://vitess.io/docs/18.0/user-guides/schema-changes/) tools. Once the change is made, a deploy request is [also revertible without data loss](https://planetscale.com/blog/revert-a-migration-without-losing-data). None of this is possible when running `rails db:migrate` directly against your production database.
|
74
|
+
|
75
|
+
We recommend using GitHub Actions to automate the creation of PlanetScale branches and deploy requests. Then when you are ready to merge, you can run the deploy request before merging in your code.
|
76
|
+
|
77
|
+
**When not to use deploy requests**
|
78
|
+
|
79
|
+
If your application has minimal data and schema changes are a low risk event, then running `psdb:migrate` directly against production is perfectly fine. As your datasize grows and your application becomes busier, the risk of schema changes increase and we highly recommend using the deploy request flow. It's the best way available to safely migrate your schema.
|
80
|
+
|
91
81
|
## Usage with GitHub Actions
|
92
82
|
|
93
83
|
See the [GitHub Actions examples](actions-example.md) doc for ways to automate your schema migrations with PlanetScale + Actions.
|
data/actions-example.md
CHANGED
@@ -18,7 +18,7 @@ Secrets needed to be set:
|
|
18
18
|
- `PLANETSCALE_SERVICE_TOKEN_ID`
|
19
19
|
- `PLANETSCALE_SERVICE_TOKEN`
|
20
20
|
|
21
|
-
The PlanetScale service token must have
|
21
|
+
The PlanetScale service token must have the `connect_branch`, `create_branch`, `delete_branch_password`, `read_branch`, `create_deploy_request`, and `read_deploy_request` permissions on the database.
|
22
22
|
|
23
23
|
```yaml
|
24
24
|
name: Run database migrations
|
@@ -7,18 +7,13 @@ require "colorize"
|
|
7
7
|
|
8
8
|
databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
|
9
9
|
|
10
|
-
def shared_deps(name = nil)
|
11
|
-
return [:environment, :check_ci, "setup_pscale:#{name}".to_sym] if name
|
12
|
-
return %i[environment check_ci] if name.nil?
|
13
|
-
end
|
14
|
-
|
15
10
|
def puts_deploy_request_instructions
|
16
11
|
ps_config = YAML.load_file(".pscale.yml")
|
17
12
|
database = ps_config["database"]
|
18
13
|
branch = ps_config["branch"]
|
19
14
|
org = ps_config["org"]
|
20
15
|
|
21
|
-
puts "Create a deploy request for '#{branch}' by running:\n"
|
16
|
+
puts "Create a deploy request for '#{branch.colorize(:blue)}' by running:\n"
|
22
17
|
puts " pscale deploy-request create #{database} #{branch} --org #{org}\n\n"
|
23
18
|
end
|
24
19
|
|
@@ -26,6 +21,28 @@ def kill_pscale_process
|
|
26
21
|
Process.kill("TERM", ENV["PSCALE_PID"].to_i) if ENV["PSCALE_PID"]
|
27
22
|
end
|
28
23
|
|
24
|
+
def delete_password
|
25
|
+
password_id = ENV["PSCALE_PASSWORD_ID"]
|
26
|
+
return unless password_id
|
27
|
+
|
28
|
+
ps_config = YAML.load_file(".pscale.yml")
|
29
|
+
database = ps_config["database"]
|
30
|
+
branch = ps_config["branch"]
|
31
|
+
|
32
|
+
command = "pscale password delete #{database} #{branch} #{password_id} #{ENV["SERVICE_TOKEN_CONFIG"]} --force"
|
33
|
+
output = `#{command}`
|
34
|
+
|
35
|
+
return if $CHILD_STATUS.success?
|
36
|
+
|
37
|
+
puts "Failed to cleanup credentials used for PlanetScale connection. Password ID: #{password_id}".colorize(:red)
|
38
|
+
puts "Command: #{command}"
|
39
|
+
puts "Output: #{output}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def db_branch_colorized(database, branch)
|
43
|
+
"#{database.colorize(:blue)}/#{branch.colorize(:blue)}"
|
44
|
+
end
|
45
|
+
|
29
46
|
namespace :psdb do
|
30
47
|
task check_ci: :environment do
|
31
48
|
use_service_token = ENV["PSCALE_SERVICE_TOKEN"] && ENV["PSCALE_SERVICE_TOKEN_ID"]
|
@@ -38,91 +55,63 @@ namespace :psdb do
|
|
38
55
|
end
|
39
56
|
end
|
40
57
|
|
41
|
-
|
42
|
-
task "setup_pscale" => shared_deps do
|
43
|
-
ENV["ENABLE_PSDB"] = "1"
|
44
|
-
ENV["DISABLE_PS_GEM"] = "1"
|
58
|
+
def create_connection_string
|
45
59
|
ps_config = YAML.load_file(".pscale.yml")
|
46
60
|
database = ps_config["database"]
|
47
61
|
branch = ps_config["branch"]
|
48
62
|
|
49
63
|
raise "You must have `pscale` installed on your computer".colorize(:red) unless command?("pscale")
|
50
64
|
if branch.blank? || database.blank?
|
51
|
-
raise "
|
52
|
-
end
|
53
|
-
|
54
|
-
r, = PTY.open
|
55
|
-
|
56
|
-
puts "Connecting to PlanetScale..."
|
57
|
-
|
58
|
-
# Spawns the process in the background
|
59
|
-
pid = Process.spawn("pscale connect #{database} #{branch} --port 3305 #{ENV["SERVICE_TOKEN_CONFIG"]}", out: r)
|
60
|
-
ENV["PSCALE_PID"] = pid.to_s
|
61
|
-
|
62
|
-
out = ""
|
63
|
-
start_time = Time.current
|
64
|
-
time_elapsed = Time.current - start_time
|
65
|
-
sleep(1)
|
66
|
-
while out.blank? && time_elapsed < 10.seconds
|
67
|
-
PTY.check(pid, true)
|
68
|
-
out = r.gets
|
69
|
-
time_elapsed = Time.current - start_time
|
65
|
+
raise "Could not determine which PlanetScale branch to use from .pscale.yml. Please switch to a branch by using: `pscale branch switch branch-name --database db-name --create --wait`".colorize(:red)
|
70
66
|
end
|
71
67
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
68
|
+
short_hash = SecureRandom.hex(2)[0, 4]
|
69
|
+
password_name = "planetscale-rails-#{short_hash}"
|
70
|
+
command = "pscale password create #{database} #{branch} #{password_name} -f json #{ENV["SERVICE_TOKEN_CONFIG"]}"
|
76
71
|
|
77
|
-
|
78
|
-
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
79
|
-
desc "Setup a proxy to connect to #{name} in PlanetScale"
|
80
|
-
task name => shared_deps do
|
81
|
-
ENV["ENABLE_PSDB"] = "1"
|
82
|
-
ENV["DISABLE_PS_GEM"] = "1"
|
83
|
-
ps_config = YAML.load_file(".pscale.yml")
|
84
|
-
database = ps_config["database"]
|
85
|
-
branch = ps_config["branch"]
|
86
|
-
|
87
|
-
raise "You must have `pscale` installed on your computer" unless command?("pscale")
|
88
|
-
if branch.blank? || database.blank?
|
89
|
-
raise "Your branch is not properly setup, please switch to a branch by using the CLI."
|
90
|
-
end
|
72
|
+
output = `#{command}`
|
91
73
|
|
92
|
-
|
74
|
+
if $CHILD_STATUS.success?
|
75
|
+
response = JSON.parse(output)
|
76
|
+
puts "Successfully created credentials for PlanetScale #{db_branch_colorized(database, branch)}"
|
77
|
+
host = response["access_host_url"]
|
78
|
+
username = response["username"]
|
79
|
+
password = response["plain_text"]
|
80
|
+
ENV["PSCALE_PASSWORD_ID"] = response["id"]
|
93
81
|
|
94
|
-
|
82
|
+
adapter = "mysql2"
|
95
83
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
# Spawns the process in the background
|
101
|
-
pid = Process.spawn("pscale connect #{database} #{branch} --port 3305 #{ENV["SERVICE_TOKEN_CONFIG"]}", out: r)
|
102
|
-
ENV["PSCALE_PID"] = pid.to_s
|
84
|
+
if defined?(Trilogy)
|
85
|
+
adapter = "trilogy"
|
86
|
+
end
|
103
87
|
|
104
|
-
|
105
|
-
|
106
|
-
time_elapsed = Time.current - start_time
|
107
|
-
sleep(1)
|
108
|
-
while out.blank? && time_elapsed < 10.seconds
|
109
|
-
PTY.check(pid, true)
|
110
|
-
out = r.gets
|
111
|
-
time_elapsed = Time.current - start_time
|
112
|
-
end
|
88
|
+
# Setting schema_dump to nil is intentional. It prevents Rails from creating a dump after running migrations.
|
89
|
+
url = "#{adapter}://#{username}:#{password}@#{host}:3306/#{database}?ssl_mode=VERIFY_IDENTITY&schema_dump="
|
113
90
|
|
114
|
-
|
91
|
+
# Check common CA paths for certs.
|
92
|
+
ssl_ca_path = %w[/etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt /etc/ssl/ca-bundle.pem /etc/ssl/cert.pem].find { |f| File.exist?(f) }
|
115
93
|
|
116
|
-
|
117
|
-
|
118
|
-
ensure
|
119
|
-
r&.close
|
94
|
+
if ssl_ca_path
|
95
|
+
url += "&sslca=#{ssl_ca_path}"
|
120
96
|
end
|
97
|
+
|
98
|
+
url
|
99
|
+
else
|
100
|
+
puts "Failed to create credentials for PlanetScale #{db_branch_colorized(database, branch)}"
|
101
|
+
puts "Command: #{command}"
|
102
|
+
puts "Output: #{output}"
|
103
|
+
puts "Please verify that you have the correct permissions to create a password for this branch."
|
104
|
+
exit 1
|
121
105
|
end
|
122
106
|
end
|
123
107
|
|
124
|
-
desc "
|
125
|
-
task
|
108
|
+
desc "Create credentials for PlanetScale and sets them to ENV['PSCALE_DATABASE_URL']"
|
109
|
+
task "create_creds" => %i[environment check_ci] do
|
110
|
+
ENV["PSCALE_DATABASE_URL"] = create_connection_string
|
111
|
+
end
|
112
|
+
|
113
|
+
desc "Connects to the current PlanetScale branch and runs rails db:migrate"
|
114
|
+
task migrate: %i[environment check_ci create_creds] do
|
126
115
|
db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
|
127
116
|
|
128
117
|
unless db_configs.size == 1
|
@@ -130,41 +119,45 @@ namespace :psdb do
|
|
130
119
|
end
|
131
120
|
|
132
121
|
puts "Running migrations..."
|
133
|
-
|
134
|
-
|
135
|
-
|
122
|
+
|
123
|
+
command = "DATABASE_URL=\"#{ENV["PSCALE_DATABASE_URL"]}\" bundle exec rails db:migrate"
|
124
|
+
IO.popen(command) do |io|
|
125
|
+
io.each_line do |line|
|
126
|
+
puts line
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
if $CHILD_STATUS.success?
|
131
|
+
puts_deploy_request_instructions
|
132
|
+
else
|
133
|
+
puts "Failed to run migrations".colorize(:red)
|
134
|
+
end
|
136
135
|
ensure
|
137
|
-
|
136
|
+
delete_password
|
138
137
|
end
|
139
138
|
|
140
139
|
namespace :migrate do
|
141
140
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
142
|
-
desc "
|
143
|
-
task name =>
|
141
|
+
desc "Connects to the current PlanetScale branch and runs rails db:migrate:#{name}"
|
142
|
+
task name => %i[environment check_ci create_creds] do
|
144
143
|
puts "Running migrations..."
|
145
|
-
# We run it using the Kernel.system here because this properly handles
|
146
|
-
# when exceptions occur whereas Rake::Task.invoke does not.
|
147
|
-
Kernel.system("bundle exec rake db:migrate:#{name}")
|
148
144
|
|
149
|
-
|
150
|
-
|
151
|
-
ensure
|
152
|
-
kill_pscale_process
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
145
|
+
name_env_key = "#{name.upcase}_DATABASE_URL"
|
146
|
+
command = "#{name_env_key}=\"#{ENV["PSCALE_DATABASE_URL"]}\" bundle exec rails db:migrate:#{name}"
|
156
147
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
148
|
+
IO.popen(command) do |io|
|
149
|
+
io.each_line do |line|
|
150
|
+
puts line
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
if $CHILD_STATUS.success?
|
155
|
+
puts_deploy_request_instructions
|
156
|
+
else
|
157
|
+
puts "Failed to run migrations".colorize(:red)
|
158
|
+
end
|
166
159
|
ensure
|
167
|
-
|
160
|
+
delete_password
|
168
161
|
end
|
169
162
|
end
|
170
163
|
end
|
@@ -172,31 +165,79 @@ namespace :psdb do
|
|
172
165
|
namespace :schema do
|
173
166
|
namespace :load do
|
174
167
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
175
|
-
desc "
|
176
|
-
task name =>
|
168
|
+
desc "Connects to the current PlanetScale branch and runs rails db:schema:load:#{name}"
|
169
|
+
task name => %i[environment check_ci create_creds] do
|
177
170
|
puts "Loading schema..."
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
171
|
+
|
172
|
+
name_env_key = "#{name.upcase}_DATABASE_URL"
|
173
|
+
command = "#{name_env_key}=\"#{ENV["PSCALE_DATABASE_URL"]}\" bundle exec rake db:schema:load:#{name}"
|
174
|
+
|
175
|
+
IO.popen(command) do |io|
|
176
|
+
io.each_line do |line|
|
177
|
+
puts line
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
unless $CHILD_STATUS.success?
|
182
|
+
puts "Failed to load schema".colorize(:red)
|
183
|
+
end
|
182
184
|
ensure
|
183
|
-
|
185
|
+
delete_password
|
184
186
|
end
|
185
187
|
end
|
186
188
|
end
|
187
189
|
end
|
188
190
|
|
191
|
+
desc "Connects to the current PlanetScale branch and runs rails db:rollback"
|
192
|
+
task rollback: %i[environment check_ci create_creds] do
|
193
|
+
db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
|
194
|
+
|
195
|
+
unless db_configs.size == 1
|
196
|
+
raise "Found multiple database configurations, please specify which database you want to rollback using `psdb:rollback:<database_name>`".colorize(:red)
|
197
|
+
end
|
198
|
+
|
199
|
+
command = "DATABASE_URL=\"#{ENV["PSCALE_DATABASE_URL"]}\" bundle exec rails db:rollback"
|
200
|
+
|
201
|
+
IO.popen(command) do |io|
|
202
|
+
io.each_line do |line|
|
203
|
+
puts line
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
unless $CHILD_STATUS.success?
|
208
|
+
puts "Failed to rollback migrations".colorize(:red)
|
209
|
+
end
|
210
|
+
ensure
|
211
|
+
delete_password
|
212
|
+
end
|
213
|
+
|
189
214
|
namespace :rollback do
|
190
215
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
191
|
-
desc "
|
192
|
-
task name =>
|
216
|
+
desc "Connects to the current PlanetScale branch and runs rails db:rollback:#{name}"
|
217
|
+
task name => %i[environment check_ci create_creds] do
|
218
|
+
required_version = Gem::Version.new("6.1.0.0")
|
219
|
+
rails_version = Gem::Version.new(Rails.version)
|
220
|
+
|
221
|
+
if rails_version < required_version
|
222
|
+
raise "This version of Rails does not support rollback commands for multi-database Rails apps. Please upgrade to at least Rails 6.1"
|
223
|
+
end
|
224
|
+
|
193
225
|
puts "Rolling back migrations..."
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
226
|
+
|
227
|
+
name_env_key = "#{name.upcase}_DATABASE_URL"
|
228
|
+
command = "#{name_env_key}=\"#{ENV["PSCALE_DATABASE_URL"]}\" bundle exec rake db:rollback:#{name}"
|
229
|
+
|
230
|
+
IO.popen(command) do |io|
|
231
|
+
io.each_line do |line|
|
232
|
+
puts line
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
unless $CHILD_STATUS.success?
|
237
|
+
puts "Failed to rollback migrations".colorize(:red)
|
238
|
+
end
|
198
239
|
ensure
|
199
|
-
|
240
|
+
delete_password
|
200
241
|
end
|
201
242
|
end
|
202
243
|
end
|
data/planetscale_rails.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: planetscale_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Coutermarsh
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-01-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: colorize
|
@@ -29,16 +29,22 @@ dependencies:
|
|
29
29
|
name: rails
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - "
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '6.0'
|
35
|
+
- - "<"
|
33
36
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
37
|
+
version: '8'
|
35
38
|
type: :runtime
|
36
39
|
prerelease: false
|
37
40
|
version_requirements: !ruby/object:Gem::Requirement
|
38
41
|
requirements:
|
39
|
-
- - "
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '6.0'
|
45
|
+
- - "<"
|
40
46
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
47
|
+
version: '8'
|
42
48
|
description: A collection of rake tasks to make managing schema migrations with PlanetScale
|
43
49
|
easy
|
44
50
|
email:
|