cpflow 4.1.1 → 5.0.0.rc.0

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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/commands/update-changelog.md +367 -0
  3. data/.github/workflows/claude-code-review.yml +44 -0
  4. data/.github/workflows/claude.yml +55 -0
  5. data/.gitignore +2 -0
  6. data/.overcommit.yml +43 -3
  7. data/.rubocop.yml +3 -3
  8. data/CHANGELOG.md +39 -3
  9. data/CONTRIBUTING.md +6 -0
  10. data/Gemfile +8 -7
  11. data/Gemfile.lock +93 -73
  12. data/README.md +53 -22
  13. data/cpflow.gemspec +5 -5
  14. data/docs/ai-github-flow-prompt.md +61 -0
  15. data/docs/ci-automation.md +335 -0
  16. data/docs/commands.md +70 -5
  17. data/docs/releasing.md +153 -0
  18. data/lib/command/ai_github_flow_prompt.rb +47 -0
  19. data/lib/command/base.rb +14 -0
  20. data/lib/command/cleanup_images.rb +1 -1
  21. data/lib/command/cleanup_stale_apps.rb +1 -1
  22. data/lib/command/copy_image_from_upstream.rb +14 -3
  23. data/lib/command/exists.rb +13 -2
  24. data/lib/command/generate.rb +153 -4
  25. data/lib/command/generate_github_actions.rb +170 -0
  26. data/lib/command/generator_helpers.rb +31 -0
  27. data/lib/command/github_flow_readiness.rb +37 -0
  28. data/lib/command/ps_wait.rb +5 -1
  29. data/lib/command/run.rb +4 -21
  30. data/lib/command/terraform/generate.rb +1 -0
  31. data/lib/command/version.rb +1 -0
  32. data/lib/constants/exit_code.rb +1 -0
  33. data/lib/core/config.rb +1 -1
  34. data/lib/core/controlplane.rb +13 -10
  35. data/lib/core/controlplane_api_direct.rb +25 -3
  36. data/lib/core/github_flow_readiness/checks.rb +143 -0
  37. data/lib/core/github_flow_readiness_service.rb +453 -0
  38. data/lib/core/repo_introspection.rb +118 -0
  39. data/lib/core/terraform_config/dsl.rb +1 -1
  40. data/lib/core/terraform_config/local_variable.rb +1 -1
  41. data/lib/cpflow/version.rb +1 -1
  42. data/lib/cpflow.rb +66 -3
  43. data/lib/generator_templates/Dockerfile +59 -3
  44. data/lib/generator_templates/controlplane.yml +27 -39
  45. data/lib/generator_templates/entrypoint.sh +1 -1
  46. data/lib/generator_templates/release_script.sh +23 -0
  47. data/lib/generator_templates/templates/app.yml +5 -8
  48. data/lib/generator_templates/templates/rails.yml +2 -11
  49. data/lib/generator_templates_sqlite/controlplane.yml +46 -0
  50. data/lib/generator_templates_sqlite/release_script.sh +25 -0
  51. data/lib/generator_templates_sqlite/templates/app.yml +15 -0
  52. data/lib/generator_templates_sqlite/templates/db.yml +6 -0
  53. data/lib/generator_templates_sqlite/templates/rails.yml +32 -0
  54. data/lib/generator_templates_sqlite/templates/storage.yml +6 -0
  55. data/lib/github_flow_templates/.github/actions/cpflow-build-docker-image/action.yml +131 -0
  56. data/lib/github_flow_templates/.github/actions/cpflow-delete-control-plane-app/action.yml +24 -0
  57. data/lib/github_flow_templates/.github/actions/cpflow-delete-control-plane-app/delete-app.sh +50 -0
  58. data/lib/github_flow_templates/.github/actions/cpflow-detect-release-phase/action.yml +62 -0
  59. data/lib/github_flow_templates/.github/actions/cpflow-setup-environment/action.yml +98 -0
  60. data/lib/github_flow_templates/.github/actions/cpflow-validate-config/action.yml +85 -0
  61. data/lib/github_flow_templates/.github/actions/cpflow-wait-for-health/action.yml +92 -0
  62. data/lib/github_flow_templates/.github/cpflow-help.md +47 -0
  63. data/lib/github_flow_templates/.github/workflows/cpflow-cleanup-stale-review-apps.yml +56 -0
  64. data/lib/github_flow_templates/.github/workflows/cpflow-delete-review-app.yml +142 -0
  65. data/lib/github_flow_templates/.github/workflows/cpflow-deploy-review-app.yml +445 -0
  66. data/lib/github_flow_templates/.github/workflows/cpflow-deploy-staging.yml +140 -0
  67. data/lib/github_flow_templates/.github/workflows/cpflow-help-command.yml +53 -0
  68. data/lib/github_flow_templates/.github/workflows/cpflow-promote-staging-to-production.yml +490 -0
  69. data/lib/github_flow_templates/.github/workflows/cpflow-review-app-help.yml +46 -0
  70. data/rakelib/create_release.rake +662 -37
  71. data/script/check_command_docs +4 -2
  72. data/script/check_cpln_links +25 -11
  73. data/script/precommit/check_command_docs +22 -0
  74. data/script/precommit/check_cpln_links +21 -0
  75. data/script/precommit/check_trailing_newlines +68 -0
  76. data/script/precommit/get_changed_files +49 -0
  77. data/script/precommit/ruby_autofix +52 -0
  78. data/script/precommit/ruby_lint +33 -0
  79. metadata +56 -15
  80. /data/docs/{migrating.md → migrating-heroku-to-control-plane.md} +0 -0
data/Gemfile.lock CHANGED
@@ -1,106 +1,125 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cpflow (4.1.1)
5
- dotenv (~> 2.8.1)
6
- jwt (~> 2.8.1)
7
- psych (~> 5.1.0)
8
- thor (~> 1.2.1)
4
+ cpflow (5.0.0.rc.0)
5
+ dotenv (~> 3.1)
6
+ jwt (~> 3.1)
7
+ psych (~> 5.2)
8
+ thor (~> 1.4)
9
9
 
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- addressable (2.8.7)
14
- public_suffix (>= 2.0.2, < 7.0)
15
- ast (2.4.2)
16
- base64 (0.2.0)
17
- bigdecimal (3.1.8)
18
- childprocess (4.1.0)
19
- crack (1.0.0)
13
+ addressable (2.8.9)
14
+ public_suffix (>= 2.0.2, < 8.0)
15
+ ast (2.4.3)
16
+ base64 (0.3.0)
17
+ bigdecimal (4.1.0)
18
+ childprocess (5.1.0)
19
+ logger (~> 1.5)
20
+ crack (1.0.1)
20
21
  bigdecimal
21
22
  rexml
22
- debug (1.9.2)
23
+ date (3.5.1)
24
+ debug (1.11.1)
23
25
  irb (~> 1.10)
24
26
  reline (>= 0.3.8)
25
- diff-lcs (1.5.1)
26
- docile (1.4.0)
27
- dotenv (2.8.1)
28
- hashdiff (1.1.0)
27
+ diff-lcs (1.6.2)
28
+ docile (1.4.1)
29
+ dotenv (3.2.0)
30
+ erb (6.0.2)
31
+ gem-release (2.2.4)
32
+ hashdiff (1.2.1)
29
33
  iniparse (1.5.0)
30
- io-console (0.7.2)
31
- irb (1.13.2)
34
+ io-console (0.8.2)
35
+ irb (1.17.0)
36
+ pp (>= 0.6.0)
37
+ prism (>= 1.3.0)
32
38
  rdoc (>= 4.0.0)
33
39
  reline (>= 0.4.2)
34
- json (2.7.2)
35
- jwt (2.8.2)
40
+ json (2.19.3)
41
+ jwt (3.1.2)
36
42
  base64
37
- language_server-protocol (3.17.0.3)
38
- overcommit (0.60.0)
39
- childprocess (>= 0.6.3, < 5)
43
+ language_server-protocol (3.17.0.5)
44
+ lint_roller (1.1.0)
45
+ logger (1.7.0)
46
+ overcommit (0.69.0)
47
+ childprocess (>= 0.6.3, < 6)
40
48
  iniparse (~> 1.4)
41
- rexml (~> 3.2)
42
- parallel (1.25.1)
43
- parser (3.3.3.0)
49
+ rexml (>= 3.3.9)
50
+ parallel (1.28.0)
51
+ parser (3.3.11.1)
44
52
  ast (~> 2.4.1)
45
53
  racc
46
- psych (5.1.2)
54
+ pp (0.6.3)
55
+ prettyprint
56
+ prettyprint (0.2.0)
57
+ prism (1.9.0)
58
+ psych (5.3.1)
59
+ date
47
60
  stringio
48
- public_suffix (6.0.0)
49
- racc (1.8.0)
61
+ public_suffix (7.0.5)
62
+ racc (1.8.1)
50
63
  rainbow (3.1.1)
51
- rake (13.2.1)
52
- rdoc (6.7.0)
64
+ rake (13.3.1)
65
+ rdoc (7.2.0)
66
+ erb
53
67
  psych (>= 4.0.0)
54
- regexp_parser (2.9.2)
55
- reline (0.5.9)
68
+ tsort
69
+ regexp_parser (2.11.3)
70
+ reline (0.6.3)
56
71
  io-console (~> 0.5)
57
- rexml (3.3.1)
58
- strscan
59
- rspec (3.12.0)
60
- rspec-core (~> 3.12.0)
61
- rspec-expectations (~> 3.12.0)
62
- rspec-mocks (~> 3.12.0)
63
- rspec-core (3.12.3)
64
- rspec-support (~> 3.12.0)
65
- rspec-expectations (3.12.4)
72
+ rexml (3.4.4)
73
+ rspec (3.13.2)
74
+ rspec-core (~> 3.13.0)
75
+ rspec-expectations (~> 3.13.0)
76
+ rspec-mocks (~> 3.13.0)
77
+ rspec-core (3.13.6)
78
+ rspec-support (~> 3.13.0)
79
+ rspec-expectations (3.13.5)
66
80
  diff-lcs (>= 1.2.0, < 2.0)
67
- rspec-support (~> 3.12.0)
68
- rspec-mocks (3.12.7)
81
+ rspec-support (~> 3.13.0)
82
+ rspec-mocks (3.13.8)
69
83
  diff-lcs (>= 1.2.0, < 2.0)
70
- rspec-support (~> 3.12.0)
84
+ rspec-support (~> 3.13.0)
71
85
  rspec-retry (0.6.2)
72
86
  rspec-core (> 3.3)
73
- rspec-support (3.12.2)
74
- rubocop (1.64.1)
87
+ rspec-support (3.13.7)
88
+ rubocop (1.86.0)
75
89
  json (~> 2.3)
76
- language_server-protocol (>= 3.17.0)
90
+ language_server-protocol (~> 3.17.0.2)
91
+ lint_roller (~> 1.1.0)
77
92
  parallel (~> 1.10)
78
93
  parser (>= 3.3.0.2)
79
94
  rainbow (>= 2.2.2, < 4.0)
80
- regexp_parser (>= 1.8, < 3.0)
81
- rexml (>= 3.2.5, < 4.0)
82
- rubocop-ast (>= 1.31.1, < 2.0)
95
+ regexp_parser (>= 2.9.3, < 3.0)
96
+ rubocop-ast (>= 1.49.0, < 2.0)
83
97
  ruby-progressbar (~> 1.7)
84
- unicode-display_width (>= 2.4.0, < 3.0)
85
- rubocop-ast (1.31.3)
86
- parser (>= 3.3.1.0)
87
- rubocop-rake (0.6.0)
88
- rubocop (~> 1.0)
89
- rubocop-rspec (3.0.1)
90
- rubocop (~> 1.61)
98
+ unicode-display_width (>= 2.4.0, < 4.0)
99
+ rubocop-ast (1.49.1)
100
+ parser (>= 3.3.7.2)
101
+ prism (~> 1.7)
102
+ rubocop-rake (0.7.1)
103
+ lint_roller (~> 1.1)
104
+ rubocop (>= 1.72.1)
105
+ rubocop-rspec (3.9.0)
106
+ lint_roller (~> 1.1)
107
+ rubocop (~> 1.81)
91
108
  ruby-progressbar (1.13.0)
92
109
  simplecov (0.22.0)
93
110
  docile (~> 1.1)
94
111
  simplecov-html (~> 0.11)
95
112
  simplecov_json_formatter (~> 0.1)
96
- simplecov-html (0.12.3)
113
+ simplecov-html (0.13.2)
97
114
  simplecov_json_formatter (0.1.4)
98
- stringio (3.1.1)
99
- strscan (3.1.0)
100
- thor (1.2.2)
115
+ stringio (3.2.0)
116
+ thor (1.5.0)
101
117
  timecop (0.9.10)
102
- unicode-display_width (2.5.0)
103
- webmock (3.18.1)
118
+ tsort (0.2.0)
119
+ unicode-display_width (3.2.0)
120
+ unicode-emoji (~> 4.1)
121
+ unicode-emoji (4.2.0)
122
+ webmock (3.26.2)
104
123
  addressable (>= 2.8.0)
105
124
  crack (>= 0.3.2)
106
125
  hashdiff (>= 0.4.0, < 2.0.0)
@@ -112,16 +131,17 @@ PLATFORMS
112
131
  DEPENDENCIES
113
132
  cpflow!
114
133
  debug (~> 1)
115
- overcommit (~> 0.60.0)
134
+ gem-release (~> 2.2)
135
+ overcommit (~> 0.69.0)
116
136
  rake (~> 13.0)
117
- rspec (~> 3.12.0)
137
+ rspec (~> 3.13)
118
138
  rspec-retry (~> 0.6.2)
119
- rubocop (~> 1.64.1)
120
- rubocop-rake (~> 0.6.0)
121
- rubocop-rspec (~> 3.0.1)
139
+ rubocop (~> 1.81)
140
+ rubocop-rake (~> 0.7.1)
141
+ rubocop-rspec (~> 3.8)
122
142
  simplecov (~> 0.22.0)
123
- timecop (~> 0.9.6)
124
- webmock (~> 3.18.1)
143
+ timecop (~> 0.9.10)
144
+ webmock (~> 3.26)
125
145
 
126
146
  BUNDLED WITH
127
- 2.3.26
147
+ 4.0.7
data/README.md CHANGED
@@ -22,9 +22,17 @@ _If you need a free demo account for Control Plane (no CC required), you can con
22
22
 
23
23
  ---
24
24
 
25
- Be sure to see the [demo app](https://github.com/shakacode/react-webpack-rails-tutorial/tree/master/.controlplane), which includes simple YAML configurations and setup for `cpflow`.
25
+ To bootstrap a new project, run three commands from the repo root:
26
26
 
27
- Also, check [how the `cpflow` gem (this project) is used in the Github actions](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.github/actions/deploy-to-control-plane/action.yml).
27
+ 1. **`cpflow github-flow-readiness`** gate for common rollout blockers (missing Rails runtime scaffold, legacy Ruby or Bundler toolchains, unpublished exact-pinned gems or npm packages, missing production Dockerfiles). Exits non-zero on any blocker.
28
+ 2. **`cpflow generate`** — creates `.controlplane/` scaffolding. Infers the app prefix from the repo directory, the base Ruby version from `.ruby-version`/`.tool-versions`/`Gemfile`, the JS package manager from `package.json`, repo-defined frontend precompile hooks (Shakapacker `precompile_hook`, React on Rails auto bundle generation), and switches to persistent `db` + `storage` volume templates when `config/database.yml` shows SQLite in production.
29
+ 3. **`cpflow generate-github-actions`** — adds the reusable GitHub Actions pipeline for review apps, staging deploys, and manual production promotion.
30
+
31
+ The generated scaffold is a starting point. After generation, adapt `.controlplane/` for app-specific workloads (Sidekiq, Node renderer), wire any private-dependency Docker build settings (SSH key, optional known-host overrides), and verify that the production Docker build succeeds.
32
+
33
+ See [CI automation](./docs/ci-automation.md) for the full setup and required GitHub secrets and variables. For an AI agent rollout, see the [AI rollout prompt](./docs/ai-github-flow-prompt.md) or run `cpflow ai-github-flow-prompt` inside the target repo to print a copy-paste prompt with that repo's default app prefix filled in.
34
+
35
+ For a live reference, see the [demo app](https://github.com/shakacode/react-webpack-rails-tutorial/tree/master/.controlplane) and its [GitHub Actions flow](https://github.com/shakacode/react-webpack-rails-tutorial/tree/master/.github).
28
36
  Here is a brief [video overview](https://www.youtube.com/watch?v=llaQoAV_6Iw).
29
37
 
30
38
  ---
@@ -37,7 +45,7 @@ many "Heroku" abstractions and naming conventions.
37
45
 
38
46
  Control Plane provides access to raw cloud computing power but lacks the simple abstractions of Heroku. The `cpflow` CLI bridges this gap, delivering a streamlined and familiar experience for developers.
39
47
 
40
- While this repository simplifies migration from Heroku, the `cpflow` CLI is versatile and can be used for new applications as well. It follows a **concept mapping** and **helper CLI** approach to streamline deployment workflows and minimize manual effort.
48
+ While this repository simplifies migration from Heroku, the `cpflow` CLI is versatile and can be used for any application. This document contains **concept mapping** and **helper CLI** approach to streamline deployment workflows and minimize manual effort.
41
49
 
42
50
  Additionally, the documentation includes numerous examples and practical tips for teams transitioning from Heroku to Kubernetes, helping them make the most of Control Plane's advanced features.
43
51
 
@@ -64,6 +72,7 @@ Additionally, the documentation includes numerous examples and practical tips fo
64
72
  - Extensive Heroku-to-Control Plane migration examples included in the documentation.
65
73
  - Convention-driven configuration to simplify workflows and reduce custom scripting requirements.
66
74
  - Easy to understand Heroku to Control Plane conventions in setup and naming.
75
+ - GitHub Actions generator for on-demand review apps, automatic staging deploys, and manual promotion to production.
67
76
  - **Safe, production-ready** equivalents of `heroku run` and `heroku run:detached` for Control Plane.
68
77
  - Automatic sequential release tagging for Docker images.
69
78
  - A project-aware CLI that enables working on multiple projects.
@@ -82,7 +91,7 @@ On Control Plane, we can map a Heroku app to a GVC (Global Virtual Cloud). Such
82
91
  be anything that can run as a container.
83
92
 
84
93
  | Heroku | Control Plane |
85
- | ---------------- | ------------------------------------------- |
94
+ |------------------|---------------------------------------------|
86
95
  | _app_ | _GVC_ (Global Virtual Cloud) |
87
96
  | _dyno_ | _workload_ |
88
97
  | _add-on_ | either a _workload_ or an external resource |
@@ -105,7 +114,12 @@ For the typical Rails app, this means:
105
114
  | in-memory db | `redis`, `memcached` | add-on | external provider or can be set up for development/testing with Docker image (lacks persistence between restarts) |
106
115
  | others | `mailtrap` | add-on | external provider or can be set up for development/testing with Docker image (lacks persistence between restarts) |
107
116
 
108
- ## Installation
117
+ ## Migration Strategy
118
+ See this doc for [detailed migration steps](./docs/migrating-heroku-to-control-plane.md) from Heroku to Control Plane. Even if you are coming from a platform other than Heroku, you can still benefit from the migration steps.
119
+
120
+ ## System Prerequisites
121
+
122
+ _Note, if you want to use Terraform with cpflow, you will start the same way below._
109
123
 
110
124
  1. Ensure your [Control Plane](https://shakacode.controlplane.com/) account is set up. Set up an `organization` `<your-org>` for testing in that account and modify the value for `aliases.common.cpln_org` in `.controlplane/controlplane.yml`, or you can also set it with the `CPLN_ORG` environment variable. If you need an organization, please [contact Shakacode](mailto:controlplane@shakacode.com).
111
125
 
@@ -113,7 +127,9 @@ For the typical Rails app, this means:
113
127
 
114
128
  3. Install [Ruby](https://www.ruby-lang.org/en/) (required for these helpers).
115
129
 
116
- 4. Install Control Plane CLI, and configure access ([docs here](https://shakadocs.controlplane.com/quickstart/quick-start-3-cli#getting-started-with-the-cli)).
130
+ 4. Purely local bootstrap commands can run before Control Plane CLI is installed. That includes `cpflow help`, `cpflow version`, `cpflow github-flow-readiness`, `cpflow ai-github-flow-prompt`, `cpflow generate`, `cpflow generate-github-actions`, and `cpflow terraform generate`. Install Control Plane CLI before any `cpflow` command that talks to Control Plane infrastructure.
131
+
132
+ 5. Install Control Plane CLI, and configure access ([docs here](https://shakadocs.controlplane.com/quickstart/quick-start-3-cli#getting-started-with-the-cli)).
117
133
 
118
134
  ```sh
119
135
  # Install CLI
@@ -126,19 +142,15 @@ cpln login
126
142
  npm update -g @controlplane/cli
127
143
  ```
128
144
 
129
- 5. Run `cpln image docker-login --org <your-org>` to ensure that you have access to the Control Plane Docker registry.
145
+ 6. Run `cpln image docker-login --org <your-org>` to ensure that you have access to the Control Plane Docker registry.
130
146
 
131
- 6. Install Control Plane Flow `cpflow` CLI as a [Ruby gem](https://rubygems.org/gems/cpflow): `gem install cpflow`. If you want to use `cpflow` from Rake tasks in a Rails project, use `Bundler.with_unbundled_env { `cpflow help` } or else you'll get an error that `cpflow` cannot be found. While you can add `cpflow` to your Gemfile, it's not recommended because it might trigger conflicts with other gems.
147
+ 7. Install Control Plane Flow `cpflow` CLI as a [Ruby gem](https://rubygems.org/gems/cpflow): `gem install cpflow`. If you want to use `cpflow` from Rake tasks in a Rails project, use `Bundler.with_unbundled_env { `cpflow help` } or else you'll get an error that `cpflow` cannot be found. While you can add `cpflow` to your Gemfile, it's not recommended because it might trigger conflicts with other gems.
132
148
 
133
- 7. You can use [this Dockerfile](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/Dockerfile) as an example for your project. Ensure that you have Docker running.
149
+ 8. You will need a production-ready Dockerfile. If you're using Rails, consider the default one that ships with Rails 8. You can use [this Dockerfile](https://github.com/shakacode/rails-v8-kamal-v2-terraform-gcp-tutorial/blob/master/Dockerfile) as an example for your project. Ensure that you have Docker running.
134
150
 
135
151
  **Note:** Do not confuse the `cpflow` CLI with the `cpln` CLI. The `cpflow` CLI is the Control Plane Flow playbook CLI.
136
152
  The `cpln` CLI is the Control Plane CLI.
137
153
 
138
- ## Steps to Migrate
139
-
140
- Click [here](https://www.shakacode.com/control-plane-flow/docs/migrating/) to see the steps to migrate.
141
-
142
154
  ## Configuration Files
143
155
 
144
156
  The `cpflow` gem is based on several configuration files within a `/.controlplane` top-level directory in your project.
@@ -147,20 +159,22 @@ The `cpflow` gem is based on several configuration files within a `/.controlplan
147
159
  .controlplane/
148
160
  ├─ templates/
149
161
  │ ├─ app.yml
150
- │ ├─ postgres.yml
162
+ │ ├─ postgres.yml or db.yml + storage.yml
151
163
  │ ├─ rails.yml
152
164
  ├─ controlplane.yml
153
165
  ├─ Dockerfile
154
166
  ├─ entrypoint.sh
167
+ ├─ release_script.sh
155
168
  ```
156
169
 
157
- 1. `controlplane.yml` describes the overall application. Be sure to have `<your-org>` as the value for `aliases.common.cpln_org`, or set it with the `CPLN_ORG` environment variable.
158
- 2. `Dockerfile` builds the production application. `entrypoint.sh` is an _example_ entrypoint script for the production application, referenced in your Dockerfile.
159
- 3. `templates` directory contains the templates for the various workloads, such as `rails.yml` and `postgres.yml`.
160
- 4. `templates/app.yml` defines your project's GVC (like a Heroku app). More importantly, it contains ENV values for the app.
161
- 5. `templates/rails.yml` defines your Rails workload. It may inherit ENV values from the parent GVC, which is populated from the `templates/app.yml`. This file also configures scaling, sizing, firewalls, and other workload-specific values.
162
- 6. For other workloads (like lines in a Heroku `Procfile`), you create additional template files. For example, you can base a `templates/sidekiq.yml` on the `templates/rails.yml` file.
163
- 7. You can have other files in the `templates` directory, such as `redis.yml` and `postgres.yml`, which could setup Redis and Postgres for a testing application.
170
+ 1. `controlplane.yml` describes the overall application. The generated version includes staging, review, and production entries named from the repo directory, plus `setup_app_templates` and `release_script` defaults. Be sure to update `<your-org>` as the value for `aliases.common.cpln_org`, or set it with the `CPLN_ORG` environment variable.
171
+ 2. `Dockerfile` builds the production application. The generated example includes Node.js, package-manager auto-detection (`npm`, Yarn, or `pnpm`), a Ruby base-image hint derived from `.ruby-version`, `.tool-versions`, or the app's `Gemfile`, and any detected repo-defined asset precompile hook such as a Shakapacker `precompile_hook` or React on Rails auto bundle generation step so Rails apps with frontend assets can precompile from a clean clone. `entrypoint.sh` is an _example_ entrypoint script for the production application, referenced in your Dockerfile.
172
+ 3. `release_script.sh` is the generated release-phase entrypoint used by `cpflow deploy-image --run-release-phase` and `cpflow promote-app-from-upstream --run-release-phase`.
173
+ 4. `templates` directory contains the templates for the various workloads, such as `rails.yml` and either `postgres.yml` or the SQLite `db.yml` and `storage.yml` pair.
174
+ 5. `templates/app.yml` defines your project's GVC (like a Heroku app). More importantly, it contains ENV values for the app.
175
+ 6. `templates/rails.yml` defines your Rails workload. It may inherit ENV values from the parent GVC, which is populated from the `templates/app.yml`. This file also configures scaling, sizing, firewalls, and other workload-specific values.
176
+ 7. For other workloads (like lines in a Heroku `Procfile`), you create additional template files. For example, you can base a `templates/sidekiq.yml` on the `templates/rails.yml` file.
177
+ 8. You can have other files in the `templates` directory, such as `redis.yml`, `postgres.yml`, or SQLite-backed `db.yml` and `storage.yml`, depending on the application runtime.
164
178
 
165
179
  Here's a complete example of all supported config keys explained for the `controlplane.yml` file:
166
180
 
@@ -329,8 +343,25 @@ apps:
329
343
 
330
344
  ## Workflow
331
345
 
346
+ ### Bootstrap a New Repo
347
+
348
+ ```sh
349
+ # Check the repo for common rollout blockers before generating files
350
+ cpflow github-flow-readiness
351
+
352
+ # Create the .controlplane/ scaffolding
353
+ cpflow generate
354
+
355
+ # Create reusable GitHub Actions for review apps, staging, and production promotion
356
+ cpflow generate-github-actions
357
+ ```
358
+
359
+ `cpflow github-flow-readiness` exits non-zero when it finds blockers such as unpublished exact-pinned packages or a missing production Dockerfile, so use it as the gate before generation. Then review the generated `.controlplane/controlplane.yml` entries, adjust any app-specific workloads, and configure the GitHub repository variables and secrets described in [CI automation](./docs/ci-automation.md), including the optional Docker build settings for private GitHub dependencies and custom SSH known hosts. `cpflow generate` already switches to persistent `db` and `storage` volumes when `config/database.yml` shows SQLite in production and preserves detected frontend precompile hooks, but you should still confirm that the generated Dockerfile picked a Ruby base image compatible with the app's declared Ruby requirement and that the emitted workload set matches the real app. If you want an AI agent to do this end to end, start with the [AI rollout prompt](./docs/ai-github-flow-prompt.md) or run `cpflow ai-github-flow-prompt` in the target repo rather than giving a vague "set up CI" request.
360
+
332
361
  For a live example, see the [react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/readme.md) repository.
333
362
 
363
+ You can use this repository as a reference for setting up your own project.
364
+
334
365
  This example should closely match the below example.
335
366
 
336
367
  Suppose your app is called `tutorial-app`. You can run the following commands.
@@ -384,7 +415,7 @@ cpflow build-image -a tutorial-app --commit ABCD
384
415
 
385
416
  ### Real World
386
417
 
387
- Most companies will configure their CI system to handle the above steps. Please [contact Shakacode](mailto:controlplane@shakacode.com) for examples of how to do this.
418
+ Most teams will automate the above steps in CI. Run `cpflow generate-github-actions` to scaffold the GitHub Actions flow, then follow [CI automation](./docs/ci-automation.md) to wire it to your `.controlplane/controlplane.yml` and repository settings.
388
419
 
389
420
  You can also join our [**Slack channel**](https://reactrails.slack.com/join/shared_invite/enQtNjY3NTczMjczNzYxLTlmYjdiZmY3MTVlMzU2YWE0OWM0MzNiZDI0MzdkZGFiZTFkYTFkOGVjODBmOWEyYWQ3MzA2NGE1YWJjNmVlMGE) for ShakaCode open source projects.
390
421
 
data/cpflow.gemspec CHANGED
@@ -13,12 +13,12 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = "https://github.com/shakacode/control-plane-flow"
14
14
  spec.license = "MIT"
15
15
 
16
- spec.required_ruby_version = ">= 2.7.0"
16
+ spec.required_ruby_version = ">= 3.0.0"
17
17
 
18
- spec.add_dependency "dotenv", "~> 2.8.1"
19
- spec.add_dependency "jwt", "~> 2.8.1"
20
- spec.add_dependency "psych", "~> 5.1.0"
21
- spec.add_dependency "thor", "~> 1.2.1"
18
+ spec.add_dependency "dotenv", "~> 3.1"
19
+ spec.add_dependency "jwt", "~> 3.1"
20
+ spec.add_dependency "psych", "~> 5.2"
21
+ spec.add_dependency "thor", "~> 1.4"
22
22
 
23
23
  spec.files = `git ls-files -z`.split("\x0").reject do |file|
24
24
  file.match(%r{^(coverage|pkg|spec|tmp)/})
@@ -0,0 +1,61 @@
1
+ # AI Rollout Prompt for Control Plane GitHub Flow
2
+
3
+ Use this file when you want an AI agent to add the reusable `cpflow` review-app,
4
+ staging, and production-promotion flow to a repository.
5
+
6
+ If `cpflow` is already installed in the target repo, you can print the current
7
+ copy-paste version of this prompt with:
8
+
9
+ ```sh
10
+ cpflow ai-github-flow-prompt
11
+ ```
12
+
13
+ That local-only command works even before `cpln` is installed and fills in the
14
+ repo-name default app prefix for the current checkout. You can also run
15
+ `cpflow github-flow-readiness` first to check the same blocker categories the
16
+ prompt tells the agent to stop on.
17
+
18
+ ## Recommended Prompt
19
+
20
+ ```text
21
+ Set up Control Plane GitHub Flow for this repo. Start with `cpflow github-flow-readiness` and stop on any reported blockers. The repo must be deployable from a clean clone: published package versions, complete runtime scaffold, and a production Dockerfile that can build the app. If any package version is unpublished, inaccessible from CI, or requires credentials that are not already modeled in the repo or GitHub settings, stop and report the blocker instead of generating workflow files. If the repo is a legacy sample pinned to an obsolete Ruby or Bundler toolchain, if it does not even have a production Dockerfile yet, or if it is a monorepo without an already-decided single app boundary for this flow, stop and report that as a prerequisite instead of forcing the rollout.
22
+
23
+ If `.controlplane/` is missing, run `cpflow generate`. Treat the generated app names as the repo-name default and rename them only if the project needs a different prefix. Then run `cpflow generate-github-actions` (or `cpflow generate-github-actions --staging-branch BRANCH` when staging should deploy from a branch other than `main`/`master`), keep review apps opt-in via `/deploy-review-app`, make sure any `STAGING_APP_BRANCH` repository variable is also present in the generated staging workflow's `on.push.branches` filter, and list the GitHub secrets and variables that must be configured.
24
+
25
+ Keep Node available in the final image if asset compilation or SSR depends on ExecJS, Yarn, `pnpm`, or npm after the main install layer. Make sure the generated Dockerfile uses a Ruby base image compatible with the app's declared Ruby requirement. Preserve repo-defined frontend build hooks: if `config/shakapacker.yml` defines a `precompile_hook`, or React on Rails enables `config.auto_load_bundle = true`, confirm the generated Dockerfile runs that codegen step before `rails assets:precompile`. If `config/database.yml` shows SQLite in production, confirm that the generated scaffold uses persistent `db` and `storage` volumes plus a release script that runs `rails db:prepare`; otherwise keep the default Postgres workload. If the public workload is not named `rails`, set `PRIMARY_WORKLOAD` or adjust the generated workflows. Inspect the Dockerfile and package sources for private GitHub dependencies or `RUN --mount=type=ssh`; if present, wire `DOCKER_BUILD_SSH_KEY`, optionally set `DOCKER_BUILD_SSH_KNOWN_HOSTS` for non-GitHub SSH hosts, and keep `DOCKER_BUILD_EXTRA_ARGS` to newline-delimited single tokens such as `--build-arg=FOO=bar`.
26
+
27
+ Run the real local validations you can: Docker build if feasible, repo tests or smoke checks, YAML validation, and any CI-equivalent build steps. Push the branch and check the GitHub Actions results. Only stop early for a real external blocker or a product decision that changes scope.
28
+ ```
29
+
30
+ ## Hard Stop Conditions
31
+
32
+ Stop and report the blocker instead of generating `cpflow-*` workflow files when:
33
+
34
+ - the repo is a partial sample or generator snapshot rather than a deployable app
35
+ - the app depends on unpublished or inaccessible gem or npm package versions
36
+ - the repo is pinned to a legacy Ruby or Bundler toolchain that you cannot validate in the current environment
37
+ - there is no production Dockerfile and the app's production build path is still undefined
38
+ - the repo is a monorepo or contains multiple deployable apps and the flow target is not already decided
39
+ - the local checkout does not match the intended remote repository
40
+ - the app needs product decisions about workload shape, secrets, or promotion behavior that are not already implied by the repo
41
+
42
+ ## Definition of Done
43
+
44
+ The rollout is done when all of the following are true:
45
+
46
+ - `.controlplane/` exists and matches the actual app shape
47
+ - `.github/actions/cpflow-*` and `.github/workflows/cpflow-*` are in place
48
+ - review apps are opt-in, staging auto-deploys from one branch, and production promotion is manual
49
+ - required GitHub secrets and variables are documented for the repo
50
+ - the production image build path is validated for the real app
51
+ - repo-specific runtime concerns are handled, such as SQLite volumes, sidekiq workloads, SSR runtime Node access, React on Rails pack generation hooks, or private dependency fetches
52
+ - the branch is pushed and the relevant GitHub checks are either green or blocked only by an external system failure
53
+
54
+ ## React on Rails Notes
55
+
56
+ For React on Rails and React on Rails Pro apps, explicitly verify:
57
+
58
+ - SSR or renderer workloads do not lose Node or package-manager access in the final image
59
+ - sidecar renderers or worker processes bind to `0.0.0.0`, not container-local `localhost`
60
+ - writable caches, bundle outputs, or SQLite files live in runtime-writable paths
61
+ - old demo repos are treated as legacy exceptions unless they can still build from a clean clone