-
Notifications
You must be signed in to change notification settings - Fork 22
Home
In addition to the app, you will need a Stripe account, though you can use just the test-mode keys during development.
Once you have the above, run bundle install --without production
and ensure all gems get installed.
Before running the app or its tests though, you must setup multi-tenancy and the secrets file.
This is important. By default Audience1st is designed to be setup
as multi-tenant using the apartment
gem, where each theater is a
tenant. Audience1st determines the tenant name for a given request
fomr the first subdomain in the URI, e.g. if your deployment domain is
somewhere.com
, then my-theater.somewhere.com
selects my-theater
as the tenant for that request.
For development or staging, the recommended approach is to setup a
single tenant. In this example we will call it my-tenant-name
; you can
call it whatever you want, but if you deploy to Heroku for staging,
the app name my-tenant-name.herokuapp.com
must exist, so choose
the name carefully.
In addition, Audience1st uses the figaro
gem to manage
configuration variables and secrets, many of which are necessary to run the app
in production or development and even to run the tests.
Therefore you must create a file containing the values of these secrets, some of which values may differ between production and development/testing.
- Create a file
config/application.yml
containing the following:
tenant_names: my-tenant-name
session_secret: "exactly 128 random ASCII characters"
attr_encrypted_key: "exactly 32 random characters"
STRIPE_KEY: "Publishable key from a Stripe account in test mode"
STRIPE_SECRET: "Secret key from a Stripe account in test mode"
MAILGUN_SMTP_LOGIN: postmaster@mail.yourdomain.com
MAILGUN_SMTP_PASSWORD: "your long SMTP password here"
Note 1: If the Mailgun-related keys are omitted, you won't be email to send transactional emails from the app, which may be fine.
Note 2: In a production setting, you'd have several tenant names separated by commas.
Please don't version the config/application.yml
file or include it in pull requests, nor
modify the existing config/application.yml.asc
. The .gitignore
is
deliberately set to ignore config/application.yml
when versioning.
- Create a
config/database.yml
file (and don't version it; it is also git-ignored) containingdevelopment:
andtest:
targets:
development:
adapter: sqlite3
database: db/my-tenant-name.sqlite3
test:
adapter: sqlite3
database: db/test.sqlite3
(The production
configuration, if any, depends on your deployment
environment. Heroku ignores any production
configuration because it
sets its own using PostgreSQL.)
-
After running
bundle
as usual, you can runbundle exec rake db:schema:load
to load the database schema into each tenant. -
Run
rake db:seed
on the development database, which creates a few special users, including the administrative useradmin@audience1st.com
with passwordadmin
. -
To start the app, say
rails server webrick
(assuming you want to use the simpler Webrick server locally; theProcfile
uses a 2-process Puma server for the production environment currently), but in your browser, do not try to visitlocalhost:3000
; instead visithttp://my-tenant-name.lvh.me:3000
since the multi-tenant selection relies on the first component of the URI being the tenant name. This uses the free lvh.me service that always resolves tolocalhost
. -
WARNING. When you run
rails console
to get a REPL, the first thing you should type in the console isApartment::Tenant.switch! 'my-tenant-name'
to switch to the (only) tenant's database schema. -
The app should now be able to run and you should be able to login with the administrator password. Later you can designate other users as administrators.
-
If you want fake-but-realistic data, also run the task
TENANT=my-tenant-name bundle exec rake staging:initialize
. This creates a bunch of fake users, shows, etc., courtesy of thefaker
gem.
At this point you should be able to run tests locally (rake cucumber
and rake rspec
).
Since the tests also rely on the value of the application secrets, you need to
set those values in the repo's environment variable settings in Travis CI. See
the Testing page in this wiki for how to do that and for more details on the test suite.
(If you don't plan to exercise Recurring Donations in development, you don't need to know this info.)
Recurring donations make use of Stripe callbacks and webhooks.
When the patron tries to setup a new recurring donation, the filled-out form served by RecurringDonationsController#new
is posted to RecurringDonationsController#create
, which redirects to a Stripe-hosted checkout page. Once payment info is entered and payment is verified, Stripe will do a GET
to stripe_callback_recurring_donation_success_path()
. When individual charges for each instance of the recurring donations are processed, Stripe will POST
a webhook event to [tbd].
This means that the URLs used by Stripe for the callbacks/postbacks must be globally routable. In production, the app looks at the protocol/hostname/port portion of the request
to construct the URL. But if you're developing using lvh.me
as recommended, obviously that hostname won't work for callback/postback URLs since it just resolves to localhost
, and Stripe certainly should not be posting to that!
The ngrok
tool solves this problem by exposing a globally routable hostname that tunnels to your localhost, but the free plan just creates an ephemeral domain such as 4ED9-B1F8-40F9-82BF.ngrok-free.app
. This fails because multi-tenancy uses the first subdomain of the URL to identify the tenant, so we need to force the first subdomain to be a1-staging
. The rest of the domain doesn't matter: it can be a1-staging.ngrok-free.app
, a1-staging.my-ngrok-subdomain.ngrok.io
, etc. But you need a paid ngrok
plan to configure a static non-ephemeral hostname for the tunnel.
Once you do this, when running rails server
, start the tunnel and then set the envariable CALLBACK_HOST
to the protocol+hostname+port used by your tunnel:
export CALLBACK_HOST=https://a1-staging.my-ngrok-domain.ngrok.io
ngrok http --domain=$CALLBACK_HOST localhost:3000
The method RecurringDonation#prepare_checkout
is responsible for creating the callback URL to pass to Stripe. If you are running in development and the above envariable is not set, the app will raise an unhandled exception.
These instructions are for Heroku and assume that you have created a Heroku app container and provisioned it with the basic (free) level of Heroku Postgres. You can adapt these instructions for other deployment environments.
-
Get the code pushed to the deployment environment (
git push heroku master
usually). -
Ensure that the
config/application.yml
on your development computer contains the correct configuration data. -
If using Heroku,
figaro heroku:set -e production
to makeapplication.yml
's environment variables available to Heroku, including the value oftenant_names
. For staging-type deployments to Heroku, the correct value is the Heroku appname, so if your app isluminous-coconut.herokuapp.com
, thetenant_names
environment variable should be set toluminous-coconut
. -
If this is the first deployment, you have to create the tenant(s) schema(ta).
To do this, first doheroku run rake db:schema:load
to create and seed Postgres'public
schema. Thepublic
schema is not actually used by any Audience1st tenant but it is cloned whenever a new tenant is created and must be present or migrations will fail. Next sayheroku run TENANT=my-tenant-name rake a1client:create
, which will create the schema formy-tenant-name
. (The code for the Rake task in inlib/tasks/client.rb
.) Finally,heroku run rake db:migrate
to ensure the schema is up-to-date. From now onrake db:migrate
and other database-related tasks will automatically be applied to all tenants. Repeat thea1client:create
task any time you need to add a tenant. There is also ana1client:drop
task to delete a tenant's schema and all of its data. Whenever the list of tenants changes, don't forget to also adjust the value of thetenant_names
variable. -
If the environment variable
EDGE_URL
is set on Heroku,config.action_controller.asset_host
will be set to that value to serve static assets from a CDN, which you must configure (the current deployment uses the Edge CDN add-on for Heroku, which uses Amazon CloudFront as a CDN). If not set, assets will be served the usual way without CDN. (If you're just deploying a staging server, you should not set this variable.) -
The task
Customer.notify_upcoming_birthdays
emails an administrator or boxoffice manager with information about customers whose birthdays are coming up soon. The threshold for "soon" can be set in Admin > Options.
In production, email confirmations are sent for various things. Audience1st is configured to use Mailgun. If you do nothing, transactional emails will be suppressed in your staging/production environment. If you want to use Mailgun for real email sending in your staging/production app, do the following:
-
Provision the Mailgun add-on for Heroku and obtain the necessary credentials.
-
config/application.yml
file should contain the Mailgun-related keys above. You may need tofigaro heroku:set -e production
to get the key values into Heroku's production environment. -
Login to Audience1st as an administrator, go to Options, and enter the Mailgun domain (i.e. the domain from which transactional emails will appear to come, usually something like
your-app.herokuapp.com
for a staging environment). -
Be sure that same domain name appears among the "allowed domains" in the Mailgun settings. You'll have to set up various DNS entries to support DKIM as well.
The main production deployment of Audience1st runs two periodic jobs using Heroku Scheduler:
-
Daily around 1AM Pacific:
./bin/backup_postgres_to_s3
, a shell script that encrypts the entire Postgres database withBACKUP_GPG_KEY
and backs it up to S3 bucketBACKUP_S3_BUCKET
with a filename based on the current date. -
Every 10 minutes:
NEW_RELIC_AGENT_ENABLED=false rake a1:restart_if_memory_exceeded
, a Rake task that uses the Heroku API to check if any dynos have exceeded their memory quota (i.e. are swapping) and does a restart-all-dynos if so. This relies on enabling Heroku runtime metrics sampling on the app. Empirically, under heavy usage, the 512MB dynos start to swap and I need to figure out what allocation pattern causes this.
This requires removing a few files. Do not make any PRs that delete those files since we need them in the main/production version.
-
Remove
gem 'apartment'
from theGemfile
before runningbundle install
-
Remove the file
config/initializers/apartment.rb
-
Make sure your
config/application.yml
does not contain any mention oftenant_names
If you decide to use multi-tenancy but change the
tenant-selection scheme in config/initializers/apartment.rb
(see the apartment
gem's documentation for
what this means), you'll also need to edit the before-suite logic in
features/support/env.rb
and spec/support/rails_helper.rb
. Those
bits of code ensure that testing works properly with multi-tenancy
enabled, but they rely on the tenant name being the DNS subdomain. If
you don't know what this means, you should probably ask for assistance
deploying this software. :-)