cpflow 6.0.0.rc.0 → 6.0.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/.agents/agent-workflow.yml +16 -38
- data/.agents/bin/README.md +7 -8
- data/.agents/legacy-workflow-policy.yml +11 -0
- data/.agents/shaka.md +20 -0
- data/.agents/trusted-actions.yml +12 -0
- data/.coderabbit.yaml +1 -0
- data/.github/actions/cpflow-build-docker-image/action.yml +153 -22
- data/.github/actions/cpflow-delete-control-plane-app/delete-app.sh +3 -0
- data/.github/actions/cpflow-preview-promotion/action.yml +82 -0
- data/.github/actions/cpflow-preview-promotion/preview-promotion.sh +90 -0
- data/.github/workflows/cpflow-deploy-review-app.yml +13 -1
- data/.github/workflows/cpflow-deploy-staging.yml +12 -1
- data/.github/workflows/cpflow-promote-staging-to-production.yml +128 -9
- data/.github/workflows/rspec.yml +24 -0
- data/AGENTS.md +18 -3
- data/CHANGELOG.md +18 -3
- data/CONTRIBUTING.md +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +5 -2
- data/docs/ai-github-flow-prompt.md +2 -2
- data/docs/ci-automation.md +178 -14
- data/docs/commands.md +26 -13
- data/docs/postgres-review-apps.md +90 -0
- data/docs/postgres.md +233 -375
- data/docs/secrets-and-env-values.md +42 -0
- data/docs/sidebars.ts +1 -0
- data/lib/command/ai_github_flow_prompt.rb +2 -2
- data/lib/command/apply_template.rb +36 -4
- data/lib/command/base.rb +56 -3
- data/lib/command/delete.rb +174 -4
- data/lib/command/deploy_image.rb +6 -0
- data/lib/command/generate.rb +247 -3
- data/lib/command/generate_github_actions.rb +7 -1
- data/lib/command/setup_app.rb +92 -10
- data/lib/command/update_github_actions.rb +81 -43
- data/lib/core/config.rb +73 -0
- data/lib/core/controlplane.rb +22 -2
- data/lib/core/controlplane_api.rb +28 -2
- data/lib/core/controlplane_api_direct.rb +17 -0
- data/lib/core/disposable_postgres_helpers.rb +167 -0
- data/lib/core/doctor_service.rb +7 -0
- data/lib/core/github_flow_readiness/checks.rb +2 -1
- data/lib/core/github_flow_readiness_service.rb +4 -0
- data/lib/core/repo_introspection.rb +112 -2
- data/lib/cpflow/version.rb +1 -1
- data/lib/generator_templates/.dockerignore +16 -0
- data/lib/generator_templates/Dockerfile +9 -5
- data/lib/generator_templates/entrypoint.sh +2 -0
- data/lib/generator_templates/templates/postgres.yml +9 -0
- data/lib/generator_templates_sqlite/controlplane.yml +2 -1
- data/lib/generator_templates_sqlite/release_script.sh +1 -1
- data/lib/generator_templates_sqlite/templates/rails.yml +2 -1
- data/lib/github_flow_templates/.github/cpflow-help.md +39 -12
- data/lib/github_flow_templates/.github/workflows/cpflow-deploy-review-app.yml +1 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-deploy-staging.yml +1 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-promote-staging-to-production.yml +128 -9
- data/lib/github_flow_templates/bin/pin-cpflow-github-ref +37 -13
- data/lib/github_flow_templates/bin/test-cpflow-github-flow +62 -43
- metadata +11 -3
data/docs/ci-automation.md
CHANGED
|
@@ -77,7 +77,7 @@ The second command writes namespaced files so they can coexist with an app's exi
|
|
|
77
77
|
Docker base Ruby version from `.ruby-version`, `.tool-versions`, or the app's
|
|
78
78
|
`Gemfile`, preserves repo-defined frontend precompile hooks such as Shakapacker
|
|
79
79
|
`precompile_hook` commands or React on Rails auto bundle generation, and
|
|
80
|
-
switches to persistent SQLite
|
|
80
|
+
switches to persistent SQLite data and Active Storage templates when
|
|
81
81
|
`config/database.yml` shows SQLite in production.
|
|
82
82
|
|
|
83
83
|
`cpflow github-flow-readiness` checks public RubyGems and npm registry metadata
|
|
@@ -230,14 +230,75 @@ because they could change the target org name after normalization.
|
|
|
230
230
|
|
|
231
231
|
Production promotion copies the exact image currently deployed on the selected
|
|
232
232
|
staging workload. If that staging image is digest-pinned, the digest is used for
|
|
233
|
-
the source copy while the production tag is derived from the tag portion.
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
the source copy while the production tag is derived from the tag portion. Staging tags must
|
|
234
|
+
include a full lowercase 40-character Git commit SHA suffix (`_<commit>`),
|
|
235
|
+
which is preserved in the new production tag. A staging image without that
|
|
236
|
+
provenance stops promotion before approval. The copy step uses
|
|
236
237
|
`docker buildx imagetools create --prefer-index=false --tag` with isolated
|
|
237
238
|
Docker credentials, which preserves multi-architecture manifests, preserves
|
|
238
239
|
single-platform manifest format when supported, and avoids pulling image layers
|
|
239
240
|
onto the GitHub Actions runner.
|
|
240
241
|
|
|
242
|
+
When you start production promotion, the **preview-promotion** job finishes
|
|
243
|
+
before GitHub requests approval for the protected production Environment. Open
|
|
244
|
+
the run summary’s **Commits ready for production** section before approving. It
|
|
245
|
+
compares staging’s deployed primary-workload image with the last recorded
|
|
246
|
+
successful `production-*` GitHub release. It links the full comparison, lists up
|
|
247
|
+
to 100 commit subjects, and flags diverged history or staging behind production.
|
|
248
|
+
Matching SHAs report no commits to promote. Release discovery checks the latest
|
|
249
|
+
100 releases; missing production history or GitHub API failures produce an
|
|
250
|
+
explicit availability notice. The preview uses the existing staging token and
|
|
251
|
+
GitHub `contents: read` permission; it has no production token.
|
|
252
|
+
|
|
253
|
+
The preview selects the primary workload from the staging app’s
|
|
254
|
+
`app_workloads` configuration. `PRODUCTION_APP_NAME` and
|
|
255
|
+
`CPLN_ORG_PRODUCTION` can remain production Environment variables. When staging
|
|
256
|
+
and production have different primary-workload defaults, set `PRIMARY_WORKLOAD`
|
|
257
|
+
as a repository variable shared by both jobs; the protected job rejects a
|
|
258
|
+
workload-selection mismatch. A Control Plane read failure or invalid staging
|
|
259
|
+
SHA fails the preview and prevents approval from starting.
|
|
260
|
+
|
|
261
|
+
After approval, the protected job checks that staging still uses the captured
|
|
262
|
+
image and, when a release baseline was available, that live production matches
|
|
263
|
+
that release’s commit. A mismatch stops before copying or deploying an image;
|
|
264
|
+
rerun after staging changes, or reconcile the production release record after an
|
|
265
|
+
out-of-band production deployment. If production history was unavailable, the
|
|
266
|
+
summary does not claim to know the production-to-staging diff.
|
|
267
|
+
|
|
268
|
+
Existing repositories adopt this with
|
|
269
|
+
`cpflow update-github-actions --workflows cpflow-promote-staging-to-production.yml`.
|
|
270
|
+
Review and reapply downstream workflow customizations before committing the
|
|
271
|
+
replacement and the refreshed local composite actions. The bare update command
|
|
272
|
+
preserves existing top-level workflows.
|
|
273
|
+
|
|
274
|
+
### Recover a missing or stale production release record
|
|
275
|
+
|
|
276
|
+
A successful production deployment and its GitHub release are separate jobs.
|
|
277
|
+
If deployment succeeded but **create-github-release** failed, open that original
|
|
278
|
+
Actions run and choose **Re-run failed jobs**. This retries release publication
|
|
279
|
+
at the original promoted SHA; do not rerun the whole promotion merely to repair
|
|
280
|
+
the record. Confirm the resulting `production-*` release targets the live
|
|
281
|
+
production image’s SHA, then start a fresh promotion preview.
|
|
282
|
+
|
|
283
|
+
After an out-of-band production deploy or rollback, an app maintainer should
|
|
284
|
+
first verify the healthy live primary-workload image and its full commit suffix
|
|
285
|
+
with `cpln workload get <primary-workload> --gvc <production-app> --org
|
|
286
|
+
<production-org> -o json`. Use that SHA to publish a fresh release record; do not
|
|
287
|
+
move an existing release tag. For example, after replacing `<verified-live-sha>`:
|
|
288
|
+
|
|
289
|
+
```sh
|
|
290
|
+
gh release create "production-$(date -u +%Y-%m-%d-%H%M%S)-0" \
|
|
291
|
+
--target <verified-live-sha> \
|
|
292
|
+
--title "Production state reconciliation" \
|
|
293
|
+
--notes "Records the verified live production commit after a manual deployment or rollback."
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Run this in the app repository with the maintainer’s normal GitHub credentials.
|
|
297
|
+
Verify the new tag’s commit and the live image agree, then rerun promotion to
|
|
298
|
+
produce a fresh preview. If the live image has no commit suffix, establish its
|
|
299
|
+
provenance and use a traceable image before recording a baseline; guessing a
|
|
300
|
+
branch head would make the comparison misleading.
|
|
301
|
+
|
|
241
302
|
Before copying the image, production promotion compares the environment variable
|
|
242
303
|
names exposed by staging and production at both the GVC level and each configured
|
|
243
304
|
app workload's container level. Variables present in staging are treated as
|
|
@@ -425,9 +486,11 @@ Recommended org layout:
|
|
|
425
486
|
review/staging CI operations; use a dedicated review-app org only if you also customize the generated
|
|
426
487
|
workflow/configuration to target that org separately
|
|
427
488
|
|
|
428
|
-
Optional repository
|
|
489
|
+
Optional repository secrets for Docker builds:
|
|
429
490
|
|
|
430
491
|
- `DOCKER_BUILD_SSH_KEY`: private SSH key used when the Dockerfile needs `RUN --mount=type=ssh` to fetch private GitHub dependencies during image build
|
|
492
|
+
- `DOCKER_BUILD_SECRETS`: staging build credentials as newline-delimited `id=value` entries supplied through BuildKit secret mounts. Values must be single-line; spaces and additional `=` characters are preserved. IDs may contain letters, digits, underscores, and hyphens, and must start with a letter or digit. Empty values and duplicate IDs are rejected. Leave this secret unset when the build does not need credentials.
|
|
493
|
+
- `REVIEW_APP_DOCKER_BUILD_SECRETS`: separate credentials for review-app builds, using the same format. The generated review-app caller uses only this secret; it does not fall back to `DOCKER_BUILD_SECRETS`. Leave it unset to supply no BuildKit secrets to review apps.
|
|
431
494
|
|
|
432
495
|
Optional repository variables for private dependency builds:
|
|
433
496
|
|
|
@@ -570,6 +633,30 @@ The generated `cpflow-build-docker-image` action supports this without hardcodin
|
|
|
570
633
|
- set `DOCKER_BUILD_SSH_KEY` if the Docker build needs SSH access to GitHub
|
|
571
634
|
- optionally set `DOCKER_BUILD_SSH_KNOWN_HOSTS` when the SSH build host is not GitHub.com or you need custom host entries
|
|
572
635
|
- set `DOCKER_BUILD_EXTRA_ARGS` when you need extra `docker build` flags
|
|
636
|
+
- set `DOCKER_BUILD_SECRETS` for staging builds that need credentials such as a private package token or a source-map upload token
|
|
637
|
+
- set `REVIEW_APP_DOCKER_BUILD_SECRETS` separately if review-app builds need credentials
|
|
638
|
+
|
|
639
|
+
For example, store the following as the **value** of the `DOCKER_BUILD_SECRETS` GitHub Actions secret:
|
|
640
|
+
|
|
641
|
+
```text
|
|
642
|
+
sentry_auth_token=<source-map upload token>
|
|
643
|
+
npm_token=<private package token>
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
The generated staging caller forwards `DOCKER_BUILD_SECRETS`. The review-app caller forwards `REVIEW_APP_DOCKER_BUILD_SECRETS`, the only build-secret parameter the reusable review-app workflow accepts, so review builds never receive the staging secret. The build action writes each value to a private temporary file, passes only its path through `--secret=id=...,src=...`, and removes the files on success or failure. Values are not passed as build arguments or persisted through `GITHUB_ENV`.
|
|
647
|
+
|
|
648
|
+
A Dockerfile can consume a token only for the command that needs it:
|
|
649
|
+
|
|
650
|
+
```dockerfile
|
|
651
|
+
# syntax=docker/dockerfile:1
|
|
652
|
+
ARG SENTRY_UPLOAD=false
|
|
653
|
+
RUN --mount=type=secret,id=sentry_auth_token,env=SENTRY_AUTH_TOKEN \
|
|
654
|
+
SENTRY_UPLOAD=${SENTRY_UPLOAD} npm run build
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
If the application's build requires an explicit upload opt-in, pass `docker_build_extra_args: --build-arg=SENTRY_UPLOAD=true` in the caller workflow's `with` block, or add that token to `DOCKER_BUILD_EXTRA_ARGS`. The optional workflow input is appended after the repository variable, retaining existing build arguments. Token availability alone need not enable uploads. BuildKit secret values do not invalidate build caches; force the relevant build step to run again when rotating a credential requires repeating an upload.
|
|
658
|
+
|
|
659
|
+
Every secret supplied to a review build is accessible to the PR-controlled Dockerfile, which can read and transmit it. Automatic rebuilds of an existing review app also receive these secrets; approval to create the app does not approve later commits. Configure only credentials whose access can be entrusted to anyone able to change the deployed branch, scoped to the minimum review-build permissions. Separate secret names reduce accidental sharing but do not prevent the Dockerfile from accessing supplied credentials. If a credential cannot be entrusted to branch authors, omit it from review builds or use a customized approval gate that approves each deployed commit. Apply the review-app security guidance above.
|
|
573
660
|
|
|
574
661
|
For example, a repo that installs private dependencies from GitHub during Docker build can set:
|
|
575
662
|
|
|
@@ -797,11 +884,88 @@ bundle exec cpflow update-github-actions
|
|
|
797
884
|
bin/test-cpflow-github-flow bundle exec cpflow
|
|
798
885
|
```
|
|
799
886
|
|
|
800
|
-
`cpflow update-github-actions`
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
887
|
+
`cpflow update-github-actions` refreshes local composite actions and helpers.
|
|
888
|
+
It preserves every top-level workflow by default, including refs, triggers,
|
|
889
|
+
permissions, and downstream deployment ownership. It does not create staging
|
|
890
|
+
or production deployment workflows when another CI system owns those deploys.
|
|
891
|
+
Select the wrappers you intend to replace explicitly; see
|
|
892
|
+
`cpflow update-github-actions --help` for the current interface:
|
|
893
|
+
|
|
894
|
+
```sh
|
|
895
|
+
bundle exec cpflow update-github-actions --workflows \
|
|
896
|
+
cpflow-deploy-review-app.yml cpflow-delete-review-app.yml \
|
|
897
|
+
cpflow-cleanup-stale-review-apps.yml cpflow-help-command.yml \
|
|
898
|
+
cpflow-review-app-help.yml
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
Each selected wrapper is replaced in full with the installed gem's template
|
|
902
|
+
and release ref. Review the diff and reapply downstream changes before
|
|
903
|
+
committing. Unselected wrappers keep their refs: preservation is not evidence
|
|
904
|
+
that old wrappers are compatible with new local actions. Migrate wrapper
|
|
905
|
+
contracts and source pins together, then run the validator in the same PR.
|
|
906
|
+
For a selected staging wrapper, a single existing push branch or the default
|
|
907
|
+
main/master pair can be inferred. Missing, malformed, or ambiguous branch
|
|
908
|
+
configuration requires an explicit `--staging-branch BRANCH`; that option also
|
|
909
|
+
requires selecting `cpflow-deploy-staging.yml`.
|
|
910
|
+
|
|
911
|
+
### Preserving downstream validation
|
|
912
|
+
|
|
913
|
+
The generated `bin/test-cpflow-github-flow` runs baseline checks followed by
|
|
914
|
+
an optional executable `bin/test-cpflow-github-flow-custom`. The extension runs
|
|
915
|
+
from the repository root with the cpflow command argv forwarded unchanged
|
|
916
|
+
(for example, `bundle`, `exec`, `cpflow`), and its nonzero exit fails validation.
|
|
917
|
+
The generator never creates or overwrites the custom extension. Baseline
|
|
918
|
+
production checks apply when the generated production workflow exists;
|
|
919
|
+
downstream-owned production workflows belong in the custom checks.
|
|
920
|
+
|
|
921
|
+
An existing validator that differs from the installed template blocks the
|
|
922
|
+
entire update before any writes. This includes unmodified validators from
|
|
923
|
+
older releases: the updater cannot safely distinguish them from custom code.
|
|
924
|
+
For a legacy installation such as HiChee's 5.3-to-6.0 RC migration:
|
|
925
|
+
|
|
926
|
+
1. Save the old validator in version control and compare it with its original
|
|
927
|
+
release. Extract the downstream checks into `bin/test-cpflow-github-flow-custom`
|
|
928
|
+
and make it executable. If it is entirely downstream-specific, rename it
|
|
929
|
+
directly. Remove any call back to the generated validator to avoid recursion.
|
|
930
|
+
2. Remove or rename the old `bin/test-cpflow-github-flow` after preserving those
|
|
931
|
+
checks, then run the update command with the selected wrappers. No override
|
|
932
|
+
flag bypasses this check. Do not use `generate-github-actions --force` as a
|
|
933
|
+
migration shortcut: it intentionally replaces the full generated flow.
|
|
934
|
+
3. Run the new validator. Confirm that the custom checks execute and that a
|
|
935
|
+
failing custom check still fails the command. Repeating the updater with the
|
|
936
|
+
same selected workflows should produce no further diff.
|
|
937
|
+
|
|
938
|
+
### Migrating trusted action allowlists
|
|
939
|
+
|
|
940
|
+
Repositories using a closed `trusted_actions` policy must review these exact
|
|
941
|
+
repositories used by the complete generated output:
|
|
942
|
+
|
|
943
|
+
```yaml
|
|
944
|
+
trusted_actions:
|
|
945
|
+
- actions/checkout
|
|
946
|
+
- docker/setup-buildx-action
|
|
947
|
+
- ruby/setup-ruby
|
|
948
|
+
- shakacode/control-plane-flow
|
|
949
|
+
```
|
|
950
|
+
|
|
951
|
+
Merge the needed entries into your existing policy rather than replacing it.
|
|
952
|
+
`ruby/setup-ruby` is used by the generated local setup action, including in
|
|
953
|
+
review-app-only installations. `actions/checkout` and `docker/setup-buildx-action`
|
|
954
|
+
are used directly by the generated production wrapper;
|
|
955
|
+
`shakacode/control-plane-flow` supplies the reusable wrappers. Other existing
|
|
956
|
+
downstream workflows may need additional entries. Upstream reusable workflows
|
|
957
|
+
also use `actions/github-script`; reviewing that upstream implementation remains
|
|
958
|
+
part of trusting `shakacode/control-plane-flow`.
|
|
959
|
+
|
|
960
|
+
Allowlisting does not waive immutable pin requirements. For a policy requiring
|
|
961
|
+
full SHAs, resolve and independently verify the chosen upstream release tag or
|
|
962
|
+
test commit, then run `bin/pin-cpflow-github-ref --version <reviewed-version-tag>
|
|
963
|
+
<full-sha>`. The helper writes that version/tag beside all cpflow SHA pins and
|
|
964
|
+
updates obsolete same-line comments. The label is supplied by the caller; the
|
|
965
|
+
helper does not contact GitHub or certify tag-to-SHA identity. For an unreleased
|
|
966
|
+
test commit, use its source version tag as context and record the exact commit
|
|
967
|
+
in the PR. Review the generated diff and run your repository's action security
|
|
968
|
+
scanner after updating its allowlist.
|
|
805
969
|
|
|
806
970
|
When keeping `cpflow` in an app Gemfile, leave a comment next to the gem entry
|
|
807
971
|
so future dependency bumps include the wrapper update:
|
|
@@ -849,14 +1013,14 @@ releasing it. Use an immutable commit SHA from the upstream PR branch:
|
|
|
849
1013
|
|
|
850
1014
|
```sh
|
|
851
1015
|
ruby /path/to/control-plane-flow/bin/cpflow update-github-actions
|
|
852
|
-
bin/pin-cpflow-github-ref <upstream-pr-sha>
|
|
1016
|
+
bin/pin-cpflow-github-ref --version <reviewed-version-tag> <upstream-pr-sha>
|
|
853
1017
|
```
|
|
854
1018
|
|
|
855
1019
|
The update command copies the PR checkout's canonical composite actions into
|
|
856
1020
|
`.github/actions/cpflow-*`. The pin helper then updates every generated
|
|
857
1021
|
reusable-workflow `uses:` ref plus the production workflow's pinned
|
|
858
1022
|
`control-plane-flow` checkout and setup validation ref. It accepts release
|
|
859
|
-
tags and full commit SHAs
|
|
1023
|
+
tags and full commit SHAs (with a reviewed `--version` label), rejects branch names such as `main` or
|
|
860
1024
|
`feature/foo`, and requires `--allow-moving-ref` for short-lived local
|
|
861
1025
|
experiments that should not be committed.
|
|
862
1026
|
|
|
@@ -961,7 +1125,7 @@ In practice, porting the flow into a demo app usually follows five phases.
|
|
|
961
1125
|
|
|
962
1126
|
4. Update `.controlplane/controlplane.yml` with staging, review, and production entries.
|
|
963
1127
|
5. Confirm that the generated Dockerfile picked a Ruby base image compatible with the app's declared Ruby requirement.
|
|
964
|
-
6. For SQLite-backed apps, confirm that the generated scaffold
|
|
1128
|
+
6. For SQLite-backed apps, confirm that the generated scaffold redirects every production database file into persistent `/app/data` (or keeps it under persistent `/app/storage`) without hiding image migrations under `/app/db`, mounts Active Storage at `/app/storage`, and adds a release script that runs `rails db:prepare`.
|
|
965
1129
|
|
|
966
1130
|
**Adapt for the app's runtime:**
|
|
967
1131
|
|
|
@@ -1005,7 +1169,7 @@ Expand that prompt with app-specific requirements before editing files:
|
|
|
1005
1169
|
- make sure the generated Dockerfile uses a Ruby base image compatible with the app's declared Ruby requirement
|
|
1006
1170
|
- preserve repo-defined frontend precompile hooks, such as Shakapacker `precompile_hook` commands or React on Rails `config.auto_load_bundle = true`
|
|
1007
1171
|
- keep Node available in the final image if Rails or SSR depends on ExecJS, Yarn, or `pnpm` after the main `npm install` layer
|
|
1008
|
-
- if `config/database.yml` shows SQLite in production, confirm that `cpflow generate`
|
|
1172
|
+
- if `config/database.yml` shows SQLite in production, confirm that `cpflow generate` redirected every production database path into persistent `/app/data` or `/app/storage`, emitted both volumes without mounting over `/app/db`, and added a `rails db:prepare` release script; otherwise keep the default Postgres workload
|
|
1009
1173
|
- inspect the production Dockerfile and package sources for private GitHub dependencies, and wire `DOCKER_BUILD_SSH_KEY` plus `DOCKER_BUILD_SSH_KNOWN_HOSTS` when the build uses `RUN --mount=type=ssh` against non-GitHub hosts
|
|
1010
1174
|
- add extra `app_workloads` and template files for any runtime sidecars, workers, or renderer processes
|
|
1011
1175
|
- make sure any sidecar process exposed to sibling workloads binds to `0.0.0.0` instead of container-local `localhost`
|
data/docs/commands.md
CHANGED
|
@@ -30,6 +30,7 @@ cpflow ai-github-flow-prompt
|
|
|
30
30
|
- Picks templates from the `.controlplane/templates` directory
|
|
31
31
|
- Templates are ordinary Control Plane templates but with variable preprocessing
|
|
32
32
|
- Use `--preserve-existing-runtime` to retain each workload container's configured app image, even when the workload is unready, and skip existing secret resources entirely while applying other template changes
|
|
33
|
+
- Use `--exclude-secret-template NAME` and `--exclude-policy-template NAME` to exclude exact named templates without changing workload image handling
|
|
33
34
|
- Missing or invalid workload images use only an unambiguous app image from ready workloads; refresh fails before applying templates when no safe fallback exists
|
|
34
35
|
|
|
35
36
|
**Preprocessed template variables:**
|
|
@@ -135,6 +136,7 @@ cpflow copy-image-from-upstream -a $APP_NAME --upstream-token $UPSTREAM_TOKEN --
|
|
|
135
136
|
- Deletes the whole app (GVC with all workloads, all volumesets and all images) or a specific workload
|
|
136
137
|
- Also unbinds the app from the secrets policy and any configured `shared_secret_grants` policies, as long as both the identity and each policy exist (and are bound)
|
|
137
138
|
- For the app-specific secrets policy, removes every permission held by the app identity; for `shared_secret_grants`, removes only `reveal`
|
|
139
|
+
- Removes a marked per-app dictionary and exact-target unbound policy for generated review credentials, including after the opt-in is removed from a dynamically matched review-app entry
|
|
138
140
|
- Will ask for explicit user confirmation
|
|
139
141
|
- Runs a pre-deletion hook before the app is deleted if `hooks.pre_deletion` is specified in the `.controlplane/controlplane.yml` file
|
|
140
142
|
- If the hook exits with a non-zero code, the command will stop executing and also exit with a non-zero code
|
|
@@ -217,7 +219,7 @@ Creates base Control Plane config and template files for a Rails project:
|
|
|
217
219
|
- infers the app prefix from the current directory and wires staging, review, and production entries
|
|
218
220
|
- infers the Docker base Ruby version from `.ruby-version`, `.tool-versions`, or the app's `Gemfile`
|
|
219
221
|
- preserves repo-defined asset precompile hooks, including React on Rails auto bundle generation
|
|
220
|
-
- detects SQLite in `config/database.yml` and generates persistent `
|
|
222
|
+
- detects SQLite in `config/database.yml` and generates persistent `/app/data` and `/app/storage` volume templates without hiding image migrations under `/app/db`
|
|
221
223
|
|
|
222
224
|
```sh
|
|
223
225
|
# Creates .controlplane directory with Control Plane config and starter templates
|
|
@@ -558,13 +560,14 @@ cpflow run -a $APP_NAME --entrypoint /app/alternative-entrypoint.sh -- rails db:
|
|
|
558
560
|
- Configures app to have org-level secrets with default name `"{APP_PREFIX}-secrets"`
|
|
559
561
|
using org-level policy with default name `"{APP_PREFIX}-secrets-policy"` (names can be customized, see docs)
|
|
560
562
|
- Creates identity for secrets if it does not exist
|
|
563
|
+
- For dynamically named review apps with `generated_review_secret_keys`, checks an existing policy before writing credentials, creates a per-app dictionary, skips its secret template during initial setup, and fills missing disposable keys without printing or rotating values
|
|
561
564
|
- Binds the app identity to any configured `shared_secret_grants` policies as part of the secrets setup flow; skipped when `--skip-secrets-setup` or `--skip-secret-access-binding` is provided, or `skip_secrets_setup` is set
|
|
562
565
|
- Use `--skip-secrets-setup` to prevent the automatic setup of secrets,
|
|
563
566
|
or set it through `skip_secrets_setup` in the `.controlplane/controlplane.yml` file
|
|
564
567
|
- Runs a post-creation hook after the app is created if `hooks.post_creation` is specified in the `.controlplane/controlplane.yml` file
|
|
565
568
|
- If the hook exits with a non-zero code, the command will stop executing and also exit with a non-zero code
|
|
566
569
|
- Use `--skip-post-creation-hook` to skip the hook if specified in `controlplane.yml`
|
|
567
|
-
- Use `--refresh-templates` to apply configured templates noninteractively to an existing app while preserving each workload's configured app image even when workloads are unready or use mixed image versions, skipping existing secret
|
|
570
|
+
- Use `--refresh-templates` to apply configured templates noninteractively to an existing app while preserving each workload's configured app image even when workloads are unready or use mixed image versions, skipping existing secret templates (but filling missing opt-in generated review keys), repairing secrets access bindings, and skipping the post-creation hook
|
|
568
571
|
|
|
569
572
|
```sh
|
|
570
573
|
cpflow setup-app -a $APP_NAME
|
|
@@ -588,25 +591,35 @@ cpflow terraform import
|
|
|
588
591
|
|
|
589
592
|
### `update-github-actions`
|
|
590
593
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
594
|
+
Refreshes local composite actions and helper files from the installed gem.
|
|
595
|
+
All top-level workflows are preserved by default, including their refs,
|
|
596
|
+
triggers, permissions, and deployment ownership. Use --workflows FILE...
|
|
597
|
+
to explicitly add or replace named generated workflows. Replacement resets
|
|
598
|
+
each selected workflow to its template and matching v6.0.0 ref;
|
|
599
|
+
review and reapply any downstream customizations in the same PR.
|
|
596
600
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
601
|
+
Selecting cpflow-deploy-staging.yml preserves a single existing push branch
|
|
602
|
+
or the default main/master pair. Missing or ambiguous branches require
|
|
603
|
+
--staging-branch BRANCH. This option requires selecting the staging workflow.
|
|
604
|
+
|
|
605
|
+
A differing existing bin/test-cpflow-github-flow blocks all writes. Move
|
|
606
|
+
downstream checks to executable bin/test-cpflow-github-flow-custom and
|
|
607
|
+
remove or rename the old validator before updating. The generated validator
|
|
608
|
+
invokes that extension after its baseline checks; the extension is never
|
|
609
|
+
generated or overwritten. See docs/ci-automation.md for migration guidance.
|
|
600
610
|
|
|
601
611
|
```sh
|
|
602
|
-
#
|
|
612
|
+
# Refresh actions/helpers while preserving downstream workflows
|
|
603
613
|
cpflow update-github-actions
|
|
604
614
|
|
|
605
615
|
# When running cpflow through Bundler
|
|
606
616
|
bundle exec cpflow update-github-actions
|
|
607
617
|
|
|
608
|
-
#
|
|
609
|
-
cpflow update-github-actions --
|
|
618
|
+
# Explicitly replace the review-app wrapper
|
|
619
|
+
cpflow update-github-actions --workflows cpflow-deploy-review-app.yml
|
|
620
|
+
|
|
621
|
+
# Explicitly add or replace staging deployment from develop
|
|
622
|
+
cpflow update-github-actions --workflows cpflow-deploy-staging.yml --staging-branch develop
|
|
610
623
|
```
|
|
611
624
|
|
|
612
625
|
### `version`
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# PostgreSQL for disposable review apps
|
|
2
|
+
|
|
3
|
+
Use the generated `.controlplane/templates/postgres.yml` for a PostgreSQL workload
|
|
4
|
+
that belongs to one disposable review app. For production database migration, see
|
|
5
|
+
[Migrating PostgreSQL from Heroku to RDS](./postgres.md).
|
|
6
|
+
|
|
7
|
+
## Enable cleanup for new review apps
|
|
8
|
+
|
|
9
|
+
The generated template marks three helper resources:
|
|
10
|
+
|
|
11
|
+
| Resource | Purpose |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| `<APP>-pg` | Credential dictionary |
|
|
14
|
+
| `<APP>-pg-script` | Initialization-script secret |
|
|
15
|
+
| `<APP>-pg-access` | Policy granting access to those secrets |
|
|
16
|
+
|
|
17
|
+
Each helper template carries this tag:
|
|
18
|
+
|
|
19
|
+
```yaml
|
|
20
|
+
tags:
|
|
21
|
+
cpflow-disposable-postgres-app: "{{APP_NAME}}"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`cpflow apply-template` retains the tag for dynamically named review apps and removes
|
|
25
|
+
it for persistent apps. In an existing project, add the tag to all three helper
|
|
26
|
+
**templates before creating new review apps**. Reapplying a marked template to an
|
|
27
|
+
existing unmarked resource is refused; it does not adopt that resource.
|
|
28
|
+
|
|
29
|
+
Before opting in, check that your deployment token can:
|
|
30
|
+
|
|
31
|
+
- Read and delete the three helper resources.
|
|
32
|
+
- Read each secret's effective access report (`viewAccessReport` on the org).
|
|
33
|
+
|
|
34
|
+
A missing or incomplete access report blocks cleanup before app data is deleted.
|
|
35
|
+
|
|
36
|
+
## Delete an app
|
|
37
|
+
|
|
38
|
+
Run the normal app deletion command:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
cpflow delete -a APP_NAME
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Cleanup validates the helpers before deleting app data. It removes the marked
|
|
45
|
+
policy and secrets before deleting the GVC. Deleting a single workload with
|
|
46
|
+
`cpflow delete -a APP_NAME -w WORKLOAD_NAME` preserves the helpers.
|
|
47
|
+
|
|
48
|
+
The ownership checks require:
|
|
49
|
+
|
|
50
|
+
- The same app marker on every surviving helper.
|
|
51
|
+
- A policy targeting exactly the two helper secrets.
|
|
52
|
+
- Only `reveal` grants in that policy, for the app and PostgreSQL identities in the
|
|
53
|
+
app's GVC.
|
|
54
|
+
- No helper listed in `shared_secret_grants`.
|
|
55
|
+
- No effective secret access through another application policy or identity.
|
|
56
|
+
|
|
57
|
+
Reapplying marked helpers with `cpflow apply-template` uses the same checks.
|
|
58
|
+
|
|
59
|
+
## Understand a cleanup refusal
|
|
60
|
+
|
|
61
|
+
Cleanup preserves resources when a marker, policy, or access report cannot establish
|
|
62
|
+
exclusive ownership. A refusal aborts whole-app deletion before live app data is
|
|
63
|
+
deleted. Fix the reported condition before retrying; do not remove a
|
|
64
|
+
sharing grant until you know which applications depend on it.
|
|
65
|
+
|
|
66
|
+
| Condition | Result |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| All helpers are unmarked legacy resources | App deletion proceeds; helpers are preserved |
|
|
69
|
+
| Marked and unmarked helpers coexist | Cleanup refuses deletion |
|
|
70
|
+
| A marker names another app | Cleanup refuses deletion |
|
|
71
|
+
| Policy targets or principals differ from the expected app scope | Cleanup refuses deletion |
|
|
72
|
+
| A helper is configured as shared | Cleanup refuses deletion |
|
|
73
|
+
| Secret access reports are unavailable or incomplete | Cleanup refuses deletion |
|
|
74
|
+
|
|
75
|
+
The access checks include permissions implied by `edit` or `manage`. Global `manage`
|
|
76
|
+
grants to org groups, users, or service accounts count as org administration.
|
|
77
|
+
Targeted or query grants, and grants to other GVC identities, block cleanup.
|
|
78
|
+
|
|
79
|
+
For shared staging credentials, use the
|
|
80
|
+
[shared-secret configuration guide](./secrets-and-env-values.md#shared-secrets-for-review-apps)
|
|
81
|
+
instead of marking them as disposable helpers.
|
|
82
|
+
|
|
83
|
+
## Recover after interruption
|
|
84
|
+
|
|
85
|
+
Repeat `cpflow delete` with the same app name. Cleanup tolerates an already absent
|
|
86
|
+
GVC, policy, or secret and rechecks the surviving helpers before deleting them.
|
|
87
|
+
|
|
88
|
+
Unmarked legacy helpers need manual cleanup after you establish that no other app
|
|
89
|
+
uses them. Rolling back to an older cpflow version leaves the tags in place but
|
|
90
|
+
stops automatic helper cleanup.
|