Skip to content

Commit

Permalink
Merge pull request #108 from CS3219-AY2324S1/deployment
Browse files Browse the repository at this point in the history
Deployment edits
  • Loading branch information
Gabau authored Nov 14, 2023
2 parents 516c266 + 4b84594 commit 07719f7
Show file tree
Hide file tree
Showing 14 changed files with 171 additions and 151 deletions.
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ NODE_ENV=development
PORT=3000
# Websocket port
NEXT_PUBLIC_WS_PORT=3002
NEXT_PUBLIC_WS_URL="http://localhost:${PORT}"
NEXT_PUBLIC_PORT=3000

# PostgreSQL
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password
POSTGRES_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/db?schema=public"

## MongoDB

MONGO_USER=root
MONGO_PASSWORD=password
Expand All @@ -38,6 +39,7 @@ NEXTAUTH_URL="http://localhost:${PORT}"
# Judge0
J0_URL="http://localhost:2358"


# S3
S3_ENDPOINT="http://localhost:9000"
S3_BUCKET_NAME=s3
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: c-hive/gha-yarn-cache@v2
- name: Set Node.js 16.x
- name: Set Node.js 18.x
uses: actions/setup-node@v3
with:
node-version: 16.x
node-version: 18.x

- name: Run install
uses: borales/actions-yarn@v4
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ FROM node:18-alpine
WORKDIR /app

COPY . .
COPY /production/.env .env
COPY /production/.env.example .env

RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
Expand Down
7 changes: 7 additions & 0 deletions cloudbuild.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
steps:
- name: 'gcr.io/cloud-builders/docker'
args: [
'build', '-t', 'asia-east1-docker.pkg.dev/$PROJECT_ID/twrepo/peerprep-image', '.'
]
images:
- 'asia-east1-docker.pkg.dev/$PROJECT_ID/twrepo/peerprep-image'
6 changes: 4 additions & 2 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
version: '3'
include:
- judge0-v1.13.0/docker-compose.yml
services:
Expand All @@ -8,9 +9,10 @@ services:
dockerfile: Dockerfile
working_dir: /app
ports:
- "3000:3000"
- ${NEXT_PUBLIC_WS_PORT}:${NEXT_PUBLIC_WS_PORT}
- "${PORT}:${PORT}"
image: t3-app
env_file:
- './.env'
profiles:
- prod
postgres_db:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"dotenv-cli": "^7.3.0",
"nanoid": "3.0.0",
"net": "^1.0.2",
"next": "^13.4.13",
"next": "^14.0.1",
"next-auth": "^4.22.4",
"npm-run-all": "^4.1.5",
"openai": "^4.16.1",
Expand Down
46 changes: 12 additions & 34 deletions production/.env.example
Original file line number Diff line number Diff line change
@@ -1,38 +1,16 @@
# Since the ".env" file is gitignored, you can use the ".env.example" file to
# build a new ".env" file when you clone the repo. Keep this file up-to-date
# when you add new variables to `.env`.

## Node
NODE_ENV=production
PORT=3000
# Websocket port
NEXT_PUBLIC_WS_PORT=3002

# PostgreSQL
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_URL=

## MongoDB
MONGO_USER=
MONGO_PASSWORD=
MONGO_URL=

# Next Auth
# You can generate a new secret on the command line with:
# openssl rand -base64 32
# https://next-auth.js.org/configuration/options#secret
NEXTAUTH_SECRET=EXAMPLE_NEXTAUTH_SEC
NEXTAUTH_URL="http://localhost:${PORT}"
# This file will be committed to version control, so make sure not to have any
# secrets in it. If you are cloning this repo, create a copy of this file named
# ".env" and populate it with your secrets.

S3_ENDPOINT="http://localhost:9000"

# When adding additional environment variables, the schema in "/src/env.mjs"
# should be updated accordingly.

# JUDGE0
J0_URL="http://j0-server:2358"

S3_BUCKET_NAME=some
# Next auth secret
NEXT_AUTH_SECRET=EXAMPLE_JWT_SECRET

# Github OAuth Provider
GITHUB_ID=
GITHUB_SECRET=
OPENAI_API_KEY=
## Node
NEXT_PUBLIC_WS_PORT=3000
NEXT_PUBLIC_WS_URL=wss://peerprep-j2ljsx7boa-de.a.run.app
NEXT_PUBLIC_PORT=3000
10 changes: 9 additions & 1 deletion src/env.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export const env = createEnv({
// Add `.min(1) on ID and SECRET if you want to make sure they're not empty
GITHUB_ID: z.string().min(1),
GITHUB_SECRET: z.string().min(1),
S3_REGION: z.string().optional(),
S3_ACCESS_KEY_ID: z.string(),
S3_SECRET_ACCESS_KEY: z.string()
},

/**
Expand All @@ -35,6 +38,7 @@ export const env = createEnv({
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string().min(1),
NEXT_PUBLIC_WS_PORT: z.string().min(1),
NEXT_PUBLIC_WS_URL: z.string().min(1)
},

/**
Expand All @@ -50,13 +54,17 @@ export const env = createEnv({
MONGO_URL: process.env.MONGO_URL,
NODE_ENV: process.env.NODE_ENV,
NEXTAUTH_SECRET: process.env.NEXT_AUTH_SECRET,
NEXT_PUBLIC_WS_PORT: process.env.NODE_ENV === "production" ? process.env.NEXT_PUBLIC_WS_PORT : "3002",
NEXT_PUBLIC_WS_PORT: process.env.NODE_ENV === "production" ? process.env.NEXT_PUBLIC_PORT : process.env.NEXT_PUBLIC_WS_PORT,
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
S3_BUCKET_NAME: process.env.S3_BUCKET_NAME,
S3_ENDPOINT: process.env.S3_ENDPOINT,
J0_URL: process.env.J0_URL,
GITHUB_ID: process.env.GITHUB_ID,
GITHUB_SECRET: process.env.GITHUB_SECRET,
NEXT_PUBLIC_WS_URL: process.env.NODE_ENV === "production" ? process.env.NEXT_PUBLIC_WS_URL : `ws://localhost:${process.env.NEXT_PUBLIC_WS_PORT}`,
S3_REGION: process.env.S3_REGION ?? "us-east-1",
S3_ACCESS_KEY_ID: process.env.S3_ACCESS_KEY_ID ?? "S3RVER",
S3_SECRET_ACCESS_KEY: process.env.S3_SECRET_ACCESS_KEY ?? "S3RVER",
},
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation.
Expand Down
13 changes: 12 additions & 1 deletion src/hooks/useCodeSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Update } from "@codemirror/collab";
import { ChangeSet, Text as CMText } from "@uiw/react-codemirror";
import { useSession } from "next-auth/react";
import { useState, useEffect } from "react";
import toast from "react-hot-toast";
import toast, { useToasterStore } from "react-hot-toast";
import { api } from "~/utils/api";

export type CodeSessionResult = [
Expand All @@ -22,6 +22,17 @@ export default function useCodeSession(
enabled: false,
});

const { toasts } = useToasterStore();

const TOAST_LIMIT = 3

useEffect(() => {
toasts
.filter((t) => t.visible) // Only consider visible toasts
.filter((_, i) => i >= TOAST_LIMIT) // Is toast index over limit?
.forEach((t) => toast.dismiss(t.id)); // Dismiss – Use toast.remove(t.id) for no exit animation
}, [toasts]);

const codeSessionQuery = api.codeSession.getSession.useQuery(
{
codeSession: codeSessionId,
Expand Down
31 changes: 22 additions & 9 deletions src/pages/maintainer/environments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,14 @@ const CreateEnvironment = () => {
}
}, [router]);
const [formData, setFormData] = useState<FormState>(emptyFormState);
const languages = api.judge.getLanguages.useQuery();
const [tempLangID, setTempLangID] = useState<number | null>(null);

const languages = api.judge.getLanguages.useQuery();

const setFormDataWrapper = (item: Partial<FormState>) => {
if (item.languageId) {
setTempLangID(item.languageId);
}
setFormData((prev) => ({
...prev,
...item,
Expand Down Expand Up @@ -165,23 +170,31 @@ const CreateEnvironment = () => {


useEffect(() => {
if (tempLangID === null && useQuestionObject.environment) {
setTempLangID(useQuestionObject.environment.languageId);
setFormData(useQuestionObject.environment);
return;
}
if (tempLangID === null) {
return;
}

if (useQuestionObject.environment
&& useQuestionObject.environment.languageId === formData.languageId) {
setFormData({
...useQuestionObject.environment,
});
&& useQuestionObject.environment.languageId === tempLangID) {
setFormData(useQuestionObject.environment);
}
}, [useQuestionObject.environmentId, useQuestionObject.environment, formData.languageId]);
}, [useQuestionObject.environmentId, tempLangID]);

useEffect(() => {
if (!inEnvironments(formData.languageId)) {
if (tempLangID === null) return;
if (!inEnvironments(tempLangID)) {
const { languageId, ...empty } = emptyFormState;
setFormDataWrapper(empty);
return;
}
useQuestionObject.setCurrentLanguage(useQuestionObject.languages.find((val) => val.id === formData.languageId)!);
useQuestionObject.setCurrentLanguage(useQuestionObject.languages.find((val) => val.id === tempLangID)!);

}, [formData.languageId])
}, [tempLangID])

return (
<div className="flex flex-col bg-slate-600 h-screen text-white">
Expand Down
6 changes: 3 additions & 3 deletions src/server/api/routers/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { createTRPCRouter, publicProcedure } from "../trpc";
const UPLOAD_MAX_FILE_SIZE = 400000;

const s3Client = new S3Client({
region: "us-east-1",
region: env.S3_REGION,
endpoint: env.S3_ENDPOINT,
forcePathStyle: true,
credentials: {
accessKeyId: "S3RVER",
secretAccessKey: "S3RVER",
accessKeyId: env.S3_ACCESS_KEY_ID,
secretAccessKey: env.S3_SECRET_ACCESS_KEY,
},
});

Expand Down
40 changes: 20 additions & 20 deletions src/server/prodServer.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { appRouter } from "./api/root";
import { applyWSSHandler } from "@trpc/server/adapters/ws";
import http from "http";
import { createServer } from "node:http";
import next from "next";
import { parse } from "url";
import ws from "ws";
import ws, { WebSocketServer } from "ws";
import { createWSTRPCContext } from "./api/trpc";
import { env } from "~/env.mjs";

Expand All @@ -17,26 +17,19 @@ void app
.prepare()
.then(() => {
console.log("Preparing server");
const server = http.createServer((req, res) => {
const proto = req.headers["x-forwarded-proto"];
if (proto && proto === "http") {
// redirect to ssl
res.writeHead(303, {
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
location: `https://` + req.headers.host + (req.headers.url ?? ""),
});
res.end();
return;
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const parsedUrl = parse(req.url!, true);
void handle(req, res, parsedUrl);
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const server = createServer(async (req, res) => {
if (!req.url) return;
const parsedUrl = parse(req.url, true);
await handle(req, res, parsedUrl).catch((e) => {
console.log(e);
});
});
console.log("Created http server");
// todo: Can't quite get a http server to pass through to the ws server
/// const wss = new ws.Server({ server });
const wss = new ws.Server({
port: Number(env.NEXT_PUBLIC_WS_PORT) ?? 3002,
const wss = new WebSocketServer({
server,
});
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const handler = applyWSSHandler({
Expand All @@ -45,10 +38,17 @@ void app
createContext: createWSTRPCContext,
});

process.on("SIGTERM", () => {
console.log("SIGTERM");
process.on('SIGTERM', () => {
console.log('SIGTERM');
handler.broadcastReconnectNotification();
});

server.on('upgrade', (req, socket, head) => {
wss.handleUpgrade(req, socket, head, (ws) => {
wss.emit('connection', ws, req);
});
});

server.listen(port);

console.log(
Expand Down
2 changes: 1 addition & 1 deletion src/utils/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function getEndingLink(ctx: NextPageContext | undefined) {
});
}
const client = createWSClient({
url: `ws://localhost:${env.NEXT_PUBLIC_WS_PORT ?? 3002}`,
url: env.NEXT_PUBLIC_WS_URL,
});
return wsLink<AppRouter>({
client,
Expand Down
Loading

0 comments on commit 07719f7

Please sign in to comment.