cpflow 5.0.1 → 5.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -1
- data/Gemfile.lock +1 -1
- data/docs/ai-github-flow-prompt.md +1 -1
- data/docs/ci-automation.md +50 -0
- data/docs/commands.md +1 -1
- data/lib/command/ai_github_flow_prompt.rb +1 -1
- data/lib/command/run.rb +11 -1
- data/lib/command/setup_app.rb +1 -1
- data/lib/cpflow/version.rb +1 -1
- data/lib/generator_templates/Dockerfile +8 -3
- data/lib/generator_templates/templates/app.yml +3 -3
- data/lib/generator_templates/templates/postgres.yml +19 -16
- data/lib/generator_templates/templates/rails.yml +3 -1
- data/lib/generator_templates_sqlite/templates/app.yml +3 -3
- data/lib/generator_templates_sqlite/templates/rails.yml +3 -1
- data/lib/github_flow_templates/.github/cpflow-help.md +20 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f6a3d49d8db4d5df28b82fa8cfb81af3470299d485169997c2904c683b1a56c6
|
|
4
|
+
data.tar.gz: 48cacf78f5d61ca95405b46e152b26547536a3862a06d93433efaa7c52f7f85d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9158740f20c83981417325473f6f9d3b27fee1e0967b31746d44f32d4d6e0dca2d14ab17dfd05d2f27a10a745b33e663cc775c562919fdaa2311e554cddfb2af
|
|
7
|
+
data.tar.gz: c822be6375f28c6c01e13b397f5857fa4d3cd8463cc787cd6dc9be5a6f4967aa17a84af19f4e31c6b565e8325e19286de1c0fa398c22db4966a3f723e7adfb1a
|
data/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,14 @@ In addition to the standard keepachangelog.com categories, this project uses a l
|
|
|
12
12
|
|
|
13
13
|
## [Unreleased]
|
|
14
14
|
|
|
15
|
+
## [5.0.2] - 2026-05-25
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **Fixed generated Dockerfiles so Node package-manager shims (`npm`, `npx`, and `corepack`) remain working symlinks in the final Ruby image instead of broken dereferenced files.** [PR 322](https://github.com/shakacode/control-plane-flow/pull/322) by [Justin Gordon](https://github.com/justin808). Generated Dockerfiles now fail fast if the Node shim paths are no longer valid.
|
|
20
|
+
- **Fixed generated Control Plane templates so app workloads receive app identity links, templated YAML scalars are parseable, and generated Postgres resources/secrets are app-scoped.** [PR 322](https://github.com/shakacode/control-plane-flow/pull/322) by [Justin Gordon](https://github.com/justin808). This lets review apps resolve `cpln://secret/...` values reliably from Rails, worker, renderer, and release jobs.
|
|
21
|
+
- **Fixed `cpflow run` so existing runner workloads stay in sync with the source workload `identityLink`.** [PR 322](https://github.com/shakacode/control-plane-flow/pull/322) by [Justin Gordon](https://github.com/justin808). Existing runner jobs now gain or drop the app identity as the source workload changes.
|
|
22
|
+
|
|
15
23
|
## [5.0.1] - 2026-05-24
|
|
16
24
|
|
|
17
25
|
### Breaking Changes
|
|
@@ -374,7 +382,8 @@ Deprecated `cpl` gem. New gem is `cpflow`.
|
|
|
374
382
|
|
|
375
383
|
First release.
|
|
376
384
|
|
|
377
|
-
[Unreleased]: https://github.com/shakacode/control-plane-flow/compare/v5.0.
|
|
385
|
+
[Unreleased]: https://github.com/shakacode/control-plane-flow/compare/v5.0.2...HEAD
|
|
386
|
+
[5.0.2]: https://github.com/shakacode/control-plane-flow/compare/v5.0.1...v5.0.2
|
|
378
387
|
[5.0.1]: https://github.com/shakacode/control-plane-flow/compare/v5.0.0...v5.0.1
|
|
379
388
|
[5.0.0]: https://github.com/shakacode/control-plane-flow/compare/v5.0.0.rc.3...v5.0.0
|
|
380
389
|
[5.0.0.rc.3]: https://github.com/shakacode/control-plane-flow/compare/v5.0.0.rc.1...v5.0.0.rc.3
|
data/Gemfile.lock
CHANGED
|
@@ -20,7 +20,7 @@ prompt tells the agent to stop on.
|
|
|
20
20
|
```text
|
|
21
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
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 `+review-app-deploy`, 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. Do not hand-edit duplicated upstream refs into the generated wrappers: the only downstream Control Plane Flow pin should be the reusable workflow `uses: ...@vX.Y.Z` value generated from the installed `cpflow` gem version, and upstream workflows load their matching shared actions automatically. Keep the standard path simple: review apps require only `CPLN_TOKEN_STAGING` when the generated review app config can be inferred. For production promotion, document a protected `production` GitHub Environment with required reviewers, prevent self-review, and `CPLN_TOKEN_PRODUCTION` stored as an environment secret, not as a repository or organization secret.
|
|
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 `+review-app-deploy`, 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. Do not hand-edit duplicated upstream refs into the generated wrappers: the only downstream Control Plane Flow pin should be the reusable workflow `uses: ...@vX.Y.Z` value generated from the installed `cpflow` gem version, and upstream workflows load their matching shared actions automatically. Keep the standard path simple: review apps require only `CPLN_TOKEN_STAGING` when the generated review app config can be inferred. Document the one-time Control Plane bootstrap command for persistent staging and production apps with `cpflow setup-app --skip-post-creation-hook`; for existing apps or later template updates, document `cpflow apply-template` and the need for the app identity to have `reveal` on the app secret policy. Do not imply the staging deploy or promotion workflows create those persistent GVCs. For production promotion, document a protected `production` GitHub Environment with required reviewers, prevent self-review, and `CPLN_TOKEN_PRODUCTION` stored as an environment secret, not as a repository or organization secret.
|
|
24
24
|
|
|
25
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
26
|
|
data/docs/ci-automation.md
CHANGED
|
@@ -214,6 +214,56 @@ needs. They do not use `secrets: inherit`; the production token is supplied by
|
|
|
214
214
|
the protected `production` Environment after approval, not forwarded from a
|
|
215
215
|
repository secret.
|
|
216
216
|
|
|
217
|
+
## First-Time Control Plane Bootstrap
|
|
218
|
+
|
|
219
|
+
GitHub settings only give the workflows permission to act. They do not create
|
|
220
|
+
the persistent staging or production GVCs for you on the first merge.
|
|
221
|
+
|
|
222
|
+
Before the first staging deploy, bootstrap the staging app once:
|
|
223
|
+
|
|
224
|
+
```sh
|
|
225
|
+
cpflow setup-app -a my-app-staging --org my-org-staging --skip-post-creation-hook
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
`setup-app` reads the `setup_app_templates` list from
|
|
229
|
+
`.controlplane/controlplane.yml`. It creates the persistent staging GVC,
|
|
230
|
+
workloads, app identity, app secret dictionary, app secret policy, and policy
|
|
231
|
+
binding that grants the app identity `reveal` permission on that dictionary.
|
|
232
|
+
Use `--skip-post-creation-hook` for first-time bootstrap so a database hook does
|
|
233
|
+
not try to run before the first image exists.
|
|
234
|
+
|
|
235
|
+
After the persistent app exists, use `apply-template` for later template
|
|
236
|
+
updates. Adjust the template list to match your repo, such as adding `worker`,
|
|
237
|
+
`sidekiq`, `renderer`, `redis`, or other templates present under
|
|
238
|
+
`.controlplane/templates`:
|
|
239
|
+
|
|
240
|
+
```sh
|
|
241
|
+
cpflow apply-template app postgres rails -a my-app-staging --org my-org-staging --yes --add-app-identity
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
If you use `apply-template` to create or repair an existing app, also confirm
|
|
245
|
+
that the app identity has `reveal` permission on the app secret policy. Without
|
|
246
|
+
that binding, workloads that reference `cpln://secret/<app-secrets>.*` stay
|
|
247
|
+
paused until the policy is fixed.
|
|
248
|
+
|
|
249
|
+
Before the first production promotion, run the same kind of bootstrap for the
|
|
250
|
+
production app in the production org:
|
|
251
|
+
|
|
252
|
+
```sh
|
|
253
|
+
cpflow setup-app -a my-app-production --org my-org-production --skip-post-creation-hook
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Use production-only runtime secrets and values for the production app. The
|
|
257
|
+
protected GitHub Environment controls who can run the promotion workflow, but
|
|
258
|
+
the production app resources still need to exist before the first promotion.
|
|
259
|
+
|
|
260
|
+
Review apps are different: the generated `+review-app-deploy` workflow creates
|
|
261
|
+
temporary PR apps as needed, including the identity and secret policy binding.
|
|
262
|
+
You still need the shared review-app runtime secret values described by your
|
|
263
|
+
templates, and the staging token must have access to create and update
|
|
264
|
+
review-app GVCs, workloads, images, identities, policies, and secrets in the
|
|
265
|
+
staging org.
|
|
266
|
+
|
|
217
267
|
### Production Promotion Safety
|
|
218
268
|
|
|
219
269
|
`CPLN_TOKEN_PRODUCTION` can change live production workloads, images, releases,
|
data/docs/commands.md
CHANGED
|
@@ -503,7 +503,7 @@ cpflow run -a $APP_NAME --entrypoint /app/alternative-entrypoint.sh -- rails db:
|
|
|
503
503
|
|
|
504
504
|
- Creates an app and all its workloads
|
|
505
505
|
- Specify the templates for the app and workloads through `setup_app_templates` in the `.controlplane/controlplane.yml` file
|
|
506
|
-
-
|
|
506
|
+
- Use this for temporary apps like review apps and for first-time bootstrap of persistent staging or production apps; after a persistent app exists, use 'cpflow apply-template' for template updates
|
|
507
507
|
- Configures app to have org-level secrets with default name `"{APP_PREFIX}-secrets"`
|
|
508
508
|
using org-level policy with default name `"{APP_PREFIX}-secrets-policy"` (names can be customized, see docs)
|
|
509
509
|
- Creates identity for secrets if it does not exist
|
|
@@ -32,7 +32,7 @@ module Command
|
|
|
32
32
|
<<~PROMPT
|
|
33
33
|
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.
|
|
34
34
|
|
|
35
|
-
If `.controlplane/` is missing, run `cpflow generate`. Treat the generated app names as the repo-name default (`#{inferred_app_prefix}`) 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 `+review-app-deploy`, 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. Do not hand-edit duplicated upstream refs into the generated wrappers: the only downstream Control Plane Flow pin should be the reusable workflow `uses: ...@vX.Y.Z` value generated from the installed `cpflow` gem version, and upstream workflows load their matching shared actions automatically. Keep the standard path simple: review apps require only `CPLN_TOKEN_STAGING` when the generated review app config can be inferred. For production promotion, document a protected `production` GitHub Environment with required reviewers, prevent self-review, and `CPLN_TOKEN_PRODUCTION` stored as an environment secret, not as a repository or organization secret.
|
|
35
|
+
If `.controlplane/` is missing, run `cpflow generate`. Treat the generated app names as the repo-name default (`#{inferred_app_prefix}`) 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 `+review-app-deploy`, 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. Do not hand-edit duplicated upstream refs into the generated wrappers: the only downstream Control Plane Flow pin should be the reusable workflow `uses: ...@vX.Y.Z` value generated from the installed `cpflow` gem version, and upstream workflows load their matching shared actions automatically. Keep the standard path simple: review apps require only `CPLN_TOKEN_STAGING` when the generated review app config can be inferred. Document the one-time Control Plane bootstrap command for persistent staging and production apps with `cpflow setup-app --skip-post-creation-hook`; for existing apps or later template updates, document `cpflow apply-template` and the need for the app identity to have `reveal` on the app secret policy. Do not imply the staging deploy or promotion workflows create those persistent GVCs. For production promotion, document a protected `production` GitHub Environment with required reviewers, prevent self-review, and `CPLN_TOKEN_PRODUCTION` stored as an environment secret, not as a repository or organization secret.
|
|
36
36
|
|
|
37
37
|
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`.
|
|
38
38
|
|
data/lib/command/run.rb
CHANGED
|
@@ -197,7 +197,7 @@ module Command
|
|
|
197
197
|
spec = nil
|
|
198
198
|
|
|
199
199
|
step("Checking if runner workload '#{runner_workload}' needs to be updated") do # rubocop:disable Metrics/BlockLength
|
|
200
|
-
|
|
200
|
+
original_spec, original_container_spec = base_workload_specs(original_workload)
|
|
201
201
|
spec, container_spec = base_workload_specs(runner_workload)
|
|
202
202
|
|
|
203
203
|
# Keep ENV synced between original and runner workloads
|
|
@@ -208,6 +208,16 @@ module Command
|
|
|
208
208
|
should_update = true
|
|
209
209
|
end
|
|
210
210
|
|
|
211
|
+
# Keep the app identity in sync so runner jobs can resolve GVC-level secrets.
|
|
212
|
+
if spec["identityLink"] != original_spec["identityLink"]
|
|
213
|
+
if original_spec["identityLink"]
|
|
214
|
+
spec["identityLink"] = original_spec["identityLink"]
|
|
215
|
+
else
|
|
216
|
+
spec.delete("identityLink")
|
|
217
|
+
end
|
|
218
|
+
should_update = true
|
|
219
|
+
end
|
|
220
|
+
|
|
211
221
|
if container_spec["image"] != default_image
|
|
212
222
|
container_spec["image"] = default_image
|
|
213
223
|
should_update = true
|
data/lib/command/setup_app.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Command
|
|
|
13
13
|
LONG_DESCRIPTION = <<~DESC
|
|
14
14
|
- Creates an app and all its workloads
|
|
15
15
|
- Specify the templates for the app and workloads through `setup_app_templates` in the `.controlplane/controlplane.yml` file
|
|
16
|
-
-
|
|
16
|
+
- Use this for temporary apps like review apps and for first-time bootstrap of persistent staging or production apps; after a persistent app exists, use 'cpflow apply-template' for template updates
|
|
17
17
|
- Configures app to have org-level secrets with default name `"{APP_PREFIX}-secrets"`
|
|
18
18
|
using org-level policy with default name `"{APP_PREFIX}-secrets-policy"` (names can be customized, see docs)
|
|
19
19
|
- Creates identity for secrets if it does not exist
|
data/lib/cpflow/version.rb
CHANGED
|
@@ -17,12 +17,17 @@ WORKDIR /app
|
|
|
17
17
|
# rely on ExecJS in production. Narrowed to just what the node stage actually
|
|
18
18
|
# ships under /usr/local so we don't drag in unused Debian libs from that image.
|
|
19
19
|
COPY --from=node /usr/local/bin/node /usr/local/bin/node
|
|
20
|
-
COPY --from=node /usr/local/bin/npm /usr/local/bin/npm
|
|
21
|
-
COPY --from=node /usr/local/bin/npx /usr/local/bin/npx
|
|
22
|
-
COPY --from=node /usr/local/bin/corepack /usr/local/bin/corepack
|
|
23
20
|
COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
|
|
24
21
|
COPY --from=node /usr/local/include/node /usr/local/include/node
|
|
25
22
|
|
|
23
|
+
RUN ln -sf ../lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
|
|
24
|
+
ln -sf ../lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx && \
|
|
25
|
+
ln -sf ../lib/node_modules/corepack/dist/corepack.js /usr/local/bin/corepack && \
|
|
26
|
+
chmod +x /usr/local/lib/node_modules/npm/bin/npm-cli.js \
|
|
27
|
+
/usr/local/lib/node_modules/npm/bin/npx-cli.js \
|
|
28
|
+
/usr/local/lib/node_modules/corepack/dist/corepack.js && \
|
|
29
|
+
node --version && npm --version && corepack --version
|
|
30
|
+
|
|
26
31
|
# Expose Corepack-managed shims so later build steps can call yarn/pnpm
|
|
27
32
|
# directly during asset precompilation hooks.
|
|
28
33
|
RUN printf '%s\n' '#!/bin/sh' 'exec corepack yarn "$@"' > /usr/bin/yarn && \
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Template setup of the GVC, roughly corresponding to a Heroku app
|
|
2
2
|
kind: gvc
|
|
3
|
-
name: {{APP_NAME}}
|
|
3
|
+
name: "{{APP_NAME}}"
|
|
4
4
|
spec:
|
|
5
5
|
env:
|
|
6
6
|
- name: DATABASE_URL
|
|
@@ -12,7 +12,7 @@ spec:
|
|
|
12
12
|
- name: RAILS_SERVE_STATIC_FILES
|
|
13
13
|
value: "true"
|
|
14
14
|
- name: SECRET_KEY_BASE
|
|
15
|
-
value: cpln://secret/{{APP_SECRETS}}.SECRET_KEY_BASE
|
|
15
|
+
value: "cpln://secret/{{APP_SECRETS}}.SECRET_KEY_BASE"
|
|
16
16
|
staticPlacement:
|
|
17
17
|
locationLinks:
|
|
18
|
-
- {{APP_LOCATION_LINK}}
|
|
18
|
+
- "{{APP_LOCATION_LINK}}"
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
# https://github.com/controlplane-com/examples/blob/main/examples/postgres/manifest.yaml
|
|
3
3
|
|
|
4
4
|
kind: volumeset
|
|
5
|
-
name:
|
|
6
|
-
description:
|
|
5
|
+
name: "{{APP_NAME}}-pg-vs"
|
|
6
|
+
description: "{{APP_NAME}}-pg-vs"
|
|
7
7
|
spec:
|
|
8
8
|
autoscaling:
|
|
9
9
|
maxCapacity: 1000
|
|
@@ -18,7 +18,7 @@ spec:
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
kind: secret
|
|
21
|
-
name:
|
|
21
|
+
name: "{{APP_NAME}}-pg"
|
|
22
22
|
description: ''
|
|
23
23
|
type: dictionary
|
|
24
24
|
data:
|
|
@@ -27,7 +27,7 @@ data:
|
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
kind: secret
|
|
30
|
-
name:
|
|
30
|
+
name: "{{APP_NAME}}-pg-script"
|
|
31
31
|
type: opaque
|
|
32
32
|
data:
|
|
33
33
|
encoding: base64
|
|
@@ -92,13 +92,13 @@ data:
|
|
|
92
92
|
|
|
93
93
|
---
|
|
94
94
|
kind: identity
|
|
95
|
-
name:
|
|
96
|
-
description:
|
|
95
|
+
name: "{{APP_NAME}}-pg-identity"
|
|
96
|
+
description: "{{APP_NAME}}-pg-identity"
|
|
97
97
|
|
|
98
98
|
---
|
|
99
99
|
kind: policy
|
|
100
|
-
name:
|
|
101
|
-
description:
|
|
100
|
+
name: "{{APP_NAME}}-pg-access"
|
|
101
|
+
description: "{{APP_NAME}}-pg-access"
|
|
102
102
|
bindings:
|
|
103
103
|
- permissions:
|
|
104
104
|
- reveal
|
|
@@ -106,11 +106,14 @@ bindings:
|
|
|
106
106
|
# - use
|
|
107
107
|
# - view
|
|
108
108
|
principalLinks:
|
|
109
|
-
- //gvc/{{APP_NAME}}/identity/
|
|
109
|
+
- "//gvc/{{APP_NAME}}/identity/{{APP_NAME}}-pg-identity"
|
|
110
|
+
# cpflow apply-template replaces {{APP_IDENTITY_LINK}} with the full app workload identity link.
|
|
111
|
+
# Example: //gvc/{{APP_NAME}}/identity/{{APP_NAME}}-identity.
|
|
112
|
+
- "{{APP_IDENTITY_LINK}}"
|
|
110
113
|
targetKind: secret
|
|
111
114
|
targetLinks:
|
|
112
|
-
- //secret/
|
|
113
|
-
- //secret/
|
|
115
|
+
- "//secret/{{APP_NAME}}-pg"
|
|
116
|
+
- "//secret/{{APP_NAME}}-pg-script"
|
|
114
117
|
|
|
115
118
|
---
|
|
116
119
|
kind: workload
|
|
@@ -130,9 +133,9 @@ spec:
|
|
|
130
133
|
- name: PGDATA #The location postgres stores the db. This can be anything other than /var/lib/postgresql/data, but it must be inside the mount point for the volume set
|
|
131
134
|
value: "/var/lib/postgresql/data/pg_data"
|
|
132
135
|
- name: POSTGRES_PASSWORD #The password for the default user
|
|
133
|
-
value: cpln://secret/
|
|
136
|
+
value: "cpln://secret/{{APP_NAME}}-pg.password"
|
|
134
137
|
- name: POSTGRES_USER #The name of the default user
|
|
135
|
-
value: cpln://secret/
|
|
138
|
+
value: "cpln://secret/{{APP_NAME}}-pg.username"
|
|
136
139
|
name: postgres
|
|
137
140
|
image: postgres:15
|
|
138
141
|
command: /bin/bash
|
|
@@ -146,10 +149,10 @@ spec:
|
|
|
146
149
|
- number: 5432
|
|
147
150
|
protocol: tcp
|
|
148
151
|
volumes:
|
|
149
|
-
- uri: cpln://volumeset/
|
|
152
|
+
- uri: "cpln://volumeset/{{APP_NAME}}-pg-vs"
|
|
150
153
|
path: "/var/lib/postgresql/data"
|
|
151
154
|
# Make the ENV value for the entry script a file
|
|
152
|
-
- uri: cpln://secret/
|
|
155
|
+
- uri: "cpln://secret/{{APP_NAME}}-pg-script"
|
|
153
156
|
path: "/usr/local/bin/cpln-entrypoint.sh"
|
|
154
157
|
inheritEnv: false
|
|
155
158
|
livenessProbe:
|
|
@@ -160,7 +163,7 @@ spec:
|
|
|
160
163
|
tcpSocket:
|
|
161
164
|
port: 5432
|
|
162
165
|
failureThreshold: 1
|
|
163
|
-
identityLink: //identity/
|
|
166
|
+
identityLink: "//identity/{{APP_NAME}}-pg-identity"
|
|
164
167
|
defaultOptions:
|
|
165
168
|
capacityAI: false
|
|
166
169
|
autoscaling:
|
|
@@ -8,7 +8,7 @@ spec:
|
|
|
8
8
|
- name: rails
|
|
9
9
|
cpu: 300m
|
|
10
10
|
inheritEnv: true
|
|
11
|
-
image: {{APP_IMAGE_LINK}}
|
|
11
|
+
image: "{{APP_IMAGE_LINK}}"
|
|
12
12
|
memory: 512Mi
|
|
13
13
|
ports:
|
|
14
14
|
- number: 3000
|
|
@@ -29,3 +29,5 @@ spec:
|
|
|
29
29
|
- 0.0.0.0/0
|
|
30
30
|
outboundAllowCIDR:
|
|
31
31
|
- 0.0.0.0/0
|
|
32
|
+
# cpflow apply-template replaces {{APP_IDENTITY_LINK}} with the app workload identity link.
|
|
33
|
+
identityLink: "{{APP_IDENTITY_LINK}}"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
kind: gvc
|
|
2
|
-
name: {{APP_NAME}}
|
|
2
|
+
name: "{{APP_NAME}}"
|
|
3
3
|
spec:
|
|
4
4
|
env:
|
|
5
5
|
- name: RAILS_ENV
|
|
@@ -9,7 +9,7 @@ spec:
|
|
|
9
9
|
- name: RAILS_SERVE_STATIC_FILES
|
|
10
10
|
value: "true"
|
|
11
11
|
- name: SECRET_KEY_BASE
|
|
12
|
-
value: cpln://secret/{{APP_SECRETS}}.SECRET_KEY_BASE
|
|
12
|
+
value: "cpln://secret/{{APP_SECRETS}}.SECRET_KEY_BASE"
|
|
13
13
|
staticPlacement:
|
|
14
14
|
locationLinks:
|
|
15
|
-
- {{APP_LOCATION_LINK}}
|
|
15
|
+
- "{{APP_LOCATION_LINK}}"
|
|
@@ -6,7 +6,7 @@ spec:
|
|
|
6
6
|
- name: rails
|
|
7
7
|
cpu: 300m
|
|
8
8
|
inheritEnv: true
|
|
9
|
-
image: {{APP_IMAGE_LINK}}
|
|
9
|
+
image: "{{APP_IMAGE_LINK}}"
|
|
10
10
|
memory: 512Mi
|
|
11
11
|
ports:
|
|
12
12
|
- number: 3000
|
|
@@ -34,3 +34,5 @@ spec:
|
|
|
34
34
|
- 0.0.0.0/0
|
|
35
35
|
outboundAllowCIDR:
|
|
36
36
|
- 0.0.0.0/0
|
|
37
|
+
# cpflow apply-template replaces {{APP_IDENTITY_LINK}} with the app workload identity link.
|
|
38
|
+
identityLink: "{{APP_IDENTITY_LINK}}"
|
|
@@ -39,6 +39,23 @@ Optional overrides exist for forks, clones, and unusual apps:
|
|
|
39
39
|
## Staging And Production
|
|
40
40
|
|
|
41
41
|
Staging deploys use the same `CPLN_TOKEN_STAGING` secret plus `STAGING_APP_NAME`.
|
|
42
|
+
Before the first staging deploy, bootstrap the persistent staging app once:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
cpflow setup-app -a "$STAGING_APP_NAME" --org "$CPLN_ORG_STAGING" --skip-post-creation-hook
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`setup-app` reads `.controlplane/controlplane.yml`'s `setup_app_templates` and
|
|
49
|
+
creates the app identity, app secret dictionary, app secret policy, policy
|
|
50
|
+
binding, and template resources. Use `--skip-post-creation-hook` so first-time
|
|
51
|
+
bootstrap does not try to run database setup before an image exists. For later
|
|
52
|
+
template updates on an existing persistent app, use `cpflow apply-template`
|
|
53
|
+
with the same template list and make sure the app identity has `reveal`
|
|
54
|
+
permission on the app secret policy.
|
|
55
|
+
|
|
56
|
+
Review apps are temporary and are created by the `+review-app-deploy` workflow,
|
|
57
|
+
but staging and production are persistent apps and should be bootstrapped
|
|
58
|
+
explicitly.
|
|
42
59
|
|
|
43
60
|
Production promotion is part of the generated flow, but keep it protected:
|
|
44
61
|
|
|
@@ -53,6 +70,9 @@ prevent self-review. The generated promotion wrapper passes only the staging
|
|
|
53
70
|
token from repository secrets; GitHub injects `CPLN_TOKEN_PRODUCTION` only after
|
|
54
71
|
the environment approval gate passes.
|
|
55
72
|
|
|
73
|
+
Before the first promotion, bootstrap the production app the same way in the
|
|
74
|
+
production org, using production-only secrets and values.
|
|
75
|
+
|
|
56
76
|
## Version Locking
|
|
57
77
|
|
|
58
78
|
Generated wrappers pin Control Plane Flow once with the reusable workflow
|