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. |
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.
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. The generated promotion wrapper passes only the staging
token from repository secrets; GitHub injects CPLN_TOKEN_PRODUCTION only after
the environment approval gate passes.
If promotion 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. A repository or organization
secret with the same name is not enough for this workflow. Create or verify the
environment secret with:
gh secret set CPLN_TOKEN_PRODUCTION --repo shakacode/react-webpack-rails-tutorial --env production
gh secret list --repo shakacode/react-webpack-rails-tutorial --env productionBefore the first promotion, bootstrap the production app the same way in the production org, using production-only secrets and values.
Generated wrappers pin Control Plane Flow once with the reusable workflow
uses: ref, for example @v5.0.4. For stable releases,
this ref should be a release tag. The upstream reusable workflow automatically
loads its matching shared actions from GitHub's workflow context, so downstream
wrappers should not pass a duplicate Control Plane Flow ref input. If your
generated wrappers still include a with: block whose only purpose is to repeat
the same ref, regenerate them with a newer cpflow.
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, for example CPFLOW_VERSION=5.0.4 with a wrapper pinned to
uses: ...@v5.0.4.
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 |
Private SSH key for Docker builds that fetch private dependencies. |
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 != ''.