From 5b6bc8334bef9d3bfa4f43e11f201871f36b4a50 Mon Sep 17 00:00:00 2001 From: Mostafa Ahangarha Date: Fri, 8 Dec 2023 08:01:35 +0330 Subject: [PATCH] Add cpln config (#13) * Add config files based on RWRT * Remove copying client directory * Remove uglifier for js compression * Add storage config * Use right name for the app name in docs * Set capacityAI to true * Fix copy destination for package.json --- .controlplane/Dockerfile | 40 +++++++++++ .controlplane/controlplane.yml | 19 +++++ .controlplane/readme.md | 113 ++++++++++++++++++++++++++++++ .controlplane/templates/gvc.yml | 18 +++++ .controlplane/templates/rails.yml | 36 ++++++++++ Gemfile | 2 - Gemfile.lock | 3 - config/environments/production.rb | 2 +- config/storage.yml | 7 ++ 9 files changed, 234 insertions(+), 6 deletions(-) create mode 100644 .controlplane/Dockerfile create mode 100644 .controlplane/controlplane.yml create mode 100644 .controlplane/readme.md create mode 100644 .controlplane/templates/gvc.yml create mode 100644 .controlplane/templates/rails.yml create mode 100644 config/storage.yml diff --git a/.controlplane/Dockerfile b/.controlplane/Dockerfile new file mode 100644 index 0000000..1eb9037 --- /dev/null +++ b/.controlplane/Dockerfile @@ -0,0 +1,40 @@ +FROM ruby:3.1.2 + +RUN apt-get update + +# install node and yarn +RUN curl -sL https://deb.nodesource.com/setup_18.x | bash +RUN apt-get install -y nodejs +RUN npm install -g yarn + +WORKDIR /app + +# install ruby gems +COPY Gemfile* ./ + +RUN bundle config set without 'development test' && \ + bundle config set with 'staging production' && \ + bundle install --jobs=3 --retry=3 + +# install node packages +COPY package.json yarn.lock ./ +RUN yarn install + +# pick necessary app files +COPY Gemfile* config.ru Rakefile babel.config.js postcss.config.js ./ +COPY app ./app +COPY bin ./bin +COPY config ./config +COPY db ./db +COPY lib ./lib +COPY public ./public + +ENV RAILS_ENV=production +ENV NODE_ENV=production + +# compiling assets requires any value for ENV of SECRET_KEY_BASE +ENV SECRET_KEY_BASE=NOT_USED_NON_BLANK + +RUN rails assets:precompile + +CMD ["rails", "s"] diff --git a/.controlplane/controlplane.yml b/.controlplane/controlplane.yml new file mode 100644 index 0000000..37c35b5 --- /dev/null +++ b/.controlplane/controlplane.yml @@ -0,0 +1,19 @@ +# Configuration for "Heroku to CPLN playbook" custom scripts +aliases: + common: &common + # Change this to your org name for staging. Production apps will use a different org + # for security. + cpln_org: shakacode-open-source-examples + # Change `shakacode-staging` to your-org-name-for-staging + # Example apps use only location. CPLN offers the ability to use multiple locations. + default_location: aws-us-east-2 + # Configure the workload name used as a template for one-off scripts, like a Heroku one-off dyno. + one_off_workload: rails + # Like the entries in the Heroku Procfile that get deployed when the application code changes + # and the application image updates. + app_workloads: + - rails + +apps: + react-rails-example-app: + <<: *common diff --git a/.controlplane/readme.md b/.controlplane/readme.md new file mode 100644 index 0000000..a971e4f --- /dev/null +++ b/.controlplane/readme.md @@ -0,0 +1,113 @@ +# Deploying tutorial app on Control Plane + +## Overview +This simple example shows how to deploy a simple app on Control Plane using the `cpl` gem. + +To maximize simplicity, +this example creates Postgres and Redis as workloads in the same GVC as the app. +In a real app, +you would likely use persistent, +external resources, +such as AWS RDS and AWS ElastiCache. + +You can see the definition of Postgres and Redis in the `.controlplane/templates` directory. + +## Prerequisites + +1. Ensure your +[Control Plane](https://controlplane.com) +account is set up. + +2. Set up an `organization` for testing in that account +and modify `aliases.common.cpln_org` in `.controlplane/controlplane.yml`. + +3. Install Control Plane CLI (and configure access) +[docs here](https://docs.controlplane.com/quickstart/quick-start-3-cli#getting-started-with-the-cli). +You can update the `cpln` command line with the same command as installation, +`npm install -g @controlplane/cli`. +Then run `cpln login` to ensure access. + +4. Install +[Heroku to Control Plane](https://github.com/shakacode/heroku-to-control-plane) +playbook CLI +[`cpl` gem](https://rubygems.org/gems/cpl) +on your project's Gemfile or globally. + +5. This project has a `Dockerfile` for Control Plane in this directory. +You can use it as an example for your project. +Ensure that you have Docker running. + +## Tips +Do not confuse the `cpl` CLI with the `cpln` CLI. +The `cpl` CLI is the Heroku to Control Plane playbook CLI. +The `cpln` CLI is the Control Plane CLI. + +## Project Configuration +See the filese in the `./controlplane` directory. + +1. `/templates`: defines the objects created with the `cpl setup` command. +2. `/controlplane.yml`: defines the organization, location, and app name. +3. `Dockerfile`: defines the Docker image used to run the app on Control Plane. +4. `entrypoint.sh`: defines the entrypoint script used to run the app on Control Plane. + +## Setup and run + +Check if the Control Plane organization and location are correct in `.controlplane/controlplane.yml`. +You should be able to see this information in the Control Plane UI. + +```sh +# Note, below commands use `cpl` which is the Heroku to Control Plane playbook script. + +# Provision all infrastructure on Control Plane. +# app react-rails-example-app will be created per definition in .controlplane/controlplane.yml +cpl apply-template gvc rails -a react-rails-example-app + +# Build and push docker image to Control Plane repository +# Note, may take many minutes. Be patient. +cpl build-image -a react-rails-example-app + +# Promote image to app after running `cpl build-image command` +cpl deploy-image -a react-rails-example-app + +# See how app is starting up +cpl logs -a react-rails-example-app + +# Open app in browser (once it has started up) +cpl open -a react-rails-example-app +``` + +Notice that in the first attempt to build the image, you may get it interrupted with a message like this: + +``` +89c3244a87b2: Waiting +80231db1194c: Waiting +f1c1f2298584: Waiting +ccba29d69370: Waiting +unsupported: +*** You are trying to push/pull to your org's private registry in Control Plane. *** +*** First, grant docker access the registry using the 'cpln' command: *** + + cpln image docker-login --org react-rails-example-app +``` + +Run the given command as instructed and repeat the `build-image` command. + +## Promoting code upgrades + +```sh +# Build and push new image with sequential image tagging, e.g. 'ror-tutorial_123' +cpl build-image -a react-rails-example-app + +# OR +# Build and push with sequential image tagging and commit SHA, e.g. 'ror-tutorial_123_ABCD' +cpl build-image -a react-rails-example-app --commit ABCD + +# Run database migrations (or other release tasks) with latest image, +# while app is still running on previous image. +# This is analogous to the release phase. +cpl runner rails db:migrate -a react-rails-example-app --image latest + +# Pomote latest image to app +cpl deploy-image -a react-rails-example-app +``` + diff --git a/.controlplane/templates/gvc.yml b/.controlplane/templates/gvc.yml new file mode 100644 index 0000000..12cc335 --- /dev/null +++ b/.controlplane/templates/gvc.yml @@ -0,0 +1,18 @@ +# Template setup of the GVC, roughly corresponding to a Heroku app +kind: gvc +name: APP_GVC +spec: + # For using templates for test apps, put ENV values here, stored in git repo. + # Production apps will have values configured manually after app creation. + env: + - name: RAILS_ENV + value: production + - name: NODE_ENV + value: production + - name: RAILS_SERVE_STATIC_FILES + value: 'true' + + # Part of standard configuration + staticPlacement: + locationLinks: + - /org/APP_ORG/location/APP_LOCATION diff --git a/.controlplane/templates/rails.yml b/.controlplane/templates/rails.yml new file mode 100644 index 0000000..a677384 --- /dev/null +++ b/.controlplane/templates/rails.yml @@ -0,0 +1,36 @@ +# Template setup of Rails server workload, roughly corresponding to Heroku dyno +# type within Procfile. +kind: workload +name: rails +spec: + type: standard + containers: + - name: rails + # 300m is a good starting place for a test app. You can experiment with CPU configuration + # once your app is running. + cpu: 300m + env: + - name: LOG_LEVEL + value: debug + # Inherit other ENV values from GVC + inheritEnv: true + image: '/org/APP_ORG/image/APP_IMAGE' + # 512 corresponds to a standard 1x dyno type + memory: 512Mi + ports: + - number: 3000 + protocol: http + defaultOptions: + # Start out like this for "test apps" + autoscaling: + # Max of 1 effectively disables autoscaling, so like a Heroku dyno count of 1 + maxScale: 1 + capacityAI: true + firewallConfig: + external: + # Default to allow public access to Rails server + inboundAllowCIDR: + - 0.0.0.0/0 + # Could configure outbound for more security + outboundAllowCIDR: + - 0.0.0.0/0 diff --git a/Gemfile b/Gemfile index 21ed879..389713d 100644 --- a/Gemfile +++ b/Gemfile @@ -13,8 +13,6 @@ gem 'sqlite3' gem 'puma', '~> 5.0' # Use SCSS for stylesheets gem 'sass-rails', '~> 5.0' -# Use Uglifier as compressor for JavaScript assets -gem 'uglifier', '>= 1.3.0' # Transpile app-like JavaScript. Read more: https://github.com/shakacode/shakapacker gem 'shakapacker', '7.0.2' # See https://github.com/rails/execjs#readme for more supported runtimes diff --git a/Gemfile.lock b/Gemfile.lock index 4931d3d..b6b64fa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -241,8 +241,6 @@ GEM turbolinks-source (5.2.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - uglifier (4.2.0) - execjs (>= 0.3.0, < 3) web-console (4.2.0) actionview (>= 6.0.0) activemodel (>= 6.0.0) @@ -275,7 +273,6 @@ DEPENDENCIES sqlite3 turbolinks (~> 5) tzinfo-data - uglifier (>= 1.3.0) web-console (>= 3.3.0) BUNDLED WITH diff --git a/config/environments/production.rb b/config/environments/production.rb index ed7778f..dc63d34 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -24,7 +24,7 @@ config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? # Compress JavaScripts and CSS. - config.assets.js_compressor = :uglifier + # config.assets.js_compressor = :uglifier # config.assets.css_compressor = :sass # Do not fallback to assets pipeline if a precompiled asset is missed. diff --git a/config/storage.yml b/config/storage.yml new file mode 100644 index 0000000..695f17b --- /dev/null +++ b/config/storage.yml @@ -0,0 +1,7 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %>