Skip to content

Commit

Permalink
Implement runtime config with next.js (#869)
Browse files Browse the repository at this point in the history
* Migrate process.env to next runtime config

* Remove unneeded build args
  • Loading branch information
rschlaefli committed Feb 8, 2019
1 parent cb4f8e2 commit 5bcc9f2
Show file tree
Hide file tree
Showing 18 changed files with 138 additions and 124 deletions.
55 changes: 0 additions & 55 deletions .travis.yml
Expand Up @@ -62,15 +62,6 @@ jobs:
- docker pull $IMAGE_NAME:latest
- >
docker build .
--build-arg APP_BASE_URL=$STAGING_APP_BASE_URL
--build-arg API_ENDPOINT=$STAGING_API_ENDPOINT
--build-arg API_ENDPOINT_WS=$STAGING_API_ENDPOINT_WS
--build-arg APP_PERSIST_QUERIES=$STAGING_APP_PERSIST_QUERIES
--build-arg S3_ROOT_URL=$STAGING_S3_ROOT_URL
--build-arg SERVICES_GOOGLE_ANALYTICS_TRACKING_ID=$STAGING_SERVICES_GOOGLE_ANALYTICS_TRACKING_ID
--build-arg SERVICES_LOGROCKET_APP_ID=$STAGING_SERVICES_LOGROCKET_APP_ID
--build-arg SERVICES_SENTRY_DSN=$STAGING_SERVICES_SENTRY_DSN
--build-arg SERVICES_SLAASK_WIDGET_KEY=$STAGING_SERVICES_SLAASK_WIDGET_KEY
--build-arg VERSION=$TRAVIS_TAG
--cache-from $IMAGE_NAME:latest
-t $IMAGE_NAME:latest
Expand All @@ -84,12 +75,6 @@ jobs:
- docker pull $IMAGE_NAME:nightly
- >
docker build .
--build-arg APP_BASE_URL=$STAGING_APP_BASE_URL
--build-arg API_ENDPOINT=$STAGING_API_ENDPOINT
--build-arg API_ENDPOINT_WS=$STAGING_API_ENDPOINT_WS
--build-arg APP_PERSIST_QUERIES=$STAGING_APP_PERSIST_QUERIES
--build-arg S3_ROOT_URL=$STAGING_S3_ROOT_URL
--build-arg SERVICES_SENTRY_DSN=$STAGING_SERVICES_SENTRY_DSN
--build-arg VERSION=$TRAVIS_TAG
--cache-from $IMAGE_NAME:nightly
-t $IMAGE_NAME:nightly
Expand All @@ -105,11 +90,6 @@ jobs:
- travis_retry docker pull $IMAGE_NAME:latest
- >
docker build .
--build-arg APP_BASE_URL=$STAGING_APP_BASE_URL
--build-arg API_ENDPOINT=$STAGING_API_ENDPOINT
--build-arg API_ENDPOINT_WS=$STAGING_API_ENDPOINT_WS
--build-arg APP_PERSIST_QUERIES=$STAGING_APP_PERSIST_QUERIES
--build-arg S3_ROOT_URL=$STAGING_S3_ROOT_URL
--build-arg VERSION=$TRAVIS_TAG
--cache-from $IMAGE_NAME:latest
-t $IMAGE_NAME:$TRAVIS_TAG
Expand All @@ -129,16 +109,6 @@ jobs:
script:
- >
docker build .
--build-arg APP_BASE_URL=$PROD_APP_BASE_URL
--build-arg APP_JOIN_URL=$PROD_APP_JOIN_URL
--build-arg API_ENDPOINT=$PROD_API_ENDPOINT
--build-arg API_ENDPOINT_WS=$PROD_API_ENDPOINT_WS
--build-arg APP_PERSIST_QUERIES=$PROD_APP_PERSIST_QUERIES
--build-arg S3_ROOT_URL=$PROD_S3_ROOT_URL
--build-arg SERVICES_GOOGLE_ANALYTICS_TRACKING_ID=$PROD_SERVICES_GOOGLE_ANALYTICS_TRACKING_ID
--build-arg SERVICES_LOGROCKET_APP_ID=$PROD_SERVICES_LOGROCKET_APP_ID
--build-arg SERVICES_SENTRY_DSN=$PROD_SERVICES_SENTRY_DSN
--build-arg SERVICES_SLAASK_WIDGET_KEY=$PROD_SERVICES_SLAASK_WIDGET_KEY
--build-arg VERSION=$TRAVIS_TAG
-t $IMAGE_NAME:$TRAVIS_TAG
- travis_retry docker push $IMAGE_NAME:$TRAVIS_TAG
Expand All @@ -157,16 +127,6 @@ jobs:
script:
- >
docker build .
--build-arg APP_BASE_URL=$PROD_APP_BASE_URL
--build-arg APP_JOIN_URL=$PROD_APP_JOIN_URL
--build-arg API_ENDPOINT=$PROD_API_ENDPOINT
--build-arg API_ENDPOINT_WS=$PROD_API_ENDPOINT_WS
--build-arg APP_PERSIST_QUERIES=$PROD_APP_PERSIST_QUERIES
--build-arg S3_ROOT_URL=$PROD_S3_ROOT_URL
--build-arg SERVICES_GOOGLE_ANALYTICS_TRACKING_ID=$PROD_SERVICES_GOOGLE_ANALYTICS_TRACKING_ID
--build-arg SERVICES_LOGROCKET_APP_ID=$PROD_SERVICES_LOGROCKET_APP_ID
--build-arg SERVICES_SENTRY_DSN=$PROD_SERVICES_SENTRY_DSN
--build-arg SERVICES_SLAASK_WIDGET_KEY=$PROD_SERVICES_SLAASK_WIDGET_KEY
--build-arg VERSION=$TRAVIS_TAG
-t $IMAGE_NAME:$TRAVIS_TAG
- travis_retry docker push $IMAGE_NAME:$TRAVIS_TAG
Expand All @@ -178,11 +138,6 @@ jobs:
script:
- >
docker build .
--build-arg APP_BASE_URL=$PROD_APP_BASE_URL
--build-arg API_ENDPOINT=$PROD_API_ENDPOINT
--build-arg API_ENDPOINT_WS=$PROD_API_ENDPOINT_WS
--build-arg APP_PERSIST_QUERIES=$PROD_APP_PERSIST_QUERIES
--build-arg S3_ROOT_URL=$PROD_S3_ROOT_URL
--build-arg VERSION=$TRAVIS_TAG
-t $IMAGE_NAME:stable
-t $IMAGE_NAME:$TRAVIS_TAG
Expand All @@ -204,16 +159,6 @@ jobs:
script:
- >
docker build .
--build-arg APP_BASE_URL=$PROD_APP_BASE_URL
--build-arg APP_JOIN_URL=$PROD_APP_JOIN_URL
--build-arg API_ENDPOINT=$PROD_API_ENDPOINT
--build-arg API_ENDPOINT_WS=$PROD_API_ENDPOINT_WS
--build-arg APP_PERSIST_QUERIES=$PROD_APP_PERSIST_QUERIES
--build-arg S3_ROOT_URL=$PROD_S3_ROOT_URL
--build-arg SERVICES_GOOGLE_ANALYTICS_TRACKING_ID=$PROD_SERVICES_GOOGLE_ANALYTICS_TRACKING_ID
--build-arg SERVICES_LOGROCKET_APP_ID=$PROD_SERVICES_LOGROCKET_APP_ID
--build-arg SERVICES_SENTRY_DSN=$PROD_SERVICES_SENTRY_DSN
--build-arg SERVICES_SLAASK_WIDGET_KEY=$PROD_SERVICES_SLAASK_WIDGET_KEY
--build-arg VERSION=$TRAVIS_TAG
-t $IMAGE_NAME:stable
-t $IMAGE_NAME:$TRAVIS_TAG
Expand Down
22 changes: 11 additions & 11 deletions Dockerfile
Expand Up @@ -26,20 +26,20 @@ COPY --chown=1000:0 . $KLICKER_DIR/
# pre-build the application
# define available build arguments
# these are then bundled into the js
ARG APP_BASE_URL
ARG APP_JOIN_URL
ARG API_ENDPOINT
ARG API_ENDPOINT_WS
ARG APP_PERSIST_QUERIES
ARG S3_ROOT_URL
# ARG APP_BASE_URL
# ARG APP_JOIN_URL
# ARG API_ENDPOINT
# ARG API_ENDPOINT_WS
# ARG APP_PERSIST_QUERIES
# ARG S3_ROOT_URL
ARG VERSION

# optional build arguments
ARG SECURITY_FINGERPRINTING="true"
ARG SERVICES_GOOGLE_ANALYTICS_TRACKING_ID
ARG SERVICES_LOGROCKET_APP_ID
ARG SERVICES_SENTRY_DSN
ARG SERVICES_SLAASK_WIDGET_KEY
# ARG SECURITY_FINGERPRINTING="true"
# ARG SERVICES_GOOGLE_ANALYTICS_TRACKING_ID
# ARG SERVICES_LOGROCKET_APP_ID
# ARG SERVICES_SENTRY_DSN
# ARG SERVICES_SLAASK_WIDGET_KEY

RUN set -x \
&& yarn run build
Expand Down
7 changes: 5 additions & 2 deletions src/components/common/navbar/Navbar.js
Expand Up @@ -2,17 +2,20 @@

import React from 'react'
import PropTypes from 'prop-types'
import getConfig from 'next/config'
import Router from 'next/router'
import { intlShape } from 'react-intl'
import { Icon, Menu } from 'semantic-ui-react'
import { Query, Mutation } from 'react-apollo'
import Router from 'next/router'

import { AccountSummaryQuery, LogoutMutation } from '../../../graphql'

import AccountArea from './AccountArea'
import SearchArea from './SearchArea'
import SessionArea from './SessionArea'

const { publicRuntimeConfig } = getConfig()

const propTypes = {
// filters: PropTypes.object,
handleSidebarToggle: PropTypes.func.isRequired,
Expand Down Expand Up @@ -97,7 +100,7 @@ export const NavbarPres = ({ intl, search, sidebarVisible, title, handleSidebarT
shortname: accountShort,
// user_hash: userHash,
})
window._slaask.init(process.env.SERVICES_SLAASK_WIDGET_KEY, accountId)
window._slaask.init(publicRuntimeConfig.slaaskWidgetKey, accountId)
/* window._slaask.init(process.env.SLAASK_WIDGET_KEY, {
user_hash: userHash,
user_token: accountId,
Expand Down
8 changes: 5 additions & 3 deletions src/components/forms/RegistrationForm.js
@@ -1,16 +1,18 @@
import React from 'react'
import PropTypes from 'prop-types'
import _isEmpty from 'lodash/isEmpty'
import getConfig from 'next/config'
import { FormattedMessage, intlShape } from 'react-intl'
import { Button, Checkbox, Form } from 'semantic-ui-react'
import { object, boolean } from 'yup'

import { Formik } from 'formik'
import _isEmpty from 'lodash/isEmpty'

import { FormikInput } from '.'
import validationSchema from './common/validationSchema'
import messages from './common/messages'

const { publicRuntimeConfig } = getConfig()

const { email, shortname, institution, password, passwordRepeat, useCase } = validationSchema

const propTypes = {
Expand Down Expand Up @@ -59,7 +61,7 @@ const RegistrationForm = ({ intl, loading, onSubmit }) => (
handleBlur={handleBlur}
handleChange={handleChange}
icon="hashtag"
inlineLabel={`${process.env.APP_BASE_URL}/join/`}
inlineLabel={`${publicRuntimeConfig.baseUrl}/join/`}
intl={intl}
label={intl.formatMessage(messages.shortnameLabel)}
name="shortname"
Expand Down
5 changes: 4 additions & 1 deletion src/components/forms/questionManagement/FileDropzone.js
@@ -1,9 +1,12 @@
import React from 'react'
import PropTypes from 'prop-types'
import Dropzone from 'react-dropzone'
import getConfig from 'next/config'
import { FormattedMessage } from 'react-intl'
import { Icon, Card, Image, Button } from 'semantic-ui-react'

const { publicRuntimeConfig } = getConfig()

const propTypes = {
disabled: PropTypes.bool,
files: PropTypes.arrayOf(PropTypes.shape({})),
Expand Down Expand Up @@ -35,7 +38,7 @@ const FileDropzone = ({ disabled, files, onChangeFiles }) => (

<div className="previews">
{files.map((file, index) => {
const imageSrc = `${process.env.S3_ROOT_URL}/${file.name}`
const imageSrc = `${publicRuntimeConfig.s3root}/${file.name}`
return (
<div className="imagePreview" key={file.id || index}>
<Card>
Expand Down
11 changes: 7 additions & 4 deletions src/components/forms/questionManagement/QuestionCreationForm.js
@@ -1,11 +1,12 @@
import React from 'react'
import PropTypes from 'prop-types'
import { defineMessages, FormattedMessage, intlShape } from 'react-intl'
import { Button, Form, Message, List, Loader } from 'semantic-ui-react'
import { Formik } from 'formik'
import getConfig from 'next/config'
import _isEmpty from 'lodash/isEmpty'
import _isNumber from 'lodash/isNumber'
import _some from 'lodash/some'
import { defineMessages, FormattedMessage, intlShape } from 'react-intl'
import { Button, Form, Message, List, Loader } from 'semantic-ui-react'
import { Formik } from 'formik'
import { EditorState } from 'draft-js'

import FileDropzone from './FileDropzone'
Expand All @@ -21,6 +22,8 @@ import { QUESTION_TYPES } from '../../../lib'
import { QUESTION_GROUPS } from '../../../constants'
import { FormikInput } from '../components'

const { publicRuntimeConfig } = getConfig()

const messages = defineMessages({
contentEmpty: {
defaultMessage: 'Please add a question',
Expand Down Expand Up @@ -224,7 +227,7 @@ const QuestionCreationForm = ({ intl, tags, tagsLoading, onSubmit, onDiscard })
/>
</div>

{process.env.S3_ROOT_URL && (
{publicRuntimeConfig.s3root && (
<div className="questionInput questionFiles">
<h2>
<FormattedMessage defaultMessage="Attached Images (Beta)" id="createQuestion.filesLabel" />
Expand Down
7 changes: 5 additions & 2 deletions src/components/forms/questionManagement/QuestionEditForm.js
@@ -1,8 +1,9 @@
import React from 'react'
import PropTypes from 'prop-types'
import { compose, withProps } from 'recompose'
import _isEmpty from 'lodash/isEmpty'
import _isNumber from 'lodash/isNumber'
import getConfig from 'next/config'
import { compose, withProps } from 'recompose'
import { EditorState, ContentState, convertFromRaw } from 'draft-js'
import { defineMessages, FormattedMessage, intlShape } from 'react-intl'
import { Button, Form, Dropdown, Message } from 'semantic-ui-react'
Expand All @@ -15,6 +16,8 @@ import { ContentInput, TagInput } from '../../questions'
import { FREECreationOptions, SCCreationOptions } from '../../questionTypes'
import { QUESTION_TYPES, QUESTION_GROUPS } from '../../../constants'

const { publicRuntimeConfig } = getConfig()

const messages = defineMessages({
contentEmpty: {
defaultMessage: 'Please add a question.',
Expand Down Expand Up @@ -251,7 +254,7 @@ const QuestionEditForm = ({
/>
</div>

{process.env.S3_ROOT_URL && (
{publicRuntimeConfig.s3root && (
<div className="questionInput questionFiles">
<h3>
<FormattedMessage defaultMessage="Attached Files (Beta)" id="createQuestion.filesLabel" />
Expand Down
5 changes: 4 additions & 1 deletion src/components/forms/userSettings/AccountDataForm.js
Expand Up @@ -4,13 +4,16 @@ import { intlShape, FormattedMessage } from 'react-intl'
import { Formik } from 'formik'
import { object } from 'yup'
import { Form, Button } from 'semantic-ui-react'
import getConfig from 'next/config'

import { AccountSummaryQuery, ModifyUserMutation } from '../../../graphql'
import { FormikInput } from '..'
import validationSchema from '../common/validationSchema'
import messages from '../common/messages'
import { Errors } from '../../../constants'

const { publicRuntimeConfig } = getConfig()

const { email, institution, useCase, shortname } = validationSchema

const propTypes = {
Expand Down Expand Up @@ -69,7 +72,7 @@ const AccountDataForm = ({ intl }) => (
handleBlur={handleBlur}
handleChange={handleChange}
icon="hashtag"
inlineLabel={`${process.env.APP_BASE_URL}/join/`}
inlineLabel={`${publicRuntimeConfig.baseUrl}/join/`}
intl={intl}
label={intl.formatMessage(messages.shortnameLabel)}
name="shortname"
Expand Down
11 changes: 7 additions & 4 deletions src/components/sessions/SessionTimeline.js
Expand Up @@ -2,10 +2,13 @@ import React from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
import QRCode from 'qrcode.react'
import getConfig from 'next/config'
import { defineMessages, intlShape, FormattedMessage } from 'react-intl'
import { Button, Checkbox, Icon, Popup, Message } from 'semantic-ui-react'
import { QuestionBlock } from '../questions'

const { publicRuntimeConfig } = getConfig()

const messages = defineMessages({
buttonCloseBlock: {
defaultMessage: 'Close current block',
Expand Down Expand Up @@ -126,14 +129,14 @@ const SessionTimeline = ({
<div className="popupContent">
<div className="link">
<strong>
{process.env.APP_JOIN_URL
? `${process.env.APP_JOIN_URL}/${shortname}`
: `${process.env.APP_BASE_URL}/join/${shortname}`}
{publicRuntimeConfig.joinUrl
? `${publicRuntimeConfig.joinUrl}/${shortname}`
: `${publicRuntimeConfig.baseUrl}/join/${shortname}`}
</strong>
</div>

<div className="qr">
<QRCode size={200} value={`${process.env.APP_BASE_URL}/join/${shortname}`} />
<QRCode size={200} value={`${publicRuntimeConfig.baseUrl}/join/${shortname}`} />
</div>

<a href={`/qr/${shortname}`} rel="noopener noreferrer" target="_blank">
Expand Down
5 changes: 4 additions & 1 deletion src/components/sessions/join/QuestionArea.js
Expand Up @@ -4,6 +4,7 @@ import classNames from 'classnames'
import _without from 'lodash/without'
import v8n from 'v8n'
import dayjs from 'dayjs'
import getConfig from 'next/config'

import { FormattedMessage } from 'react-intl'
import { convertFromRaw } from 'draft-js'
Expand All @@ -14,6 +15,8 @@ import { QUESTION_TYPES, QUESTION_GROUPS } from '../../../constants'
import { ActionMenu, Collapser } from '../../common'
import { QuestionDescription, SCAnswerOptions, FREEAnswerOptions } from '../../questionTypes'

const { publicRuntimeConfig } = getConfig()

const propTypes = {
active: PropTypes.bool.isRequired,
activeQuestion: PropTypes.number,
Expand Down Expand Up @@ -127,7 +130,7 @@ function QuestionArea({
</Collapser>
</div>

{process.env.S3_ROOT_URL && files.length > 0 && (
{publicRuntimeConfig.s3root && files.length > 0 && (
<div className="files">
<QuestionFiles files={files} />
</div>
Expand Down
4 changes: 3 additions & 1 deletion src/components/sessions/join/QuestionFiles.js
@@ -1,7 +1,9 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Card, Image, Modal } from 'semantic-ui-react'
import getConfig from 'next/config'

const { publicRuntimeConfig } = getConfig()
const propTypes = {
files: PropTypes.arrayOf(
PropTypes.shape({
Expand All @@ -16,7 +18,7 @@ const defaultProps = {
const QuestionFiles = ({ files }) => (
<div className="questionFiles">
{files.map(({ id, name }, ix) => {
const fileSrc = `${process.env.S3_ROOT_URL}/${name}`
const fileSrc = `${publicRuntimeConfig.s3root}/${name}`
const previewImage = (
<Card>
<Image height="auto" src={fileSrc} width="100%" />
Expand Down

0 comments on commit 5bcc9f2

Please sign in to comment.