-
Notifications
You must be signed in to change notification settings - Fork 1
ci: gate production deploys with a protected environment #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| # Production deployment environment runbook | ||
|
|
||
| Status: prepared; human execution required | ||
|
|
||
| This runbook creates the GitHub `production` environment that gates | ||
| `.github/workflows/deploy.yml`. An agent must not execute the settings change: | ||
| the shared agent identity is `willwashburn`, and an identity that can create, | ||
| edit, or delete its own gate is not constrained by that gate. | ||
|
|
||
| The environment needs two independent controls. Required reviewers and | ||
| prevent-self-review determine **who** may approve a deployment. A custom | ||
| deployment branch policy determines **what** may deploy by restricting the | ||
| environment to `main`. Neither control substitutes for the other. | ||
|
|
||
| ## Required human decision | ||
|
|
||
| Chief must confirm the required reviewer before this runbook is executed. | ||
| CMO recommends `khaliqgant` (GitHub user ID `1724137`), the only known human | ||
| organization identity that is neither `willwashburn` nor a member of the | ||
| agent-oriented `claws` team. Do not substitute `willwashburn`; agents use that | ||
| credential and could approve their own deployment. | ||
|
|
||
| ## Configure with the GitHub UI | ||
|
|
||
| 1. As a human repository administrator, open **Settings → Environments** for | ||
| `AgentWorkforce/agentrelay.com`. | ||
| 2. Create an environment named exactly `production`. | ||
| 3. Attempt to enable **Required reviewers** and add the chief-confirmed human | ||
| reviewer. Availability of required environment reviewers has not been | ||
| established for this free organization plan. If GitHub does not offer the | ||
| control or refuses the change, stop and report that result; do not continue | ||
| as though the reviewer gate exists. | ||
| 4. Enable **Prevent self-review**. | ||
| 5. Under **Deployment branches and tags**, select **Selected branches and | ||
| tags**, add a custom deployment branch rule for exactly `main`, and do not | ||
| enable the branch-protection-based option. This repository has no branch | ||
| protection rules, so that option would not constrain the deployable ref. | ||
| 6. Save the protection rules. | ||
|
|
||
| ## Configure with the GitHub API | ||
|
|
||
| After chief confirms `khaliqgant`, a human repository administrator may run | ||
| the following. The first request is also the availability test for required | ||
| environment reviewers on this organization plan. If GitHub refuses it, stop | ||
| and report the response; do not create only the branch policy and treat the | ||
| environment as complete. | ||
|
|
||
| ```bash | ||
| gh api --method PUT \ | ||
| repos/AgentWorkforce/agentrelay.com/environments/production \ | ||
| --input - <<'JSON' | ||
| { | ||
| "wait_timer": 0, | ||
| "prevent_self_review": true, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: The runbook's API example and UI steps don't disable administrator bypass. According to GitHub's deployment protection rules documentation, administrators can bypass protection rules and force deployments by default, and this is a separate setting from prevent_self_review. Since the shared willwashburn identity has repository-administrator access, it could still bypass the required human reviewer gate unless can_admins_bypass is explicitly set to false. Add that setting to the API payload, add a UI step to disable admin bypass, and include the value in the required read-back check. Prompt for AI agents |
||
| "reviewers": [ | ||
|
Comment on lines
+53
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Because the shared Useful? React with 👍 / 👎. |
||
| { | ||
| "type": "User", | ||
| "id": 1724137 | ||
| } | ||
| ], | ||
| "deployment_branch_policy": { | ||
| "protected_branches": false, | ||
| "custom_branch_policies": true | ||
| } | ||
| } | ||
| JSON | ||
|
|
||
| gh api --method POST \ | ||
| repos/AgentWorkforce/agentrelay.com/environments/production/deployment-branch-policies \ | ||
| -f name=main | ||
| ``` | ||
|
|
||
| ## Required read-back | ||
|
|
||
| The resident `agentrelay-com` agent must independently run this read-only check | ||
| after the human reports completion: | ||
|
|
||
| ```bash | ||
| gh api repos/AgentWorkforce/agentrelay.com/environments/production \ | ||
| --jq '{name, protection_rules}' | ||
|
|
||
| gh api \ | ||
| repos/AgentWorkforce/agentrelay.com/environments/production/deployment-branch-policies \ | ||
| --jq '{total_count, branches: [.branch_policies[].name]}' | ||
| ``` | ||
|
|
||
| The workflow PR must not merge unless all of these are true: | ||
|
|
||
| - the response names `production`; | ||
| - `protection_rules` is non-empty; | ||
| - a `required_reviewers` rule names the chief-confirmed human reviewer; and | ||
| - the deployment-branch-policy response contains exactly one entry, `main`; | ||
| - `.github/workflows/deploy.yml` references `environment: production` on the | ||
| `deploy-production` job. | ||
|
|
||
| The reviewer rule answers who can approve. The custom branch policy answers | ||
| what can deploy. Keeping `workflow_dispatch` is safe only when the environment | ||
| rejects every triggering ref except `main`. | ||
|
|
||
| Merging the workflow reference before the protection exists would allow GitHub | ||
| to auto-create an unprotected environment during a production deploy. That is | ||
| a phantom gate and is explicitly prohibited. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Because GitHub auto-creates the
productionenvironment with no protection rules on the first deployment when it doesn't already exist, the protection provided byenvironment: productionsilently disappears if the environment is missing or its reviewers are later removed. The repository risk here is mitigated by the human-only runbook and merge ordering, but the workflow itself never verifies thatprotection_rulesis non-empty before runningwrangler deploy. Consider adding a defense-in-depth guard step near the start of the job that queriesrepos/{owner}/{repo}/environments/productionand fails the build unless arequired_reviewersprotection rule is present, so a misconfigured or auto-created phantom gate can't slip through to production.Prompt for AI agents