Merge pull request #755 from sharetribe/document-env-vars

Harmonize env var handling & document them
This commit is contained in:
Olli Vanhapiha 2018-03-15 23:25:50 +02:00 committed by GitHub
commit ee5103dae7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 190 additions and 75 deletions

32
.env-template Normal file
View file

@ -0,0 +1,32 @@
# Mandatory configuration
#
REACT_APP_SHARETRIBE_SDK_CLIENT_ID=
REACT_APP_GOOGLE_MAPS_API_KEY=
REACT_APP_STRIPE_PUBLISHABLE_KEY=
# Defaults
#
REACT_APP_SHARETRIBE_SDK_BASE_URL=http://localhost:8088
REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY=USD
REACT_APP_CANONICAL_ROOT_URL=http://localhost:3000
# This is overwritten by configuration in .env.development and
# .env.test. In production deployments use env variable and set it to
# 'production'
REACT_APP_ENV=production
# Options. Uncomment and set to test.
#
# REACT_APP_SHARETRIBE_USING_SSL=true
# SERVER_SHARETRIBE_TRUST_PROXY=true
# REACT_APP_PUBLIC_SENTRY_DSN=change-me
# SERVER_SENTRY_DSN=change-me
# REACT_APP_CSP=report
# BASIC_AUTH_USERNAME=sharetribe
# BASIC_AUTH_PASSWORD=secret
# REACT_APP_GOOGLE_ANALYTICS_ID=change-me

View file

@ -1,2 +1,2 @@
NODE_ENV=development
REACT_APP_ENV=development

View file

@ -1,3 +1,4 @@
NODE_ENV=test
REACT_APP_ENV=test
REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY=USD
REACT_APP_CANONICAL_ROOT_URL=http://localhost:3000

2
.gitignore vendored
View file

@ -13,4 +13,4 @@ build
.DS_Store
.env
npm-debug.log
/.env.development.local
yarn-error.log

View file

@ -24,12 +24,16 @@ Clone this repository and install dependencies:
## Development
**First, you need to configure Client Id, Google Maps API key and
Stripe publishable API key via [environment
variables](./docs/env.md).** The quickest way to do this is to copy
`.env-template` -> `.env`, and edit the file to set the three mandatory
configuration values.
To develop the application and to see changes live, start the frontend development server:
yarn run dev
**You also need to [configure Google Maps api key](./docs/google-maps.md)**
**Known issues:**
* Adding/changing `import`s may not be synced properly with ESLint. You may see an error
@ -57,13 +61,6 @@ To start the test watcher, run
See more in the [testing documentation](docs/testing.md).
## Deployment
The `master` branch is automatically deployed to Heroku. If you want to deploy a feature branch,
setup the `sharetribe-starter-app` Heroku app and push the feature branch:
git push heroku my-feature-branch:master
## License
This project is licensed under the terms of the Apache-2.0 license.

View file

@ -12,7 +12,9 @@ change the color variables:
--marketplaceColorLight: #ff4c38;
--marketplaceColorDark: #8c291e;
```
N.B. search also from files color code `c0392b`. Some icons and background-images with data-URL are using it directly.
N.B. search also from files color code `c0392b`. Some icons and background-images with data-URL are
using it directly.
## Icons

View file

@ -1,36 +1,42 @@
# Customization checklist
Some generic things to update and check when starting to customize Starter app.
- [Marketplace colors](colors-and-icons.md#colors)
- [Generate app icons](colors-and-icons.md#icons)
- [Update translations](../src/translations/en.json) or [change the language](i18n.md)
- [LandingPage](../src/containers/LandingPage/LandingPage.js): update and create branded sections
- [Footer](../src/components/Footer/Footer.js)
- [AboutPage](../src/containers/AboutPage/AboutPage.js)
- [Terms of Service](terms-of-service-and-privacy-policy.md#terms-of-service)
- [Privacy Policy](terms-of-service-and-privacy-policy.md#privacy-policy)
- [Social media sharing graphics](../src/components/Page/Page.js);
- [Logo](../src/components/Logo/Logo.js) Change and check that it works on Topbar and Footer
- [Logo in CheckoutPage](../src/containers/CheckoutPage/LogoIcon.js)
- [Default background image](../src/assets/background-1440.jpg)
- [Maps Marker icon](../src/components/Map/Map/images/marker-32x32.png)
- [Config: update environment variables](../src/config.js)
- [Config: siteTitle](../src/config.js) for page schema (SEO)
- [Config: marketplace address](../src/config.js): contact details also improve SEO
- [Config: social media pages](../src/config.js)
- [Marketplace custom config](../src/marketplace-custom-config.js)
- Update [ListingPage](../src/containers/ListingPage/ListingPage.js) to show extended data (aka publicData attribute)
- Update [EditListingWizard](../src/components/EditListingWizard/EditListingWizard.js) and panels to add extended data
- Update [SearchPage](../src/containers/SearchPage/SearchPage.js) to filter with extended data
- Update [routeConfiguration](../src/routeConfiguration) if needed
- Update [Email templates](https://github.com/sharetribe/sharetribe-starter-app/tree/master/ext/mail-templates), all of them: .html, subject.txt, and text.txt
- Update [config: bookingUnitType](../src/config.js) if needed
- If `line-item/units` is used, add quantity handling
to [BookingDatesForm](../src/containers/BookingDatesForm/BookingDatesForm.js), [ListingPage](../src/containers/ListingPage/ListingPage.js), [CheckoutPage](../src/containers/CheckoutPage/CheckoutPage.js)
* [Marketplace colors](colors-and-icons.md#colors)
* [Generate app icons](colors-and-icons.md#icons)
* [Update translations](../src/translations/en.json) or [change the language](i18n.md)
* [LandingPage](../src/containers/LandingPage/LandingPage.js): update and create branded sections
* [Footer](../src/components/Footer/Footer.js)
* [AboutPage](../src/containers/AboutPage/AboutPage.js)
* [Terms of Service](terms-of-service-and-privacy-policy.md#terms-of-service)
* [Privacy Policy](terms-of-service-and-privacy-policy.md#privacy-policy)
* [Social media sharing graphics](../src/components/Page/Page.js);
* [Logo](../src/components/Logo/Logo.js) Change and check that it works on Topbar and Footer
* [Logo in CheckoutPage](../src/containers/CheckoutPage/LogoIcon.js)
* [Default background image](../src/assets/background-1440.jpg)
* [Maps Marker icon](../src/components/Map/Map/images/marker-32x32.png)
* [Config: update environment variables](../src/config.js)
* [Config: siteTitle](../src/config.js) for page schema (SEO)
* [Config: marketplace address](../src/config.js): contact details also improve SEO
* [Config: social media pages](../src/config.js)
* [Marketplace custom config](../src/marketplace-custom-config.js)
* Update [ListingPage](../src/containers/ListingPage/ListingPage.js) to show extended data (aka
publicData attribute)
* Update [EditListingWizard](../src/components/EditListingWizard/EditListingWizard.js) and panels to
add extended data
* Update [SearchPage](../src/containers/SearchPage/SearchPage.js) to filter with extended data
* Update [routeConfiguration](../src/routeConfiguration) if needed
* Update
[Email templates](https://github.com/sharetribe/sharetribe-starter-app/tree/master/ext/mail-templates),
all of them: .html, subject.txt, and text.txt
* Update [config: bookingUnitType](../src/config.js) if needed
* If `line-item/units` is used, add quantity handling to
[BookingDatesForm](../src/containers/BookingDatesForm/BookingDatesForm.js),
[ListingPage](../src/containers/ListingPage/ListingPage.js),
[CheckoutPage](../src/containers/CheckoutPage/CheckoutPage.js)
## What else
- Do you need more [static pages](static-pages.md)?
- Changes to existing pages
- Changes to transaction process (API + Web app)
* Do you need more [static pages](static-pages.md)?
* Changes to existing pages
* Changes to transaction process (API + Web app)

41
docs/env.md Normal file
View file

@ -0,0 +1,41 @@
# Environment configuration variables
The following configuration variables can be set to control the Starter App behaviour. Most of them
have defaults that work for development environment. For production deploys most should be set.
| Variable | Description |
| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| REACT_APP_GOOGLE_MAPS_API_KEY | See: [Google Maps API key](./google-maps.md) |
| REACT_APP_SHARETRIBE_SDK_CLIENT_ID | Client ID (API key). You will get this from the Sharetribe team. |
| REACT_APP_STRIPE_PUBLISHABLE_KEY | Stripe publishable API key for generating tokens with Stripe API. Use test key (prefix pk*test*) for development. |
| REACT_APP_SHARETRIBE_SDK_BASE_URL | The base url to access the Sharetribe Flex Marketplace API. |
| REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY | The currency used in the Marketplace as ISO 4217 currency code. For example: USD, EUR, CAD, AUD, etc. |
| REACT_APP_CANONICAL_ROOT_URL | Canonical root url of the marketplace. Needed for social media sharing and SEO optimization. |
| NODE_ENV | Node env. Use 'development' for development and 'production' for production. |
| PORT | Port for server to accept connections. |
| REACT_APP_ENV | Env for client side. Use the same value as with NODE_ENV. |
| REACT_APP_SHARETRIBE_USING_SSL | Redirect HTTP to HTTPS? |
| SERVER_SHARETRIBE_TRUST_PROXY | Set when running the app behind a reverse proxy, e.g. in Heroku. |
| REACT_APP_PUBLIC_SENTRY_DSN | See: [Error logging with Sentry](./sentry.md) |
| SERVER_SENTRY_DSN | See: [Error logging with Sentry](./sentry.md) |
| REACT_APP_CSP | See: [Content Security Policy (CSP)](./content-security-policy.md) |
| BASIC_AUTH_USERNAME | Set to enable HTTP Basic Auth |
| BASIC_AUTH_PASSWORD | Set to enable HTTP Basic Auth |
| REACT_APP_GOOGLE_ANALYTICS_ID | See: [Google Analytics](./analytics.md) |
## Defining configuration
When the Starter App is started locally with `yarn run dev` or `yarn run dev-server`, you can set
environment variables by using the (gitignored) `.env` file. The repository contains a template file
`.env-template` with default configuration. Just copy that as `.env` and edit as necessary.
In production, it's recommended that you set the configuration via env variables and do not deploy
an .env file. The client application will only be packaged with env variables that start with
REACT_APP. This way server secrets don't end up in client bundles.
**With deploys note that the configuration options are bundled in the
client package at build time.** The configuration of the build
environment must match run environment for things to work
consistently. To apply changes to configuration values client bundle
must be rebuilt. Just restarting the server is not enough.

View file

@ -20,8 +20,7 @@ section of the Places library documentation to enable using the Google Places AP
## Setup the application to use the API key
The application uses the `REACT_APP_GOOGLE_MAPS_API_KEY` environment variable for the key value. For
local development, you can add the variable in the Gitignored `.env.development.local` file in the
project root:
local development, you can add the variable in the Gitignored `.env` file in the project root:
```
REACT_APP_GOOGLE_MAPS_API_KEY=my-key-here

View file

@ -24,16 +24,15 @@ the logging logic in general.
## Source map retrieval
By default Sentry fetches the source maps for minified javascript files. However, this might now work
in case some sort of authentication, e.g. basic auth, is required to reach your application. To
By default Sentry fetches the source maps for minified javascript files. However, this might now
work in case some sort of authentication, e.g. basic auth, is required to reach your application. To
circumvent this a security token can be configured to Sentry. Sentry then adds this token to the
source maps request header so that the server hosting Starter App can then be configured to let those
requests access the source maps.
source maps request header so that the server hosting Starter App can then be configured to let
those requests access the source maps.
For basic auth the security token can be configured as follows:
In *Project > Settings > General > Client Security* set the following values
In _Project > Settings > General > Client Security_ set the following values
* **Security token** - `Basic <your username:password in Base 64>`
* **Security token header** - `Authorization`

View file

@ -66,7 +66,7 @@
"test-ci": "sharetribe-scripts test --env=jsdom --runInBand",
"eject": "sharetribe-scripts eject",
"start": "node server/index.js",
"dev-server": "export REACT_APP_ENV=development REACT_APP_CANONICAL_ROOT_URL=http://localhost:4000&&yarn run build&&nodemon --watch server server/index.js",
"dev-server": "export NODE_ENV=development PORT=4000 REACT_APP_CANONICAL_ROOT_URL=http://localhost:4000&&yarn run build&&nodemon --watch server server/index.js",
"heroku-prebuild": "./heroku-copy-ssh-key-from-env.sh",
"heroku-postbuild": "yarn run build",
"audit": "nsp check --preprocessor yarn"

View file

@ -1,5 +1,4 @@
const helmet = require('helmet');
const { config } = require('./importer');
const dev = process.env.REACT_APP_ENV === 'development';
const googleAnalyticsEnabled = !!process.env.REACT_APP_GOOGLE_ANALYTICS_ID;
@ -21,7 +20,7 @@ module.exports = (reportUri, enforceSsl, reportOnly) => {
const self = "'self'";
const inline = "'unsafe-inline'";
const data = 'data:';
const sharetribeApi = config.sdk.baseUrl;
const sharetribeApi = process.env.REACT_APP_SHARETRIBE_SDK_BASE_URL;
const sharetribeAssets = 'https://assets-sharetribecom.sharetribe.com/';
const imgix = '*.imgix.net/';
const loremPixel = 'https://lorempixel.com/';

41
server/env.js Normal file
View file

@ -0,0 +1,41 @@
/**
Implements .env file loading that mimicks the way create-react-app
does it. We want this to get consistent configuration handling
between client and node server.
*/
const fs = require('fs');
const NODE_ENV = process.env.NODE_ENV;
if (!NODE_ENV) {
throw new Error('The NODE_ENV environment variable is required but was not specified.');
}
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
var dotenvFiles = [
`.env.${NODE_ENV}.local`,
`.env.${NODE_ENV}`,
// Don't include `.env.local` for `test` environment
// since normally you expect tests to produce the same
// results for everyone
NODE_ENV !== 'test' && `env.local`,
'.env',
].filter(Boolean);
const configureEnv = () => {
// Load environment variables from .env* files. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set.
// https://github.com/motdotla/dotenv
dotenvFiles.forEach(dotenvFile => {
if (fs.existsSync(dotenvFile)) {
console.log('Loading env from file:' + dotenvFile);
require('dotenv').config({ path: dotenvFile });
}
});
};
module.exports = {
configureEnv: configureEnv,
};

View file

@ -17,5 +17,4 @@ module.exports = {
matchPathname: mainJs.matchPathname,
configureStore: mainJs.configureStore,
routeConfiguration: mainJs.routeConfiguration,
config: mainJs.config,
};

View file

@ -16,6 +16,9 @@
// This enables nice stacktraces from the minified production bundle
require('source-map-support').install();
// Configure process.env with .env.* files
require('./env').configureEnv();
const express = require('express');
const helmet = require('helmet');
const compression = require('compression');
@ -35,12 +38,11 @@ const { sitemapStructure } = require('./sitemap');
const csp = require('./csp');
const buildPath = path.resolve(__dirname, '..', 'build');
const env = process.env.REACT_APP_ENV || 'production';
const env = process.env.REACT_APP_ENV;
const dev = process.env.REACT_APP_ENV === 'development';
const PORT = process.env.PORT || 4000;
const CLIENT_ID =
process.env.REACT_APP_SHARETRIBE_SDK_CLIENT_ID || '08ec69f6-d37e-414d-83eb-324e94afddf0';
const BASE_URL = process.env.REACT_APP_SHARETRIBE_SDK_BASE_URL || 'http://localhost:8088';
const PORT = parseInt(process.env.PORT, 10);
const CLIENT_ID = process.env.REACT_APP_SHARETRIBE_SDK_CLIENT_ID;
const BASE_URL = process.env.REACT_APP_SHARETRIBE_SDK_BASE_URL;
const USING_SSL = process.env.REACT_APP_SHARETRIBE_USING_SSL === 'true';
const TRUST_PROXY = process.env.SERVER_SHARETRIBE_TRUST_PROXY || null;
const CSP = process.env.REACT_APP_CSP;

View file

@ -1,9 +1,8 @@
const path = require('path');
const moment = require('moment');
const { config } = require('./importer');
const buildPath = path.resolve(__dirname, '..', 'build');
const PORT = process.env.PORT || 4000;
const PORT = parseInt(process.env.PORT, 10);
const USING_SSL = process.env.REACT_APP_SHARETRIBE_USING_SSL === 'true';
/**
@ -44,17 +43,17 @@ const port = rootURL => {
};
/**
* Return a structure for sitemap.xml and robots.txt to be
* used by the express-sitemap library. Uses the canonical
* URL value from config for domain and port information.
* Return a structure for sitemap.xml and robots.txt to be used by the
* express-sitemap library. Uses the canonical URL value from env
* config for domain and port information.
*/
exports.sitemapStructure = () => {
const now = moment().format('YYYY-MM-DD');
return {
url: domain(config.canonicalRootURL),
url: domain(process.env.REACT_APP_CANONICAL_ROOT_URL),
http: USING_SSL ? 'https' : 'http',
port: port(config.canonicalRootURL),
port: port(process.env.REACT_APP_CANONICAL_ROOT_URL),
sitemap: path.join(buildPath, 'static', 'sitemap.xml'),
robots: path.join(buildPath, 'robots.txt'),
sitemapSubmission: '/static/sitemap.xml',

View file

@ -1,6 +1,6 @@
import * as custom from './marketplace-custom-config.js';
const env = process.env.REACT_APP_ENV || 'production';
const env = process.env.REACT_APP_ENV;
const dev = process.env.REACT_APP_ENV === 'development';
// If you want to change the language, remember to also change the
@ -32,11 +32,10 @@ const bookingUnitType = 'line-item/night';
// script, react-scripts (and the sharetribe-scripts fork of
// react-scripts) require using the REACT_APP_ prefix to avoid
// exposing server secrets to the client side.
const sdkClientId =
process.env.REACT_APP_SHARETRIBE_SDK_CLIENT_ID || '08ec69f6-d37e-414d-83eb-324e94afddf0';
const sdkBaseUrl = process.env.REACT_APP_SHARETRIBE_SDK_BASE_URL || 'http://localhost:8088';
const sdkClientId = process.env.REACT_APP_SHARETRIBE_SDK_CLIENT_ID;
const sdkBaseUrl = process.env.REACT_APP_SHARETRIBE_SDK_BASE_URL;
const currency = process.env.REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY || 'USD';
const currency = process.env.REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY;
// Sentry DSN (Data Source Name), a client key for authenticating calls to Sentry
const sentryDsn = process.env.REACT_APP_PUBLIC_SENTRY_DSN;
@ -57,8 +56,7 @@ const currencyConfig = {
maximumFractionDigits: 2,
};
const stripePublishableKey =
process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY || 'pk_test_FWtdKPZvtrj37t45dIomssBI';
const stripePublishableKey = process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY;
// Stripe only supports payments in certain countries, see full list
// at https://stripe.com/global
@ -221,7 +219,7 @@ const postalCode = '00100';
const streetAddress = 'Bulevardi 14';
// Canonical root url is needed in social media sharing and SEO optimization purposes.
const canonicalRootURL = process.env.REACT_APP_CANONICAL_ROOT_URL || 'http://localhost:3000';
const canonicalRootURL = process.env.REACT_APP_CANONICAL_ROOT_URL;
// Site title is needed in meta tags (bots and social media sharing reads those)
const siteTitle = 'Saunatime';