planetscale_rails 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f38096cc4396fecb1efbfba9ea4bfe7f72b39c915990fb7036f8ab4ef1a1aaa2
4
- data.tar.gz: c609fbd59e9caf5682fddd1367533c3a99a80fe1bbd7c93591da6047f8ff22cf
3
+ metadata.gz: 73da9fbd9cc5287b3a3088298413ff860891d8020ee1357fa4c0940ec113c6e2
4
+ data.tar.gz: f954e8a28f986965d20219cf631bc95030c6277f2652ade883f378c9bde26194
5
5
  SHA512:
6
- metadata.gz: b4e11cfda4e78884bd30fe672b06517320f74a36244d96c61688d5d339478c99cff30050e31f049578fa27e5358692697b9019d0032108223d4c6dbb2e9a7c97
7
- data.tar.gz: d236ee3a8a70d8e37be836e344c8e1a565c99149d7f301760810c8efc03ebea30e1cdb1e78458fc788b9fd9f41b1fe98fdaa4f9fc9e29cad1fb64636bf6d579f
6
+ metadata.gz: f964ab82aa2ce073f464d7d9e353714cae00a37f20a134a95a1650a7f9b78f69441297b639c702ddd48b2163ca363307d552567297536631263aae87c5b17e9e
7
+ data.tar.gz: 43537d76a32c25583c46d607e06b24b3f84ceb099e2083b13bbed6409bf43c0a74eb082b2682c32ff63748d45fbd8193d6517510338867dc05909753a603f274
data/.rubocop.yml CHANGED
@@ -12,6 +12,12 @@ Style/StringLiteralsInInterpolation:
12
12
  Layout/LineLength:
13
13
  Max: 180
14
14
 
15
+ Metrics/MethodLength:
16
+ Enabled: false
17
+
18
+ Metrics/AbcSize:
19
+ Enabled: false
20
+
15
21
  Metrics/BlockLength:
16
22
  Enabled: false
17
23
 
data/Gemfile.lock CHANGED
@@ -1,74 +1,74 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- planetscale_rails (0.1.1)
4
+ planetscale_rails (0.2.0)
5
5
  colorize (~> 0.8.1)
6
- rails (~> 7.0)
6
+ rails (>= 6.0, < 8)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- actioncable (7.0.4.2)
12
- actionpack (= 7.0.4.2)
13
- activesupport (= 7.0.4.2)
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.4.2)
17
- actionpack (= 7.0.4.2)
18
- activejob (= 7.0.4.2)
19
- activerecord (= 7.0.4.2)
20
- activestorage (= 7.0.4.2)
21
- activesupport (= 7.0.4.2)
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.4.2)
27
- actionpack (= 7.0.4.2)
28
- actionview (= 7.0.4.2)
29
- activejob (= 7.0.4.2)
30
- activesupport (= 7.0.4.2)
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.4.2)
37
- actionview (= 7.0.4.2)
38
- activesupport (= 7.0.4.2)
39
- rack (~> 2.0, >= 2.2.0)
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.4.2)
44
- actionpack (= 7.0.4.2)
45
- activerecord (= 7.0.4.2)
46
- activestorage (= 7.0.4.2)
47
- activesupport (= 7.0.4.2)
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.4.2)
51
- activesupport (= 7.0.4.2)
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.4.2)
57
- activesupport (= 7.0.4.2)
56
+ activejob (7.0.6)
57
+ activesupport (= 7.0.6)
58
58
  globalid (>= 0.3.6)
59
- activemodel (7.0.4.2)
60
- activesupport (= 7.0.4.2)
61
- activerecord (7.0.4.2)
62
- activemodel (= 7.0.4.2)
63
- activesupport (= 7.0.4.2)
64
- activestorage (7.0.4.2)
65
- actionpack (= 7.0.4.2)
66
- activejob (= 7.0.4.2)
67
- activerecord (= 7.0.4.2)
68
- activesupport (= 7.0.4.2)
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.4.2)
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.12.0)
86
+ i18n (1.14.1)
87
87
  concurrent-ruby (~> 1.0)
88
88
  json (2.6.3)
89
- loofah (2.19.1)
89
+ loofah (2.21.3)
90
90
  crass (~> 1.0.2)
91
- nokogiri (>= 1.5.9)
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.18.0)
101
- net-imap (0.3.4)
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,40 @@ GEM
107
107
  timeout
108
108
  net-smtp (0.3.3)
109
109
  net-protocol
110
- nio4r (2.5.8)
111
- nokogiri (1.14.2-x86_64-darwin)
112
- racc (~> 1.4)
113
- nokogiri (1.14.2-x86_64-linux)
110
+ nio4r (2.5.9)
111
+ nokogiri (1.15.3-x86_64-darwin)
114
112
  racc (~> 1.4)
115
113
  parallel (1.22.1)
116
114
  parser (3.2.1.0)
117
115
  ast (~> 2.4.1)
118
- racc (1.6.2)
119
- rack (2.2.6.3)
120
- rack-test (2.0.2)
116
+ racc (1.7.1)
117
+ rack (2.2.7)
118
+ rack-test (2.1.0)
121
119
  rack (>= 1.3)
122
- rails (7.0.4.2)
123
- actioncable (= 7.0.4.2)
124
- actionmailbox (= 7.0.4.2)
125
- actionmailer (= 7.0.4.2)
126
- actionpack (= 7.0.4.2)
127
- actiontext (= 7.0.4.2)
128
- actionview (= 7.0.4.2)
129
- activejob (= 7.0.4.2)
130
- activemodel (= 7.0.4.2)
131
- activerecord (= 7.0.4.2)
132
- activestorage (= 7.0.4.2)
133
- activesupport (= 7.0.4.2)
120
+ rails (7.0.6)
121
+ actioncable (= 7.0.6)
122
+ actionmailbox (= 7.0.6)
123
+ actionmailer (= 7.0.6)
124
+ actionpack (= 7.0.6)
125
+ actiontext (= 7.0.6)
126
+ actionview (= 7.0.6)
127
+ activejob (= 7.0.6)
128
+ activemodel (= 7.0.6)
129
+ activerecord (= 7.0.6)
130
+ activestorage (= 7.0.6)
131
+ activesupport (= 7.0.6)
134
132
  bundler (>= 1.15.0)
135
- railties (= 7.0.4.2)
136
- rails-dom-testing (2.0.3)
137
- activesupport (>= 4.2.0)
133
+ railties (= 7.0.6)
134
+ rails-dom-testing (2.1.1)
135
+ activesupport (>= 5.0.0)
136
+ minitest
138
137
  nokogiri (>= 1.6)
139
- rails-html-sanitizer (1.5.0)
140
- loofah (~> 2.19, >= 2.19.1)
141
- railties (7.0.4.2)
142
- actionpack (= 7.0.4.2)
143
- activesupport (= 7.0.4.2)
138
+ rails-html-sanitizer (1.6.0)
139
+ loofah (~> 2.21)
140
+ nokogiri (~> 1.14)
141
+ railties (7.0.6)
142
+ actionpack (= 7.0.6)
143
+ activesupport (= 7.0.6)
144
144
  method_source
145
145
  rake (>= 12.2)
146
146
  thor (~> 1.0)
@@ -175,15 +175,15 @@ GEM
175
175
  rubocop-ast (1.27.0)
176
176
  parser (>= 3.2.1.0)
177
177
  ruby-progressbar (1.12.0)
178
- thor (1.2.1)
179
- timeout (0.3.2)
178
+ thor (1.2.2)
179
+ timeout (0.4.0)
180
180
  tzinfo (2.0.6)
181
181
  concurrent-ruby (~> 1.0)
182
182
  unicode-display_width (2.4.2)
183
- websocket-driver (0.7.5)
183
+ websocket-driver (0.7.6)
184
184
  websocket-extensions (>= 0.1.0)
185
185
  websocket-extensions (0.1.5)
186
- zeitwerk (2.6.7)
186
+ zeitwerk (2.6.9)
187
187
 
188
188
  PLATFORMS
189
189
  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
@@ -42,12 +41,13 @@ First, make sure you have the [`pscale` CLI installed](https://github.com/planet
42
41
  that this is the branch you want to migrate.
43
42
 
44
43
  ```
45
- pscale branch switch my-new-branch-name --database my-db-name --create
44
+ pscale branch switch my-new-branch-name --database my-db-name --create --wait
46
45
  ```
47
46
 
48
- **Tip:** In your database settings. Enable "Automatically copy migration data." Select "Rails/Phoenix" as the migration framework. This will auto copy your `schema_migrations` table between branches.
47
+ **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.
49
48
 
50
- 2. Once your branch is ready, you can then use the `psdb` rake task to connect to your branch and run `db:migrate`.
49
+ 2. Once your branch is ready, you can then use the `psdb` rake task to connect to your branch and run `db:migrate`. The command will run against
50
+ the branch specified in your `.pscale.yml` file.
51
51
 
52
52
  ```
53
53
  bundle exec rails psdb:migrate
@@ -59,8 +59,6 @@ If you run multiple databases in your Rails app, you can specify the DB name.
59
59
  bundle exec rails psdb:migrate:primary
60
60
  ```
61
61
 
62
- This will connect to the branch that you created, and run migrations against the branch.
63
-
64
62
  If you make a mistake, you can use `bundle exec rails psdb:rollback` to rollback the changes on your PlanetScale branch.
65
63
 
66
64
  3. Next, you can either open the Deploy Request via the UI. Or the CLI.
@@ -72,6 +70,9 @@ pscale deploy-request create database-name my-new-branch-name
72
70
 
73
71
  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.
74
72
 
73
+ ## Usage with GitHub Actions
74
+
75
+ See the [GitHub Actions examples](actions-example.md) doc for ways to automate your schema migrations with PlanetScale + Actions.
75
76
 
76
77
  ## Development
77
78
 
@@ -0,0 +1,129 @@
1
+ ## GitHub Actions example
2
+
3
+ To automate branch creation and running migrations, you can setup a branch and run `rails psdb:migrate` from GitHub Actions.
4
+
5
+ Here is a full example workflow that:
6
+ 1. Creates a branch matching the git branch name.
7
+ 2. Runs rails migrations.
8
+ 3. Opens a deploy request if any migrations were run.
9
+ 4. Comments on the pull request with the diff + link to the deploy request.
10
+
11
+ ### Migrate schema workflow
12
+
13
+ This workflow will run on any pull request that is opened with a change to `db/schema.rb`.
14
+
15
+ Secrets needed to be set:
16
+ - `PLANETSCALE_ORG_NAME`
17
+ - `PLANETSCALE_DATABASE_NAME`
18
+ - `PLANETSCALE_SERVICE_TOKEN_ID`
19
+ - `PLANETSCALE_SERVICE_TOKEN`
20
+
21
+ The PlanetScale service token must have the `connect_branch`, `create_branch`, `read_branch`, `create_deploy_request`, and `read_deploy_request` permissions on the database.
22
+
23
+ ```yaml
24
+ name: Run database migrations
25
+ on:
26
+ pull_request:
27
+ branches: [ main ]
28
+ paths:
29
+ - 'db/schema.rb'
30
+
31
+ jobs:
32
+ planetscale:
33
+ permissions:
34
+ pull-requests: write
35
+ contents: read
36
+
37
+ runs-on: ubuntu-latest
38
+ steps:
39
+ - name: checkout
40
+ uses: actions/checkout@v3
41
+ - name: Create a branch
42
+ uses: planetscale/create-branch-action@v4
43
+ id: create_branch
44
+ with:
45
+ org_name: ${{ secrets.PLANETSCALE_ORG_NAME }}
46
+ database_name: ${{ secrets.PLANETSCALE_DATABASE_NAME }}
47
+ branch_name: ${{ github.head_ref }}
48
+ from: main
49
+ check_exists: true
50
+ wait: true
51
+ env:
52
+ PLANETSCALE_SERVICE_TOKEN_ID: ${{ secrets.PLANETSCALE_SERVICE_TOKEN_ID }}
53
+ PLANETSCALE_SERVICE_TOKEN: ${{ secrets.PLANETSCALE_SERVICE_TOKEN }}
54
+ - uses: actions/checkout@v3
55
+ - name: Set up Ruby
56
+ uses: ruby/setup-ruby@v1
57
+ with:
58
+ ruby-version: 3.2.1
59
+ - name: Cache Ruby gems
60
+ uses: actions/cache@v3
61
+ with:
62
+ path: vendor/bundle
63
+ key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
64
+ restore-keys: |
65
+ ${{ runner.os }}-gems-
66
+ - name: Install dependencies
67
+ run: |
68
+ bundle config --local path vendor/bundle
69
+ bundle config --local deployment true
70
+ bundle install
71
+ - name: Set migration config
72
+ run: |
73
+ echo "org: ${{ secrets.PLANETSCALE_ORG_NAME }}" > .pscale.yml
74
+ echo "database: ${{ secrets.PLANETSCALE_DATABASE_NAME }}" >> .pscale.yml
75
+ echo "branch: ${{ github.head_ref }}" >> .pscale.yml
76
+ - name: Setup pscale
77
+ uses: planetscale/setup-pscale-action@v1
78
+ - name: Run migrations
79
+ run: |
80
+ bundle exec rails psdb:migrate > migration-output.txt
81
+ env:
82
+ PSCALE_SERVICE_TOKEN_ID: ${{ secrets.PLANETSCALE_SERVICE_TOKEN_ID }}
83
+ PSCALE_SERVICE_TOKEN: ${{ secrets.PLANETSCALE_SERVICE_TOKEN }}
84
+ - name: Open DR if migrations
85
+ run: |
86
+ if grep -q "migrated" migration-output.txt; then
87
+ echo "DB_MIGRATED=true" >> $GITHUB_ENV
88
+ if pscale deploy-request create ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ github.head_ref }}; then
89
+ cat migration-output.txt
90
+ echo "DR_OPENED=true" >> $GITHUB_ENV
91
+ echo "Deploy request successfully opened"
92
+ else
93
+ echo "Error: Deployment request failed"
94
+ exit 0
95
+ fi
96
+ else
97
+ echo "Did not open a DR since nothing found in migration-output.txt"
98
+ cat migration-output.txt
99
+ exit 0
100
+ fi
101
+ env:
102
+ PLANETSCALE_SERVICE_TOKEN_ID: ${{ secrets.PLANETSCALE_SERVICE_TOKEN_ID }}
103
+ PLANETSCALE_SERVICE_TOKEN: ${{ secrets.PLANETSCALE_SERVICE_TOKEN }}
104
+ - name: Get Deploy Requests
105
+ if: ${{ env.DR_OPENED }}
106
+ env:
107
+ PLANETSCALE_SERVICE_TOKEN_ID: ${{ secrets.PLANETSCALE_SERVICE_TOKEN_ID }}
108
+ PLANETSCALE_SERVICE_TOKEN: ${{ secrets.PLANETSCALE_SERVICE_TOKEN }}
109
+ run: |
110
+ deploy_request_number=$(pscale deploy-request show ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ github.head_ref }} -f json | jq -r '.number')
111
+ echo "DEPLOY_REQUEST_NUMBER=$deploy_request_number" >> $GITHUB_ENV
112
+ - name: Comment PR - db migrated
113
+ if: ${{ env.DR_OPENED }}
114
+ env:
115
+ PLANETSCALE_SERVICE_TOKEN_ID: ${{ secrets.PLANETSCALE_SERVICE_TOKEN_ID }}
116
+ PLANETSCALE_SERVICE_TOKEN: ${{ secrets.PLANETSCALE_SERVICE_TOKEN }}
117
+ run: |
118
+ sleep 2
119
+ echo "Deploy request opened: https://app.planetscale.com/${{ secrets.PLANETSCALE_ORG_NAME }}/${{ secrets.PLANETSCALE_DATABASE_NAME }}/deploy-requests/${{ env.DEPLOY_REQUEST_NUMBER }}" >> migration-message.txt
120
+ echo "" >> migration-message.txt
121
+ echo "\`\`\`diff" >> migration-message.txt
122
+ pscale deploy-request diff ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.DEPLOY_REQUEST_NUMBER }} -f json | jq -r '.[].raw' >> migration-message.txt
123
+ echo "\`\`\`" >> migration-message.txt
124
+ - name: Comment PR - db migrated
125
+ uses: thollander/actions-comment-pull-request@v2
126
+ if: ${{ env.DR_OPENED }}
127
+ with:
128
+ filePath: migration-message.txt
129
+ ```
@@ -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,92 +55,53 @@ namespace :psdb do
38
55
  end
39
56
  end
40
57
 
41
- desc "Setup a proxy to connect to PlanetScale"
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 "Your branch is not properly setup, please switch to a branch by using the CLI.".colorize(:red)
65
+ raise "Could not determine which PlanetScale branch to use from .pscale.yml. Please switch to a branch by using: `pscale switch database-name branch-name`".colorize(:red)
52
66
  end
53
67
 
54
- r, = PTY.open
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"]}"
55
71
 
56
- puts "Connecting to PlanetScale..."
72
+ output = `#{command}`
57
73
 
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
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"]
61
81
 
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
70
- end
82
+ adapter = "mysql2"
71
83
 
72
- raise "Timed out waiting for PlanetScale connection to be established".colorize(:red) if time_elapsed > 10.seconds
73
- ensure
74
- r&.close
75
- end
76
-
77
- namespace :setup_pscale do
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
91
- raise "Unable to run migrations against the main branch" if branch == "main"
92
-
93
- config = Rails.configuration.database_configuration[Rails.env][name]
94
-
95
- raise "Database #{name} is not configured for the current environment" unless config
96
-
97
- r, = PTY.open
98
-
99
- puts "Connecting to PlanetScale..."
100
-
101
- # Spawns the process in the background
102
- pid = Process.spawn("pscale connect #{database} #{branch} --port 3305 #{ENV["SERVICE_TOKEN_CONFIG"]}", out: r)
103
- ENV["PSCALE_PID"] = pid.to_s
104
-
105
- out = ""
106
- start_time = Time.current
107
- time_elapsed = Time.current - start_time
108
- sleep(1)
109
- while out.blank? && time_elapsed < 10.seconds
110
- PTY.check(pid, true)
111
- out = r.gets
112
- time_elapsed = Time.current - start_time
113
- end
114
-
115
- raise "Timed out waiting for PlanetScale connection to be established" if time_elapsed > 10.seconds
116
-
117
- # Comment out for now, this messes up when running migrations.
118
- # Kernel.system("bundle exec rails db:environment:set RAILS_ENV=development")
119
- ensure
120
- r&.close
84
+ if defined?(Trilogy)
85
+ adapter = "trilogy"
121
86
  end
87
+
88
+ "#{adapter}://#{username}:#{password}@#{host}:3306/#{database}?ssl_mode=VERIFY_IDENTITY"
89
+ else
90
+ puts "Failed to create credentials for PlanetScale #{db_branch_colorized(database, branch)}"
91
+ puts "Command: #{command}"
92
+ puts "Output: #{output}"
93
+ puts "Please verify that you have the correct permissions to create a password for this branch."
94
+ exit 1
122
95
  end
123
96
  end
124
97
 
125
- desc "Migrate the database for current environment"
126
- task migrate: %i[environment check_ci setup_pscale] do
98
+ desc "Create credentials for PlanetScale and sets them to ENV['PSCALE_DATABASE_URL']"
99
+ task "create_creds" => %i[environment check_ci] do
100
+ ENV["PSCALE_DATABASE_URL"] = create_connection_string
101
+ end
102
+
103
+ desc "Connects to the current PlanetScale branch and runs rails db:migrate"
104
+ task migrate: %i[environment check_ci create_creds] do
127
105
  db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
128
106
 
129
107
  unless db_configs.size == 1
@@ -131,41 +109,45 @@ namespace :psdb do
131
109
  end
132
110
 
133
111
  puts "Running migrations..."
134
- Kernel.system("bundle exec rails db:migrate")
135
- puts "Finished running migrations\n".colorize(:green)
136
- puts_deploy_request_instructions
112
+
113
+ command = "DATABASE_URL=#{ENV["PSCALE_DATABASE_URL"]} bundle exec rails db:migrate"
114
+ IO.popen(command) do |io|
115
+ io.each_line do |line|
116
+ puts line
117
+ end
118
+ end
119
+
120
+ if $CHILD_STATUS.success?
121
+ puts_deploy_request_instructions
122
+ else
123
+ puts "Failed to run migrations".colorize(:red)
124
+ end
137
125
  ensure
138
- kill_pscale_process
126
+ delete_password
139
127
  end
140
128
 
141
129
  namespace :migrate do
142
130
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
143
- desc "Migrate #{name} database for current environment"
144
- task name => shared_deps(name) do
131
+ desc "Connects to the current PlanetScale branch and runs rails db:migrate:#{name}"
132
+ task name => %i[environment check_ci create_creds] do
145
133
  puts "Running migrations..."
146
- # We run it using the Kernel.system here because this properly handles
147
- # when exceptions occur whereas Rake::Task.invoke does not.
148
- Kernel.system("bundle exec rake db:migrate:#{name}")
149
134
 
150
- puts "Finished running migrations\n".colorize(:green)
151
- puts_deploy_request_instructions
152
- ensure
153
- kill_pscale_process
154
- end
155
- end
156
- end
135
+ name_env_key = "#{name.upcase}_DATABASE_URL"
136
+ command = "#{name_env_key}=#{ENV["PSCALE_DATABASE_URL"]} bundle exec rails db:migrate:#{name}"
157
137
 
158
- namespace :truncate_all do
159
- ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
160
- desc "Truncate all tables in #{name} database for current environment"
161
- task name => shared_deps(name) do
162
- puts "Truncating database..."
163
- # We run it using the Kernel.system here because this properly handles
164
- # when exceptions occur whereas Rake::Task.invoke does not.
165
- Kernel.system("bundle exec rake db:truncate_all")
166
- puts "Finished truncating database."
138
+ IO.popen(command) do |io|
139
+ io.each_line do |line|
140
+ puts line
141
+ end
142
+ end
143
+
144
+ if $CHILD_STATUS.success?
145
+ puts_deploy_request_instructions
146
+ else
147
+ puts "Failed to run migrations".colorize(:red)
148
+ end
167
149
  ensure
168
- kill_pscale_process
150
+ delete_password
169
151
  end
170
152
  end
171
153
  end
@@ -173,31 +155,79 @@ namespace :psdb do
173
155
  namespace :schema do
174
156
  namespace :load do
175
157
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
176
- desc "Load the current schema into the #{name} database"
177
- task name => shared_deps(name) do
158
+ desc "Connects to the current PlanetScale branch and runs rails db:schema:load:#{name}"
159
+ task name => %i[environment check_ci create_creds] do
178
160
  puts "Loading schema..."
179
- # We run it using the Kernel.system here because this properly handles
180
- # when exceptions occur whereas Rake::Task.invoke does not.
181
- Kernel.system("bundle exec rake db:schema:load:#{name}")
182
- puts "Finished loading schema."
161
+
162
+ name_env_key = "#{name.upcase}_DATABASE_URL"
163
+ command = "#{name_env_key}=#{ENV["PSCALE_DATABASE_URL"]} bundle exec rake db:schema:load:#{name}"
164
+
165
+ IO.popen(command) do |io|
166
+ io.each_line do |line|
167
+ puts line
168
+ end
169
+ end
170
+
171
+ unless $CHILD_STATUS.success?
172
+ puts "Failed to load schema".colorize(:red)
173
+ end
183
174
  ensure
184
- kill_pscale_process
175
+ delete_password
185
176
  end
186
177
  end
187
178
  end
188
179
  end
189
180
 
181
+ desc "Connects to the current PlanetScale branch and runs rails db:rollback"
182
+ task rollback: %i[environment check_ci create_creds] do
183
+ db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
184
+
185
+ unless db_configs.size == 1
186
+ raise "Found multiple database configurations, please specify which database you want to rollback using `psdb:rollback:<database_name>`".colorize(:red)
187
+ end
188
+
189
+ command = "DATABASE_URL=#{ENV["PSCALE_DATABASE_URL"]} bundle exec rails db:rollback"
190
+
191
+ IO.popen(command) do |io|
192
+ io.each_line do |line|
193
+ puts line
194
+ end
195
+ end
196
+
197
+ unless $CHILD_STATUS.success?
198
+ puts "Failed to rollback migrations".colorize(:red)
199
+ end
200
+ ensure
201
+ delete_password
202
+ end
203
+
190
204
  namespace :rollback do
191
205
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
192
- desc "Rollback #{name} database for current environment"
193
- task name => shared_deps(name) do
206
+ desc "Connects to the current PlanetScale branch and runs rails db:rollback:#{name}"
207
+ task name => %i[environment check_ci create_creds] do
208
+ required_version = Gem::Version.new("6.1.0.0")
209
+ rails_version = Gem::Version.new(Rails.version)
210
+
211
+ if rails_version < required_version
212
+ rails "This version of Rails does not support rollback commands for multi-database Rails apps. Please upgrade to at least Rails 6.1"
213
+ end
214
+
194
215
  puts "Rolling back migrations..."
195
- # We run it using the Kernel.system here because this properly handles
196
- # when exceptions occur whereas Rake::Task.invoke does not.
197
- Kernel.system("bundle exec rake db:rollback:#{name}")
198
- puts "Finished rolling back migrations.".colorize(:green)
216
+
217
+ name_env_key = "#{name.upcase}_DATABASE_URL"
218
+ command = "#{name_env_key}=#{ENV["PSCALE_DATABASE_URL"]} bundle exec rake db:rollback:#{name}"
219
+
220
+ IO.popen(command) do |io|
221
+ io.each_line do |line|
222
+ puts line
223
+ end
224
+ end
225
+
226
+ unless $CHILD_STATUS.success?
227
+ puts "Failed to rollback migrations".colorize(:red)
228
+ end
199
229
  ensure
200
- kill_pscale_process
230
+ delete_password
201
231
  end
202
232
  end
203
233
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PlanetscaleRails
4
- VERSION = "0.1.3"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -29,5 +29,5 @@ Gem::Specification.new do |spec|
29
29
  spec.require_paths = ["lib"]
30
30
 
31
31
  spec.add_dependency "colorize", "~> 0.8.1"
32
- spec.add_dependency "rails", "~> 7.0"
32
+ spec.add_dependency "rails", ">= 6.0", "< 8"
33
33
  end
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.3
4
+ version: 0.2.0
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: 2023-03-18 00:00:00.000000000 Z
12
+ date: 2023-11-09 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: '7.0'
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: '7.0'
47
+ version: '8'
42
48
  description: A collection of rake tasks to make managing schema migrations with PlanetScale
43
49
  easy
44
50
  email:
@@ -60,6 +66,7 @@ files:
60
66
  - LICENSE.txt
61
67
  - README.md
62
68
  - Rakefile
69
+ - actions-example.md
63
70
  - bin/console
64
71
  - bin/setup
65
72
  - lib/Rakefile