cpl 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -3
- data/Gemfile.lock +2 -2
- data/README.md +44 -109
- data/docs/commands.md +12 -0
- data/docs/migrating.md +262 -0
- data/lib/command/ps_start.rb +1 -3
- data/lib/command/ps_stop.rb +3 -5
- data/lib/command/ps_wait.rb +35 -0
- data/lib/core/controlplane.rb +20 -0
- data/lib/cpl/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97534e7ffeb4c0b6c7db70851d6cbac5f86ca0329a76af9975dc4a164eeb08b3
|
4
|
+
data.tar.gz: 3e8a4e9a60af5859bf157464a164f3b7b430a335a33815d65d9bbc54415d43b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41f11336b2c8a741693e5acc415225bf64d19b4fd0f2240da6ee3de884a517abdb23a37b1ebe166b5b8fd0ccf4d0ae0b95cb7fb3cce0c8f770bfd7c7bc5c6e3e
|
7
|
+
data.tar.gz: e3367bea0aeca04add5823d7129f0ffa3f276709e967d5fe6e533241c8fbace80dd1811b54cb2ee7fd71ce500d54535e4bbe4aea76a1c58114ecf324a3fee763
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,38 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
|
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
|
-
|
5
|
+
## Contributors
|
6
6
|
|
7
|
-
|
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.
|
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.
|
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. [
|
32
|
-
|
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
|
-
##
|
111
|
+
## Steps to Migrate
|
114
112
|
|
115
|
-
|
113
|
+
Click [here](/docs/migrating.md) to see the steps to migrate.
|
116
114
|
|
117
|
-
|
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
|
-
|
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.
|
data/lib/command/ps_start.rb
CHANGED
@@ -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.
|
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
|
data/lib/command/ps_stop.rb
CHANGED
@@ -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
|
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
|
45
|
-
cp.
|
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
|
data/lib/core/controlplane.rb
CHANGED
@@ -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
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.
|
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-
|
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
|