diff --git a/.gitignore b/.gitignore index b0cb4689..90f56827 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ # Generated configs /terraform/ /.controlplane/ + +.qodo diff --git a/README.md b/README.md index 6b346340..e5fac9aa 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ many "Heroku" abstractions and naming conventions. Control Plane provides access to raw cloud computing power but lacks the simple abstractions of Heroku. The `cpflow` CLI bridges this gap, delivering a streamlined and familiar experience for developers. -While this repository simplifies migration from Heroku, the `cpflow` CLI is versatile and can be used for new applications as well. It follows a **concept mapping** and **helper CLI** approach to streamline deployment workflows and minimize manual effort. +While this repository simplifies migration from Heroku, the `cpflow` CLI is versatile and can be used for any applications. This document contains **concept mapping** and **helper CLI** approach to streamline deployment workflows and minimize manual effort. Additionally, the documentation includes numerous examples and practical tips for teams transitioning from Heroku to Kubernetes, helping them make the most of Control Plane's advanced features. @@ -82,7 +82,7 @@ On Control Plane, we can map a Heroku app to a GVC (Global Virtual Cloud). Such be anything that can run as a container. | Heroku | Control Plane | -| ---------------- | ------------------------------------------- | +|------------------|---------------------------------------------| | _app_ | _GVC_ (Global Virtual Cloud) | | _dyno_ | _workload_ | | _add-on_ | either a _workload_ or an external resource | @@ -105,7 +105,12 @@ For the typical Rails app, this means: | in-memory db | `redis`, `memcached` | add-on | external provider or can be set up for development/testing with Docker image (lacks persistence between restarts) | | others | `mailtrap` | add-on | external provider or can be set up for development/testing with Docker image (lacks persistence between restarts) | -## Installation +## Migration Strategy +See this doc for [detailed migration steps](./docs/migrating-heroku-to-control-plane) from Heroku to Control Plane. Even if you are coming from a platform other than Heroku, you can still benefit from the migration steps. + +## System Prerequisites + +_Note, if you want to use Terraform with cpflow, you will start the same way below._ 1. Ensure your [Control Plane](https://shakacode.controlplane.com/) account is set up. Set up an `organization` `` for testing in that account and modify the value for `aliases.common.cpln_org` in `.controlplane/controlplane.yml`, or you can also set it with the `CPLN_ORG` environment variable. If you need an organization, please [contact Shakacode](mailto:controlplane@shakacode.com). @@ -130,15 +135,11 @@ npm update -g @controlplane/cli 6. Install Control Plane Flow `cpflow` CLI as a [Ruby gem](https://rubygems.org/gems/cpflow): `gem install cpflow`. If you want to use `cpflow` from Rake tasks in a Rails project, use `Bundler.with_unbundled_env { `cpflow help` } or else you'll get an error that `cpflow` cannot be found. While you can add `cpflow` to your Gemfile, it's not recommended because it might trigger conflicts with other gems. -7. You can use [this Dockerfile](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/Dockerfile) as an example for your project. Ensure that you have Docker running. +7. You will need a production-ready Dockerfile. If you're using Rails, consider the default one that ships with Rails 8. You can use [this Dockerfile](https://github.com/shakacode/rails-v8-kamal-v2-terraform-gcp-tutorial/blob/master/Dockerfile) as an example for your project. Ensure that you have Docker running. **Note:** Do not confuse the `cpflow` CLI with the `cpln` CLI. The `cpflow` CLI is the Control Plane Flow playbook CLI. The `cpln` CLI is the Control Plane CLI. -## Steps to Migrate - -Click [here](https://www.shakacode.com/control-plane-flow/docs/migrating/) to see the steps to migrate. - ## Configuration Files The `cpflow` gem is based on several configuration files within a `/.controlplane` top-level directory in your project. @@ -331,7 +332,9 @@ apps: For a live example, see the [react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/readme.md) repository. -This example should closely match the below example. +You can use this repository as a reference for setting up your own project. + +This example should closely match the instructions example. Suppose your app is called `tutorial-app`. You can run the following commands. diff --git a/docs/ci-automation.md b/docs/ci-automation.md new file mode 100644 index 00000000..f6c51ff2 --- /dev/null +++ b/docs/ci-automation.md @@ -0,0 +1,33 @@ +# CI Automation, Review Apps, Staging, and Promoting to Production + +## Setting up Tokens for CI Automation + +The examples uses Github Actions as an example. 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 7 secrets set in your Github repository + + + +3. Go to the Control Plane UI for your organization's staging org +3. and make a new service account diff --git a/docs/commands.md b/docs/commands.md index 405a98aa..78f1cb5a 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -354,13 +354,17 @@ cpflow ps:stop -a $APP_NAME -w $WORKLOAD_NAME -r $REPLICA_NAME ### `ps:wait` - Waits for workloads in app to be ready after re-deployment +- Use Unix timeout command to set a maximum wait time (e.g., `timeout 300 cpflow ps:wait ...`) ```sh # Waits for all workloads in app. cpflow ps:wait -a $APP_NAME # Waits for a specific workload in app. -cpflow ps:swait -a $APP_NAME -w $WORKLOAD_NAME +cpflow ps:wait -a $APP_NAME -w $WORKLOAD_NAME + +# Waits for all workloads with a 5-minute timeout. +timeout 300 cpflow ps:wait -a $APP_NAME ``` ### `run` diff --git a/docs/migrating.md b/docs/migrating-heroku-to-control-plane.md similarity index 100% rename from docs/migrating.md rename to docs/migrating-heroku-to-control-plane.md diff --git a/lib/command/ps_wait.rb b/lib/command/ps_wait.rb index fff0e633..ab5ffd12 100644 --- a/lib/command/ps_wait.rb +++ b/lib/command/ps_wait.rb @@ -11,6 +11,7 @@ class PsWait < Base DESCRIPTION = "Waits for workloads in app to be ready after re-deployment" LONG_DESCRIPTION = <<~DESC - Waits for workloads in app to be ready after re-deployment + - Use Unix timeout command to set a maximum wait time (e.g., `timeout 300 cpflow ps:wait ...`) DESC EXAMPLES = <<~EX ```sh @@ -18,7 +19,10 @@ class PsWait < Base cpflow ps:wait -a $APP_NAME # Waits for a specific workload in app. - cpflow ps:swait -a $APP_NAME -w $WORKLOAD_NAME + cpflow ps:wait -a $APP_NAME -w $WORKLOAD_NAME + + # Waits for all workloads with a 5-minute timeout. + timeout 300 cpflow ps:wait -a $APP_NAME ``` EX diff --git a/spec/dummy/.controlplane/entrypoint.sh b/spec/dummy/.controlplane/entrypoint.sh index 7baa04c8..d5310a68 100755 --- a/spec/dummy/.controlplane/entrypoint.sh +++ b/spec/dummy/.controlplane/entrypoint.sh @@ -22,6 +22,7 @@ wait_for_services() wait_for_services # If running the rails server then create or migrate existing database +# TODO: Why are migrations (db:prepare) not done in the release script? if [ "${1}" = "./bin/rails" ] && [ "${2}" = "server" ]; then echo "Preparing database..." ./bin/rails db:prepare