Skip to content

Document cpflow downstream setup#747

Open
justin808 wants to merge 4 commits into
masterfrom
jg-codex/downstream-cpflow-setup-docs
Open

Document cpflow downstream setup#747
justin808 wants to merge 4 commits into
masterfrom
jg-codex/downstream-cpflow-setup-docs

Conversation

@justin808
Copy link
Copy Markdown
Member

@justin808 justin808 commented May 24, 2026

Summary

  • document the minimal GitHub setup for generated review apps
  • spell out Control Plane-side orgs, app names, secret dictionaries, and sensitive production token handling
  • pin generated cpflow wrappers to the same upstream commit used by the starter test PR and wire production promotion through the protected production environment

Validation

  • git diff --check
  • bin/conductor-exec bin/test-cpflow-github-flow ruby /private/tmp/control-plane-flow-release-check.lWpUu0/repo/bin/cpflow
  • actionlint -ignore SC2129 .github/workflows/cpflow-*.yml

Note

Medium Risk
Repins all deployment workflows to a new upstream commit (behavior change) and documents production token handling via a protected environment; mostly docs plus CI wrapper changes, not application runtime code.

Overview
This PR expands downstream cpflow setup documentation and aligns generated GitHub Actions with the newer upstream flow.

Documentation now describes a minimal review-app path: only CPLN_TOKEN_STAGING is required, with REVIEW_APP_PREFIX and staging org inferred from .controlplane/controlplane.yml (app key qa-react-webpack-rails-tutorial, not the old -pr suffix). It adds tables for optional GitHub overrides, staging variables, protected production environment secrets (CPLN_TOKEN_PRODUCTION), and Control Plane orgs, apps, and secret dictionaries (SECRET_KEY_BASE, etc.). Internal team notes and .github/cpflow-help.md match this model and add guidance on pinning unreleased control-plane-flow via commit SHA vs release tags.

Workflows repin all cpflow-* reusable workflows from 3e0e7e1… to cfe494bf…, pass the same control_plane_flow_ref, wire promotion through production_environment: production with comments on permissions and secrets: inherit, and remove the vars.REVIEW_APP_PREFIX != '' guard on PR-open help so help posts without setting that variable.

Reviewed by Cursor Bugbot for commit 8e2722f. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Documentation
    • Expanded Review App setup: clearer required secrets/variables, guidance to leave the review-app prefix unset (workflow will infer names), require GitHub settings to match app names, separate staging vs production promotion instructions, note production token stored in a protected Environment, and added advanced testing guidance for unreleased control-plane-flow changes.
  • Chores
    • Updated pinned reusable workflow references used by CI workflows.

Review Change Stack

@github-actions
Copy link
Copy Markdown

🚀 Quick Review App Commands

Welcome! Here are the commands you can use in this PR:

+review-app-deploy

Deploy your PR branch for testing.

+review-app-delete

Remove the review app when done.

+review-app-help

Show detailed instructions, environment setup, and configuration options.

Comment +review-app-help for full setup details.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 24, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ef29a94b-5577-42ec-8ed5-c50a72c98413

📥 Commits

Reviewing files that changed from the base of the PR and between c78d0f1 and 8e2722f.

📒 Files selected for processing (7)
  • .github/workflows/cpflow-cleanup-stale-review-apps.yml
  • .github/workflows/cpflow-delete-review-app.yml
  • .github/workflows/cpflow-deploy-review-app.yml
  • .github/workflows/cpflow-deploy-staging.yml
  • .github/workflows/cpflow-help-command.yml
  • .github/workflows/cpflow-promote-staging-to-production.yml
  • .github/workflows/cpflow-review-app-help.yml
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/cpflow-help-command.yml

Walkthrough

Adds a "GitHub Review App Setup" section and clarifies cpflow secrets/variables and advanced testing; repins all cpflow wrapper workflows to a newer immutable upstream commit SHA, and annotates promotion workflow permissions and environment secret usage.

Changes

Control Plane Documentation and Workflow Reference Update

Layer / File(s) Summary
Control Plane setup documentation
.controlplane/readme.md
Adds a "GitHub Review App Setup" section describing required secrets/variables, naming inference from .controlplane/controlplane.yml, optional overrides, and staging/production environment configuration. Updates REVIEW_APP_PREFIX guidance to leave it unset so names are inferred.
CI/CD help documentation and advanced testing reference
.github/cpflow-help.md
Revises secrets and variables guidance, clarifies CPLN_TOKEN_PRODUCTION as a protected production GitHub Environment secret, adjusts required vs optional variables for review apps vs staging/promote, and adds an "Advanced" section detailing how to test unreleased control-plane-flow via pinned refs and CPFLOW_VERSION.
Shakacode team deployment notes
.controlplane/shakacode-team.md
Updates team guidance to prefer leaving REVIEW_APP_PREFIX unset, splits staging vs production required secrets/vars, and documents using a protected production environment for promotion secrets and reviewer protections.
Workflow upstream reference pins to new commit SHA
.github/workflows/cpflow-*.yml
Updates all cpflow wrapper workflows to use the new upstream shakacode/control-plane-flow commit SHA (matching control_plane_flow_ref inputs) across cpflow-cleanup, delete, deploy-review-app, deploy-staging, help-command, promote-staging-to-production, and review-app-help workflows; promotion workflow permissions block annotated.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I nibbled docs and nudged the SHA,
Review apps learn their names today,
Secrets tucked in envs that gleam,
Workflows hum a safer dream,
Rabbit hops—CI streams OK!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'Document cpflow downstream setup' directly and clearly summarizes the main change: updating documentation and GitHub Actions configuration for cpflow downstream setup. The title accurately reflects the core objective of documenting minimal GitHub setup for review apps and aligning generated workflows.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jg-codex/downstream-cpflow-setup-docs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Reviewed by Cursor Bugbot for commit d5e1fd6. Configure here.

Comment thread .github/workflows/cpflow-review-app-help.yml Outdated
@@ -15,4 +15,4 @@ permissions:
jobs:
show-help:
if: vars.REVIEW_APP_PREFIX != ''
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guard contradicts the new documentation. The README and cpflow-help.md now say REVIEW_APP_PREFIX is optional and inferred from controlplane.yml, but this condition means the help workflow will be silently skipped when REVIEW_APP_PREFIX is unset — which is the new recommended default.

If the upstream reusable workflow now supports inferring the prefix, this guard should be removed (or updated to a condition that always evaluates to true for authorized callers). As-is, teams following the new "leave REVIEW_APP_PREFIX unset" guidance will never see the help command fire.

Suggested change
if: vars.REVIEW_APP_PREFIX != ''
if: true

# upstream workflow. The upstream workflow only reads the named secrets it
# references, but GitHub does not enforce that boundary. Strict consumers can
# set CPFLOW_GITHUB_ACTIONS_REF to an immutable commit SHA.
secrets: inherit
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment mentions CPFLOW_GITHUB_ACTIONS_REF as an env var for strict consumers, but the actual input used everywhere else in these workflows is control_plane_flow_ref. This looks like a variable name that doesn't exist — it may confuse readers trying to act on this guidance.

Consider referencing the correct mechanism (the control_plane_flow_ref workflow input or the @<sha> ref in uses:) instead.

@claude
Copy link
Copy Markdown

claude Bot commented May 24, 2026

Code Review: Document cpflow downstream setup

Overview

This PR documents the minimal GitHub/Control Plane setup for review apps, staging, and production, and bumps all generated cpflow workflow wrappers from commit 3e0e7e1 to db013e1. The documentation work is solid and the security guidance around CPLN_TOKEN_PRODUCTION isolation is a meaningful improvement.


Issues

Bug: cpflow-review-app-help.yml guard conflicts with new documentation
The if: vars.REVIEW_APP_PREFIX != '' condition in cpflow-review-app-help.yml will silently skip the help workflow for any team following the new recommended default of leaving REVIEW_APP_PREFIX unset. This is the most actionable issue — see the inline comment.

Minor: Misleading variable name in secrets: inherit comment
The comment in cpflow-promote-staging-to-production.yml references CPFLOW_GITHUB_ACTIONS_REF as a mechanism for strict consumers to limit secret exposure, but this variable doesn't appear elsewhere in the workflows. The correct mechanism is the control_plane_flow_ref input or the pinned @<sha> ref in uses:. See inline comment.


Security

  • Isolating CPLN_TOKEN_PRODUCTION to a protected GitHub Environment with required reviewers is the right call — good improvement over a plain repository secret.
  • The secrets: inherit pattern passes all caller repository secrets to the upstream reusable workflow. GitHub does not filter to only referenced secrets. The added comment acknowledges this honestly. Teams managing strict secret compartmentalization should note that CPLN_TOKEN_PRODUCTION living in the production environment (not the repo) limits its exposure to this specific job, which mitigates most of the risk.
  • Pinning workflow refs to full 40-character commit SHAs (rather than mutable tags or branch names) is a supply-chain best practice and is consistently applied across all workflow files.

Documentation Quality

The new sections in .controlplane/readme.md and .github/cpflow-help.md are clear and well-structured. The table-driven format for secrets/variables is easy to scan. The "Advanced: testing unreleased control-plane-flow changes" section appropriately cautions against pinning to moving branches.

One minor note: the README update changes the review app naming convention from qa-react-webpack-rails-tutorial-pr-<number> (old) to qa-react-webpack-rails-tutorial-<number> (new, without the -pr segment). This is likely intentional but could affect teams who have existing named apps or tooling that pattern-matches on the old format.


Summary

The cpflow-review-app-help.yml guard is the one change that needs attention before merging — everything else is either a straightforward ref bump or documentation improvement.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 24, 2026

Greptile Summary

This PR documents the minimal GitHub and Control Plane setup required for generated cpflow review apps, staging deploys, and production promotion, and bumps all workflow SHA pins from 3e0e7e1 to db013e1 consistently across six workflow files.

  • Documentation: Adds comprehensive setup tables to .controlplane/readme.md and .github/cpflow-help.md covering required/optional secrets, variables, Control Plane org/app/secret-dictionary names, and production environment isolation. REVIEW_APP_PREFIX and CPLN_ORG_STAGING are now marked optional (inferred from controlplane.yml).
  • Promotion workflow: Adds production_environment: production input so the upstream reusable workflow gates production secrets behind the protected GitHub Environment, and adds inline comments explaining the secrets: inherit scope limitation.
  • SHA pins: All six uses: refs and matching control_plane_flow_ref inputs are updated to the same new commit SHA.

Confidence Score: 4/5

Safe to merge with one follow-up: the REVIEW_APP_PREFIX guard in cpflow-review-app-help.yml should be removed or relaxed now that the variable is documented as optional.

The documentation and SHA-pin changes are accurate and consistent. The only functional mismatch is in cpflow-review-app-help.yml, where a pre-existing guard silently suppresses the onboarding help comment for any repo that follows the newly documented standard setup without setting REVIEW_APP_PREFIX. Deploys still work — only the help message is lost — but it directly contradicts the intent of this PR.

.github/workflows/cpflow-review-app-help.yml — the REVIEW_APP_PREFIX guard needs to be removed or updated to match the new optional-variable documentation.

Security Review

  • secrets: inherit scope in promote workflow (.github/workflows/cpflow-promote-staging-to-production.yml): all repository secrets, including CPLN_TOKEN_STAGING and DOCKER_BUILD_SSH_KEY, are forwarded to the upstream reusable workflow. GitHub does not restrict the callee to only the named secrets it references. The PR pins the upstream to an immutable SHA which limits supply-chain risk, but the broad secret exposure during production-promotion runs is worth verifying against org policy.

Important Files Changed

Filename Overview
.github/workflows/cpflow-review-app-help.yml SHA bumped to db013e1; the pre-existing if: vars.REVIEW_APP_PREFIX != '' guard now contradicts the updated docs that say REVIEW_APP_PREFIX is optional, meaning the help job is silently skipped for standard setups.
.github/workflows/cpflow-promote-staging-to-production.yml Added production_environment: production input to gate production secrets behind the protected GitHub Environment; added explanatory comments; SHA bumped. The acknowledged secrets: inherit scope is worth verifying against org policy.
.controlplane/readme.md Large documentation addition covering GitHub secrets/variables, Control Plane org/app/secret-dictionary setup, and production promotion isolation. Content is accurate and consistent with the workflow changes.
.github/cpflow-help.md Updated secrets/variables tables to mark REVIEW_APP_PREFIX optional, clarified CPLN_TOKEN_PRODUCTION placement, and added an advanced section on testing upstream PRs with commit-SHA pins.
.github/workflows/cpflow-cleanup-stale-review-apps.yml SHA bumped from 3e0e7e1 to db013e1 in both uses: and control_plane_flow_ref; no other changes.
.github/workflows/cpflow-delete-review-app.yml SHA bumped consistently; no other changes.
.github/workflows/cpflow-deploy-review-app.yml SHA bumped consistently; no other changes. No REVIEW_APP_PREFIX guard here (intentional asymmetry with cpflow-review-app-help.yml).
.github/workflows/cpflow-deploy-staging.yml SHA bumped consistently; no other changes.
.github/workflows/cpflow-help-command.yml SHA bumped consistently; no other changes.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    PR[Pull Request opened/sync] --> DeployJob[cpflow-deploy-review-app\nno REVIEW_APP_PREFIX guard]
    PR --> HelpJob{cpflow-review-app-help\nif REVIEW_APP_PREFIX != ''}
    HelpJob -- "var set" --> PostHelp[Post help comment on PR]
    HelpJob -- "var unset\n(new standard setup)" --> Skip[Job skipped — no help posted]
    DeployJob --> UpstreamDeploy[Upstream reusable workflow\ninfers prefix from controlplane.yml]
    Master[Push to master] --> StagingDeploy[cpflow-deploy-staging]
    StagingDeploy --> UpstreamStaging[Upstream staging workflow]
    ManualTrigger[workflow_dispatch\nconfirm_promotion=promote] --> PromoteJob[cpflow-promote-staging-to-production]
    PromoteJob --> EnvGate{Protected GitHub Environment\nproduction — requires reviewer approval}
    EnvGate -- approved --> UpstreamPromote[Upstream promote workflow\nreads CPLN_TOKEN_PRODUCTION]
    EnvGate -- rejected --> Blocked[Promotion blocked]
Loading

Reviews (1): Last reviewed commit: "Document cpflow downstream setup" | Re-trigger Greptile

@@ -15,4 +15,4 @@ permissions:
jobs:
show-help:
if: vars.REVIEW_APP_PREFIX != ''
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Help message silently suppressed for standard setups

The updated docs explicitly say REVIEW_APP_PREFIX is optional and inferred from controlplane.yml, but the guard if: vars.REVIEW_APP_PREFIX != '' remains. Any repo that follows the new standard setup (leaving REVIEW_APP_PREFIX unset) will never see the help comment posted on opened PRs — the job is skipped entirely. The deploy workflow (cpflow-deploy-review-app.yml) has no such guard, so deploys work but onboarding help is silently absent.

Comment on lines +28 to 32
# `secrets: inherit` passes all caller repository secrets to the trusted
# upstream workflow. The upstream workflow only reads the named secrets it
# references, but GitHub does not enforce that boundary. Strict consumers can
# set CPFLOW_GITHUB_ACTIONS_REF to an immutable commit SHA.
secrets: inherit
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 security secrets: inherit exposes all repository secrets to the upstream workflow

The inline comment correctly notes that secrets: inherit passes every caller repository secret to the upstream reusable workflow, and that GitHub does not enforce the named-secrets boundary. In the current setup this includes CPLN_TOKEN_STAGING, any DOCKER_BUILD_SSH_KEY, and any other repository secrets. If the upstream SHA (db013e...) ever changes to include malicious or compromised code, those secrets are exposed during a production-promotion run. The PR already pins to an immutable SHA which limits supply-chain risk, but consider whether your org's policy requires explicit secret whitelisting via environment-level scoping rather than secrets: inherit.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.controlplane/readme.md:
- Around line 489-493: The README guidance and shakacode-team doc disagree about
review-app naming: update .controlplane/shakacode-team.md to match
.controlplane/readme.md by changing the instructions that set REVIEW_APP_PREFIX
to instead instruct leaving REVIEW_APP_PREFIX unset (or to document the inferred
name qa-react-webpack-rails-tutorial) and reference
.controlplane/controlplane.yml for app name alignment; ensure the text mentions
the generated review app pattern qa-react-webpack-rails-tutorial-<PR number> and
remove the conflicting example
REVIEW_APP_PREFIX=qa-react-webpack-rails-tutorial-pr so both docs are
consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 339f15eb-4b09-48f3-897d-86bcf9c18dec

📥 Commits

Reviewing files that changed from the base of the PR and between 1fb4cdd and d5e1fd6.

📒 Files selected for processing (9)
  • .controlplane/readme.md
  • .github/cpflow-help.md
  • .github/workflows/cpflow-cleanup-stale-review-apps.yml
  • .github/workflows/cpflow-delete-review-app.yml
  • .github/workflows/cpflow-deploy-review-app.yml
  • .github/workflows/cpflow-deploy-staging.yml
  • .github/workflows/cpflow-help-command.yml
  • .github/workflows/cpflow-promote-staging-to-production.yml
  • .github/workflows/cpflow-review-app-help.yml

Comment thread .controlplane/readme.md
@claude
Copy link
Copy Markdown

claude Bot commented May 24, 2026

Code Review: Document cpflow downstream setup

Overview

This PR improves the setup experience for downstream cpflow users by consolidating documentation and fixing the production token exposure model. The security change—moving CPLN_TOKEN_PRODUCTION from a repo secret to a protected GitHub Environment—is a meaningful improvement. The workflow pin bump is mechanical and applied consistently across all six files.


Security

Positive: Gating CPLN_TOKEN_PRODUCTION behind a protected GitHub Environment with required reviewers is the right approach. Before this PR, anyone who could trigger cpflow-promote-staging-to-production.yml could potentially exercise the production token. The environment gate closes that gap.

Concern — secrets: inherit on the promote workflow: The added comment correctly acknowledges that secrets: inherit passes all caller repository secrets (including CPLN_TOKEN_STAGING) to the upstream reusable workflow, not only explicitly named ones. GitHub has no enforcement boundary here. The mitigation offered is pinning both refs to an immutable SHA, which is already done. However, the comment could clarify that the environment-level CPLN_TOKEN_PRODUCTION secret is not passed via secrets: inherit—environment secrets are only injected when a job directly references that environment—so the production token isolation is actually stronger than the comment implies.


Breaking Change: Review App Naming Convention

The PR changes the review app naming scheme from qa-react-webpack-rails-tutorial-pr-<N> to qa-react-webpack-rails-tutorial-<N>. Any currently running review apps using the old -pr- convention will become orphaned—the cleanup workflows won't find them because they query by the new prefix. Teams should manually delete old-convention review apps before or shortly after merging. This should be called out explicitly in the PR description or a migration note.


Documentation Quality

The new ## GitHub Review App Setup section in readme.md is well-structured. The tables cleanly separate required vs. optional settings. One fragility worth noting: the docs state that the staging org and review app prefix are inferred when controlplane.yml defines "exactly one app with match_if_app_name_starts_with: true." If a second such app is ever added, inference silently breaks with no obvious error. A one-line note pointing readers to override CPLN_ORG_STAGING and REVIEW_APP_PREFIX in that scenario would make this more robust.

The advanced section in cpflow-help.md on pinning vs. CPFLOW_VERSION is genuinely useful and clearly written.


Workflow Changes

  • cpflow-review-app-help.yml: Removing if: vars.REVIEW_APP_PREFIX != '' is correct given that the prefix is now inferred rather than required. No issue.
  • cpflow-help-command.yml and cpflow-review-app-help.yml: These lack a with: control_plane_flow_ref: block. For help-display-only workflows this appears intentional (they don't invoke cpflow), but worth confirming with the upstream workflow definition that omitting control_plane_flow_ref is valid and has a safe default.
  • Consistent SHA bump: 3e0e7e1…db013e1… applied uniformly across all six workflow files. Good.

Summary

Area Assessment
Security (production token) Improvement
Breaking naming change Needs migration note
secrets: inherit scope Documented; clarification suggested
Inference fragility Minor; worth a note
Documentation clarity Good
Workflow consistency Good

Overall this is a solid improvement. Address the naming-convention migration note and clarify the secrets: inherit / environment-secret boundary before merging.

# references, but GitHub does not enforce that boundary. Strict consumers can
# keep both the `uses:` ref and `control_plane_flow_ref` pinned to an
# immutable commit SHA.
secrets: inherit
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says the upstream workflow "only reads the named secrets it references," which is accurate for repository secrets. Worth clarifying here that environment secrets (e.g. CPLN_TOKEN_PRODUCTION) are not passed via secrets: inherit—they're only injected when the job itself directly references the production environment. So the production token isolation is actually stronger than this comment implies; a reader might incorrectly assume CPLN_TOKEN_PRODUCTION leaks through secrets: inherit.

Comment thread .controlplane/readme.md
`qa-react-webpack-rails-tutorial` and staging org
`shakacode-open-source-examples-staging` from `.controlplane/controlplane.yml`
because that file defines exactly one app with
`match_if_app_name_starts_with: true`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This inference assumption is fragile: if controlplane.yml ever gains a second app entry with match_if_app_name_starts_with: true, the inference will fail (or pick the wrong one) with no clear error. Consider adding a sentence here directing readers to set CPLN_ORG_STAGING and REVIEW_APP_PREFIX explicitly if they hit ambiguous inference, so the failure mode is less opaque.

- Leave `REVIEW_APP_PREFIX` unset for the standard path. The workflow infers
`qa-react-webpack-rails-tutorial` from `.controlplane/controlplane.yml`, so
generated review apps use names like
`qa-react-webpack-rails-tutorial-1234`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking change — naming convention. The old scheme was qa-react-webpack-rails-tutorial-pr-<N>; the new scheme omits the -pr segment. Any live review apps created under the old convention become orphaned after this merges: the cleanup and delete workflows query by the new prefix and won't find them. Recommend adding a migration note (e.g. in the PR description or a one-time manual cleanup step) so operators know to delete old-style apps before merging.

@claude
Copy link
Copy Markdown

claude Bot commented May 24, 2026

Code Review: Document cpflow downstream setup

Overall assessment: Low-risk, well-structured documentation PR. The shift of `CPLN_TOKEN_PRODUCTION` from a repository secret to a protected GitHub Environment is a genuine security improvement. SHA pinning and the two-pin comment in the promotion workflow are both good practices.


✅ Strengths

  • Security uplift: Moving `CPLN_TOKEN_PRODUCTION` to a protected GitHub Environment (with required reviewers + prevent self-review) meaningfully narrows who can trigger production deploys vs. the old repo-secret approach.
  • SHA pinning: All reusable workflow `uses:` refs and `control_plane_flow_ref` inputs are pinned to the same immutable commit SHA — good supply-chain hygiene.
  • Two-pin invariant comment in the promotion workflow is clear and will prevent future drift.
  • `contents: write` explanation clarifies what would otherwise look like an overly broad permission grant.
  • Advanced testing section in `cpflow-help.md` is valuable operational documentation, especially the warning about never pinning to a moving branch.

Issues

1. Contradictory `Required` column for production variables in `cpflow-help.md`

The table rows for `CPLN_ORG_PRODUCTION` and `PRODUCTION_APP_NAME` say `yes (for promote)` in the Required column — implying repository variables — but the Notes column says "Prefer a `production` environment variable." The recommendation and the column label contradict each other. Readers who follow the `yes` column will put these in repo variables; readers who follow the note will put them in the environment. The table should be updated to say something like `yes (for promote) — as environment variable` or the Required column should use a different marker for environment variables. (See inline comment.)

2. `STAGING_APP_BRANCH` / `PRIMARY_WORKLOAD` required vs. optional discrepancy

`shakacode-team.md` lists both under "Required repository variables for staging deploys", while `cpflow-help.md` marks both as optional. At minimum `PRIMARY_WORKLOAD` defaults to `rails`, so listing it as required in one doc and optional in the other will confuse fork maintainers.

3. `SECRET_KEY_BASE` test placeholder

The readme documents that the review/staging template "currently contains a test placeholder for `SECRET_KEY_BASE`" and asks readers to replace it before production. This is a hard security requirement, not just guidance — a placeholder key in staging means any staging environment is running with a known, weak secret. Consider either removing the placeholder in a follow-up PR and replacing it with a proper secret reference, or at minimum adding a CI check that fails if the placeholder value is detected.

4. Minor `secrets: inherit` comment improvement

The acknowledgment in the promotion workflow is transparent and appreciated. One thing worth making explicit: because `CPLN_TOKEN_PRODUCTION` is now an environment secret (not a repo secret), `secrets: inherit` in the staging and review-app workflows won't inadvertently expose it — the environment gate is the actual isolation boundary, not just the upstream workflow's access pattern. Adding that note would help future readers understand why the security model holds.

Comment thread .github/cpflow-help.md
| `CPLN_ORG_STAGING` | yes | Control Plane org on controlplane.com for staging and review apps. |
| `CPLN_ORG_PRODUCTION` | yes (for promote) | Control Plane org on controlplane.com for production. |
| `CPLN_ORG_STAGING` | optional for review apps; yes for staging | Override the staging/review Control Plane org inferred from `controlplane.yml`. |
| `CPLN_ORG_PRODUCTION` | yes (for promote) | Control Plane org on controlplane.com for production. Prefer a `production` environment variable. |
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Required column says yes (for promote) — which implies a repository variable — but the Notes column says "Prefer a production environment variable." These two signals contradict each other. Readers who scan the Required column will put this in repo variables; readers who follow the note will put it in the protected environment. Suggest picking one canonical placement and stating it clearly, e.g. updating the Required cell to yes — environment variable or splitting the secrets and environment-variable rows into separate tables.

Comment thread .github/cpflow-help.md
| `PRODUCTION_APP_NAME` | yes (for promote) | App name in `controlplane.yml` used as the production deploy target. |
| `REVIEW_APP_PREFIX` | yes | Prefix for per-PR review app names (e.g. `review-app`). |
| `REVIEW_APP_DEPLOYING_ICON_URL` | optional | Custom image URL for the animated deploying icon in review-app PR comments. Set to `none` to use the text fallback icon. |
| `PRODUCTION_APP_NAME` | yes (for promote) | App name in `controlplane.yml` used as the production deploy target. Prefer a `production` environment variable. |
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as CPLN_ORG_PRODUCTION above: yes (for promote) implies a repo variable, but the Notes column recommends a production environment variable. Both entries need a consistent placement signal.

Comment on lines +28 to +32
# `secrets: inherit` passes all caller repository secrets to the trusted
# upstream workflow. The upstream workflow only reads the named secrets it
# references, but GitHub does not enforce that boundary. Strict consumers can
# keep both the `uses:` ref and `control_plane_flow_ref` pinned to an
# immutable commit SHA.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The transparency here is good. One clarification worth adding to the comment: because CPLN_TOKEN_PRODUCTION is now an environment secret (not a repo secret), secrets: inherit in the staging/review-app caller workflows won't expose it — those jobs never acquire the production environment context, so GitHub never injects the environment secret into them. The environment gate is the actual isolation boundary, not just the upstream workflow's declared access pattern. This makes the security model more robust than the comment currently implies.

Comment thread .controlplane/readme.md

Generate `SECRET_KEY_BASE` with `openssl rand -hex 64` and
`RENDERER_PASSWORD` with `openssl rand -hex 32`. The review/staging template
currently contains a test placeholder for `SECRET_KEY_BASE`; replace it with a
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documenting the placeholder is good, but this phrasing ("replace it with a secret-backed value before promoting production") leaves staging running with a known, weak SECRET_KEY_BASE. If the staging environment is internet-accessible (which review apps typically are), that's a real risk — anyone with the placeholder value can forge session cookies. Consider either removing the placeholder from the template in a follow-up and requiring an explicit secret reference, or adding a CI/readiness check that rejects deploys when SECRET_KEY_BASE matches the placeholder value.

@claude
Copy link
Copy Markdown

claude Bot commented May 24, 2026

Code Review

Overview: Documentation-heavy PR that improves the cpflow downstream setup story — moves the production token into a protected GitHub Environment, infers review-app config from controlplane.yml instead of requiring explicit variables, and repins all reusable workflows to a newer upstream commit SHA. The security posture improvements are real and the documentation is thorough.


Issues

1. control_plane_flow_ref missing from both help workflows

cpflow-help-command.yml and cpflow-review-app-help.yml both omit the with: control_plane_flow_ref: block that every other cpflow workflow passes. If those upstream reusable workflows have a setup action that checks out the gem source using that input, they'll silently fall back to whatever default the upstream YAML defines rather than the pinned SHA. All operational workflows (cleanup, delete, deploy, staging, promote) pass it consistently — the two help workflows should too, or there should be a comment explaining why they don't need it.

2. REVIEW_APP_PREFIX guard removal posts help on every PR open, including forks

Removing if: vars.REVIEW_APP_PREFIX != '' from cpflow-review-app-help.yml means the help comment now posts on every PR open event via pull_request_target. For repos or forks where review apps are not set up, contributors will see a help comment offering commands that won't work. Consider replacing the guard with a check the workflow can evaluate without requiring the variable to be pre-set (e.g., checking that the Control Plane token secret is configured, or accepting that noise on forks is an acceptable trade-off and documenting it).

3. Naming change from -pr-<N> to -<N> is a silent breaking change

The PR removes the -pr suffix from generated review app names (qa-react-webpack-rails-tutorial-pr-1234qa-react-webpack-rails-tutorial-1234) but provides no migration guidance. Any currently-running review apps under the old names, bookmarked URLs, or CI links pointing to old names will silently break. Even a one-paragraph note in the docs ("existing review apps under the old -pr naming must be deleted and redeployed") would prevent confusion.

4. secrets: inherit on the production promotion job

The inline comment acknowledges the issue but leaves it as-is. secrets: inherit sends all repository secrets — including CPLN_TOKEN_STAGING, any SSH keys, etc. — to the upstream workflow. The SHA pinning limits supply-chain risk, but a compromised or malicious upstream commit would have access to all of them, not just the production token. If the upstream workflow supports explicit secret passing, prefer it; if not, the current SHA-pinned approach is reasonable, but that trade-off is worth a word in the docs so future maintainers don't loosen the pin without realizing the exposure.


Minor

  • The contents: write permission on the promotion workflow is correctly explained in the new comment, but it applies at the job level to all callee jobs. If the upstream workflow uses separate jobs with narrower permissions, calling them from a workflow-level contents: write grants that permission to all of them. Worth verifying with the upstream workflow's job-level permissions: blocks.
  • .controlplane/readme.md duplicates some of the same table structure from .github/cpflow-help.md. Not a bug, but consider whether one can reference the other to reduce future drift.

Positives

  • Moving CPLN_TOKEN_PRODUCTION into a protected GitHub Environment with required reviewers is the right call and is a genuine security improvement over storing it as a repository secret.
  • SHA pinning for all uses: refs and control_plane_flow_ref inputs is correct practice for supply-chain safety.
  • The "Advanced: testing unreleased control-plane-flow changes" section is clear and practical — especially the guidance on not leaving downstream apps pinned to a moving branch.
  • Inline workflow comments explaining the pull_request_target rationale and secrets: inherit trade-offs are good practice.

contains(fromJson('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) ||
github.event_name == 'workflow_dispatch'
uses: shakacode/control-plane-flow/.github/workflows/cpflow-help-command.yml@3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
uses: shakacode/control-plane-flow/.github/workflows/cpflow-help-command.yml@cfe494bf32925d49508380e03856d97bd71f6689
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the operational cpflow workflows (cleanup, delete, deploy, staging, promote) pass control_plane_flow_ref as a with: input alongside the uses: SHA. This one does not. If the upstream help workflow has a setup action that uses control_plane_flow_ref to check out and build the gem, it will silently fall back to its own default rather than the pinned SHA.

Unless the upstream cpflow-help-command.yml workflow is known to not have a gem-build step, add:

Suggested change
uses: shakacode/control-plane-flow/.github/workflows/cpflow-help-command.yml@cfe494bf32925d49508380e03856d97bd71f6689
uses: shakacode/control-plane-flow/.github/workflows/cpflow-help-command.yml@cfe494bf32925d49508380e03856d97bd71f6689
with:
control_plane_flow_ref: cfe494bf32925d49508380e03856d97bd71f6689

Or add a comment explaining why this workflow doesn't need it.

show-help:
if: vars.REVIEW_APP_PREFIX != ''
uses: shakacode/control-plane-flow/.github/workflows/cpflow-review-app-help.yml@3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
uses: shakacode/control-plane-flow/.github/workflows/cpflow-review-app-help.yml@cfe494bf32925d49508380e03856d97bd71f6689
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as cpflow-help-command.yml — no with: block means control_plane_flow_ref is not passed, unlike all the operational workflows. If the upstream help workflow doesn't need it, a short comment here would prevent future maintainers from treating this as an oversight during the next SHA repin.

# references, but GitHub does not enforce that boundary. Strict consumers can
# keep both the `uses:` ref and `control_plane_flow_ref` pinned to an
# immutable commit SHA.
secrets: inherit
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

secrets: inherit sends all caller repository secrets — including CPLN_TOKEN_STAGING, SSH keys, and any other repository secrets — to the upstream reusable workflow. The SHA pin limits exposure to a known-good commit, but it is still a broader grant than strictly necessary for a production promotion job.

If the upstream cpflow-promote-staging-to-production.yml workflow supports receiving named secrets explicitly (e.g., secrets: { CPLN_TOKEN_PRODUCTION: ${{ secrets.CPLN_TOKEN_PRODUCTION }} }), that would be strictly tighter. If it requires secrets: inherit, the current approach is the practical maximum — just worth documenting explicitly so the next maintainer doesn't widen the SHA pin without realizing the implication.

Comment thread .controlplane/readme.md
`qa-react-webpack-rails-tutorial-pr-1234`.
The GitHub settings and Control Plane resources must match the app names in
`.controlplane/controlplane.yml`. For the standard review-app path, leave
`REVIEW_APP_PREFIX` unset and let the workflow infer
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This silently changes the naming convention from the previously documented qa-react-webpack-rails-tutorial-pr-<N> (with the -pr suffix) to qa-react-webpack-rails-tutorial-<N>. Any review apps currently running under the old names, bookmark links, or CI output referencing them will break without warning.

Consider adding a migration note here, even one sentence: "If you previously had REVIEW_APP_PREFIX set to qa-react-webpack-rails-tutorial-pr, delete existing review apps before switching — the old names will become orphaned resources in Control Plane."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant