Skip to content

Commit

Permalink
Inject env vars at runtime instead of build time
Browse files Browse the repository at this point in the history
  • Loading branch information
jake-low committed Oct 22, 2024
1 parent 8d15cb7 commit b6e95f8
Show file tree
Hide file tree
Showing 78 changed files with 218 additions and 139 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ chimp.js
.DS_Store
.env.local
.env.*.local
/public/env.json

npm-debug.log*
yarn-debug.log*
Expand Down
5 changes: 4 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ RUN yarn run build

FROM nginx:1.25-alpine

RUN apk update && apk add jq

COPY --from=builder /maproulette3/dist /srv/www
COPY nginx.conf /etc/nginx/templates/default.conf.template
COPY docker/nginx.conf /etc/nginx/templates/default.conf.template
COPY docker/90-write-env-to-json.sh /docker-entrypoint.d

EXPOSE 80
7 changes: 7 additions & 0 deletions docker/90-write-env-to-json.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

# Convert env to json and write out to overrides file
jq -n 'env | with_entries(select(.key | startswith("REACT_APP_")))' > /tmp/env.overrides.json
# Merge overrides and defaults together
cp /srv/www/env.json /tmp/env.default.json
jq -s '.[0] * .[1]' /tmp/env.default.json /tmp/env.overrides.json > /srv/www/env.json
File renamed without changes.
10 changes: 9 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
-->
<link rel="manifest" href="/manifest.json">

<link rel="preload" href="/env.json">
<link rel="preload" href="/src/index.jsx">

<!-- App Icons -->
<link rel="apple-touch-icon" sizes="180x180" href="/assets/images/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicons/favicon-32x32.png">
Expand All @@ -42,6 +45,11 @@
<div id="external-root"></div>
<div id="dropdown"></div>

<script type="module" src="/src/index.jsx"></script>
<script type="module">
fetch("/env.json")
.then(res => res.json())
.then(env => { window.env = env; })
.then(() => import("/src/index.jsx"));
</script>
</body>
</html>
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
"@vitejs/plugin-react-swc": "^3.7.1",
"@vitest/coverage-v8": "^2.1.2",
"dotenv": "^16.4.5",
"dotenv-cli": "^7.4.2",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.7",
"eslint": "^8.54.0",
Expand Down Expand Up @@ -138,9 +139,10 @@
"update-layers": "node scripts/update_layers.js",
"update-layers-prod": "NODE_ENV=production node scripts/update_layers.js",
"start-js": "vite",
"start": "npm-run-all -p update-layers start-js",
"start": "npm-run-all -p build-env update-layers start-js",
"build-env": "dotenv -c development -- jq -n 'env | with_entries(select(.key | startswith(\"REACT_APP_\")))' > public/env.json",
"build-js": "vite build",
"build": "yarn run build-intl && yarn run update-layers-prod && yarn run build-js",
"build": "yarn run build-env && yarn run build-intl && yarn run update-layers-prod && yarn run build-js",
"test": "vitest",
"test:cov": "vitest run --coverage",
"lint": "eslint src/",
Expand Down
2 changes: 1 addition & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class App extends Component {
render() {
// We don't currently support mobile devices. Unless the mobile feature
// is explicitly enabled, inform user that mobile is not supported.
if (import.meta.env.REACT_APP_FEATURE_MOBILE_DEVICES !== 'enabled') {
if (window.env.REACT_APP_FEATURE_MOBILE_DEVICES !== 'enabled') {
// This is a pretty simplistic check, but it should catch most cases.
if (/iPhone|iPad|iPod|BlackBerry|IEMobile|Fennec|Android|Mobile|Tablet/i.test(navigator.userAgent)) {
return <MobileNotSupported />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import ConfirmAction from "../../../ConfirmAction/ConfirmAction";
import messages from "../ChallengeDashboard/Messages";

const isEmailRequired = (user) => {
if (import.meta.env.REACT_APP_EMAIL_ENFORCEMENT === "required") {
if (window.env.REACT_APP_EMAIL_ENFORCEMENT === "required") {
if (!user?.settings?.email) {
return true;
}
Expand All @@ -33,7 +33,7 @@ const handleTasksNeedRebuild = (dateString) => {
if (dateString) {
const lastRefreshDate = new Date(dateString);
const today = new Date();
const staleMonths = Number(import.meta.env.REACT_APP_ARCHIVE_STALE_TIME_IN_MONTHS) || 6
const staleMonths = Number(window.env.REACT_APP_ARCHIVE_STALE_TIME_IN_MONTHS) || 6
const staleDate = today.setMonth(today.getMonth() - staleMonths);

return lastRefreshDate < staleDate;
Expand Down Expand Up @@ -136,7 +136,7 @@ export default class ChallengeControls extends Component {
)}
{this.props.includeCopyURL && (
<CopyToClipboard
text={`${import.meta.env.REACT_APP_URL}/browse/challenges/${this.props.challenge.id}`}
text={`${window.env.REACT_APP_URL}/browse/challenges/${this.props.challenge.id}`}
onCopy={this.props.onControlComplete}
>
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export class ChallengeDashboard extends Component {
day="2-digit"
/>{" "}
<FormattedMessage {...manageMessages.staleChallengeMessage2} />
{` ${Number(import.meta.env.REACT_APP_ARCHIVE_STALE_TIME_IN_MONTHS) || 6} `}
{` ${Number(window.env.REACT_APP_ARCHIVE_STALE_TIME_IN_MONTHS) || 6} `}
<FormattedMessage {...manageMessages.staleChallengeMessage3} />
</div>
)}
Expand All @@ -160,7 +160,7 @@ export class ChallengeDashboard extends Component {
challenges={[this.props.challenge]}
pageId="ChallengeDashboard"
metaReviewEnabled={
import.meta.env.REACT_APP_FEATURE_META_QC === "enabled"
window.env.REACT_APP_FEATURE_META_QC === "enabled"
}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import SvgSymbol from "../../../SvgSymbol/SvgSymbol";
import messages from "../Messages";

const EmailRequirementNotice = (props) => {
if (import.meta.env.REACT_APP_EMAIL_ENFORCEMENT === "required") {
if (window.env.REACT_APP_EMAIL_ENFORCEMENT === "required") {
if (!props.user?.settings?.email) {
return (
<ul className="mr-bg-gradient-b-blue-darker-blue-dark mr-text-white mr-w-full">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const jsSchema = (
required: ["name"],
};

if (import.meta.env.REACT_APP_EMAIL_ENFORCEMENT === "required") {
if (window.env.REACT_APP_EMAIL_ENFORCEMENT === "required") {
if (!user?.settings?.email) {
schema.properties.email = {
title: intl.formatMessage(messages.emailLabel),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const validateMinLength = val => {
}

export const jsSchema = (intl) => {
const minLengthEnvValue = import.meta.env.REACT_APP_CHALLENGE_INSTRUCTIONS_MIN_LENGTH
const minLengthEnvValue = window.env.REACT_APP_CHALLENGE_INSTRUCTIONS_MIN_LENGTH
const instructionsMinLength = validateMinLength(minLengthEnvValue)

const schemaFields = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,6 @@ export const uiSchema = (intl, user, challengeData, extraErrors, options={}) =>
* necessary
*/
export const numericEnvSetting = (settingName, defaultValue) => {
const setting = _get(import.meta.env, settingName, defaultValue)
const setting = _get(window.env, settingName, defaultValue)
return _isString(setting) ? parseInt(setting, 10) : setting
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export class ProjectCard extends Component {
<a
target="_blank"
rel="noopener noreferrer"
href={`${import.meta.env.REACT_APP_MAP_ROULETTE_SERVER_URL}/api/v2/project/${this.props.project.id}/tasks/extract`}
href={`${window.env.REACT_APP_MAP_ROULETTE_SERVER_URL}/api/v2/project/${this.props.project.id}/tasks/extract`}
className="mr-flex mr-items-center"
>
<SvgSymbol
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export default class ProjectOverview extends Component {
{!this.props.project.enabled &&
<div className="mr-text-red-light mr-flex mr-items-center mr-text-base mr-uppercase mr-mt-2">
<a
href={`${import.meta.env.REACT_APP_DOCS_URL}/documentation/challenge-visibility-and-discovery/`}
href={`${window.env.REACT_APP_DOCS_URL}/documentation/challenge-visibility-and-discovery/`}
className="mr-mr-2 mr-flex mr-items-center"
target="_blank"
rel="noopener noreferrer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export class RebuildTasksControl extends Component {
<FormattedMessage {...messages.warning} />
<div className="mr-my-4 mr-links-green-light">
<a
href={`${import.meta.env.REACT_APP_DOCS_URL}/documentation/rebuilding-challenge-tasks/`}
href={`${window.env.REACT_APP_DOCS_URL}/documentation/rebuilding-challenge-tasks/`}
target="_blank"
rel="noopener noreferrer"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export default class TaskPropertyStyleRules extends Component {
</div>
<div className="mr-mb-6 mr-links-green-light">
<a
href={`${import.meta.env.REACT_APP_DOCS_URL}/documentation/styling-task-features/`}
href={`${window.env.REACT_APP_DOCS_URL}/documentation/styling-task-features/`}
target="_blank"
rel="noopener noreferrer"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import messages from './Messages'
export default class GeographicIndexingNotice extends Component {
render() {
const reindexingDelay =
_get(import.meta.env, 'REACT_APP_GEOGRAPHIC_INDEXING_DELAY', 0)
_get(window.env, 'REACT_APP_GEOGRAPHIC_INDEXING_DELAY', 0)

// If enough time has passed, nothing to show
if (differenceInHours(Date.now(), _get(this.props, 'challenge.lastTaskRefresh', 0)) >
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export default class ChallengeListWidget extends Component {
<a
target="_blank"
rel="noopener noreferrer"
href={`${import.meta.env.REACT_APP_MAP_ROULETTE_SERVER_URL}` +
href={`${window.env.REACT_APP_MAP_ROULETTE_SERVER_URL}` +
`/api/v2/project/${_get(this.props, 'project.id')}` +
`/tasks/extract?${cId}&timezone=` +
`${encodeURIComponent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export default class ChallengeOverviewWidget extends Component {
{this.props.challenge.enabled && this.props.challenge.parent && !this.props.challenge.parent.enabled &&
<div className="mr-text-red-light mr-flex mr-items-center mr-text-base mr-uppercase mr-mt-2">
<a
href={`${import.meta.env.REACT_APP_DOCS_URL}/documentation/challenge-visibility-and-discovery/`}
href={`${window.env.REACT_APP_DOCS_URL}/documentation/challenge-visibility-and-discovery/`}
className="mr-mr-2 mr-flex mr-items-center"
target="_blank"
rel="noopener noreferrer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default class CommentsWidget extends Component {
<a
target="_blank"
rel="noopener noreferrer"
href={`${import.meta.env.REACT_APP_MAP_ROULETTE_SERVER_URL}/api/v2/challenge/${_get(this.props, 'challenge.id')}/comments/extract`}
href={`${window.env.REACT_APP_MAP_ROULETTE_SERVER_URL}/api/v2/challenge/${_get(this.props, 'challenge.id')}/comments/extract`}
className="mr-button mr-button--green-lighter mr-button--small mr-button--with-icon mr-text-sm"
>
<SvgSymbol
Expand Down
12 changes: 6 additions & 6 deletions src/components/ChallengeDetail/ChallengeDetail.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ const ClusterMap =

const ProjectPicker = WithManageableProjects(ProjectPickerModal);

const FLAG_REPO_NAME = import.meta.env.REACT_APP_GITHUB_ISSUES_API_REPO
const FLAG_REPO_OWNER = import.meta.env.REACT_APP_GITHUB_ISSUES_API_OWNER
const FLAG_TOKEN = import.meta.env.REACT_APP_GITHUB_ISSUES_API_TOKEN
const FLAG_REPO_NAME = window.env.REACT_APP_GITHUB_ISSUES_API_REPO
const FLAG_REPO_OWNER = window.env.REACT_APP_GITHUB_ISSUES_API_OWNER
const FLAG_TOKEN = window.env.REACT_APP_GITHUB_ISSUES_API_TOKEN
const FLAGGING_ACTIVE = FLAG_REPO_NAME && FLAG_REPO_OWNER && FLAG_TOKEN

const DETAIL_TABS = {
Expand Down Expand Up @@ -127,8 +127,8 @@ export class ChallengeDetail extends Component {
queryForIssue = async (id) => {
this.setState({ flagLoading: true });

const owner = import.meta.env.REACT_APP_GITHUB_ISSUES_API_OWNER
const repo = import.meta.env.REACT_APP_GITHUB_ISSUES_API_REPO
const owner = window.env.REACT_APP_GITHUB_ISSUES_API_OWNER
const repo = window.env.REACT_APP_GITHUB_ISSUES_API_REPO
const query = `q='Reported+Challenge+${encodeURIComponent('#') + id}'+in:title+state:open+repo:${owner}/${repo}`;
const response = await fetch(`https://api.github.com/search/issues?${query}`, {
method: 'GET',
Expand Down Expand Up @@ -569,7 +569,7 @@ export class ChallengeDetail extends Component {
</strong>{' '}
<a
className="mr-text-green-lighter hover:mr-text-white"
href={import.meta.env.REACT_APP_OSM_SERVER + '/user/' + owner.osmProfile.displayName}
href={window.env.REACT_APP_OSM_SERVER + '/user/' + owner.osmProfile.displayName}
target="_blank"
rel="noopener"
>
Expand Down
10 changes: 5 additions & 5 deletions src/components/ChallengeDetail/FlagCommentInput.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ export class FlagCommentInput extends Component {
this.props.handleCheckboxError()
} else {
const challenge = this.props.challenge
const owner = import.meta.env.REACT_APP_GITHUB_ISSUES_API_OWNER
const repo = import.meta.env.REACT_APP_GITHUB_ISSUES_API_REPO
const body = `Challenge: [#${challenge.id} - ${challenge.name}](${import.meta.env.REACT_APP_URL}/browse/challenges/${challenge.id}) \n\n Reported by: [${this.props.user.osmProfile.displayName}](https://www.openstreetmap.org/user/${encodeURIComponent(this.props.user.osmProfile.displayName)})\n\n${this.state.value}`
const owner = window.env.REACT_APP_GITHUB_ISSUES_API_OWNER
const repo = window.env.REACT_APP_GITHUB_ISSUES_API_REPO
const body = `Challenge: [#${challenge.id} - ${challenge.name}](${window.env.REACT_APP_URL}/browse/challenges/${challenge.id}) \n\n Reported by: [${this.props.user.osmProfile.displayName}](https://www.openstreetmap.org/user/${encodeURIComponent(this.props.user.osmProfile.displayName)})\n\n${this.state.value}`
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/issues`, {
method: 'POST',
body: JSON.stringify({
Expand All @@ -38,7 +38,7 @@ export class FlagCommentInput extends Component {
state: 'open'
}),
headers: {
'Authorization': `token ${import.meta.env.REACT_APP_GITHUB_ISSUES_API_TOKEN}`,
'Authorization': `token ${window.env.REACT_APP_GITHUB_ISSUES_API_TOKEN}`,
'Content-Type': 'application/json',
'Accept': 'application/vnd.github.v3+json',
},
Expand All @@ -48,7 +48,7 @@ export class FlagCommentInput extends Component {
const responseBody = await response.json()
this.props.onModalSubmit(responseBody)
const issue_link = responseBody.html_url
const comment = `This challenge, challenge [#${challenge.id} - ${challenge.name}](${import.meta.env.REACT_APP_URL}/browse/challenges/${challenge.id}) in project [#${challenge.parent.id} - ${challenge.parent.displayName}](${import.meta.env.REACT_APP_URL}/browse/projects/${challenge.parent.id}), has been reported by [${this.props.user.osmProfile.displayName}](${import.meta.env.REACT_APP_OSM_SERVER}/user/${encodeURIComponent(this.props.user.osmProfile.displayName)}). Please use [this GitHub issue](${issue_link}) to discuss. \n\n Report Content: \n ${this.state.value}`
const comment = `This challenge, challenge [#${challenge.id} - ${challenge.name}](${window.env.REACT_APP_URL}/browse/challenges/${challenge.id}) in project [#${challenge.parent.id} - ${challenge.parent.displayName}](${window.env.REACT_APP_URL}/browse/projects/${challenge.parent.id}), has been reported by [${this.props.user.osmProfile.displayName}](${window.env.REACT_APP_OSM_SERVER}/user/${encodeURIComponent(this.props.user.osmProfile.displayName)}). Please use [this GitHub issue](${issue_link}) to discuss. \n\n Report Content: \n ${this.state.value}`
await postChallengeComment(challenge.id, comment)
this.props.handleViewCommentsSubmit()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import messages from './Messages'
import './ChallengeResultList.scss'

const limitUserResults = (challenges) => {
const ownerLimit = Number(import.meta.env.REACT_APP_BROWSE_CHALLENGES_OWNER_LIMIT);
const ownerLimit = Number(window.env.REACT_APP_BROWSE_CHALLENGES_OWNER_LIMIT);

if (ownerLimit) {
const userDictionary = {};
Expand Down Expand Up @@ -85,7 +85,7 @@ export class ChallengeResultList extends Component {

if (query) {
try {
const response = await fetch(`${import.meta.env.REACT_APP_MAP_ROULETTE_SERVER_URL}/api/v2/task/${query}`);
const response = await fetch(`${window.env.REACT_APP_MAP_ROULETTE_SERVER_URL}/api/v2/task/${query}`);
const responseJson = await response.json();
this.setState({ data: responseJson });
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class StartVirtualChallenge extends Component {
/** Invoked to cancel editing of the name */
cancelEditing = () => this.setState({editingName: false, challengeName: ''})

maxAllowedTasks = () => parseInt(_get(import.meta.env, 'REACT_APP_VIRTUAL_CHALLENGE_MAX_TASKS', 10000))
maxAllowedTasks = () => parseInt(_get(window.env, 'REACT_APP_VIRTUAL_CHALLENGE_MAX_TASKS', 10000))

render() {
const taskCount =
Expand Down
2 changes: 1 addition & 1 deletion src/components/EnhancedMap/LayerToggle/LayerToggle.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ const overlayToggles = props => {
}

if (props.toggleOSMData &&
_get(import.meta.env, 'REACT_APP_OSM_DATA_OVERLAY', 'enabled') !== 'disabled') {
_get(window.env, 'REACT_APP_OSM_DATA_OVERLAY', 'enabled') !== 'disabled') {
toggles.push({
id: "osm-data",
label: <FormattedMessage {...messages.showOSMDataLabel} />,
Expand Down
2 changes: 1 addition & 1 deletion src/components/EnhancedMap/PropertyList/PropertyList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import messages from './Messages'
const PropertyList = props => {
// Default is lightMode -- only do darkMode if the value is present and false
const darkMode = props.lightMode === false
const tagInfo = import.meta.env.REACT_APP_TAGINFO_SERVER_URL
const tagInfo = window.env.REACT_APP_TAGINFO_SERVER_URL
const header = (
<h3 className="mr-flex mr-items-center">
{props.onBack && <a onClick={props.onBack} className="mr-mr-4">
Expand Down
10 changes: 5 additions & 5 deletions src/components/Footer/Footer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Footer extends Component {
}

renderMyData(){
fetch(`${import.meta.env.REACT_APP_MAP_ROULETTE_SERVER_URL}/api/v2/service/info`)
fetch(`${window.env.REACT_APP_MAP_ROULETTE_SERVER_URL}/api/v2/service/info`)
.then((response) => response.json())
.then((responseJson) => {
this.setState({ data : responseJson })
Expand All @@ -39,9 +39,9 @@ class Footer extends Component {
<FormattedMessage {...messages.versionLabel} />{' '}
<span className="mr-text-green-light mr-font-mono mr-text-base">
<a
href={`https://github.com/maproulette/maproulette3/releases/tag/v${import.meta.env.REACT_APP_VERSION_SEMVER}`}
href={`https://github.com/maproulette/maproulette3/releases/tag/v${window.env.REACT_APP_VERSION_SEMVER}`}
>
v{import.meta.env.REACT_APP_VERSION_SEMVER}
v{window.env.REACT_APP_VERSION_SEMVER}
</a>
</span>
</h3>
Expand All @@ -64,14 +64,14 @@ class Footer extends Component {
<ul className="mr-list-reset mr-text-sm">
<li>
<a
href={import.meta.env.REACT_APP_DOCS_URL}
href={window.env.REACT_APP_DOCS_URL}
target="_blank"
rel="noopener noreferrer"
><FormattedMessage {...messages.getHelp} /></a>
</li>
<li>
<a
href={import.meta.env.REACT_APP_BLOG_URL}
href={window.env.REACT_APP_BLOG_URL}
target="_blank"
rel="noopener noreferrer"
><FormattedMessage {...messages.viewBlog} /></a>
Expand Down
Loading

0 comments on commit b6e95f8

Please sign in to comment.