Skip to content

Commit 77eae2b

Browse files
authored
Document cpflow downstream setup (#747)
* Document cpflow downstream setup * Address cpflow setup review feedback * Clarify inferred review app overrides * Pin cpflow workflows to latest upstream review fix * Harden cpflow workflow secret forwarding * Pin cpflow workflows to shared resolver * Clarify cpflow production secret docs * Pin cpflow workflows to final review polish * Document final cpflow PR pin * Pin cpflow workflows to latest PR head * Pin cpflow workflows to latest upstream PR * Pin cpflow workflows to safety guard fixes * Pin cpflow workflows to final PR head * Simplify downstream cpflow docs * Address cpflow docs review follow-up * Regenerate cpflow wrappers from merged upstream * Regenerate cpflow wrappers from release polish * Pin cpflow workflows to v5.0.1
1 parent 1fb4cdd commit 77eae2b

15 files changed

Lines changed: 355 additions & 428 deletions

.controlplane/controlplane.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ apps:
5252

5353
react-webpack-rails-tutorial-staging:
5454
<<: *common
55-
# QA Apps are like Heroku review apps, but the use `prefix` so you can run a commmand like
55+
# QA Apps are like Heroku review apps, but they use `prefix` so you can run a command like
5656
# this to create a QA app for the tutorial app.
57-
# `cpflow setup gvc postgres redis rails -a qa-react-webpack-rails-tutorial-pr-1234`
57+
# `cpflow setup gvc postgres redis rails -a qa-react-webpack-rails-tutorial-1234`
5858
qa-react-webpack-rails-tutorial:
5959
<<: *common
6060
# Order matters!
Lines changed: 39 additions & 223 deletions
Original file line numberDiff line numberDiff line change
@@ -1,258 +1,74 @@
11
# Testing cpflow GitHub Actions Changes
22

3-
Use this guide when changing generated `cpflow-*` GitHub Actions, updating the
4-
`cpflow` generator version, or debugging review-app automation.
5-
6-
## What To Test
7-
8-
Test the flow in three layers:
9-
10-
1. Local generated-file checks catch YAML, metadata, and lint problems before a PR.
11-
2. GitHub workflow checks prove GitHub can load the workflow and run CI.
12-
3. A real review-app deploy proves the default-branch trusted actions, GitHub
13-
secrets, Docker build, and Control Plane deploy all work together.
14-
15-
The third layer matters because the review-app workflow intentionally checks out
16-
trusted workflow sources from the repository default branch before passing
17-
Control Plane secrets to local composite actions. A PR branch can contain fixed
18-
`.github/actions/*` files, but the deploy job still loads those local actions
19-
from `master` until the fix is merged there.
20-
21-
## How Upstream Code Is Pinned
22-
23-
Generated `cpflow-*` workflows are thin wrappers around reusable workflows in
24-
`shakacode/control-plane-flow`. GitHub reusable workflows cannot be loaded from
25-
a Ruby gem; GitHub resolves them from a repository ref. Each wrapper therefore
26-
has two upstream pins that must stay in sync:
27-
28-
```yaml
29-
uses: shakacode/control-plane-flow/.github/workflows/cpflow-deploy-review-app.yml@<ref>
30-
with:
31-
control_plane_flow_ref: <ref>
32-
```
33-
34-
`uses: ...@<ref>` chooses the reusable workflow file. `control_plane_flow_ref`
35-
chooses the same upstream checkout for shared composite actions and, when
36-
`CPFLOW_VERSION` is unset, the source used to build and install the `cpflow` gem
37-
inside the workflow.
38-
39-
The stable release path is still gem-driven:
40-
41-
1. Install or update to a released `cpflow` gem.
42-
2. Run `cpflow generate-github-actions --staging-branch master`.
43-
3. The generated wrappers use `v<cpflow gem version>` as the upstream ref.
44-
45-
That tag should point to the same source that produced the RubyGems release, so
46-
the workflow code is locked to a release tag rather than a moving branch. Do not
47-
pin production workflows to `main` or a feature branch. For unreleased testing,
48-
pin to an immutable commit SHA, not a branch name, then regenerate or repin to
49-
the release tag after the upstream release is published.
50-
51-
`CPFLOW_VERSION` is separate from the GitHub workflow ref. If the repository
52-
variable is set, the setup action runs `gem install cpflow -v <version>`. If it
53-
is unset, the setup action builds `cpflow` from the checked-out upstream ref.
54-
For normal releases, either leave `CPFLOW_VERSION` unset while using the matching
55-
`v<version>` upstream tag, or set `CPFLOW_VERSION` to the same released gem
56-
version without the leading `v`.
57-
58-
This repo is currently pinned to an upstream commit SHA because the reusable
59-
workflow change was tested before a new `cpflow` gem release existed. That is
60-
safer than pinning a branch, but it should be treated as a temporary test pin
61-
until the next upstream release tag is available.
62-
63-
What is tied to the upstream repo:
64-
65-
- The downstream workflow wrapper hardcodes `shakacode/control-plane-flow` in
66-
`uses:`.
67-
- The reusable workflow file comes from the ref after `@`.
68-
- The reusable workflow checks out `control-plane-flow` at
69-
`control_plane_flow_ref` to load shared composite actions.
70-
- When `CPFLOW_VERSION` is empty, the setup action builds and installs the
71-
`cpflow` gem from that checked-out repository ref.
72-
73-
What is tied to RubyGems:
74-
75-
- A released `cpflow` gem is the normal source used to generate downstream
76-
workflow wrappers.
77-
- The `CPFLOW_VERSION` repository variable is a runtime override that runs
78-
`gem install cpflow -v <version>` inside workflows.
79-
80-
For stable downstream automation, prefer the release path: generate from a
81-
released gem and pin wrappers to the matching upstream release tag. For
82-
pre-release validation, pin to a full commit SHA from the upstream PR, never a
83-
moving branch.
84-
85-
## Testing An Unmerged Upstream PR Downstream
86-
87-
You can test an upstream `control-plane-flow` PR in this downstream app before
88-
merging upstream, without publishing a gem. Use an immutable commit SHA from the
89-
upstream PR branch:
90-
91-
1. Push the upstream PR branch and copy its head commit SHA.
92-
2. In a downstream test branch, pin every generated wrapper ref:
93-
94-
```sh
95-
bin/pin-cpflow-github-ref <upstream-pr-sha>
96-
```
97-
98-
The helper accepts release tags and full 40-character commit SHAs by default.
99-
It rejects branch names such as `main` or `feature/foo`; use
100-
`--allow-moving-ref` only for short-lived local experiments that will not be
101-
committed. The resulting diff should replace both pins in each reusable
102-
workflow call:
103-
104-
```yaml
105-
uses: shakacode/control-plane-flow/.github/workflows/cpflow-deploy-review-app.yml@<upstream-pr-sha>
106-
with:
107-
control_plane_flow_ref: <upstream-pr-sha>
108-
```
109-
110-
3. Keep `CPFLOW_VERSION` unset unless you intentionally want to test a released
111-
RubyGems version instead of building `cpflow` from the upstream PR SHA.
112-
4. Run `bin/test-cpflow-github-flow`.
113-
5. Open a downstream PR and trigger a real review app with a comment whose body
114-
is exactly:
115-
116-
```text
117-
+review-app-deploy
118-
```
119-
120-
6. Verify the deploy logs show the expected upstream commit SHA, the setup step
121-
prints the expected `cpflow` version/source, and the review app URL returns
122-
HTTP 200.
123-
7. After the upstream PR merges and releases, regenerate or repin downstream to
124-
the release tag instead of leaving the temporary commit SHA forever.
125-
126-
This tests the real reusable workflow and shared composite actions from the
127-
upstream PR. It avoids merging upstream blind while also avoiding a mutable
128-
branch ref in downstream automation.
3+
Generic reusable-workflow behavior belongs upstream in the
4+
[`control-plane-flow` CI automation guide](https://github.com/shakacode/control-plane-flow/blob/main/docs/ci-automation.md).
5+
Use this repo note only as the canary checklist for
6+
`react-webpack-rails-tutorial`.
1297

1308
## Local Checks
1319

132-
After regenerating the flow, run these checks from the repository root. If
133-
`cpflow` is installed as a gem, use `cpflow` directly:
10+
After regenerating the generated `cpflow-*` wrappers, run:
13411

13512
```sh
136-
bin/conductor-exec cpflow generate-github-actions --staging-branch master
137-
bin/test-cpflow-github-flow
13+
bin/conductor-exec bin/test-cpflow-github-flow
13814
```
13915

140-
When testing an unreleased upstream `control-plane-flow` checkout, replace
141-
`cpflow` with that checkout's `bin/cpflow`:
16+
When testing an unreleased upstream `control-plane-flow` checkout, pass that
17+
checkout's `bin/cpflow`:
14218

14319
```sh
144-
bin/conductor-exec ruby /path/to/control-plane-flow/bin/cpflow generate-github-actions --staging-branch master
145-
bin/test-cpflow-github-flow ruby /path/to/control-plane-flow/bin/cpflow
20+
bin/conductor-exec bin/test-cpflow-github-flow ruby /path/to/control-plane-flow/bin/cpflow
14621
```
14722

148-
Why the explicit description check exists: GitHub parses expression-like snippets
149-
inside composite action metadata, including `description:` fields. Literal
150-
examples such as `${{ vars.SOME_VALUE }}` can fail action loading before any
151-
shell step starts. The wrapper runs `cpflow github-flow-readiness`, parses the
152-
generated YAML, checks action input descriptions for literal GitHub expressions,
153-
checks that every generated wrapper keeps `uses:` and `control_plane_flow_ref`
154-
on the same upstream ref across all `cpflow-*` wrappers, checks that any
155-
secret-inheriting reusable workflow passes `control_plane_flow_ref`, and runs
156-
`actionlint -ignore 'SC2129' .github/workflows/cpflow-*.yml`.
157-
158-
## PR Checks
23+
## Testing An Upstream PR Downstream
15924

160-
Open a normal PR for the generated-file diff and wait for CI. The workflow PR
161-
itself is useful for syntax and CI validation, but it does not fully prove
162-
review-app deployment changes that live under `.github/actions/`.
163-
164-
For top-level workflow edits, you can manually dispatch the PR branch workflow:
25+
Use an immutable upstream commit SHA, not a branch:
16526

16627
```sh
167-
gh workflow run cpflow-deploy-review-app.yml --ref <branch> -f pr_number=<pr-number>
28+
bin/pin-cpflow-github-ref <40-character-control-plane-flow-commit-sha>
29+
bin/conductor-exec bin/test-cpflow-github-flow ruby /path/to/control-plane-flow/bin/cpflow
16830
```
16931

170-
This loads the workflow file from `<branch>`, but the deploy workflow's
171-
`Checkout trusted workflow sources` step still checks out `master` before using
172-
local composite actions with secrets. Treat this as a partial smoke test, not as
173-
proof that PR-branch composite action changes work.
174-
175-
## Post-Merge Review-App Test
32+
Leave `CPFLOW_VERSION` unset while testing a commit SHA. After the upstream gem
33+
and tag ship, repin wrappers to the release tag, such as `v5.0.1`.
17634

177-
After the workflow PR merges to `master`, test a real review-app deployment:
35+
## Review App Canary
17836

179-
1. Pick a same-repository PR to use as the canary.
180-
2. If the review app does not exist yet, comment exactly `+review-app-deploy` on
181-
that PR.
182-
3. If a previous deploy run failed, rerun the failed deploy run after the
183-
workflow PR is merged.
184-
4. Confirm the deploy run checks out `master` at the merge commit in
185-
`Checkout trusted workflow sources`.
186-
5. Confirm `Setup environment` succeeds and prints the expected `cpflow` version.
187-
6. Confirm `Check if review app exists`, `Build Docker image`, and
188-
`Deploy to Control Plane` all run as expected.
189-
7. Open the review-app URL from the PR comment or deployment status and verify
190-
it returns HTTP 200.
37+
1. Open or reuse a same-repository PR.
38+
2. Comment exactly `+review-app-deploy`.
39+
3. Confirm the deploy job checks out the expected upstream Control Plane Flow
40+
source selected by the generated wrapper's `uses:` ref.
41+
4. Confirm `Setup environment`, `Check if review app exists`,
42+
`Build Docker image`, and `Deploy to Control Plane` all pass.
43+
5. Open the review-app URL from the PR comment and verify it returns HTTP 200.
19144

192-
Use the generated app name from the workflow log:
45+
Comment-triggered workflows run from the repository default branch. If you are
46+
testing edits to a workflow file before merging, manually dispatch the PR branch
47+
workflow:
19348

194-
```text
195-
APP_NAME: ${REVIEW_APP_PREFIX}-${PR_NUMBER}
49+
```sh
50+
gh workflow run cpflow-deploy-review-app.yml --ref <branch> -f pr_number=<pr-number>
19651
```
19752

198-
This is a template from the workflow output, not a literal command to evaluate
199-
unless those environment variables are already set. For this repo, verify the
200-
actual `REVIEW_APP_PREFIX` repository variable before assuming the final app
201-
name.
202-
20353
## Troubleshooting Signals
20454

205-
### Composite action metadata fails before setup
206-
207-
Error shape:
208-
209-
```text
210-
Unrecognized named-value: 'vars'
211-
Failed to load ./.github/actions/cpflow-setup-environment/action.yml
212-
```
213-
214-
Cause: GitHub parsed a literal expression inside composite action metadata,
215-
usually an input description. Because trusted local actions come from `master`,
216-
fix and merge the generated action metadata on `master`, then rerun the deploy.
217-
218-
### Setup succeeds, then `cpflow exists` reports token format
219-
220-
Error shape:
55+
### Token Format Error
22156

22257
```text
22358
ERROR: Unknown API token format. Please re-run 'cpln profile login' or set the correct CPLN_TOKEN env variable.
22459
```
22560

226-
Cause: the workflow can read `CPLN_TOKEN_STAGING`, but the value is not a valid
227-
Control Plane service-account token for the installed Control Plane CLI. Rotate
228-
the GitHub secret, then rerun the failed deploy job.
229-
230-
### PR pushes do not create a new review app
61+
The workflow can read `CPLN_TOKEN_STAGING`, but the secret value is not a valid
62+
Control Plane service-account token. Rotate the GitHub secret and rerun the
63+
deploy.
23164

232-
This is expected. Pushes redeploy only after the review app already exists.
233-
Create the first review app by commenting exactly:
65+
### No Deploy After Push
23466

235-
```text
236-
+review-app-deploy
237-
```
67+
Pushes redeploy only after the review app already exists. Create the first one
68+
with an exact `+review-app-deploy` PR comment.
23869

239-
## Ways To Make This Easier
70+
### No Visible Workflow Changes
24071

241-
- Extend `bin/pin-cpflow-github-ref` so it can also run
242-
`bin/test-cpflow-github-flow`, open a downstream PR, and print or post the
243-
exact `+review-app-deploy` command needed to start the canary deploy.
244-
- Add CI coverage that runs `bin/test-cpflow-github-flow` on generated workflow
245-
changes, so ref mismatches and action metadata parsing issues are caught
246-
before review.
247-
- Add a no-secret GitHub Actions smoke workflow that loads generated local
248-
composite actions from the PR branch and fails fast on action metadata parsing.
249-
- Extend `bin/test-cpflow-github-flow` as more local cpflow GitHub Actions
250-
checks become worth standardizing.
251-
- Add an early token sanity step after `Setup environment` so invalid
252-
`CPLN_TOKEN_STAGING` and `CPLN_TOKEN_PRODUCTION` values fail with a named
253-
"validate Control Plane token" step instead of surfacing later during
254-
`cpflow exists`.
255-
- Keep a tiny canary PR open for review-app workflow testing so post-merge
256-
deploy verification does not depend on whichever feature PR happens to exist.
257-
- Upstream the metadata-description check to `cpflow github-flow-readiness` so
258-
downstream repos get the guard automatically.
72+
Comment-triggered runs use workflow files from `master`. For PR-branch workflow
73+
edits, use `workflow_dispatch` as shown above or merge first and test with a
74+
real review-app deploy.

0 commit comments

Comments
 (0)