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.
- checksums.yaml +4 -4
- data/.claude/commands/update-changelog.md +367 -0
- data/.github/workflows/claude-code-review.yml +44 -0
- data/.github/workflows/claude.yml +55 -0
- data/.gitignore +2 -0
- data/.overcommit.yml +43 -3
- data/.rubocop.yml +3 -3
- data/CHANGELOG.md +39 -3
- data/CONTRIBUTING.md +6 -0
- data/Gemfile +8 -7
- data/Gemfile.lock +93 -73
- data/README.md +53 -22
- data/cpflow.gemspec +5 -5
- data/docs/ai-github-flow-prompt.md +61 -0
- data/docs/ci-automation.md +335 -0
- data/docs/commands.md +70 -5
- data/docs/releasing.md +153 -0
- data/lib/command/ai_github_flow_prompt.rb +47 -0
- data/lib/command/base.rb +14 -0
- data/lib/command/cleanup_images.rb +1 -1
- data/lib/command/cleanup_stale_apps.rb +1 -1
- data/lib/command/copy_image_from_upstream.rb +14 -3
- data/lib/command/exists.rb +13 -2
- data/lib/command/generate.rb +153 -4
- data/lib/command/generate_github_actions.rb +170 -0
- data/lib/command/generator_helpers.rb +31 -0
- data/lib/command/github_flow_readiness.rb +37 -0
- data/lib/command/ps_wait.rb +5 -1
- data/lib/command/run.rb +4 -21
- data/lib/command/terraform/generate.rb +1 -0
- data/lib/command/version.rb +1 -0
- data/lib/constants/exit_code.rb +1 -0
- data/lib/core/config.rb +1 -1
- data/lib/core/controlplane.rb +13 -10
- data/lib/core/controlplane_api_direct.rb +25 -3
- data/lib/core/github_flow_readiness/checks.rb +143 -0
- data/lib/core/github_flow_readiness_service.rb +453 -0
- data/lib/core/repo_introspection.rb +118 -0
- data/lib/core/terraform_config/dsl.rb +1 -1
- data/lib/core/terraform_config/local_variable.rb +1 -1
- data/lib/cpflow/version.rb +1 -1
- data/lib/cpflow.rb +66 -3
- data/lib/generator_templates/Dockerfile +59 -3
- data/lib/generator_templates/controlplane.yml +27 -39
- data/lib/generator_templates/entrypoint.sh +1 -1
- data/lib/generator_templates/release_script.sh +23 -0
- data/lib/generator_templates/templates/app.yml +5 -8
- data/lib/generator_templates/templates/rails.yml +2 -11
- data/lib/generator_templates_sqlite/controlplane.yml +46 -0
- data/lib/generator_templates_sqlite/release_script.sh +25 -0
- data/lib/generator_templates_sqlite/templates/app.yml +15 -0
- data/lib/generator_templates_sqlite/templates/db.yml +6 -0
- data/lib/generator_templates_sqlite/templates/rails.yml +32 -0
- data/lib/generator_templates_sqlite/templates/storage.yml +6 -0
- data/lib/github_flow_templates/.github/actions/cpflow-build-docker-image/action.yml +131 -0
- data/lib/github_flow_templates/.github/actions/cpflow-delete-control-plane-app/action.yml +24 -0
- data/lib/github_flow_templates/.github/actions/cpflow-delete-control-plane-app/delete-app.sh +50 -0
- data/lib/github_flow_templates/.github/actions/cpflow-detect-release-phase/action.yml +62 -0
- data/lib/github_flow_templates/.github/actions/cpflow-setup-environment/action.yml +98 -0
- data/lib/github_flow_templates/.github/actions/cpflow-validate-config/action.yml +85 -0
- data/lib/github_flow_templates/.github/actions/cpflow-wait-for-health/action.yml +92 -0
- data/lib/github_flow_templates/.github/cpflow-help.md +47 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-cleanup-stale-review-apps.yml +56 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-delete-review-app.yml +142 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-deploy-review-app.yml +445 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-deploy-staging.yml +140 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-help-command.yml +53 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-promote-staging-to-production.yml +490 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-review-app-help.yml +46 -0
- data/rakelib/create_release.rake +662 -37
- data/script/check_command_docs +4 -2
- data/script/check_cpln_links +25 -11
- data/script/precommit/check_command_docs +22 -0
- data/script/precommit/check_cpln_links +21 -0
- data/script/precommit/check_trailing_newlines +68 -0
- data/script/precommit/get_changed_files +49 -0
- data/script/precommit/ruby_autofix +52 -0
- data/script/precommit/ruby_lint +33 -0
- metadata +56 -15
- /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 (
|
|
5
|
-
dotenv (~>
|
|
6
|
-
jwt (~>
|
|
7
|
-
psych (~> 5.
|
|
8
|
-
thor (~> 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.
|
|
14
|
-
public_suffix (>= 2.0.2, <
|
|
15
|
-
ast (2.4.
|
|
16
|
-
base64 (0.
|
|
17
|
-
bigdecimal (
|
|
18
|
-
childprocess (
|
|
19
|
-
|
|
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
|
-
|
|
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.
|
|
26
|
-
docile (1.4.
|
|
27
|
-
dotenv (2.
|
|
28
|
-
|
|
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.
|
|
31
|
-
irb (1.
|
|
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.
|
|
35
|
-
jwt (
|
|
40
|
+
json (2.19.3)
|
|
41
|
+
jwt (3.1.2)
|
|
36
42
|
base64
|
|
37
|
-
language_server-protocol (3.17.0.
|
|
38
|
-
|
|
39
|
-
|
|
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 (
|
|
42
|
-
parallel (1.
|
|
43
|
-
parser (3.3.
|
|
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
|
-
|
|
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 (
|
|
49
|
-
racc (1.8.
|
|
61
|
+
public_suffix (7.0.5)
|
|
62
|
+
racc (1.8.1)
|
|
50
63
|
rainbow (3.1.1)
|
|
51
|
-
rake (13.
|
|
52
|
-
rdoc (
|
|
64
|
+
rake (13.3.1)
|
|
65
|
+
rdoc (7.2.0)
|
|
66
|
+
erb
|
|
53
67
|
psych (>= 4.0.0)
|
|
54
|
-
|
|
55
|
-
|
|
68
|
+
tsort
|
|
69
|
+
regexp_parser (2.11.3)
|
|
70
|
+
reline (0.6.3)
|
|
56
71
|
io-console (~> 0.5)
|
|
57
|
-
rexml (3.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
rspec-
|
|
61
|
-
rspec-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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.
|
|
68
|
-
rspec-mocks (3.
|
|
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.
|
|
84
|
+
rspec-support (~> 3.13.0)
|
|
71
85
|
rspec-retry (0.6.2)
|
|
72
86
|
rspec-core (> 3.3)
|
|
73
|
-
rspec-support (3.
|
|
74
|
-
rubocop (1.
|
|
87
|
+
rspec-support (3.13.7)
|
|
88
|
+
rubocop (1.86.0)
|
|
75
89
|
json (~> 2.3)
|
|
76
|
-
language_server-protocol (
|
|
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 (>=
|
|
81
|
-
|
|
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, <
|
|
85
|
-
rubocop-ast (1.
|
|
86
|
-
parser (>= 3.3.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
rubocop (
|
|
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.
|
|
113
|
+
simplecov-html (0.13.2)
|
|
97
114
|
simplecov_json_formatter (0.1.4)
|
|
98
|
-
stringio (3.
|
|
99
|
-
|
|
100
|
-
thor (1.2.2)
|
|
115
|
+
stringio (3.2.0)
|
|
116
|
+
thor (1.5.0)
|
|
101
117
|
timecop (0.9.10)
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
|
|
134
|
+
gem-release (~> 2.2)
|
|
135
|
+
overcommit (~> 0.69.0)
|
|
116
136
|
rake (~> 13.0)
|
|
117
|
-
rspec (~> 3.
|
|
137
|
+
rspec (~> 3.13)
|
|
118
138
|
rspec-retry (~> 0.6.2)
|
|
119
|
-
rubocop (~> 1.
|
|
120
|
-
rubocop-rake (~> 0.
|
|
121
|
-
rubocop-rspec (~> 3.
|
|
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.
|
|
124
|
-
webmock (~> 3.
|
|
143
|
+
timecop (~> 0.9.10)
|
|
144
|
+
webmock (~> 3.26)
|
|
125
145
|
|
|
126
146
|
BUNDLED WITH
|
|
127
|
-
|
|
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
|
-
|
|
25
|
+
To bootstrap a new project, run three commands from the repo root:
|
|
26
26
|
|
|
27
|
-
|
|
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
|
|
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
|
-
##
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
158
|
-
2. `Dockerfile` builds the production application. `entrypoint.sh` is an _example_ entrypoint script for the production application, referenced in your Dockerfile.
|
|
159
|
-
3. `
|
|
160
|
-
4. `templates
|
|
161
|
-
5. `templates/
|
|
162
|
-
6.
|
|
163
|
-
7.
|
|
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
|
|
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 = ">=
|
|
16
|
+
spec.required_ruby_version = ">= 3.0.0"
|
|
17
17
|
|
|
18
|
-
spec.add_dependency "dotenv", "~>
|
|
19
|
-
spec.add_dependency "jwt", "~>
|
|
20
|
-
spec.add_dependency "psych", "~> 5.
|
|
21
|
-
spec.add_dependency "thor", "~> 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
|