diff --git a/.actrc b/.actrc new file mode 100644 index 000000000..e69de29bb diff --git a/.dockerignore b/.dockerignore index 45b2204e4..a8fddc7ab 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,3 +4,6 @@ node_modules .github .git Dockerfile + +.env.local +.env.**.local \ No newline at end of file diff --git a/.env b/.env new file mode 100644 index 000000000..2f1d23d1f --- /dev/null +++ b/.env @@ -0,0 +1,29 @@ +## General ## +############# + +COMPOSE_PROJECT_NAME=podkrepi +NODE_ENV=production # development, production +TARGET_ENV=production # development, production + +## API ## +######### + +API_URL=https://api.podkrepi.bg/ # https://api.dp.localhost/ + +## APP ## +######### + +APP_URL=https://app.podkrepi.bg # http://localhost:3040 +APP_PORT=80 # 3040 + +## Next Auth ## +############# + +NEXTAUTH_URL=https://auth.podkrepi.bg # http://localhost:3040 +JWT_SECRET=!Change__Me! + +## Discord ## +############# + +DISCORD_CLIENT_ID= +DISCORD_CLIENT_SECRET=!Change___Me! diff --git a/.env.example b/.env.example deleted file mode 100644 index 78b2d5a83..000000000 --- a/.env.example +++ /dev/null @@ -1,30 +0,0 @@ -## General ## -############# - -COMPOSE_PROJECT_NAME=dp -NODE_ENV=development # development, production -TARGET_ENV=development # development, production - -## API ## -######### - -API_URL=https://api.dp.localhost/ - -## APP ## -######### - -APP_URL=http://localhost:3040 -APP_PORT=3040 - - -## Next Auth ## -############# - -NEXTAUTH_URL=http://localhost:3040 -JWT_SECRET=jwt-random-secret - -## Discord ## -############# - -DISCORD_CLIENT_ID= -DISCORD_CLIENT_SECRET= diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7cdaee050..2df647de2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,8 +18,5 @@ jobs: - name: Install dependencies run: yarn - - name: Setup environment - run: cp .env.example .env - - name: Build frontend run: yarn build diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows/deploy-staging.yml index eada19e68..3cc26135f 100644 --- a/.github/workflows/deploy-staging.yml +++ b/.github/workflows/deploy-staging.yml @@ -3,7 +3,7 @@ on: workflow_dispatch: jobs: - deploy: + staging: runs-on: ubuntu-latest steps: - name: Checkout diff --git a/.github/workflows/docker-build-pr.yml b/.github/workflows/docker-build-pr.yml index e5c026830..a3c7b3058 100644 --- a/.github/workflows/docker-build-pr.yml +++ b/.github/workflows/docker-build-pr.yml @@ -9,7 +9,7 @@ on: - 'public/**' jobs: - build-image: + build-pr: runs-on: ubuntu-latest env: diff --git a/.github/workflows/docker-build-ghcr.yml b/.github/workflows/docker-deploy.yml similarity index 58% rename from .github/workflows/docker-build-ghcr.yml rename to .github/workflows/docker-deploy.yml index 7eab2d5a2..ba1b7a83e 100644 --- a/.github/workflows/docker-build-ghcr.yml +++ b/.github/workflows/docker-deploy.yml @@ -7,8 +7,9 @@ on: - '*' jobs: - build-packages: + deploy: runs-on: ubuntu-latest + environment: prod strategy: matrix: @@ -25,7 +26,7 @@ jobs: uses: docker/login-action@v1 with: registry: ghcr.io - username: ${{ github.repository_owner }} + username: ${{ secrets.GHCR_USERNAME }} password: ${{ secrets.GHCR_TOKEN }} - name: Build web @@ -40,14 +41,9 @@ jobs: --tag $IMAGE_NAME:ci-run \ . - - name: Push image to GitHub Container Registry - id: push-images-container-registry + - name: Get the latest tag version + id: get-version run: | - IMAGE_ID=ghcr.io/${{ github.repository }}/$IMAGE_NAME - - # Change all uppercase to lowercase - IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') - # Strip git ref prefix from version VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') @@ -57,8 +53,38 @@ jobs: # Use Docker `latest` tag convention [ "$VERSION" == "master" ] && VERSION=latest + echo $VERSION + echo ::set-output name=VERSION::$VERSION + + - name: Push image to GitHub Container Registry + id: push-images-container-registry + run: | + IMAGE_ID=ghcr.io/${{ github.repository }}/$IMAGE_NAME + + # Change all uppercase to lowercase + IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') + VERSION=${{ steps.get-version.outputs.VERSION }} + echo IMAGE_ID=$IMAGE_ID echo VERSION=$VERSION docker tag $IMAGE_NAME $IMAGE_ID:$VERSION docker push $IMAGE_ID:$VERSION + + - name: Start Deployment + uses: TapTap21/docker-remote-deployment-action@v1.0 + env: + JWT_SECRET: ${{ secrets.APP_JWT_SECRET }} + DISCORD_CLIENT_ID: ${{ secrets.APP_DISCORD_CLIENT_ID }} + DISCORD_CLIENT_SECRET: ${{ secrets.APP_DISCORD_CLIENT_SECRET }} + DEPLOY_TAG: ${{ steps.get-version.outputs.VERSION }} + HOST_IPV4_ADDRESS: "172.14.0.4" + with: + remote_docker_host: ${{ secrets.REMOTE_DOCKER_HOST }} + ssh_public_key: ${{ secrets.SSH_PUBLIC_KEY }} + ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} + stack_file_name: docker-compose.prod.yml + docker_login_user: ${{ secrets.GHCR_USERNAME }} + docker_login_password: ${{ secrets.GHCR_TOKEN }} + docker_login_registry: ghcr.io + args: up -d diff --git a/.gitignore b/.gitignore index 4b19ff117..587303ebc 100644 --- a/.gitignore +++ b/.gitignore @@ -33,5 +33,5 @@ coverage !.vscode/launch.json !.vscode/extensions.json -# Env -.env \ No newline at end of file +.env*.local +.actrc.secrets.local diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 90f8155de..c02bbb2c9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,7 +27,7 @@ git clone git@github.com:daritelska-platforma/frontend.git cd frontend # Symlink dev environment -ln -s .env.example .env +ln -s .env.example .env.local # Install dependencies yarn @@ -137,7 +137,7 @@ import styles from './advanced.module.scss' ### File structure -Inherits AirBnb naming convention https://github.com/airbnb/javascript/tree/master/react#naming +Inherits AirBnb naming convention Use PascalCase for React components and camelCase for their instances @@ -185,7 +185,7 @@ export default function AdvancedForm({ title = 'Nice', children, age }: Advanced ### Components -#### Preferred export style :sun_with_face: +#### Preferred export style :sun_with_face - Nice IDE support and readability @@ -237,7 +237,7 @@ export default function RegisterPage() { **Discouraged** - https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md + ```tsx export default () =>
page
@@ -261,7 +261,7 @@ There are three common ways to style a component: #### Styles using the [`` component](https://material-ui.com/components/box/) -Single component that inherits all sizing props from MUI https://material-ui.com/system/basics/#all-inclusive +Single component that inherits all sizing props from MUI :sun_with_face: Nice for quick layouts that should follow the theme diff --git a/Dockerfile b/Dockerfile index ecbcb95a3..a7b2f86f5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,9 @@ ARG NODE_ENV=production ENV PATH=/app/node_modules/.bin:$PATH \ NODE_ENV="$NODE_ENV" COPY package.json yarn.lock /app/ +RUN apk add --update-cache \ + curl \ + && rm -rf /var/cache/apk/* EXPOSE 3040 # Build target dependencies # @@ -39,3 +42,5 @@ COPY --from=builder /app/.next /app/.next COPY --from=dependencies /prod_node_modules /app/node_modules COPY . /app CMD [ "yarn", "start" ] + +HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD curl --fail http://localhost:3040 || exit 1 diff --git a/README.md b/README.md index bba1baf7c..dbad6140e 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ git clone git@github.com:daritelska-platforma/frontend.git cd frontend # Symlink dev environment -ln -s .env.example .env +ln -s .env.example .env.local ``` ## Development diff --git a/bin/act.sh b/bin/act.sh new file mode 100755 index 000000000..450102776 --- /dev/null +++ b/bin/act.sh @@ -0,0 +1,10 @@ +#!/bin/bash +act \ + -s GHCR_TOKEN="${A_GHCR_TOKEN}" \ + -s GHCR_USERNAME="${A_GHCR_USERNAME}" \ + -s REMOTE_DOCKER_HOST="${A_REMOTE_DOCKER_HOST}" \ + -s SSH_PUBLIC_KEY="${A_SSH_PUBLIC_KEY}" \ + -s SSH_PRIVATE_KEY="${A_SSH_PRIVATE_KEY}" \ + -s APP_JWT_SECRET="${APP_JWT_SECRET}" \ + -s APP_DISCORD_CLIENT_ID="${APP_DISCORD_CLIENT_ID}" \ + -s APP_DISCORD_CLIENT_SECRET="${APP_DISCORD_CLIENT_SECRET}" $@ diff --git a/bin/docker-compose.sh b/bin/docker-compose.sh new file mode 100755 index 000000000..186be4f8b --- /dev/null +++ b/bin/docker-compose.sh @@ -0,0 +1,2 @@ +#!/bin/bash +DOCKER_BUILDKIT=1 docker-compose --env-file=.env.local $@ diff --git a/bin/logs.sh b/bin/logs.sh new file mode 100755 index 000000000..d9e6552df --- /dev/null +++ b/bin/logs.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose --env-file=.env.local logs --tail 200 --follow $@ diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 000000000..089262133 --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,22 @@ +version: '3' +services: + app: + image: ghcr.io/daritelska-platforma/frontend/web:${DEPLOY_TAG} + container_name: app-frontend-prod + restart: always + networks: + pub1: + ipv4_address: ${HOST_IPV4_ADDRESS} + healthcheck: + interval: 10s + timeout: 3s + retries: 3 + environment: + API_URL: ${API_URL} + NEXTAUTH_URL: ${NEXTAUTH_URL} + JWT_SECRET: ${JWT_SECRET} + DISCORD_CLIENT_ID: ${DISCORD_CLIENT_ID} + DISCORD_CLIENT_SECRET: ${DISCORD_CLIENT_SECRET} +networks: + pub1: + external: true diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml index 3b8d2c8e2..cfda69041 100644 --- a/docker-compose.staging.yml +++ b/docker-compose.staging.yml @@ -14,6 +14,10 @@ services: - app-network ports: - '3041:3040' + healthcheck: + interval: 10s + timeout: 3s + retries: 3 networks: app-network: driver: bridge diff --git a/docker-compose.yml b/docker-compose.yml index 47d79567e..35020c13f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ version: '3.8' services: - frontend: + app: container_name: ${COMPOSE_PROJECT_NAME?}-frontend build: @@ -10,6 +10,10 @@ services: args: NODE_ENV: ${NODE_ENV} + env_file: + - .env + - .env.local + networks: - net-frontend @@ -26,6 +30,9 @@ services: environment: API_URL: ${API_URL} NEXTAUTH_URL: ${NEXTAUTH_URL} + JWT_SECRET: ${JWT_SECRET} + DISCORD_CLIENT_ID: ${DISCORD_CLIENT_ID} + DISCORD_CLIENT_SECRET: ${DISCORD_CLIENT_SECRET} networks: net-frontend: diff --git a/next.config.js b/next.config.js index 459dec725..248b31e43 100644 --- a/next.config.js +++ b/next.config.js @@ -1,9 +1,16 @@ const path = require('path') +require('dotenv').config() + module.exports = { sassOptions: { includePaths: [path.join(__dirname, 'src/styles')], }, + serverRuntimeConfig: { + JWT_SECRET: process.env.JWT_SECRET, + DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID, + DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET, + }, publicRuntimeConfig: { API_URL: process.env.API_URL, APP_URL: process.env.APP_URL, diff --git a/package.json b/package.json index af1d11c21..5a07bb094 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@types/yup": "^0.29.11", "@typescript-eslint/eslint-plugin": "^4.13.0", "@typescript-eslint/parser": "^4.13.0", + "dotenv": "^8.2.0", "eslint": "^7.18.0", "eslint-config-prettier": "^7.1.0", "eslint-plugin-prettier": "^3.3.1", diff --git a/src/pages/api/auth/[...nextauth].ts b/src/pages/api/auth/[...nextauth].ts index 2300edb99..3c0cd9bd5 100644 --- a/src/pages/api/auth/[...nextauth].ts +++ b/src/pages/api/auth/[...nextauth].ts @@ -1,17 +1,22 @@ import NextAuth from 'next-auth' +import getConfig from 'next/config' import Providers from 'next-auth/providers' +const { + serverRuntimeConfig: { DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET, JWT_SECRET }, +} = getConfig() + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore export default NextAuth({ // Configure one or more authentication providers providers: [ Providers.Discord({ - clientId: `${process.env.DISCORD_CLIENT_ID}`, - clientSecret: `${process.env.DISCORD_CLIENT_SECRET}`, + clientId: DISCORD_CLIENT_ID, + clientSecret: DISCORD_CLIENT_SECRET, }), ], - secret: `${process.env.JWT_SECRET}`, + secret: JWT_SECRET, session: { jwt: true }, })