These commands are generated by cpflow. For full setup, version-pinning, and troubleshooting details, see the upstream CI automation guide.
Comment with exactly one command, with no surrounding text or trailing spaces. A single trailing newline from GitHub's comment editor is accepted.
| Command | What it does |
|---|---|
+review-app-deploy |
Builds the PR image, creates the review app if needed, deploys, and comments with the review URL. |
+review-app-delete |
Deletes the review app. This also runs automatically when the PR closes. |
+review-app-help |
Posts this help message on the PR. |
For the normal generated review-app path, GitHub needs one repository secret:
| Name | Where | Notes |
|---|---|---|
CPLN_TOKEN_STAGING |
Repository secret | Control Plane service-account token for the staging/review org. |
For public repositories, use a staging/review token that cannot access production Control Plane resources. Generated review-app deploys skip fork PR heads because Docker builds use repository secrets. If a forked change needs a review app, first move the reviewed change to a trusted branch in this repository.
No repository variables are required for the standard review-app path when
.controlplane/controlplane.yml has exactly one review app entry with
match_if_app_name_starts_with: true. cpflow infers the review-app prefix and
staging org from that config.
Review apps run pull request code. Any value mounted through
cpln://secret/... can be read by that code after the workload starts, so keep
review-app secret dictionaries limited to disposable databases, review-only
renderer credentials, and license values that are acceptable for review-app
exposure.
Optional overrides exist for forks, clones, and unusual apps:
| Name | Notes |
|---|---|
CPLN_ORG_STAGING |
Override the staging/review Control Plane org inferred from controlplane.yml. |
REVIEW_APP_PREFIX |
Override the review-app prefix inferred from controlplane.yml. |
PRIMARY_WORKLOAD |
Public workload used for review URLs and health checks; defaults to rails. |
Staging deploys use the same CPLN_TOKEN_STAGING secret plus STAGING_APP_NAME.
Before the first staging deploy, bootstrap the persistent staging app once:
cpflow setup-app -a "$STAGING_APP_NAME" --org "$CPLN_ORG_STAGING" --skip-post-creation-hooksetup-app reads .controlplane/controlplane.yml's setup_app_templates and
creates the app identity, app secret dictionary, app secret policy, policy
binding, and template resources. Use --skip-post-creation-hook so first-time
bootstrap does not try to run database setup before an image exists. For later
template updates on an existing persistent app, use cpflow apply-template
with the same template list and make sure the app identity has reveal
permission on the app secret policy.
Review apps are temporary and are created by the +review-app-deploy workflow,
but staging and production are persistent apps and should be bootstrapped
explicitly.
Production promotion is part of the generated flow, but keep it protected:
| Name | Where | Notes |
|---|---|---|
CPLN_TOKEN_PRODUCTION |
production GitHub Environment secret |
Do not store this as a repository or organization secret. |
CPLN_ORG_PRODUCTION |
Prefer production Environment variable |
Production Control Plane org. |
PRODUCTION_APP_NAME |
Prefer production Environment variable |
Production app name from controlplane.yml. |
Configure the production GitHub Environment with required reviewers and
prevent self-review. Production promotion intentionally runs as a normal
caller-repo workflow job with environment: production, then checks out the
pinned control-plane-flow release for shared actions. Do not move production
promotion behind a cross-repo reusable workflow: GitHub does not expose this
repo's environment secrets to that called workflow.
Keep CPLN_TOKEN_PRODUCTION absent from repository and organization secrets. A
normal environment-gated job cannot tell which secret scope supplied a nonempty
value, so a broader secret with the same name can mask a missing environment
secret.
If the promotion workflow fails with
CPLN_TOKEN_PRODUCTION is not set. Add it as a secret on the 'production' GitHub Environment.,
the token is missing from the environment scope or the workflow job is no longer
declaring environment: production. Create or verify the environment secret
and confirm there is no same-named repository or organization secret:
You need permission to manage repository environments and secrets to run these
commands.
gh secret set CPLN_TOKEN_PRODUCTION --repo OWNER/REPO --env production
# Paste the token value when prompted.
gh secret list --repo OWNER/REPO --env production
gh secret list --repo OWNER/REPO
gh secret list --org OWNER | grep '^CPLN_TOKEN_PRODUCTION[[:space:]]' || trueBefore the first promotion, bootstrap the production app the same way in the production org, using production-only secrets and values.
Generated wrappers normally pin Control Plane Flow with a release tag, for
example v5.1.0. This branch temporarily pins the wrappers to upstream commit
d8877ca0c9c1d88947f322903e4a4344641029ba while using merged-but-unreleased
production promotion hardening plus the release-runner timeout fix. Reusable
review-app, staging, cleanup, and helper workflows pin that ref in their
uses: entry.
Production promotion pins the same ref in its control-plane-flow checkout step
so the caller-owned job can keep environment: production and receive
production environment secrets directly.
Leave CPFLOW_VERSION unset so the workflow builds cpflow from the same
checked-out upstream source. If you set CPFLOW_VERSION, it must match the
release tag your wrappers are pinned to: a CPFLOW_VERSION=5.1.x runtime
override goes with a wrapper pinned to uses: ...@v5.1.x (substitute the
release you pinned above).
After updating the cpflow gem in this repo, update the generated wrappers in
the same PR:
cpflow update-github-actions
bin/test-cpflow-github-flowIf cpflow is bundled by the app, use:
bundle exec cpflow update-github-actions
bin/test-cpflow-github-flow bundle exec cpflowDo not leave downstream apps pinned to a moving branch such as main. For a
short-lived test of an unreleased upstream PR, pin to a full 40-character commit
SHA and leave CPFLOW_VERSION unset:
bin/pin-cpflow-github-ref <40-character-control-plane-flow-commit-sha>
bin/test-cpflow-github-flow ruby /path/to/control-plane-flow/bin/cpflowMost apps do not need these:
| Name | Notes |
|---|---|
DOCKER_BUILD_EXTRA_ARGS |
Newline-delimited extra Docker build tokens. |
DOCKER_BUILD_SSH_KEY |
Read-only, revocable deploy key for Docker builds that fetch private dependencies. Do not use a personal SSH key. |
DOCKER_BUILD_SSH_KNOWN_HOSTS |
SSH known_hosts entries when SSH build hosts are not GitHub.com. |
REVIEW_APP_DEPLOYING_ICON_URL |
Cosmetic custom image URL for the animated deploying icon. Set to none to use the text fallback icon. |
STAGING_APP_BRANCH |
Custom staging branch. The branch must also appear in cpflow-deploy-staging.yml's push filter. |
CPLN_CLI_VERSION |
Pin a specific @controlplane/cli version; normally leave unset. |
The PR-open help workflow posts a short command reference whenever the generated
wrapper exists. That is intentional for configured demo repos. Forks or clones
that copy the workflow before configuring Control Plane can remove
.github/workflows/cpflow-review-app-help.yml or uncomment and adapt the
wrapper-level if: guard shown in that file, for example
vars.REVIEW_APP_PREFIX != '' || vars.CPLN_ORG_STAGING != ''.