diff --git a/.gitignore b/.gitignore index 4d29575d..7be0a94a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ # production /build +env-config.js # misc .DS_Store diff --git a/Dockerfile b/Dockerfile index 72a165c3..48fd9301 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,9 +17,20 @@ RUN npm run build ### STAGE 2: Run ### FROM nginx:alpine -COPY /nginx/default.conf /etc/nginx/conf.d/default.conf +RUN apk add --no-cache bash + +COPY /nginx /etc/nginx/conf.d RUN chown -R nginx /etc/nginx /var/run /run EXPOSE 8080 -COPY --from=builder /app/build /usr/share/nginx/html \ No newline at end of file +COPY --from=builder /app/build /usr/share/nginx/html + +# Copy .env file and shell script to container +WORKDIR /usr/share/nginx/html +COPY .env . +COPY ./env.sh . +RUN chmod +x env.sh + +# Start Nginx server +CMD ["/bin/bash", "-c", "/usr/share/nginx/html/env.sh && nginx -g \"daemon off;\""] diff --git a/env.sh b/env.sh new file mode 100755 index 00000000..823f950d --- /dev/null +++ b/env.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# (c) https://github.com/kunokdev/cra-runtime-environment-variables/blob/master/env.sh + +# Recreate config file +rm -rf ./env-config.js +touch ./env-config.js + +# Add assignment +echo "window._env_ = {" >> ./env-config.js + +# Read each line in .env file +# Each line represents key=value pairs +while read -r line || [[ -n "$line" ]]; +do + # Split env variables by character `=` + if printf '%s\n' "$line" | grep -q -e '='; then + varname=$(printf '%s\n' "$line" | sed -e 's/=.*//') + varvalue=$(printf '%s\n' "$line" | sed -e 's/^[^=]*=//') + fi + + # Read value of current variable if exists as Environment variable + value=$(printf '%s\n' "${!varname}") + # Otherwise use value from .env file + [[ -z $value ]] && value=${varvalue} + + # Append configuration property to JS file + echo " $varname: \"$value\"," >> ./env-config.js +done < .env + +echo "}" >> ./env-config.js \ No newline at end of file diff --git a/nginx/gzip.conf b/nginx/gzip.conf new file mode 100644 index 00000000..71feb532 --- /dev/null +++ b/nginx/gzip.conf @@ -0,0 +1,44 @@ +# Enable Gzip compressed. +gzip on; + +# Enable compression both for HTTP/1.0 and HTTP/1.1 (required for CloudFront). +gzip_http_version 1.0; + +# Compression level (1-9). +# 5 is a perfect compromise between size and cpu usage, offering about +# 75% reduction for most ascii files (almost identical to level 9). +gzip_comp_level 5; + +# Don't compress anything that's already small and unlikely to shrink much +# if at all (the default is 20 bytes, which is bad as that usually leads to +# larger files after gzipping). +gzip_min_length 256; + +# Compress data even for clients that are connecting to us via proxies, +# identified by the "Via" header (required for CloudFront). +gzip_proxied any; + +# Tell proxies to cache both the gzipped and regular version of a resource +# whenever the client's Accept-Encoding capabilities header varies; +# Avoids the issue where a non-gzip capable client (which is extremely rare +# today) would display gibberish if their proxy gave them the gzipped version. +gzip_vary on; + +# Compress all output labeled with one of the following MIME-types. +gzip_types +application/atom+xml +application/javascript +application/json +application/rss+xml +application/vnd.ms-fontobject +application/x-font-ttf +application/x-web-app-manifest+json +application/xhtml+xml +application/xml +font/opentype +image/svg+xml +image/x-icon +text/css +text/plain +text/x-component; +# text/html is always compressed by HttpGzipModule \ No newline at end of file diff --git a/package.json b/package.json index fb497b52..7a1c1b1b 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "use-image": "^1.0.6" }, "scripts": { + "dev": "chmod +x ./env.sh && ./env.sh && cp env-config.js ./public/ && react-scripts start", "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test" diff --git a/public/index.html b/public/index.html index 35c5c785..15585bcf 100644 --- a/public/index.html +++ b/public/index.html @@ -10,6 +10,8 @@ Visual Regression Tracker + + diff --git a/src/_config/api.config.ts b/src/_config/api.config.ts deleted file mode 100644 index e330b882..00000000 --- a/src/_config/api.config.ts +++ /dev/null @@ -1 +0,0 @@ -export const API_URL = process.env.REACT_APP_API_URL; diff --git a/src/_config/env.config.ts b/src/_config/env.config.ts new file mode 100644 index 00000000..b1495b32 --- /dev/null +++ b/src/_config/env.config.ts @@ -0,0 +1,9 @@ +export const API_URL = window._env_.REACT_APP_API_URL; + +declare global { + interface Window { + _env_: { + REACT_APP_API_URL: string; + }; + } +} diff --git a/src/contexts/socket.context.tsx b/src/contexts/socket.context.tsx index 28d24072..634347d9 100644 --- a/src/contexts/socket.context.tsx +++ b/src/contexts/socket.context.tsx @@ -8,6 +8,7 @@ import { } from "./build.context"; import { Build, TestRun } from "../types"; import { useTestRunDispatch, addTestRun } from "./testRun.context"; +import { API_URL } from "../_config/env.config"; interface IConnectAction { type: "connect"; @@ -100,13 +101,12 @@ function useSocketDispatch() { } function connect(dispatch: Dispatch) { - const apiUrl = process.env.REACT_APP_API_URL; - if (apiUrl) { - const socket = socketIOClient(apiUrl); + if (API_URL) { + const socket = socketIOClient(API_URL); dispatch({ type: "connect", payload: socket }); console.log("Socket connected"); } else { - console.log("API url is not provided: " + apiUrl); + console.log("API url is not provided"); } } diff --git a/src/services/builds.service.ts b/src/services/builds.service.ts index 14af5b6d..3b659d7f 100644 --- a/src/services/builds.service.ts +++ b/src/services/builds.service.ts @@ -1,6 +1,6 @@ import { Build } from "../types"; import { handleResponse, authHeader } from "../_helpers/service.helpers"; -import { API_URL } from "../_config/api.config"; +import { API_URL } from "../_config/env.config"; const ENDPOINT_URL = "/builds"; diff --git a/src/services/projects.service.ts b/src/services/projects.service.ts index ab261405..452fe8a7 100644 --- a/src/services/projects.service.ts +++ b/src/services/projects.service.ts @@ -1,6 +1,6 @@ import { Project } from "../types"; import { handleResponse, authHeader } from "../_helpers/service.helpers"; -import { API_URL } from "../_config/api.config"; +import { API_URL } from "../_config/env.config"; function getAll(): Promise { const requestOptions = { diff --git a/src/services/static.service.ts b/src/services/static.service.ts index cda05c82..68dd12ec 100644 --- a/src/services/static.service.ts +++ b/src/services/static.service.ts @@ -1,4 +1,4 @@ -import { API_URL } from "../_config/api.config"; +import { API_URL } from "../_config/env.config"; function getImage(name: string): string { if (name) return `${API_URL}/${name}`; diff --git a/src/services/testRun.service.ts b/src/services/testRun.service.ts index b350d5b7..1701ae8f 100644 --- a/src/services/testRun.service.ts +++ b/src/services/testRun.service.ts @@ -1,6 +1,6 @@ import { TestRun } from "../types"; import { handleResponse, authHeader } from "../_helpers/service.helpers"; -import { API_URL } from "../_config/api.config"; +import { API_URL } from "../_config/env.config"; import { IgnoreArea } from "../types/ignoreArea"; const ENDPOINT_URL = "/test-runs"; diff --git a/src/services/testVariation.service.ts b/src/services/testVariation.service.ts index 16901eac..7c4ab06a 100644 --- a/src/services/testVariation.service.ts +++ b/src/services/testVariation.service.ts @@ -1,6 +1,6 @@ import { TestVariation, Build } from "../types"; import { handleResponse, authHeader } from "../_helpers/service.helpers"; -import { API_URL } from "../_config/api.config"; +import { API_URL } from "../_config/env.config"; import { IgnoreArea } from "../types/ignoreArea"; const ENDPOINT_URL = "/test-variations"; diff --git a/src/services/users.service.ts b/src/services/users.service.ts index c77005ae..aa4a354f 100644 --- a/src/services/users.service.ts +++ b/src/services/users.service.ts @@ -1,6 +1,6 @@ import { handleResponse, authHeader } from "../_helpers/service.helpers"; import { User } from "../types/user"; -import { API_URL } from "../_config/api.config"; +import { API_URL } from "../_config/env.config"; const ENDPOINT_URL = "/users";