Skip to content

Commit d5e1fd6

Browse files
committed
Document cpflow downstream setup
1 parent 1fb4cdd commit d5e1fd6

9 files changed

Lines changed: 185 additions & 24 deletions

.controlplane/readme.md

Lines changed: 103 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,104 @@ In a real app, you would likely use persistent, external resources, such as AWS
1919

2020
You can see the definition of Postgres and Redis in the `.controlplane/templates` directory.
2121

22+
## GitHub Review App Setup
23+
24+
For normal generated review apps in this repo, GitHub needs only one repository
25+
secret:
26+
27+
| Secret | Notes |
28+
| --- | --- |
29+
| `CPLN_TOKEN_STAGING` | Control Plane service-account token for `shakacode-open-source-examples-staging`. |
30+
31+
No GitHub repository variables are required for the standard review-app path.
32+
The generated workflow infers the review app prefix
33+
`qa-react-webpack-rails-tutorial` and staging org
34+
`shakacode-open-source-examples-staging` from `.controlplane/controlplane.yml`
35+
because that file defines exactly one app with
36+
`match_if_app_name_starts_with: true`.
37+
38+
Optional review-app variables:
39+
40+
| Variable | Notes |
41+
| --- | --- |
42+
| `CPLN_ORG_STAGING` | Override the inferred staging org. |
43+
| `REVIEW_APP_PREFIX` | Override or disambiguate the inferred review app prefix. |
44+
| `PRIMARY_WORKLOAD` | Public workload name used to discover the review URL; defaults to `rails`. |
45+
46+
For staging auto-deploys, also configure:
47+
48+
| Secret or variable | Value |
49+
| --- | --- |
50+
| `CPLN_TOKEN_STAGING` | Same staging Control Plane token used by review apps. |
51+
| `CPLN_ORG_STAGING` | `shakacode-open-source-examples-staging` |
52+
| `STAGING_APP_NAME` | `react-webpack-rails-tutorial-staging` |
53+
54+
For production promotion, configure a protected GitHub Environment named
55+
`production`:
56+
57+
| Secret or variable | Value |
58+
| --- | --- |
59+
| `CPLN_TOKEN_PRODUCTION` | Environment secret on `production`, not a repository or organization secret. |
60+
| `CPLN_ORG_PRODUCTION` | Environment variable on `production`: `shakacode-open-source-examples-production` |
61+
| `PRODUCTION_APP_NAME` | Environment variable on `production`: `react-webpack-rails-tutorial-production` |
62+
63+
Protect the `production` environment with required reviewers, enable prevent
64+
self-review, and consider disabling administrator bypass. Only release managers
65+
or similarly trusted maintainers should be able to approve the promotion job.
66+
The promotion workflow uses that environment before it can access
67+
`CPLN_TOKEN_PRODUCTION`, so the production token is not exposed to ordinary
68+
review-app or staging runs.
69+
70+
Advanced optional variables:
71+
72+
| Name | Notes |
73+
| --- | --- |
74+
| `REVIEW_APP_DEPLOYING_ICON_URL` | Cosmetic custom animated icon for review-app comments. Ignore this for the standard setup. |
75+
| `CPLN_CLI_VERSION` | Pin only when Control Plane CLI compatibility requires it. |
76+
| `CPFLOW_VERSION` | Runtime gem override. Leave unset when workflow wrappers are pinned to a GitHub commit SHA for upstream PR testing. |
77+
78+
## Control Plane Setup
79+
80+
The GitHub secret is only the automation credential. The Control Plane org also
81+
needs the app resources and runtime secrets that the workloads read at boot.
82+
83+
For review-app testing, the standard setup is:
84+
85+
| Control Plane item | Where | Notes |
86+
| --- | --- | --- |
87+
| Staging/review org | `shakacode-open-source-examples-staging` | The `CPLN_TOKEN_STAGING` service account must be able to create and update GVCs, workloads, images, identities, policies, and secrets in this org. |
88+
| Review app prefix | `qa-react-webpack-rails-tutorial` | Review apps are named `qa-react-webpack-rails-tutorial-<PR number>`. This is inferred from `.controlplane/controlplane.yml`. |
89+
| Review app secret dictionary | `qa-react-webpack-rails-tutorial-secrets` | Shared by generated review apps because the QA app entry uses `match_if_app_name_starts_with: true`. |
90+
91+
For staging deploys later, also use:
92+
93+
| Control Plane item | Where | Notes |
94+
| --- | --- | --- |
95+
| Staging app | `react-webpack-rails-tutorial-staging` | The `CPLN_TOKEN_STAGING` token deploys this app from `master`. |
96+
| Staging app secret dictionary | `react-webpack-rails-tutorial-staging-secrets` | Same required keys as the review app secret dictionary. |
97+
98+
For production promotion later, use a separate production org and token:
99+
100+
| Control Plane item | Where | Notes |
101+
| --- | --- | --- |
102+
| Production org | `shakacode-open-source-examples-production` | Do not give the staging token access to this org. |
103+
| Production app | `react-webpack-rails-tutorial-production` | Promotion copies the staging image into this app. |
104+
| Production app secret dictionary | `react-webpack-rails-tutorial-production-secrets` | Create before the first promotion. Use production-only values. |
105+
| Production service-account token | GitHub Environment secret `CPLN_TOKEN_PRODUCTION` | Keep this token in the protected `production` GitHub Environment only. |
106+
107+
The app secret dictionaries must include:
108+
109+
- `SECRET_KEY_BASE`
110+
- `RENDERER_PASSWORD`
111+
- `REACT_ON_RAILS_PRO_LICENSE`
112+
113+
Generate `SECRET_KEY_BASE` with `openssl rand -hex 64` and
114+
`RENDERER_PASSWORD` with `openssl rand -hex 32`. The review/staging template
115+
currently contains a test placeholder for `SECRET_KEY_BASE`; replace it with a
116+
secret-backed value before promoting production. The demo Postgres and Redis
117+
workloads are useful for review apps and staging demos. For real production,
118+
prefer managed services and update `DATABASE_URL` and `REDIS_URL` accordingly.
119+
22120
## Prerequisites
23121

24122
1. Ensure your [Control Plane](https://shakacode.controlplane.com) account is set up.
@@ -388,11 +486,11 @@ The production promotion workflow checks that production has all environment
388486
variable names present in staging; it does not compare secret values, workload
389487
environment variables, or Control Plane secret references.
390488

391-
The repository variables and secrets must match the app names in
392-
`.controlplane/controlplane.yml`. In particular, `REVIEW_APP_PREFIX` should
393-
include the `-pr` suffix for this app, such as
394-
`qa-react-webpack-rails-tutorial-pr`, so generated review apps are named
395-
`qa-react-webpack-rails-tutorial-pr-1234`.
489+
The GitHub settings and Control Plane resources must match the app names in
490+
`.controlplane/controlplane.yml`. For the standard review-app path, leave
491+
`REVIEW_APP_PREFIX` unset and let the workflow infer
492+
`qa-react-webpack-rails-tutorial`; generated review apps are named
493+
`qa-react-webpack-rails-tutorial-<PR number>`.
396494

397495
This allows teams to:
398496
- Preview changes in a production-like environment

.github/cpflow-help.md

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,26 +35,77 @@ You asked for review app help. These commands are generated by [cpflow](https://
3535
| Name | Required | Notes |
3636
| --- | --- | --- |
3737
| `CPLN_TOKEN_STAGING` | yes | Service-account token scoped to the staging Control Plane org on controlplane.com. |
38-
| `CPLN_TOKEN_PRODUCTION` | yes (for promote) | Service-account token scoped to the production Control Plane org on controlplane.com. |
38+
| `CPLN_TOKEN_PRODUCTION` | yes (for promote) | Store this as a secret on the protected `production` GitHub Environment, not as a repository or organization secret. |
3939
| `DOCKER_BUILD_SSH_KEY` | optional | Private SSH key used when Docker builds fetch private deps via `RUN --mount=type=ssh`. |
4040

41+
For normal generated review apps, `CPLN_TOKEN_STAGING` is the only required
42+
GitHub setting. The review app prefix and staging org are inferred from
43+
`.controlplane/controlplane.yml` when it defines exactly one app with
44+
`match_if_app_name_starts_with: true`.
45+
46+
For production promotion, create a GitHub Environment named `production`, add
47+
required reviewers, enable prevent self-review, and store
48+
`CPLN_TOKEN_PRODUCTION` as an environment secret there. The generated promotion
49+
workflow uses that environment before it can access production secrets.
50+
4151
### GitHub Actions variables
4252

4353
| Name | Required | Notes |
4454
| --- | --- | --- |
45-
| `CPLN_ORG_STAGING` | yes | Control Plane org on controlplane.com for staging and review apps. |
46-
| `CPLN_ORG_PRODUCTION` | yes (for promote) | Control Plane org on controlplane.com for production. |
55+
| `CPLN_ORG_STAGING` | optional for review apps; yes for staging | Override the staging/review Control Plane org inferred from `controlplane.yml`. |
56+
| `CPLN_ORG_PRODUCTION` | yes (for promote) | Control Plane org on controlplane.com for production. Prefer a `production` environment variable. |
4757
| `STAGING_APP_NAME` | yes | App name in `controlplane.yml` used as the staging deploy target. |
48-
| `PRODUCTION_APP_NAME` | yes (for promote) | App name in `controlplane.yml` used as the production deploy target. |
49-
| `REVIEW_APP_PREFIX` | yes | Prefix for per-PR review app names (e.g. `review-app`). |
50-
| `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. |
58+
| `PRODUCTION_APP_NAME` | yes (for promote) | App name in `controlplane.yml` used as the production deploy target. Prefer a `production` environment variable. |
59+
| `REVIEW_APP_PREFIX` | optional | Override or disambiguate the review app prefix inferred from `controlplane.yml`. |
60+
| `REVIEW_APP_DEPLOYING_ICON_URL` | optional, advanced | Cosmetic custom image URL for the animated deploying icon in review-app PR comments. Set to `none` to use the text fallback icon. |
5161
| `STAGING_APP_BRANCH` | optional | Custom staging branch. Custom branches must also appear in `cpflow-deploy-staging.yml`'s push filter. |
5262
| `PRIMARY_WORKLOAD` | optional | Workload polled for health and rollback (defaults to `rails`). |
5363
| `DOCKER_BUILD_EXTRA_ARGS` | optional | Newline-delimited extra docker build tokens (e.g. `--build-arg=FOO=bar`). |
5464
| `DOCKER_BUILD_SSH_KNOWN_HOSTS` | optional | SSH known_hosts entries when SSH build hosts are not GitHub.com. |
5565
| `HEALTH_CHECK_ACCEPTED_STATUSES` | optional | Space-separated HTTP statuses considered healthy on promote (default `200 301 302`). |
5666
| `CPLN_CLI_VERSION` | optional | Pin a specific `@controlplane/cli` version; falls back to the action default when unset. |
57-
| `CPFLOW_VERSION` | optional | Runtime gem-install override. When unset, cpflow is built from the pinned upstream workflow ref. When set, use the RubyGems version without a leading `v`. |
67+
| `CPFLOW_VERSION` | optional | Pin a published RubyGems version such as `5.0.0` or `5.0.0.rc.1`. Leave unset for normal generated workflows so the setup action builds `cpflow` from the same `control-plane-flow` GitHub ref used by the reusable workflow. |
68+
69+
</details>
70+
71+
<details>
72+
<summary>Advanced: testing unreleased control-plane-flow changes</summary>
73+
74+
Generated workflow wrappers have two related pins:
75+
76+
- The `uses: shakacode/control-plane-flow/...@<ref>` GitHub ref selects the reusable workflow code.
77+
- The `control_plane_flow_ref: <ref>` input tells the setup action which `control-plane-flow` source to check out and build when `CPFLOW_VERSION` is empty.
78+
79+
The GitHub ref is the runtime lock for workflow and action behavior. The
80+
RubyGems version is used to generate/update these wrappers and, only when
81+
`CPFLOW_VERSION` is set, to install the `cpflow` CLI at runtime. A downstream
82+
repo cannot rely on the gem alone because GitHub loads reusable workflow YAML
83+
from `shakacode/control-plane-flow`, not from RubyGems.
84+
85+
For normal releases, point both pins at a release tag such as `v5.0.0`.
86+
You may leave `CPFLOW_VERSION` unset, or set it to the matching RubyGems version
87+
without the leading `v`, such as `5.0.0`. If you set `CPFLOW_VERSION` for a
88+
prerelease, use RubyGems dot syntax such as `5.0.0.rc.1`; the release tag may
89+
use either `v5.0.0.rc.1` or `v5.0.0-rc.1`.
90+
91+
To update to a new stable release, install or bundle the new `cpflow` gem, run
92+
`cpflow generate-github-actions`, and commit the regenerated wrappers. Use
93+
`bin/pin-cpflow-github-ref vX.Y.Z` only when the generated files are already
94+
current and you only need to move the upstream GitHub ref.
95+
96+
For temporary downstream testing of an upstream PR before a gem is released, pin
97+
both values to the exact 40-character commit SHA and leave `CPFLOW_VERSION`
98+
unset:
99+
100+
```sh
101+
bin/pin-cpflow-github-ref <40-character-control-plane-flow-commit-sha>
102+
bin/test-cpflow-github-flow ruby /path/to/control-plane-flow/bin/cpflow
103+
```
104+
105+
Do not leave downstream apps pinned to a moving branch such as `main`. A branch
106+
can pick up beta or work-in-progress changes without a downstream PR changing.
107+
Use commit SHAs for short-lived PR testing, then switch to the release tag once
108+
the gem and tag exist.
58109

59110
</details>
60111

.github/workflows/cpflow-cleanup-stale-review-apps.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ permissions:
1010

1111
jobs:
1212
cleanup:
13-
uses: shakacode/control-plane-flow/.github/workflows/cpflow-cleanup-stale-review-apps.yml@3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
13+
uses: shakacode/control-plane-flow/.github/workflows/cpflow-cleanup-stale-review-apps.yml@db013e139af4ee8741f791c14ff825f13c0a1021
1414
with:
15-
control_plane_flow_ref: 3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
15+
control_plane_flow_ref: db013e139af4ee8741f791c14ff825f13c0a1021
1616
secrets: inherit

.github/workflows/cpflow-delete-review-app.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
contains(fromJson('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) ||
2727
(github.event_name == 'pull_request_target' && github.event.action == 'closed') ||
2828
github.event_name == 'workflow_dispatch'
29-
uses: shakacode/control-plane-flow/.github/workflows/cpflow-delete-review-app.yml@3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
29+
uses: shakacode/control-plane-flow/.github/workflows/cpflow-delete-review-app.yml@db013e139af4ee8741f791c14ff825f13c0a1021
3030
with:
31-
control_plane_flow_ref: 3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
31+
control_plane_flow_ref: db013e139af4ee8741f791c14ff825f13c0a1021
3232
secrets: inherit

.github/workflows/cpflow-deploy-review-app.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
github.event.issue.pull_request &&
3131
contains(fromJson('["+review-app-deploy","+review-app-deploy\n","+review-app-deploy\r\n"]'), github.event.comment.body) &&
3232
contains(fromJson('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association))
33-
uses: shakacode/control-plane-flow/.github/workflows/cpflow-deploy-review-app.yml@3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
33+
uses: shakacode/control-plane-flow/.github/workflows/cpflow-deploy-review-app.yml@db013e139af4ee8741f791c14ff825f13c0a1021
3434
with:
35-
control_plane_flow_ref: 3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
35+
control_plane_flow_ref: db013e139af4ee8741f791c14ff825f13c0a1021
3636
secrets: inherit

.github/workflows/cpflow-deploy-staging.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ permissions:
1616

1717
jobs:
1818
deploy-staging:
19-
uses: shakacode/control-plane-flow/.github/workflows/cpflow-deploy-staging.yml@3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
19+
uses: shakacode/control-plane-flow/.github/workflows/cpflow-deploy-staging.yml@db013e139af4ee8741f791c14ff825f13c0a1021
2020
with:
21-
control_plane_flow_ref: 3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
21+
control_plane_flow_ref: db013e139af4ee8741f791c14ff825f13c0a1021
2222
staging_app_branch_default: ""
2323
secrets: inherit

.github/workflows/cpflow-help-command.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ jobs:
2323
contains(fromJson('["+review-app-help","+review-app-help\n","+review-app-help\r\n"]'), github.event.comment.body) &&
2424
contains(fromJson('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) ||
2525
github.event_name == 'workflow_dispatch'
26-
uses: shakacode/control-plane-flow/.github/workflows/cpflow-help-command.yml@3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
26+
uses: shakacode/control-plane-flow/.github/workflows/cpflow-help-command.yml@db013e139af4ee8741f791c14ff825f13c0a1021

.github/workflows/cpflow-promote-staging-to-production.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,24 @@ on:
99
type: string
1010

1111
permissions:
12+
# The upstream reusable workflow's create-github-release job needs
13+
# contents: write, and callers must grant the union of callee permissions.
1214
contents: write
1315

1416
jobs:
1517
promote-to-production:
1618
if: github.event.inputs.confirm_promotion == 'promote'
17-
uses: shakacode/control-plane-flow/.github/workflows/cpflow-promote-staging-to-production.yml@3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
19+
# Keep the @ref in `uses:` and `control_plane_flow_ref` below in sync: the
20+
# first selects the reusable workflow, the second selects its shared actions.
21+
uses: shakacode/control-plane-flow/.github/workflows/cpflow-promote-staging-to-production.yml@db013e139af4ee8741f791c14ff825f13c0a1021
1822
with:
19-
control_plane_flow_ref: 3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
23+
control_plane_flow_ref: db013e139af4ee8741f791c14ff825f13c0a1021
24+
# Keep CPLN_TOKEN_PRODUCTION as a secret on this protected GitHub
25+
# Environment. Required reviewers approve the job before GitHub exposes
26+
# environment secrets to the upstream reusable workflow.
27+
production_environment: production
28+
# `secrets: inherit` passes all caller repository secrets to the trusted
29+
# upstream workflow. The upstream workflow only reads the named secrets it
30+
# references, but GitHub does not enforce that boundary. Strict consumers can
31+
# set CPFLOW_GITHUB_ACTIONS_REF to an immutable commit SHA.
2032
secrets: inherit

.github/workflows/cpflow-review-app-help.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ permissions:
1515
jobs:
1616
show-help:
1717
if: vars.REVIEW_APP_PREFIX != ''
18-
uses: shakacode/control-plane-flow/.github/workflows/cpflow-review-app-help.yml@3e0e7e1f0a35c15648cc9254b573b058d77ca8c4
18+
uses: shakacode/control-plane-flow/.github/workflows/cpflow-review-app-help.yml@db013e139af4ee8741f791c14ff825f13c0a1021

0 commit comments

Comments
 (0)