-
Notifications
You must be signed in to change notification settings - Fork 5
Add reusable GitHub Actions flow generator #278
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
Draft
justin808
wants to merge
28
commits into
main
Choose a base branch
from
add-github-flow-generator
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 2 commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
25f8094
Add GitHub Actions flow generator
justin808 2f6a434
Harden generated GitHub flow workflows
justin808 8a5e4d8
Skip review app deploys until repo is configured
justin808 9215b4c
Fix external GitHub flow generator execution
justin808 b94b0e1
Stabilize latest image integration spec
justin808 8787015
Support SSH-backed Docker builds in GitHub flow
justin808 501e4c6
Fix generator spec Rubocop memoization
justin808 c983f12
Harden generated GitHub flow workflows
justin808 746e476
Validate staging config only on deployable refs
justin808 ecc4335
Document GitHub flow readiness checks
justin808 2f44d27
Support JS package managers in generated Dockerfile
justin808 cc0c6a6
Infer Ruby version for generated Dockerfile
justin808 9233492
Generate review-app ready Rails scaffolds
justin808 38a8155
Tighten generated GitHub flow scaffolds
justin808 6973c9e
Document AI rollout prompt and stop conditions
justin808 2f8ce1d
Add AI rollout prompt command and local bootstrap mode
justin808 b95a011
Add GitHub flow readiness command
justin808 20a6a27
Fix shorthand RubyGems readiness checks
justin808 2e2ca24
Harden generated GitHub flow scaffolding
justin808 901d088
Document optional Docker build inputs in help workflow
justin808 2890bf3
Preserve frontend precompile hooks in generated Dockerfiles
justin808 e58af0f
Tighten Docker build arg handling in GitHub flow
justin808 46b6fdc
Harden GitHub flow generation and readiness checks
justin808 9519b7b
Address PR review feedback on GitHub flow generator
justin808 9a6305c
Sync docs/commands.md with updated copy-image-from-upstream help text
justin808 6f53828
Address review feedback: correctness, robustness, and dedup
justin808 46c4871
Fix rollback guard and dedupe SQLite template copies
justin808 2daf69b
Address PR #278 bot review feedback: security, silent failures, consi…
justin808 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,28 +1,197 @@ | ||
| # CI Automation, Review Apps, Staging, and Promoting to Production | ||
|
|
||
| ## Setting up Tokens for CI Automation | ||
|
|
||
| This example uses Github Actions. The same applies to Circle CI and other similar CI/CD tools. | ||
|
|
||
| 1. Ensure that you have two orgs: | ||
| 1. `company-staging` (for staging deployments, developers have access) | ||
| 2. `company-production` (for production deployments, limited access) | ||
| 2. Create the token for staging org and set on Github repository secrets and variables: | ||
| 1. Go to the Control Plane UI for your organization's staging org | ||
| 2. Make a new service account called `github-actions-staging` | ||
| 3. Assign to the group `superusers` | ||
| 4. Click "Keys" and create a one with description "Github Actions" and copy the token (or download it). | ||
| 5. Add this key to your Github repository **secrets** as `CPLN_TOKEN_STAGING` | ||
| 6. Add another key to your Github repository **variables** as `CPLN_ORG_STAGING` with the name of the staging org, like `company-staging` | ||
| 3. Create the token for production org, and set on Github repository secrets and variables. | ||
| 1. Go to the Control Plane UI for your organization's production org | ||
| 2. Make a new service account called `github-actions-production` | ||
| 3. Assign to the group `superusers` | ||
| 4. Click "Keys" and create a one with description "Github Actions" and copy the token (or download it). | ||
| 5. Add this key to your Github repository **secrets** as `CPLN_TOKEN_PRODUCTION` | ||
| 6. Add another key to your Github repository **variables** as `CPLN_ORG_PRODUCTION` with the name of the production org, like `company-production` | ||
| 4. Create a few more ENV **variables** for the app name and the app prefix: | ||
| 1. `STAGING_APP_NAME` - the name of the app in Control Plane for staging, which is the GVC name, like `app-name-staging` | ||
| 2. `PRODUCTION_APP_NAME` - the name of the app in Control Plane for production, which is the GVC name, like `app-name-production` | ||
| 3. `REVIEW_APP_PREFIX` - the prefix for the review apps in Control Plane. The Review apps are named `$REVIEW_APP_PREFIX-pr-$PR_NUMBER` | ||
| 5. All in all, you should have 2 secrets and 5 variables set in your Github repository | ||
| # GitHub Actions Flow for Review Apps, Staging, and Production | ||
|
|
||
| This document describes the reusable GitHub Actions scaffolding generated by `cpflow generate-github-actions`. | ||
|
|
||
| The goal is to bring the Heroku Flow model into any `cpflow` project: | ||
|
|
||
| 1. Comment `/deploy-review-app` on a pull request to create or update a review app. | ||
| 2. Push more commits to the PR to auto-redeploy that review app. | ||
| 3. Push to the staging branch to auto-deploy staging. | ||
| 4. Promote the already-built staging artifact to production from the Actions tab. | ||
| 5. Let a nightly workflow clean up stale review apps. | ||
|
|
||
| ## Bootstrap a Project | ||
|
|
||
| Run these commands from the project root: | ||
|
|
||
| ```sh | ||
| # Create .controlplane/ if it does not exist yet | ||
| cpflow generate | ||
|
|
||
| # Add reusable GitHub Actions for the Control Plane flow | ||
| cpflow generate-github-actions | ||
| ``` | ||
|
|
||
| The second command writes namespaced files so they can coexist with an app's existing CI: | ||
|
|
||
| - `.github/actions/cpflow-build-docker-image/action.yml` | ||
| - `.github/actions/cpflow-delete-control-plane-app/action.yml` | ||
| - `.github/actions/cpflow-delete-control-plane-app/delete-app.sh` | ||
| - `.github/actions/cpflow-setup-environment/action.yml` | ||
| - `.github/workflows/cpflow-review-app-help.yml` | ||
| - `.github/workflows/cpflow-help-command.yml` | ||
| - `.github/workflows/cpflow-deploy-review-app.yml` | ||
| - `.github/workflows/cpflow-delete-review-app.yml` | ||
| - `.github/workflows/cpflow-deploy-staging.yml` | ||
| - `.github/workflows/cpflow-promote-staging-to-production.yml` | ||
| - `.github/workflows/cpflow-cleanup-stale-review-apps.yml` | ||
|
|
||
| ## Required `.controlplane/controlplane.yml` Structure | ||
|
|
||
| The generated workflows assume that `.controlplane/controlplane.yml` defines: | ||
|
|
||
| - one staging app | ||
| - one review-app prefix with `match_if_app_name_starts_with: true` | ||
| - one production app with `upstream` pointing to staging | ||
|
|
||
| Typical shape: | ||
|
|
||
| ```yaml | ||
| aliases: | ||
| common: &common | ||
| cpln_org: my-org-staging | ||
| default_location: aws-us-east-2 | ||
| setup_app_templates: | ||
| - app | ||
| - postgres | ||
| - redis | ||
| - rails | ||
| app_workloads: | ||
| - rails | ||
| additional_workloads: | ||
| - postgres | ||
| - redis | ||
|
|
||
| apps: | ||
| my-app-staging: | ||
| <<: *common | ||
|
|
||
| my-app-review: | ||
| <<: *common | ||
| match_if_app_name_starts_with: true | ||
| hooks: | ||
| post_creation: bundle exec rails db:prepare | ||
| pre_deletion: bundle exec rails db:drop | ||
|
|
||
| my-app-production: | ||
| <<: *common | ||
| allow_org_override_by_env: false | ||
| allow_app_override_by_env: false | ||
| cpln_org: my-org-production | ||
| upstream: my-app-staging | ||
| release_script: release_script.sh | ||
| ``` | ||
|
|
||
| Important points: | ||
|
|
||
| - `REVIEW_APP_PREFIX` in GitHub Actions must match the review config key prefix, for example `my-app-review`. | ||
| - `match_if_app_name_starts_with: true` is what allows a single config entry to back `my-app-review-123`, `my-app-review-456`, and cleanup commands like `cpflow cleanup-stale-apps -a my-app-review`. | ||
| - `upstream: my-app-staging` is what lets the production promotion workflow copy the exact staging artifact. | ||
| - If your main web workload is not named `rails`, set the optional `PRIMARY_WORKLOAD` repository variable described below. | ||
|
|
||
| ## Required GitHub Repository Settings | ||
|
|
||
| Configure these repository secrets: | ||
|
|
||
| - `CPLN_TOKEN_STAGING`: token for the staging Control Plane org | ||
| - `CPLN_TOKEN_PRODUCTION`: token for the production Control Plane org | ||
|
|
||
| Configure these repository variables: | ||
|
|
||
| - `CPLN_ORG_STAGING`: staging org name, for example `company-staging` | ||
| - `CPLN_ORG_PRODUCTION`: production org name, for example `company-production` | ||
| - `STAGING_APP_NAME`: staging GVC name, for example `my-app-staging` | ||
| - `PRODUCTION_APP_NAME`: production GVC name, for example `my-app-production` | ||
| - `REVIEW_APP_PREFIX`: review-app prefix, for example `my-app-review` | ||
| - `STAGING_APP_BRANCH`: optional branch that auto-deploys staging; defaults to `main` or `master` if unset | ||
| - `PRIMARY_WORKLOAD`: optional workload name used to discover the public endpoint and do production health checks; defaults to `rails` | ||
|
|
||
| Recommended org layout: | ||
|
|
||
| - keep review apps and staging in a staging org that developers can access | ||
| - keep production in a separate org with tighter access controls | ||
|
|
||
| ## Generated Workflow Behavior | ||
|
|
||
| `cpflow-review-app-help.yml` | ||
|
|
||
| - Posts a quick reference when a pull request opens. | ||
|
|
||
| `cpflow-help-command.yml` | ||
|
|
||
| - Replies to `/help` on a pull request with the commands and required repo settings. | ||
|
|
||
| `cpflow-deploy-review-app.yml` | ||
|
|
||
| - Creates a review app when someone comments `/deploy-review-app`. | ||
| - Redeploys an existing review app automatically on later PR pushes. | ||
| - Creates a GitHub deployment and comments with the review URL and logs. | ||
| - Leaves PR pushes alone until the first review app is explicitly requested, which keeps demo-app costs down. | ||
|
|
||
| `cpflow-delete-review-app.yml` | ||
|
|
||
| - Deletes the review app on `/delete-review-app`. | ||
| - Also deletes it automatically when the pull request closes. | ||
|
|
||
| `cpflow-deploy-staging.yml` | ||
|
|
||
| - Builds and deploys the staging app on pushes to `STAGING_APP_BRANCH`. | ||
| - Falls back to `main` or `master` when `STAGING_APP_BRANCH` is unset. | ||
|
|
||
| `cpflow-promote-staging-to-production.yml` | ||
|
|
||
| - Manually promotes the staging artifact to production with a confirmation input. | ||
| - Verifies that production has the env var names staging expects. | ||
| - Runs a health check and attempts a rollback of every container image in `PRIMARY_WORKLOAD` if the new production image does not come up healthy. | ||
| - Creates a GitHub release after a successful promotion. | ||
|
|
||
| `cpflow-cleanup-stale-review-apps.yml` | ||
|
|
||
| - Runs nightly and on demand. | ||
| - Deletes stale review apps using `cpflow cleanup-stale-apps`. | ||
|
|
||
| ## Composite Actions | ||
|
|
||
| The generated workflows share these local composite actions: | ||
|
|
||
| - `cpflow-setup-environment`: installs Ruby, the Control Plane CLI, and the `cpflow` gem, then logs into the target org | ||
| - `cpflow-build-docker-image`: builds and pushes the app image with the desired commit SHA | ||
| - `cpflow-delete-control-plane-app`: safely deletes temporary apps and refuses to touch names outside the configured review-app prefix | ||
|
|
||
| ## Applying This to React on Rails Demo Apps | ||
|
|
||
| This flow is a good fit for the React on Rails demo apps because they already follow the same basic assumptions: | ||
|
|
||
| - the deployable app is a Rails project | ||
| - the primary web workload is usually `rails` | ||
| - review environments should be temporary and opt-in | ||
| - staging should auto-follow a single branch | ||
| - production should promote the already-tested staging image | ||
|
|
||
| In practice, porting the flow into a demo app usually means: | ||
|
|
||
| 1. Generate `.controlplane/` if the app does not have it yet. | ||
| 2. Generate the `cpflow-*` GitHub Actions files. | ||
| 3. Update `.controlplane/controlplane.yml` with staging, review, and production entries. | ||
| 4. Add any additional app workloads the app needs at runtime, for example `sidekiq`, a Node renderer, or any other process type that should deploy the same application image. | ||
| 5. Make sure the repo variables and secrets line up with those app names. | ||
| 6. Adjust `PRIMARY_WORKLOAD` only if the public workload is not named `rails`. | ||
| 7. Validate the real production Docker build before relying on the workflows, especially if asset compilation or SSR requires Node, extra system packages, or multiple processes. | ||
|
|
||
| ## AI Playbook | ||
|
|
||
| If you want an AI agent to apply this flow to another project, this prompt is the intended starting point: | ||
|
|
||
| ```text | ||
| Set up Control Plane GitHub Flow for this repo. If `.controlplane/` is missing, run `cpflow generate`. Then run `cpflow generate-github-actions`, update `.controlplane/controlplane.yml` so it defines `<app>-staging`, `<app>-review`, and `<app>-production`, keep review apps opt-in via `/deploy-review-app`, use `STAGING_APP_BRANCH` or the default branch for staging deploys, and list the GitHub secrets/variables that must be configured. If the public workload is not named `rails`, set `PRIMARY_WORKLOAD` or adjust the generated workflows. | ||
| ``` | ||
|
|
||
| Expand that prompt with app-specific requirements before editing files: | ||
|
|
||
| - inspect the production Dockerfile and make sure it can build the app's assets in CI | ||
| - add extra `app_workloads` and template files for any runtime sidecars, workers, or renderer processes | ||
| - make sure any sidecar process exposed to sibling workloads binds to `0.0.0.0` instead of container-local `localhost` | ||
| - make sure sidecar caches or bundle directories live in writable paths for the runtime user, such as `tmp/`, instead of root-owned image paths | ||
| - keep workflow files generic and put app names, org names, and branch names in repository `vars` and `secrets` | ||
|
|
||
| When the agent applies this to a project, it should avoid hardcoding app names or org names into the workflow files. Those belong in repository `vars` and `secrets`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.