Web Client #11

Merged
Simponic merged 19 commits from web into main 2023-01-19 16:04:10 -05:00
11 changed files with 219 additions and 16 deletions
Showing only changes of commit fa5fb9fd97 - Show all commits

1
.gitignore vendored
View File

@ -26,3 +26,4 @@ server-*.tar
/tmp/ /tmp/
.env .env
.env.prod

74
Dockerfile Normal file
View File

@ -0,0 +1,74 @@
ARG ELIXIR_VERSION=1.14.0
ARG OTP_VERSION=25.2.1
ARG DEBIAN_VERSION=bullseye-20230109-slim
ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"
FROM ${BUILDER_IMAGE} as builder
# install build dependencies
RUN apt-get update -y && apt-get install -y build-essential git \
&& apt-get clean && rm -f /var/lib/apt/lists/*_*
# prepare build dir
WORKDIR /app
# install hex + rebar
RUN mix local.hex --force && \
mix local.rebar --force
# set build ENV
ENV MIX_ENV="prod"
# install mix dependencies
COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
RUN mkdir config
# copy compile-time config files before we compile dependencies
# to ensure any relevant config change will trigger the dependencies
# to be re-compiled.
COPY config/config.exs config/${MIX_ENV}.exs config/
RUN mix deps.compile
COPY priv priv
# Compile the release
COPY lib lib
RUN mix compile
# Changes to config/runtime.exs don't require recompiling the code
COPY config/runtime.exs config/
#COPY rel rel
RUN mix release
# start a new build stage so that the final image will only contain
# the compiled release and other runtime necessities
FROM ${RUNNER_IMAGE}
RUN apt-get update -y && apt-get install -y libstdc++6 openssl libncurses5 locales \
&& apt-get clean && rm -f /var/lib/apt/lists/*_*
# Set the locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
WORKDIR "/app"
RUN chown nobody /app
# set runner ENV
ENV MIX_ENV="prod"
# Only copy the final release from the build stage
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/chessh ./
COPY --from=builder --chown=nobody:root /app/priv /app/priv
USER nobody
CMD /app/bin/chessh eval "Chessh.Release.migrate" && /app/bin/chessh start

23
build.sh Normal file → Executable file
View File

@ -1,11 +1,16 @@
#!/usr/bin/env bash #!/bin/bash
# Initial setup
mix deps.get --only prod
MIX_ENV=prod mix compile
# Remove the existing release directory and build the release env_file=.env.prod
rm -rf "_build" started_in=$PWD
MIX_ENV=prod mix release
# for auto DB migration upon deploy export $(cat $env_file | xargs)
MIX_ENV=prod mix ecto.migrate
cd front
docker build \
--build-arg REACT_APP_GITHUB_OAUTH=${REACT_APP_GITHUB_OAUTH} \
--build-arg REACT_APP_SSH_SERVER=${REACT_APP_SSH_SERVER} \
--build-arg REACT_APP_SSH_PORT=${REACT_APP_SSH_PORT} \
. -t chessh/frontend
cd $started_in
docker build . -t chessh/server

55
deploy.sh Executable file
View File

@ -0,0 +1,55 @@
#!/bin/bash
datestamp=$(date +%Y%m%d-%H%M)
env_file=.env.prod
project_name=chessh
port=8080
host=127.0.0.1
container_names=("chessh-database" "chessh-server" "chessh-frontend")
for name in ${container_names[@]}; do
docker stop $name
docker rm $name
done
# Create network for chessh
docker network ls | grep -q $project_name || docker network create --driver bridge $project_name
# Start postgres container
# Firstly create pg volume if it does not exist
docker volume ls | grep -q $project_name-pgdata || docker volume create $project_name-pgdata
# Then run the pg container
docker run \
-d \
--restart unless-stopped \
--env-file $env_file \
--network $project_name \
--name $project_name-database \
--net-alias database \
--volume $project_name-pgdata:/var/lib/postgresql/data/ \
postgres
# Start backend container
# Check if running; if so, stop, and rename
docker run \
-d \
--restart unless-stopped \
--env-file $env_file \
--network $project_name \
--name $project_name-server \
--net-alias server \
chessh/server
# Start frontend container
# Check if running; if so, stop, and rename
docker run \
-d \
--restart unless-stopped \
--env-file $env_file \
--network $project_name \
--name $project_name-frontend \
--publish "${host}:${port}:80/tcp" \
--net-alias frontend \
chessh/frontend

1
front/.dockerignore Normal file
View File

@ -0,0 +1 @@
node_modules

28
front/Dockerfile Normal file
View File

@ -0,0 +1,28 @@
# Builder
FROM node:16-alpine as build
WORKDIR /usr/app
COPY package-lock.json package.json ./
RUN npm ci
COPY . /usr/app
ARG REACT_APP_GITHUB_OAUTH
ARG REACT_APP_SSH_SERVER
ARG REACT_APP_SSH_PORT
ENV REACT_APP_GITHUB_OAUTH $REACT_APP_GITHUB_OAUTH
ENV REACT_APP_SSH_SERVER $REACT_APP_SSH_SERVER
ENV REACT_APP_SSH_PORT $REACT_APP_SSH_PORT
RUN npm run build
# Runner
FROM nginx:alpine
EXPOSE 80
COPY nginx.conf /etc/nginx/conf.d/
COPY --from=build /usr/app/build /usr/share/nginx/html
RUN chown -R nginx:nginx /usr/share/nginx/html
ENTRYPOINT ["nginx", "-g", "daemon off;"]

13
front/nginx.conf Normal file
View File

@ -0,0 +1,13 @@
server {
listen 80;
location / {
root /usr/share/nginx/html/;
index index.html index.htm index.nginx-debian.html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://server:8080;
}
}

View File

@ -13,8 +13,10 @@ const useStorage = (storage, keyPrefix) => (storageKey, fallbackState) => {
if (storedString !== null) parsedObject = JSON.parse(storedString); if (storedString !== null) parsedObject = JSON.parse(storedString);
// eslint-disable-next-line react-hooks/rules-of-hooks
const [value, setValue] = useState(parsedObject ?? fallbackState); const [value, setValue] = useState(parsedObject ?? fallbackState);
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => { useEffect(() => {
storage.setItem(keyPrefix + storageKey, JSON.stringify(value)); storage.setItem(keyPrefix + storageKey, JSON.stringify(value));
}, [value, storageKey]); }, [value, storageKey]);
@ -22,6 +24,7 @@ const useStorage = (storage, keyPrefix) => (storageKey, fallbackState) => {
return [value, setValue]; return [value, setValue];
}; };
// eslint-disable-next-line react-hooks/rules-of-hooks
export const useLocalStorage = useStorage( export const useLocalStorage = useStorage(
window.localStorage, window.localStorage,
STORAGE_KEYS_PREFIX STORAGE_KEYS_PREFIX

View File

@ -174,7 +174,8 @@ textarea {
border-radius: 4px; border-radius: 4px;
border: 1px solid var(--primary-text-color); border: 1px solid var(--primary-text-color);
} }
input,textarea: focus { input:focus,
textarea:focus {
border: 1px solid var(--gold-color); border: 1px solid var(--gold-color);
} }

19
lib/chessh/release.ex Normal file
View File

@ -0,0 +1,19 @@
defmodule Chessh.Release do
@app :chessh
def migrate do
for repo <- repos() do
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
end
end
def rollback(repo, version) do
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version))
end
defp repos do
Application.load(@app)
Application.fetch_env!(@app, :ecto_repos)
end
end

View File

@ -1,9 +1,12 @@
#!/bin/sh #!/bin/sh
mkdir keys if [ ! -d "keys" ]
chmod 700 keys then
cd keys mkdir keys
chmod 700 keys
cd keys
ssh-keygen -N "" -b 256 -t ecdsa -f ssh_host_ecdsa_key ssh-keygen -N "" -b 256 -t ecdsa -f ssh_host_ecdsa_key
ssh-keygen -N "" -b 1024 -t dsa -f ssh_host_dsa_key ssh-keygen -N "" -b 1024 -t dsa -f ssh_host_dsa_key
ssh-keygen -N "" -b 2048 -t rsa -f ssh_host_rsa_key ssh-keygen -N "" -b 2048 -t rsa -f ssh_host_rsa_key
fi