Skip to content

Commit 0358b99

Browse files
authored
Fix production promotion environment secret access (#754)
* Fix production promotion environment secret access * Address production promotion review feedback * Tighten production promotion review fixes * Clarify production setup ref validation
1 parent 80c8b0d commit 0358b99

6 files changed

Lines changed: 668 additions & 55 deletions

File tree

.controlplane/readme.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,21 +85,27 @@ must be gated by a protected GitHub Environment named `production`:
8585

8686
Protect the `production` environment with required reviewers, prevent
8787
self-review, and consider disabling administrator bypass. Do not store
88-
`CPLN_TOKEN_PRODUCTION` as a repository or organization secret. The generated
89-
promotion wrapper does not use `secrets: inherit`; GitHub exposes the production
90-
token only after the environment approval gate passes.
88+
`CPLN_TOKEN_PRODUCTION` as a repository or organization secret. The production
89+
promotion workflow intentionally runs as a normal caller-repo job with
90+
`environment: production`, then checks out the pinned `control-plane-flow`
91+
release for shared actions. GitHub exposes the production token only after the
92+
environment approval gate passes.
93+
Keep `CPLN_TOKEN_PRODUCTION` absent from repository and organization secrets so
94+
a broader secret cannot mask a missing environment secret.
9195

9296
If promotion fails with
9397
`CPLN_TOKEN_PRODUCTION is not set. Add it as a secret on the 'production' GitHub Environment.`,
94-
the token is missing from the environment scope. A repository or organization
95-
secret with the same name is not enough for this workflow. Create or verify the
96-
environment secret with:
98+
the token is missing from the environment scope or the workflow job is no longer
99+
declaring `environment: production`. Create or verify the environment secret
100+
and confirm there is no same-named repository or organization secret:
97101
You need permission to manage repository environments and secrets to run these
98102
commands.
99103

100104
```sh
101105
gh secret set CPLN_TOKEN_PRODUCTION --repo shakacode/react-webpack-rails-tutorial --env production
102106
gh secret list --repo shakacode/react-webpack-rails-tutorial --env production
107+
gh secret list --repo shakacode/react-webpack-rails-tutorial
108+
gh secret list --org shakacode | grep '^CPLN_TOKEN_PRODUCTION[[:space:]]' || true
103109
```
104110

105111
The matching Control Plane resources are:

.controlplane/shakacode-team.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,26 +54,31 @@ Production promotion uses a protected GitHub Environment named `production`:
5454

5555
Protect the `production` environment with required reviewers, enable prevent
5656
self-review, and consider disabling administrator bypass. Do not store
57-
`CPLN_TOKEN_PRODUCTION` as a repository or organization secret. The caller
58-
passes `production_environment: production`; the upstream reusable workflow runs
59-
its production job in that environment, and GitHub injects the production token
60-
only after approval.
57+
`CPLN_TOKEN_PRODUCTION` as a repository or organization secret. The production
58+
promotion workflow is intentionally a normal caller-repo job with
59+
`environment: production`; it checks out the pinned `control-plane-flow` release
60+
for shared actions after GitHub makes the environment secret available.
61+
Keep `CPLN_TOKEN_PRODUCTION` absent from repository and organization secrets so
62+
a broader secret cannot mask a missing environment secret.
6163

6264
If promotion fails with
6365
`CPLN_TOKEN_PRODUCTION is not set. Add it as a secret on the 'production' GitHub Environment.`,
64-
the token is missing from the environment scope. A repository or organization
65-
secret with the same name is not enough for this workflow. Create or verify the
66-
environment secret with:
66+
the token is missing from the environment scope or the workflow job is no longer
67+
declaring `environment: production`. Create or verify the environment secret
68+
and confirm there is no same-named repository or organization secret:
6769
You need permission to manage repository environments and secrets to run these
6870
commands.
6971

7072
```sh
7173
gh secret set CPLN_TOKEN_PRODUCTION --repo shakacode/react-webpack-rails-tutorial --env production
7274
gh secret list --repo shakacode/react-webpack-rails-tutorial --env production
75+
gh secret list --repo shakacode/react-webpack-rails-tutorial
76+
gh secret list --org shakacode | grep '^CPLN_TOKEN_PRODUCTION[[:space:]]' || true
7377
```
7478

75-
Generated caller workflows pass only the named secrets each upstream workflow
76-
needs. They do not use `secrets: inherit`; `CPLN_TOKEN_PRODUCTION` is supplied
79+
Generated reusable-workflow callers pass only the named secrets each upstream
80+
workflow needs. They do not use `secrets: inherit`. Production promotion is the
81+
exception: it stays as a caller-owned job so `CPLN_TOKEN_PRODUCTION` is supplied
7782
only by the protected `production` Environment after approval.
7883

7984
Persistent staging and production apps must be bootstrapped once before the

.github/cpflow-help.md

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,35 +66,42 @@ Production promotion is part of the generated flow, but keep it protected:
6666
| `PRODUCTION_APP_NAME` | Prefer `production` Environment variable | Production app name from `controlplane.yml`. |
6767

6868
Configure the `production` GitHub Environment with required reviewers and
69-
prevent self-review. The generated promotion wrapper passes only the staging
70-
token from repository secrets; GitHub injects `CPLN_TOKEN_PRODUCTION` only after
71-
the environment approval gate passes.
69+
prevent self-review. Production promotion intentionally runs as a normal
70+
caller-repo workflow job with `environment: production`, then checks out the
71+
pinned `control-plane-flow` release for shared actions. Do not move production
72+
promotion behind a cross-repo reusable workflow: GitHub does not expose this
73+
repo's environment secrets to that called workflow.
74+
75+
Keep `CPLN_TOKEN_PRODUCTION` absent from repository and organization secrets. A
76+
normal environment-gated job cannot tell which secret scope supplied a nonempty
77+
value, so a broader secret with the same name can mask a missing environment
78+
secret.
7279

7380
If promotion fails with
7481
`CPLN_TOKEN_PRODUCTION is not set. Add it as a secret on the 'production' GitHub Environment.`,
75-
the token is missing from the environment scope. A repository or organization
76-
secret with the same name is not enough for this workflow. Create or verify the
77-
environment secret with:
82+
the token is missing from the environment scope or the workflow job is no longer
83+
declaring `environment: production`. Create or verify the environment secret
84+
and confirm there is no same-named repository or organization secret:
7885
You need permission to manage repository environments and secrets to run these
7986
commands.
8087

8188
```sh
8289
gh secret set CPLN_TOKEN_PRODUCTION --repo shakacode/react-webpack-rails-tutorial --env production
8390
gh secret list --repo shakacode/react-webpack-rails-tutorial --env production
91+
gh secret list --repo shakacode/react-webpack-rails-tutorial
92+
gh secret list --org shakacode | grep '^CPLN_TOKEN_PRODUCTION[[:space:]]' || true
8493
```
8594

8695
Before the first promotion, bootstrap the production app the same way in the
8796
production org, using production-only secrets and values.
8897

8998
## Version Locking
9099

91-
Generated wrappers pin Control Plane Flow once with the reusable workflow
92-
`uses:` ref, for example `@v5.0.4`. For stable releases,
93-
this ref should be a release tag. The upstream reusable workflow automatically
94-
loads its matching shared actions from GitHub's workflow context, so downstream
95-
wrappers should not pass a duplicate Control Plane Flow ref input. If your
96-
generated wrappers still include a `with:` block whose only purpose is to repeat
97-
the same ref, regenerate them with a newer `cpflow`.
100+
Generated wrappers pin Control Plane Flow with a release tag, for example
101+
`v5.0.4`. Reusable review-app, staging, cleanup, and helper workflows pin the
102+
tag in their `uses:` ref. Production promotion pins the same tag in the
103+
`Checkout control-plane-flow actions` step so the caller-owned job can keep
104+
`environment: production` and receive production environment secrets directly.
98105

99106
Leave `CPFLOW_VERSION` unset so the workflow builds cpflow from the same
100107
checked-out upstream source. If you set `CPFLOW_VERSION`, it must match the

0 commit comments

Comments
 (0)