cpl 1.0.1 → 1.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da0cd8b4b3f57a141b2a148a35555069f4ff4135803e4ae95932cd3887e3a567
4
- data.tar.gz: dab258fecce6a5948374057418959d736915ab69f84593e1b189c148f62f00be
3
+ metadata.gz: 97534e7ffeb4c0b6c7db70851d6cbac5f86ca0329a76af9975dc4a164eeb08b3
4
+ data.tar.gz: 3e8a4e9a60af5859bf157464a164f3b7b430a335a33815d65d9bbc54415d43b5
5
5
  SHA512:
6
- metadata.gz: 31c5cfe13e647abf6f34f6b021c808c220db07a48cd223d0d277ad7814ab0942961a7b75c63d89c3c109e7ca670d478285e5289fdb9fe64ccd828917b7fccf22
7
- data.tar.gz: 926431c8d7fb4c5f8ba7930a3a156d70718dcce6eb1c717e9859f5a8546900266e4267cee7c755ca4c99612fb1b574a7cbfdd6ca23a2fd5483c1eb3c743a83db
6
+ metadata.gz: 41f11336b2c8a741693e5acc415225bf64d19b4fd0f2240da6ee3de884a517abdb23a37b1ebe166b5b8fd0ccf4d0ae0b95cb7fb3cce0c8f770bfd7c7bc5c6e3e
7
+ data.tar.gz: e3367bea0aeca04add5823d7129f0ffa3f276709e967d5fe6e533241c8fbace80dd1811b54cb2ee7fd71ce500d54535e4bbe4aea76a1c58114ecf324a3fee763
data/CHANGELOG.md CHANGED
@@ -1,9 +1,38 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.1 - 2023-03-09
3
+ All notable changes to this project's source code will be documented in this file. Items under `Unreleased` are upcoming features that will be out in the next version.
4
4
 
5
- - Fixed issue with default gems for older Ruby versions (#14)
5
+ ## Contributors
6
6
 
7
- ## 0.1.0 - 2023-02-19
7
+ Please follow the recommendations outlined at [keepachangelog.com](https://keepachangelog.com). Please use the existing headings and styling as a guide, and add a link for the version diff at the bottom of the file. Also, please update the `Unreleased` link to compare it to the latest release version.
8
+
9
+ ## Versions
10
+
11
+ ## [Unreleased]
12
+
13
+ Changes since the last non-beta release.
14
+
15
+ _Please add entries here for your pull requests that are not yet released._
16
+
17
+ ### Added
18
+
19
+ - Added steps to migrate to docs. [PR 57](https://github.com/shakacode/heroku-to-control-plane/pull/57) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
20
+ - Added `ps:wait` command. [PR 58](https://github.com/shakacode/heroku-to-control-plane/pull/58) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
21
+
22
+ ## [1.0.1] - 2023-06-28
23
+
24
+ ### Fixed
25
+
26
+ - Fixed `cleanup-stale-apps` command when app does not have image. [PR 55](https://github.com/shakacode/heroku-to-control-plane/pull/55) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
27
+
28
+ ### Changed
29
+
30
+ - Improved docs. [PR 50](https://github.com/shakacode/heroku-to-control-plane/pull/50) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
31
+
32
+ ## [1.0.0] - 2023-05-29
8
33
 
9
34
  - Initial release
35
+
36
+ [Unreleased]: https://github.com/shakacode/heroku-to-control-plane/compare/v1.0.1...HEAD
37
+ [1.0.1]: https://github.com/shakacode/heroku-to-control-plane/compare/v1.0.0...v1.0.1
38
+ [1.0.0]: https://github.com/shakacode/heroku-to-control-plane/releases/tag/v1.0.0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cpl (1.0.1)
4
+ cpl (1.0.2)
5
5
  debug (~> 1.7.1)
6
6
  dotenv (~> 2.8.1)
7
7
  psych (~> 5.1.0)
@@ -25,7 +25,7 @@ GEM
25
25
  hashdiff (1.0.1)
26
26
  iniparse (1.5.0)
27
27
  io-console (0.6.0)
28
- irb (1.7.0)
28
+ irb (1.7.1)
29
29
  reline (>= 0.3.0)
30
30
  json (2.6.3)
31
31
  overcommit (0.60.0)
data/README.md CHANGED
@@ -28,10 +28,8 @@ a **helper CLI** based on templates to save lots of day-to-day typing (and human
28
28
  1. [Key Features](#key-features)
29
29
  2. [Concept Mapping](#concept-mapping)
30
30
  3. [Installation](#installation)
31
- 4. [Example CLI Flow for Application Build/Deployment](#example-cli-flow-for-application-builddeployment)
32
- - [Initial Setup and Deployment](#initial-setup-and-deployment)
33
- - [Promoting Code Upgrades](#promoting-code-upgrades)
34
- 5. [Example Project Modifications for Control Plane](#example-project-modifications-for-control-plane)
31
+ 4. [Steps to Migrate](#steps-to-migrate)
32
+ 5. [Config](#config)
35
33
  6. [Environment](#environment)
36
34
  7. [Database](#database)
37
35
  8. [In-memory Databases](#in-memory-databases)
@@ -110,104 +108,13 @@ gem install cpl
110
108
  **Note:** Do not confuse the `cpl` CLI with the `cpln` CLI. The `cpl` CLI is the Heroku to Control Plane playbook CLI.
111
109
  The `cpln` CLI is the Control Plane CLI.
112
110
 
113
- ## Example CLI Flow for Application Build/Deployment
111
+ ## Steps to Migrate
114
112
 
115
- **Notes:**
113
+ Click [here](/docs/migrating.md) to see the steps to migrate.
116
114
 
117
- - `my-app` is an app name defined in the `.controlplane/controlplane.yml` file, such as `ror-tutorial` in
118
- [this `controlplane.yml` file](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/controlplane.yml).
119
- - Other files in the `.controlplane/templates/` directory are used by the `cpl setup-app` and `cpl apply-template`
120
- commands.
115
+ ## Config
121
116
 
122
- ### Initial Setup and Deployment
123
-
124
- For each Git project that you want to deploy to Control Plane, copy project-specific configs to a `.controlplane/`
125
- directory at the top of your project. `cpl` will pick those up depending on which project folder tree it runs. Thus,
126
- this automates running several projects with different configs without explicitly switching configs.
127
-
128
- Before the initial setup, add the templates for the app to `.controlplane/controlplane.yml`, using the `setup` key, e.g.:
129
-
130
- ```yaml
131
- my-app:
132
- setup:
133
- - gvc
134
- - postgres
135
- - redis
136
- - memcached
137
- - rails
138
- - sidekiq
139
- ```
140
-
141
- Note how the templates correspond to files in the `.controlplane/templates/` directory.
142
-
143
- Then create a `Dockerfile` for your deployment. See
144
- [this example](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/Dockerfile).
145
-
146
- ```sh
147
- # Provision infrastructure (one-time-only for new apps) using templates.
148
- cpl setup-app -a my-app
149
-
150
- # Build and push image with auto-tagging, e.g., "my-app:1_456".
151
- cpl build-image -a my-app --commit 456
152
-
153
- # Prepare database.
154
- cpl run:detached -a my-app --image latest -- rails db:prepare
155
-
156
- # Deploy latest image.
157
- cpl deploy-image -a my-app
158
-
159
- # Open app in browser.
160
- cpl open -a my-app
161
- ```
162
-
163
- ### Promoting Code Upgrades
164
-
165
- ```sh
166
- # Build and push new image with sequential tagging, e.g., "my-app:2".
167
- cpl build-image -a my-app
168
-
169
- # Or build and push new image with sequential tagging and commit SHA, e.g., "my-app:2_ABC".
170
- cpl build-image -a my-app --commit ABC
171
-
172
- # Run database migrations (or other release tasks) with latest image, while app is still running on previous image.
173
- # This is analogous to the release phase.
174
- cpl run:detached -a my-app --image latest -- rails db:migrate
175
-
176
- # Deploy latest image.
177
- cpl deploy-image -a my-app
178
- ```
179
-
180
- ## Example Project Modifications for Control Plane
181
-
182
- _See this for a complete example._
183
-
184
- To learn how to migrate an app, we recommend following along with
185
- [this example project](https://github.com/shakacode/react-webpack-rails-tutorial).
186
-
187
- 1. Create the `.controlplane/` directory at the top of your project and copy files from the `templates/` directory of
188
- this repository to something as follows:
189
-
190
- ```sh
191
- app_main_folder/
192
- .controlplane/
193
- Dockerfile # Your app's Dockerfile, with some Control Plane changes.
194
- controlplane.yml
195
- entrypoint.sh # App-specific - edit as needed.
196
- templates/
197
- gvc.yml
198
- memcached.yml
199
- postgres.yml
200
- rails.yml
201
- redis.yml
202
- sidekiq.yml
203
- ```
204
-
205
- The example
206
- [`.controlplane/` directory](https://github.com/shakacode/react-webpack-rails-tutorial/tree/master/.controlplane)
207
- already contains these files.
208
-
209
- 2. Edit your `controlplane.yml` file as needed. For example, see
210
- [this `controlplane.yml` file](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/controlplane.yml).
117
+ Here's a complete example of all supported config keys explained:
211
118
 
212
119
  ```yaml
213
120
  # Keys beginning with "cpln_" correspond to your settings in Control Plane.
@@ -221,6 +128,16 @@ aliases:
221
128
  # Example apps use only one location. Control Plane offers the ability to use multiple locations.
222
129
  default_location: aws-us-east-2
223
130
 
131
+ # Allows running the command `cpl setup-app`
132
+ # instead of `cpl apply-template gvc redis postgres memcached rails sidekiq`.
133
+ setup:
134
+ - gvc
135
+ - redis
136
+ - postgres
137
+ - memcached
138
+ - rails
139
+ - sidekiq
140
+
224
141
  # Configure the workload name used as a template for one-off scripts, like a Heroku one-off dyno.
225
142
  one_off_workload: rails
226
143
 
@@ -235,40 +152,58 @@ aliases:
235
152
  - postgres
236
153
  - memcached
237
154
 
238
- # Configure the workload name used when maintenance mode is on (defaults to "maintenance")
155
+ # Configure the workload name used when maintenance mode is on (defaults to "maintenance").
239
156
  maintenance_workload: maintenance
240
157
 
158
+ # Fixes the remote terminal size to match the local terminal size
159
+ # when running the commands `cpl run` or `cpl run:detached`.
160
+ fix_terminal_size: true
161
+
162
+ # Apps with a deployed image created before this amount of days will be listed for deletion
163
+ # when running the command `cpl cleanup-stale-apps`.
164
+ stale_app_image_deployed_days: 5
165
+
166
+ # Images created before this amount of days will be listed for deletion
167
+ # when running the command `cpl cleanup-old-images`.
168
+ old_image_retention_days: 5
169
+
170
+ # Run workloads created before this amount of days will be listed for deletion
171
+ # when running the command `cpl run:cleanup`.
172
+ stale_run_workload_created_days: 2
173
+
241
174
  apps:
242
175
  my-app-staging:
243
176
  # Use the values from the common section above.
244
177
  <<: *common
178
+
245
179
  my-app-review:
246
180
  <<: *common
181
+
247
182
  # If `match_if_app_name_starts_with` is `true`, then use this config for app names starting with this name,
248
183
  # e.g., "my-app-review-pr123", "my-app-review-anything-goes", etc.
249
184
  match_if_app_name_starts_with: true
185
+
250
186
  my-app-production:
251
187
  <<: *common
188
+
252
189
  # Use a different organization for production.
253
190
  cpln_org: my-org-production
191
+
254
192
  # Allows running the command `cpl promote-app-from-upstream -a my-app-production`
255
193
  # to promote the staging app to production.
256
194
  upstream: my-app-staging
195
+
196
+ # Used by the command `cpl promote-app-from-upstream` to run a release script before deploying.
197
+ # This is relative to the `.controlplane/` directory.
198
+ release_script: release_script
199
+
257
200
  my-app-other:
258
201
  <<: *common
202
+
259
203
  # You can specify a different `Dockerfile` relative to the `.controlplane/` directory (defaults to "Dockerfile").
260
204
  dockerfile: ../some_other/Dockerfile
261
205
  ```
262
206
 
263
- 3. We recommend that you try out the commands listed in
264
- [the example](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/readme.md).
265
- These steps will guide you to the following:
266
-
267
- 1. Provision the GVC and workloads.
268
- 2. Build the Docker image.
269
- 3. Run Rails migrations, like in the Heroku release phase.
270
- 4. Promote the latest Docker image.
271
-
272
207
  ## Environment
273
208
 
274
209
  There are two main places where we can set up environment variables in Control Plane:
data/docs/commands.md CHANGED
@@ -285,6 +285,18 @@ cpl ps:stop -a $APP_NAME
285
285
  cpl ps:stop -a $APP_NAME -w $WORKLOAD_NAME
286
286
  ```
287
287
 
288
+ ### `ps:wait`
289
+
290
+ - Waits for workloads in app to be ready after re-deployment
291
+
292
+ ```sh
293
+ # Waits for all workloads in app.
294
+ cpl ps:wait -a $APP_NAME
295
+
296
+ # Waits for a specific workload in app.
297
+ cpl ps:swait -a $APP_NAME -w $WORKLOAD_NAME
298
+ ```
299
+
288
300
  ### `run`
289
301
 
290
302
  - Runs one-off **_interactive_** replicas (analog of `heroku run`)
data/docs/migrating.md ADDED
@@ -0,0 +1,262 @@
1
+ # Steps to Migrate from Heroku to Control Plane
2
+
3
+ We recommend following along with
4
+ [this example project](https://github.com/shakacode/react-webpack-rails-tutorial).
5
+
6
+ 1. [Clone the Staging Environment](#clone-the-staging-environment)
7
+ - [Review Special Gems](#review-special-gems)
8
+ - [Create a Minimum Bootable Config](#create-a-minimum-bootable-config)
9
+ 2. [Create the Review App Process](#create-the-review-app-process)
10
+ - [Database for Review Apps](#database-for-review-apps)
11
+ - [Redis and Memcached for Review Apps](#redis-and-memcached-for-review-apps)
12
+ 3. [Deploy to Production](#deploy-to-production)
13
+
14
+ ## Clone the Staging Environment
15
+
16
+ By cloning the staging environment on Heroku, you can speed up the initial provisioning of the app on Control Plane
17
+ without compromising your current environment.
18
+
19
+ Consider migrating just the web dyno first, and get other types of dynos working afterward. You can also move the
20
+ add-ons to Control Plane later once the app works as expected.
21
+
22
+ First, create a new Heroku app with all the add-ons, copying the data from the current staging app.
23
+
24
+ Then, copy project-specific configs to a `.controlplane/` directory at the top of your project. `cpl` will pick those up
25
+ depending on which project folder tree it runs. Thus, this automates running several projects with different configs
26
+ without explicitly switching configs.
27
+
28
+ Edit the `.controlplane/controlplane.yml` file as needed. Note that the `my-app-staging` name used in the examples below
29
+ is defined in this file. See
30
+ [this example](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/controlplane.yml).
31
+
32
+ Before the initial setup, add the templates for the app to the `.controlplane/controlplane.yml` file, using the `setup`
33
+ key, e.g.:
34
+
35
+ ```yaml
36
+ my-app-staging:
37
+ <<: *common
38
+ setup:
39
+ - gvc
40
+ - redis
41
+ - memcached
42
+ - rails
43
+ - sidekiq
44
+ ```
45
+
46
+ Note how the templates correspond to files in the `.controlplane/templates/` directory. These files will be used by the
47
+ `cpl setup-app` and `cpl apply-template` commands.
48
+
49
+ Ensure that env vars point to the Heroku add-ons in the template for the app (`.controlplane/templates/gvc.yml`). See
50
+ [this example](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/templates/gvc.yml).
51
+
52
+ After that, create a Dockerfile in `.controlplane/Dockerfile` for your deployment. See
53
+ [this example](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/Dockerfile).
54
+
55
+ You should have a folder structure similar to the following:
56
+
57
+ ```sh
58
+ app_main_folder/
59
+ .controlplane/
60
+ Dockerfile # Your app's Dockerfile, with some Control Plane changes.
61
+ controlplane.yml
62
+ entrypoint.sh # App-specific - edit as needed.
63
+ templates/
64
+ gvc.yml
65
+ memcached.yml
66
+ rails.yml
67
+ redis.yml
68
+ sidekiq.yml
69
+ ```
70
+
71
+ The example
72
+ [`.controlplane/` directory](https://github.com/shakacode/react-webpack-rails-tutorial/tree/master/.controlplane)
73
+ already contains these files.
74
+
75
+ Finally, check the app for any Heroku-specific code and update it, such as the `HEROKU_SLUG_COMMIT` env var and other
76
+ env vars beginning with `HEROKU_`. You should add some logic to check for the Control Plane equivalents - it might be
77
+ worth adding a `CONTROLPLANE` env var to act as a feature flag and help run different code for Heroku and Control Plane
78
+ until the migration is complete.
79
+
80
+ You might want to [review special gems](#review-special-gems) and
81
+ [create a minimum bootable config](#create-a-minimum-bootable-config).
82
+
83
+ At first, do the deployments from the command line. Then set up CI scripts to trigger the deployment upon merges to
84
+ master/main.
85
+
86
+ Use these commands for the initial setup and deployment:
87
+
88
+ ```sh
89
+ # Provision infrastructure (one-time-only for new apps) using templates.
90
+ cpl setup-app -a my-app-staging
91
+
92
+ # Build and push image with auto-tagging, e.g., "my-app-staging:1_456".
93
+ cpl build-image -a my-app-staging --commit 456
94
+
95
+ # Prepare database.
96
+ cpl run:detached -a my-app-staging --image latest -- rails db:prepare
97
+
98
+ # Deploy latest image.
99
+ cpl deploy-image -a my-app-staging
100
+
101
+ # Open app in browser.
102
+ cpl open -a my-app-staging
103
+ ```
104
+
105
+ Then for promoting code upgrades:
106
+
107
+ ```sh
108
+ # Build and push new image with sequential tagging, e.g., "my-app-staging:2".
109
+ cpl build-image -a my-app-staging
110
+
111
+ # Or build and push new image with sequential tagging and commit SHA, e.g., "my-app-staging:2_ABC".
112
+ cpl build-image -a my-app-staging --commit ABC
113
+
114
+ # Run database migrations (or other release tasks) with latest image, while app is still running on previous image.
115
+ # This is analogous to the release phase.
116
+ cpl run:detached -a my-app-staging --image latest -- rails db:migrate
117
+
118
+ # Deploy latest image.
119
+ cpl deploy-image -a my-app-staging
120
+ ```
121
+
122
+ ### Review Special Gems
123
+
124
+ Make sure to review "special" gems which might be related to Heroku, e.g.:
125
+
126
+ - `rails_autoscale_agent`. It's specific to Heroku, so it must be removed.
127
+ - `puma_worker_killer`. In general, it's unnecessary on Control Plane, as Kubernetes containers will restart on their
128
+ own logic and may not restart at all if everything is ok.
129
+ - `rack-timeout`. It could possibly be replaced with Control Plane's `timeout` option.
130
+
131
+ You can use the `CONTROLPLANE` env var to separate the gems, e.g.:
132
+
133
+ ```ruby
134
+ # Gemfile
135
+ group :staging, :production do
136
+ gem "rack-timeout"
137
+
138
+ unless ENV.key?("CONTROLPLANE")
139
+ gem "rails_autoscale_agent"
140
+ gem "puma_worker_killer"
141
+ end
142
+ end
143
+ ```
144
+
145
+ ### Create a Minimum Bootable Config
146
+
147
+ You can try to create a minimum bootable config to migrate parts of your app gradually. To do that, follow these steps:
148
+
149
+ 1. Rename the existing `application.yml` file to some other name (e.g., `application.old.yml`)
150
+ 2. Create a new **minimal** `application.yml` file, e.g.:
151
+
152
+ ```yaml
153
+ SECRET_KEY_BASE: "123"
154
+ # This should be enabled for `rails s`, not `rails assets:precompile`.
155
+ # DATABASE_URL: postgres://localhost:5432/dbname
156
+ # RAILS_SERVE_STATIC_FILES: "true"
157
+
158
+ # You will add whatever env vars are required here later.
159
+ ```
160
+
161
+ 3. Try running `RAILS_ENV=production CONTROLPLANE=true rails assets:precompile`
162
+ (theoretically, this should work without any additional env vars)
163
+ 4. Fix whatever code needs to be fixed and add missing env vars
164
+ (the fewer env vars are needed, the cleaner the `Dockerfile` will be)
165
+ 5. Enable `DATABASE_URL` and `RAILS_SERVE_STATIC_FILES` env vars
166
+ 6. Try running `RAILS_ENV=production CONTROLPLANE=true rails s`
167
+ 7. Fix whatever code needs to be fixed and add required env vars to `application.yml`
168
+ 8. Try running your **production** entrypoint command, e.g.,
169
+ `RAILS_ENV=production RACK_ENV=production CONTROLPLANE=true puma -C config/puma.rb`
170
+ 9. Fix whatever code needs to be fixed and add required env vars to `application.yml`
171
+
172
+ Now you should have a minimal bootable config.
173
+
174
+ Then you can temporarily set the `LOG_LEVEL=debug` env var and disable unnecessary services to help with the process,
175
+ e.g.:
176
+
177
+ ```yaml
178
+ DISABLE_SPRING: "true"
179
+ SCOUT_MONITOR: "false"
180
+ RACK_TIMEOUT_SERVICE_TIMEOUT: "0"
181
+ ```
182
+
183
+ ## Create the Review App Process
184
+
185
+ Add an entry for review apps to the `.controlplane/controlplane.yml` file. By adding a `match_if_app_name_starts_with`
186
+ key with the value `true`, any app that starts with the entry's name will use this config. Doing this allows you to
187
+ configure an entry for, e.g., `my-app-review`, and then create review apps starting with that name (e.g.,
188
+ `my-app-review-1234`, `my-app-review-5678`, etc.). Here's an example:
189
+
190
+ ```yaml
191
+ my-app-review:
192
+ <<: *common
193
+ match_if_app_name_starts_with: true
194
+ setup:
195
+ - gvc
196
+ - redis
197
+ - memcached
198
+ - rails
199
+ - sidekiq
200
+ ```
201
+
202
+ In your CI scripts, you can create a review app using some identifier (e.g., the number of the PR on GitHub).
203
+
204
+ ```yaml
205
+ # On CircleCI, you can use `echo $CIRCLE_PULL_REQUEST | grep -Eo '[0-9]+$'` to extract the number of the PR.
206
+ PR_NUM=$(... extract the number of the PR here ...)
207
+ echo "export APP_NAME=my-app-review-$PR_NUM" >> $BASH_ENV
208
+
209
+ # Only create the app if it doesn't exist yet, as we may have multiple triggers for the review app
210
+ # (such as when a PR gets updated).
211
+ if ! cpl exists -a ${APP_NAME}; then
212
+ cpl setup-app -a ${APP_NAME}
213
+ echo "export NEW_APP=true" >> $BASH_ENV
214
+ fi
215
+
216
+ # The `NEW_APP` env var that we exported above can be used to either reset or migrate the database before deploying.
217
+ if [ -n "${NEW_APP}" ]; then
218
+ cpl run:detached 'LOG_LEVEL=warn rails db:reset' -a ${APP_NAME} --image latest
219
+ else
220
+ cpl run:detached 'LOG_LEVEL=warn rails db:migrate_and_wait_replica' -a ${APP_NAME} --image latest
221
+ fi
222
+ ```
223
+
224
+ Then follow the same steps for the initial deployment or code upgrades.
225
+
226
+ ### Database for Review Apps
227
+
228
+ For the review app resources, these should be handled as env vars in the template for the app
229
+ (`.controlplane/templates/gvc.yml`), .e.g.:
230
+
231
+ ```yaml
232
+ - name: DATABASE_URL
233
+ value: postgres://postgres:XXXXXXXX@cpln-XXXX-staging.XXXXXX.us-east-1.rds.amazonaws.com:5432/APP_GVC
234
+ ```
235
+
236
+ Notice that `APP_GVC` is the app name, which is used as the database name on RDS, so that each review app gets its own
237
+ database on the one RDS instance used for all review apps, which would be, e.g., `my-app-review-1234`.
238
+
239
+ ### Redis and Memcached for Review Apps
240
+
241
+ So long as no persistence is needed for Redis and Memcached, we have templates for workloads that should be sufficient
242
+ for review apps in the `templates/` directory of this repository. Using these templates results in considerable cost
243
+ savings compared to paying for the resources on Heroku.
244
+
245
+ ```yaml
246
+ - name: MEMCACHE_SERVERS
247
+ value: memcached.APP_GVC.cpln.local
248
+ - name: REDIS_URL
249
+ value: redis://redis.APP_GVC.cpln.local:6379
250
+ ```
251
+
252
+ ## Deploy to Production
253
+
254
+ Only try deploying to production once staging and review apps are working well.
255
+
256
+ For simplicity, keep add-ons running on Heroku initially. You could move over the database to RDS first. However, it's a
257
+ bit simpler to isolate any differences in cost and performance by first moving over your compute to Control Plane.
258
+
259
+ Ensure that your Control Plane compute is in the AWS region `US-EAST-1`; otherwise, you'll have noticeable extra latency
260
+ with your calls to resources. You might also have egress charges from Control Plane.
261
+
262
+ Use the `cpl promote-app-from-upstream` command to promote the staging app to production.
@@ -42,9 +42,7 @@ module Command
42
42
 
43
43
  @workloads.reverse_each do |workload|
44
44
  step("Waiting for workload '#{workload}' to be ready", retry_on_failure: true) do
45
- cp.fetch_workload_deployments(workload)&.dig("items")&.any? do |item|
46
- item.dig("status", "ready")
47
- end
45
+ cp.workload_deployments_ready?(workload, expected_status: true)
48
46
  end
49
47
  end
50
48
  end
@@ -6,7 +6,7 @@ module Command
6
6
  OPTIONS = [
7
7
  app_option(required: true),
8
8
  workload_option,
9
- wait_option("workload to be not ready")
9
+ wait_option("workload to not be ready")
10
10
  ].freeze
11
11
  DESCRIPTION = "Stops workloads in app"
12
12
  LONG_DESCRIPTION = <<~DESC
@@ -41,10 +41,8 @@ module Command
41
41
  progress.puts
42
42
 
43
43
  @workloads.each do |workload|
44
- step("Waiting for workload '#{workload}' to be not ready", retry_on_failure: true) do
45
- cp.fetch_workload_deployments(workload)&.dig("items")&.all? do |item|
46
- !item.dig("status", "ready")
47
- end
44
+ step("Waiting for workload '#{workload}' to not be ready", retry_on_failure: true) do
45
+ cp.workload_deployments_ready?(workload, expected_status: false)
48
46
  end
49
47
  end
50
48
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Command
4
+ class PsWait < Base
5
+ NAME = "ps:wait"
6
+ OPTIONS = [
7
+ app_option(required: true),
8
+ workload_option
9
+ ].freeze
10
+ DESCRIPTION = "Waits for workloads in app to be ready after re-deployment"
11
+ LONG_DESCRIPTION = <<~DESC
12
+ - Waits for workloads in app to be ready after re-deployment
13
+ DESC
14
+ EXAMPLES = <<~EX
15
+ ```sh
16
+ # Waits for all workloads in app.
17
+ cpl ps:wait -a $APP_NAME
18
+
19
+ # Waits for a specific workload in app.
20
+ cpl ps:swait -a $APP_NAME -w $WORKLOAD_NAME
21
+ ```
22
+ EX
23
+
24
+ def call
25
+ @workloads = [config.options[:workload]] if config.options[:workload]
26
+ @workloads ||= config[:app_workloads] + config[:additional_workloads]
27
+
28
+ @workloads.reverse_each do |workload|
29
+ step("Waiting for workload '#{workload}' to be ready", retry_on_failure: true) do
30
+ cp.workload_deployments_ready?(workload, expected_status: true)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -149,6 +149,26 @@ class Controlplane # rubocop:disable Metrics/ClassLength
149
149
  api.workload_deployments(workload: workload, gvc: gvc, org: org)
150
150
  end
151
151
 
152
+ def workload_deployment_version_ready?(version, next_version, expected_status:)
153
+ return false unless version["workload"] == next_version
154
+
155
+ version["containers"]&.all? do |_, container|
156
+ ready = container.dig("resources", "replicas") == container.dig("resources", "replicasReady")
157
+ expected_status == true ? ready : !ready
158
+ end
159
+ end
160
+
161
+ def workload_deployments_ready?(workload, expected_status:)
162
+ deployments = fetch_workload_deployments(workload)["items"]
163
+ deployments.all? do |deployment|
164
+ next_version = deployment.dig("status", "expectedDeploymentVersion")
165
+
166
+ deployment.dig("status", "versions")&.all? do |version|
167
+ workload_deployment_version_ready?(version, next_version, expected_status: expected_status)
168
+ end
169
+ end
170
+ end
171
+
152
172
  def workload_set_image_ref(workload, container:, image:)
153
173
  cmd = "cpln workload update #{workload} #{gvc_org}"
154
174
  cmd += " --set spec.containers.#{container}.image=/org/#{config.org}/image/#{image}"
data/lib/cpl/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cpl
4
- VERSION = "1.0.1"
4
+ VERSION = "1.0.2"
5
5
  MIN_CPLN_VERSION = "0.0.71"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cpl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Gordon
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-06-28 00:00:00.000000000 Z
12
+ date: 2023-07-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: debug
@@ -223,6 +223,7 @@ files:
223
223
  - docs/assets/memcached.png
224
224
  - docs/assets/sidekiq-pre-stop-hook.png
225
225
  - docs/commands.md
226
+ - docs/migrating.md
226
227
  - docs/postgres.md
227
228
  - docs/redis.md
228
229
  - docs/tips.md
@@ -255,6 +256,7 @@ files:
255
256
  - lib/command/ps_restart.rb
256
257
  - lib/command/ps_start.rb
257
258
  - lib/command/ps_stop.rb
259
+ - lib/command/ps_wait.rb
258
260
  - lib/command/run.rb
259
261
  - lib/command/run_cleanup.rb
260
262
  - lib/command/run_detached.rb