Skip to content

Latest commit

 

History

History
197 lines (142 loc) · 8.43 KB

File metadata and controls

197 lines (142 loc) · 8.43 KB

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:

# 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:

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:

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.