diff --git a/.github/workflows/backend-ci-workflow.yaml b/.github/workflows/backend-ci-workflow.yaml new file mode 100644 index 0000000000..cb0279063f --- /dev/null +++ b/.github/workflows/backend-ci-workflow.yaml @@ -0,0 +1,53 @@ +name: Backend CI Workflow + +on: + pull_request: + branches: + - main + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '18' + + - name: Install Dependencies for Each Service + run: | + cd backend + for service in auth-service question-service user-service matching-service gateway-service collaboration-service; do + echo "Installing dependencies for $service" + cd $service + npm install + cd .. + done + + # Build Check for Each Service + - name: Build Each Service + run: | + cd backend + for service in auth-service question-service user-service matching-service gateway-service collaboration-service; do + echo "Building $service" + cd $service + npm run build + cd .. + done + + # Lint Check for Each Service + - name: Lint Each Service + run: | + cd backend + for service in auth-service question-service user-service matching-service gateway-service collaboration-service; do + echo "Linting $service" + cd $service + npm run lint + cd .. + done diff --git a/.github/workflows/frontend-ci-workflow.yaml b/.github/workflows/frontend-ci-workflow.yaml new file mode 100644 index 0000000000..a1e214f24f --- /dev/null +++ b/.github/workflows/frontend-ci-workflow.yaml @@ -0,0 +1,38 @@ +name: Frontend CI Workflow + +on: + pull_request: + branches: + - main + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '18' + + - name: Install Dependencies + run: | + cd frontend + npm install + + # Build Check + - name: Build Project + run: | + cd frontend + npm run build + + # Lint Check + - name: Lint Code + run: | + cd frontend + npm run lint diff --git a/backend/auth-service/Dockerfile b/backend/auth-service/Dockerfile index f31497e3a1..25989c6878 100644 --- a/backend/auth-service/Dockerfile +++ b/backend/auth-service/Dockerfile @@ -1,47 +1,13 @@ -################# -## DEVELOPMENT ## -################# -FROM node:18-alpine AS development +FROM node:18 -# Set the working directory in the container WORKDIR /app -# Copy the package.json and package-lock.json files COPY package*.json ./ -# Install dependencies RUN npm install -# Copy the rest of the application code COPY . . -# Built the app to /dist folder -RUN npm run build +EXPOSE 3003 -# Expose the port the app runs on -EXPOSE 4000 - -################ -## PRODUCTION ## -################ -FROM node:18-alpine AS production - -# Set node environment to production -ARG NODE_ENV=production -ENV NODE_ENV=${NODE_ENV} - -# Set the working directory in the container -WORKDIR /app - -# Copy only the necessary files from the previous build stage -COPY --from=development /peerprep/app/dist ./dist -COPY package*.json ./ - -# Install production dependencies only -RUN npm ci --only=production - -# Expose the port the app runs on -EXPOSE 4000 - -# Run the main file -CMD ["node", "dist/main"] \ No newline at end of file +CMD ["node", "dist/main.js"] \ No newline at end of file diff --git a/backend/auth-service/src/app.controller.spec.ts b/backend/auth-service/src/app.controller.spec.ts deleted file mode 100644 index c86814d2e4..0000000000 --- a/backend/auth-service/src/app.controller.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; - -describe('AppController', () => { - let appController: AppController; - - beforeEach(async () => { - const app: TestingModule = await Test.createTestingModule({ - controllers: [AppController], - providers: [AppService], - }).compile(); - - appController = app.get(AppController); - }); - -}); diff --git a/backend/auth-service/src/app.module.ts b/backend/auth-service/src/app.module.ts index 278b9f1ba8..97c3071f2d 100644 --- a/backend/auth-service/src/app.module.ts +++ b/backend/auth-service/src/app.module.ts @@ -3,7 +3,7 @@ import { AppController } from './app.controller'; import { AppService } from './app.service'; import { PassportModule } from '@nestjs/passport'; import { JwtModule } from '@nestjs/jwt'; -import { ClientsModule, Transport } from '@nestjs/microservices'; +import { ClientsModule } from '@nestjs/microservices'; import { HttpModule } from '@nestjs/axios'; import { AccessTokenStrategy, diff --git a/backend/auth-service/src/app.service.ts b/backend/auth-service/src/app.service.ts index 1f03ca3657..bda98b73d2 100644 --- a/backend/auth-service/src/app.service.ts +++ b/backend/auth-service/src/app.service.ts @@ -186,7 +186,7 @@ export class AppService { } public async resetPassword(dto: ResetPasswordDto): Promise { - const { userId, email } = await this.validatePasswordResetToken(dto.token); + const { userId } = await this.validatePasswordResetToken(dto.token); const hashedPassword = await bcrypt.hash(dto.password, SALT_ROUNDS); @@ -218,6 +218,7 @@ export class AppService { } return { userId, email }; } catch (err) { + console.error(err); throw new RpcException({ statusCode: HttpStatus.UNAUTHORIZED, message: 'Unauthorized: Invalid or expired password reset token', @@ -246,7 +247,7 @@ export class AppService { text: `Click here to reset your password: ${resetUrl}`, }; - transporter.sendMail(mailOptions, (error, info) => { + transporter.sendMail(mailOptions, (error) => { if (error) { throw new RpcException(`Error sending reset email: ${error.message}`); } @@ -260,6 +261,7 @@ export class AppService { }); return decoded; } catch (error) { + console.error(error); throw new RpcException('Invalid access token'); } } @@ -271,6 +273,7 @@ export class AppService { }); return decoded; } catch (error) { + console.error(error); throw new RpcException('Invalid Refresh Token'); } } diff --git a/backend/auth-service/src/constants/account-provider.enum.ts b/backend/auth-service/src/constants/account-provider.enum.ts index 3ee17560be..5cba246a70 100644 --- a/backend/auth-service/src/constants/account-provider.enum.ts +++ b/backend/auth-service/src/constants/account-provider.enum.ts @@ -2,4 +2,4 @@ export enum AccountProvider { LOCAL = 'local', GOOGLE = 'google', GITHUB = 'github', -} \ No newline at end of file +} diff --git a/backend/auth-service/src/dto/reset-password-request.dto.ts b/backend/auth-service/src/dto/reset-password-request.dto.ts index 550a2d2647..423ae52d82 100644 --- a/backend/auth-service/src/dto/reset-password-request.dto.ts +++ b/backend/auth-service/src/dto/reset-password-request.dto.ts @@ -1,4 +1,4 @@ -import { IsEmail, IsNotEmpty, IsString } from 'class-validator'; +import { IsEmail, IsNotEmpty } from 'class-validator'; export class ResetPasswordRequestDto { @IsEmail() diff --git a/backend/auth-service/src/main.ts b/backend/auth-service/src/main.ts index 45b976601c..d7f919011d 100644 --- a/backend/auth-service/src/main.ts +++ b/backend/auth-service/src/main.ts @@ -1,6 +1,6 @@ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; -import { MicroserviceOptions, Transport } from '@nestjs/microservices'; +import { MicroserviceOptions } from '@nestjs/microservices'; import { ValidationPipe } from '@nestjs/common'; import { config } from 'src/configs'; import * as dotenv from 'dotenv'; diff --git a/backend/code-execution-service/Dockerfile b/backend/code-execution-service/Dockerfile index 4350ffca70..cb6360aa8c 100644 --- a/backend/code-execution-service/Dockerfile +++ b/backend/code-execution-service/Dockerfile @@ -1,7 +1,5 @@ -################# -## DEVELOPMENT ## -################# -FROM ubuntu:20.04 AS development +# Use a single stage for both development and production +FROM ubuntu:20.04 # Set environment variables to prevent interactive prompts ENV DEBIAN_FRONTEND=noninteractive @@ -30,47 +28,11 @@ RUN npm install # Copy the rest of the application code COPY . . -# Build the app to the /dist folder +# Build the app RUN npm run build # Expose the port the app runs on EXPOSE 4000 -# Run the application in development mode -CMD ["npm", "run", "start:dev"] - - -################ -## PRODUCTION ## -################ -FROM ubuntu:20.04 AS production - -# Set environment variables to prevent interactive prompts -ENV DEBIAN_FRONTEND=noninteractive -ARG NODE_ENV=production -ENV NODE_ENV=${NODE_ENV} - -# Install only runtime dependencies (Node.js, Python, and Java) -RUN apt-get update && \ - apt-get install -y \ - python3 openjdk-11-jdk curl gnupg && \ - curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \ - apt-get install -y nodejs && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -# Set the working directory in the container -WORKDIR /app - -# Copy the build artifacts from the development stage -COPY --from=development /app/dist ./dist -COPY package*.json ./ - -# Install production dependencies only -RUN npm ci --only=production - -# Expose the port the app runs on -EXPOSE 4000 - -# Run the main application -CMD ["node", "dist/main"] \ No newline at end of file +# Set the command to run the application +CMD ["node", "dist/main.js"] \ No newline at end of file diff --git a/backend/code-execution-service/Dockerfile(copybackup) b/backend/code-execution-service/Dockerfile(copybackup) deleted file mode 100644 index f31497e3a1..0000000000 --- a/backend/code-execution-service/Dockerfile(copybackup) +++ /dev/null @@ -1,47 +0,0 @@ -################# -## DEVELOPMENT ## -################# -FROM node:18-alpine AS development - -# Set the working directory in the container -WORKDIR /app - -# Copy the package.json and package-lock.json files -COPY package*.json ./ - -# Install dependencies -RUN npm install - -# Copy the rest of the application code -COPY . . - -# Built the app to /dist folder -RUN npm run build - -# Expose the port the app runs on -EXPOSE 4000 - -################ -## PRODUCTION ## -################ -FROM node:18-alpine AS production - -# Set node environment to production -ARG NODE_ENV=production -ENV NODE_ENV=${NODE_ENV} - -# Set the working directory in the container -WORKDIR /app - -# Copy only the necessary files from the previous build stage -COPY --from=development /peerprep/app/dist ./dist -COPY package*.json ./ - -# Install production dependencies only -RUN npm ci --only=production - -# Expose the port the app runs on -EXPOSE 4000 - -# Run the main file -CMD ["node", "dist/main"] \ No newline at end of file diff --git a/backend/code-execution-service/Dockerfile.dev b/backend/code-execution-service/Dockerfile.dev new file mode 100644 index 0000000000..4350ffca70 --- /dev/null +++ b/backend/code-execution-service/Dockerfile.dev @@ -0,0 +1,76 @@ +################# +## DEVELOPMENT ## +################# +FROM ubuntu:20.04 AS development + +# Set environment variables to prevent interactive prompts +ENV DEBIAN_FRONTEND=noninteractive + +# Update package list and install Python 3, pip, Java, and Node.js +RUN apt-get update && \ + apt-get install -y \ + python3 python3-pip openjdk-11-jdk curl gnupg && \ + curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \ + apt-get install -y nodejs && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Verify installations +RUN python3 --version && java -version && node --version + +# Set the working directory in the container +WORKDIR /app + +# Copy the package.json and package-lock.json files +COPY package*.json ./ + +# Install dependencies +RUN npm install + +# Copy the rest of the application code +COPY . . + +# Build the app to the /dist folder +RUN npm run build + +# Expose the port the app runs on +EXPOSE 4000 + +# Run the application in development mode +CMD ["npm", "run", "start:dev"] + + +################ +## PRODUCTION ## +################ +FROM ubuntu:20.04 AS production + +# Set environment variables to prevent interactive prompts +ENV DEBIAN_FRONTEND=noninteractive +ARG NODE_ENV=production +ENV NODE_ENV=${NODE_ENV} + +# Install only runtime dependencies (Node.js, Python, and Java) +RUN apt-get update && \ + apt-get install -y \ + python3 openjdk-11-jdk curl gnupg && \ + curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \ + apt-get install -y nodejs && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Set the working directory in the container +WORKDIR /app + +# Copy the build artifacts from the development stage +COPY --from=development /app/dist ./dist +COPY package*.json ./ + +# Install production dependencies only +RUN npm ci --only=production + +# Expose the port the app runs on +EXPOSE 4000 + +# Run the main application +CMD ["node", "dist/main"] \ No newline at end of file diff --git a/backend/collaboration-service/Dockerfile b/backend/collaboration-service/Dockerfile index f31497e3a1..cf4f66291e 100644 --- a/backend/collaboration-service/Dockerfile +++ b/backend/collaboration-service/Dockerfile @@ -1,47 +1,13 @@ -################# -## DEVELOPMENT ## -################# -FROM node:18-alpine AS development +FROM node:18 -# Set the working directory in the container WORKDIR /app -# Copy the package.json and package-lock.json files COPY package*.json ./ -# Install dependencies RUN npm install -# Copy the rest of the application code COPY . . -# Built the app to /dist folder -RUN npm run build +EXPOSE 3005 -# Expose the port the app runs on -EXPOSE 4000 - -################ -## PRODUCTION ## -################ -FROM node:18-alpine AS production - -# Set node environment to production -ARG NODE_ENV=production -ENV NODE_ENV=${NODE_ENV} - -# Set the working directory in the container -WORKDIR /app - -# Copy only the necessary files from the previous build stage -COPY --from=development /peerprep/app/dist ./dist -COPY package*.json ./ - -# Install production dependencies only -RUN npm ci --only=production - -# Expose the port the app runs on -EXPOSE 4000 - -# Run the main file -CMD ["node", "dist/main"] \ No newline at end of file +CMD ["node", "dist/main.js"] \ No newline at end of file diff --git a/backend/docker-compose.prod.yml b/backend/docker-compose.prod.yml deleted file mode 100644 index eebef40fcd..0000000000 --- a/backend/docker-compose.prod.yml +++ /dev/null @@ -1,48 +0,0 @@ -################ -## PRODUCTION ## -################ -version: "3" -services: - gateway-service: - build: - context: ./gateway-service - target: production - container_name: gateway-service - command: npm run start:prod - ports: - - "4000:4000" - restart: always - depends_on: - - question-service - - user-service - - auth-service - networks: - - backend-network - - question-service: - build: - context: ./question-service - target: production - container_name: question-service - command: npm run start:prod - restart: always - env_file: - - ./question-service/.env - networks: - - backend-network - - user-service: - build: - context: ./user-service - target: production - container_name: user-service - command: npm run start:prod - restart: always - env_file: - - ./user-service/.env - networks: - - backend-network - -networks: - backend-network: - driver: bridge diff --git a/backend/docker-compose.yml b/backend/docker-compose.yml index 74c4aab4da..7d28c5b6f0 100644 --- a/backend/docker-compose.yml +++ b/backend/docker-compose.yml @@ -5,7 +5,6 @@ services: gateway-service: build: context: ./gateway-service - target: development container_name: gateway-service command: npm run start:dev env_file: @@ -22,7 +21,6 @@ services: - matching-service - collaboration-service - code-execution-service - # - eventstore.db - redis networks: - backend-network @@ -31,7 +29,6 @@ services: question-service: build: context: ./question-service - target: development container_name: question-service volumes: - ./question-service:/app @@ -42,12 +39,11 @@ services: networks: - backend-network ports: - - "3002:4000" + - "3002:3002" user-service: build: context: ./user-service - target: development container_name: user-service command: npm run start:dev volumes: @@ -58,12 +54,11 @@ services: networks: - backend-network ports: - - "3001:4000" + - "3001:3001" auth-service: build: context: ./auth-service - target: development container_name: auth-service volumes: - ./auth-service:/app @@ -74,12 +69,11 @@ services: networks: - backend-network ports: - - "3003:4000" + - "3003:3003" matching-service: build: context: ./matching-service - target: development container_name: matching-service volumes: - ./matching-service:/app @@ -90,7 +84,7 @@ services: networks: - backend-network ports: - - "3004:4000" + - "3004:3004" redis: image: redis:latest @@ -102,7 +96,6 @@ services: collaboration-service: build: context: ./collaboration-service - target: development container_name: collaboration-service volumes: - ./collaboration-service:/app @@ -113,12 +106,11 @@ services: networks: - backend-network ports: - - "3005:4000" + - "3005:3005" code-execution-service: build: context: ./code-execution-service - target: development container_name: code-execution-service volumes: - ./code-execution-service:/app @@ -129,12 +121,11 @@ services: networks: - backend-network ports: - - "3006:4000" + - "3006:3006" y-websocket-service: build: context: ./y-websocket-service - target: development container_name: y-websocket-service volumes: - ./y-websocket-service:/app diff --git a/backend/gateway-service/Dockerfile b/backend/gateway-service/Dockerfile index f31497e3a1..0cad640914 100644 --- a/backend/gateway-service/Dockerfile +++ b/backend/gateway-service/Dockerfile @@ -1,47 +1,13 @@ -################# -## DEVELOPMENT ## -################# -FROM node:18-alpine AS development +FROM node:18 -# Set the working directory in the container WORKDIR /app -# Copy the package.json and package-lock.json files COPY package*.json ./ -# Install dependencies RUN npm install -# Copy the rest of the application code COPY . . -# Built the app to /dist folder -RUN npm run build - -# Expose the port the app runs on -EXPOSE 4000 - -################ -## PRODUCTION ## -################ -FROM node:18-alpine AS production - -# Set node environment to production -ARG NODE_ENV=production -ENV NODE_ENV=${NODE_ENV} - -# Set the working directory in the container -WORKDIR /app - -# Copy only the necessary files from the previous build stage -COPY --from=development /peerprep/app/dist ./dist -COPY package*.json ./ - -# Install production dependencies only -RUN npm ci --only=production - -# Expose the port the app runs on EXPOSE 4000 -# Run the main file -CMD ["node", "dist/main"] \ No newline at end of file +CMD ["node", "dist/main.js"] \ No newline at end of file diff --git a/backend/gateway-service/src/app.module.ts b/backend/gateway-service/src/app.module.ts index a96bbd836c..c8fc340d8d 100644 --- a/backend/gateway-service/src/app.module.ts +++ b/backend/gateway-service/src/app.module.ts @@ -10,6 +10,7 @@ import { AtAuthGuard, RtAuthGuard } from './common/guards'; import { MatchGateway } from './modules/match/match.controller'; import { RedisMatchService } from './modules/match/redis.service'; import { config } from './common/configs'; +import { HealthController } from './modules/health/health.controller'; import { CollaborationGateway } from './modules/collaboration/collaborationws.controller'; @Module({ @@ -70,6 +71,7 @@ import { CollaborationGateway } from './modules/collaboration/collaborationws.co QuestionController, AuthController, CollaborationController, + HealthController, CodeExecutionController, ], providers: [ diff --git a/backend/gateway-service/src/common/configs/env.config.ts b/backend/gateway-service/src/common/configs/env.config.ts index 068097c122..b5c3a6c42c 100644 --- a/backend/gateway-service/src/common/configs/env.config.ts +++ b/backend/gateway-service/src/common/configs/env.config.ts @@ -1,4 +1,4 @@ -import { RpcException, Transport } from '@nestjs/microservices'; +import { Transport } from '@nestjs/microservices'; import * as dotenv from 'dotenv'; dotenv.config(); diff --git a/backend/gateway-service/src/common/constants/account-provider.enum.ts b/backend/gateway-service/src/common/constants/account-provider.enum.ts index 3ee17560be..5cba246a70 100644 --- a/backend/gateway-service/src/common/constants/account-provider.enum.ts +++ b/backend/gateway-service/src/common/constants/account-provider.enum.ts @@ -2,4 +2,4 @@ export enum AccountProvider { LOCAL = 'local', GOOGLE = 'google', GITHUB = 'github', -} \ No newline at end of file +} diff --git a/backend/gateway-service/src/common/constants/coding-languages.enum.ts b/backend/gateway-service/src/common/constants/coding-languages.enum.ts index e4c4b79897..5f7c930f79 100644 --- a/backend/gateway-service/src/common/constants/coding-languages.enum.ts +++ b/backend/gateway-service/src/common/constants/coding-languages.enum.ts @@ -2,4 +2,4 @@ export enum Languages { PYTHON = 'Python', JAVA = 'Java', CPLUSPLUS = 'C++', -} \ No newline at end of file +} diff --git a/backend/gateway-service/src/common/constants/proficiency-level.enum.ts b/backend/gateway-service/src/common/constants/proficiency-level.enum.ts index d16ed94551..6b005a58eb 100644 --- a/backend/gateway-service/src/common/constants/proficiency-level.enum.ts +++ b/backend/gateway-service/src/common/constants/proficiency-level.enum.ts @@ -2,4 +2,4 @@ export enum Proficiency { BEGINNER = 'Beginner', INTERMEDIATE = 'Intermediate', ADVANCED = 'Advanced', -} \ No newline at end of file +} diff --git a/backend/gateway-service/src/common/decorators/get-current-user-id-socket.decorator.ts b/backend/gateway-service/src/common/decorators/get-current-user-id-socket.decorator.ts index 62afd94f6c..9b4ad486a4 100644 --- a/backend/gateway-service/src/common/decorators/get-current-user-id-socket.decorator.ts +++ b/backend/gateway-service/src/common/decorators/get-current-user-id-socket.decorator.ts @@ -21,4 +21,3 @@ export const GetCurrentUserId = createParamDecorator( } }, ); */ - diff --git a/backend/gateway-service/src/modules/auth/dto/reset-password-request.dto.ts b/backend/gateway-service/src/modules/auth/dto/reset-password-request.dto.ts index 98f77f9ff8..69f4faa191 100644 --- a/backend/gateway-service/src/modules/auth/dto/reset-password-request.dto.ts +++ b/backend/gateway-service/src/modules/auth/dto/reset-password-request.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsEmail, IsNotEmpty, IsString } from 'class-validator'; +import { IsEmail, IsNotEmpty } from 'class-validator'; export class ResetPasswordRequestDto { @ApiProperty({ @@ -8,5 +8,4 @@ export class ResetPasswordRequestDto { @IsEmail() @IsNotEmpty() email: string; - } diff --git a/backend/gateway-service/src/modules/code-execution/code-execution.controller.ts b/backend/gateway-service/src/modules/code-execution/code-execution.controller.ts index a52500a3c3..76dbb45730 100644 --- a/backend/gateway-service/src/modules/code-execution/code-execution.controller.ts +++ b/backend/gateway-service/src/modules/code-execution/code-execution.controller.ts @@ -1,7 +1,9 @@ import { Controller, Post, Body, Inject } from '@nestjs/common'; import { ClientProxy } from '@nestjs/microservices'; import { ExecuteCodeDto } from './dto/execute-code.dto'; // Create this DTO +import { ApiTags } from '@nestjs/swagger'; +@ApiTags('code-execution') @Controller('code-execution') export class CodeExecutionController { constructor( diff --git a/backend/gateway-service/src/modules/health/health.controller.ts b/backend/gateway-service/src/modules/health/health.controller.ts new file mode 100644 index 0000000000..3cbaac9791 --- /dev/null +++ b/backend/gateway-service/src/modules/health/health.controller.ts @@ -0,0 +1,11 @@ +import { Controller, Get } from '@nestjs/common'; +import { Public } from 'src/common/decorators'; + +@Controller('health') +export class HealthController { + @Public() + @Get() + checkHealth() { + return { status: 'ok' }; + } +} diff --git a/backend/gateway-service/src/modules/match/dto/user-match-options.dto.ts b/backend/gateway-service/src/modules/match/dto/user-match-options.dto.ts index b2a1b40150..da85565d00 100644 --- a/backend/gateway-service/src/modules/match/dto/user-match-options.dto.ts +++ b/backend/gateway-service/src/modules/match/dto/user-match-options.dto.ts @@ -3,10 +3,9 @@ import { Type } from 'class-transformer'; import { IsArray, IsIn, IsNotEmpty, IsString } from 'class-validator'; export class UserMatchOptionsDto { - @IsString() userId: string; - + @ApiProperty({ description: 'Either Easy, Medium, or Hard', example: 'Easy', diff --git a/backend/gateway-service/src/modules/match/redis.service.ts b/backend/gateway-service/src/modules/match/redis.service.ts index 4a5ef48e5c..3194a5cebe 100644 --- a/backend/gateway-service/src/modules/match/redis.service.ts +++ b/backend/gateway-service/src/modules/match/redis.service.ts @@ -15,7 +15,7 @@ export class RedisMatchService { // Subscribe to the Redis Pub/Sub channel for match events subscribeToMatchEvents(callback: (matchedUsers: any) => void): void { - this.redisSubscriber.subscribe('matchChannel', (err, count) => { + this.redisSubscriber.subscribe('matchChannel', (err) => { if (err) { console.error('Error subscribing to Redis channel:', err); return; @@ -35,11 +35,13 @@ export class RedisMatchService { matchId: parsedMessage.matchId, matchedUserIds: parsedMessage.matchedUserIds, }); - }}}); + } + } + }); } subscribeToTimeoutEvents(callback: (matchedUsers: any) => void): void { - this.redisSubscriber.subscribe('timeoutChannel', (err, count) => { + this.redisSubscriber.subscribe('timeoutChannel', (err) => { if (err) { console.error('Error subscribing to Redis channel:', err); return; diff --git a/backend/gateway-service/src/modules/user/dto/user-response.dto.ts b/backend/gateway-service/src/modules/user/dto/user-response.dto.ts index f502c84fa7..73b256d7da 100644 --- a/backend/gateway-service/src/modules/user/dto/user-response.dto.ts +++ b/backend/gateway-service/src/modules/user/dto/user-response.dto.ts @@ -1,4 +1,4 @@ -import { Exclude, Expose, Transform } from 'class-transformer'; +import { Exclude } from 'class-transformer'; export class UsersResponseDto { @Exclude() diff --git a/backend/matching-service/Dockerfile b/backend/matching-service/Dockerfile index f31497e3a1..99163fa378 100644 --- a/backend/matching-service/Dockerfile +++ b/backend/matching-service/Dockerfile @@ -1,47 +1,13 @@ -################# -## DEVELOPMENT ## -################# -FROM node:18-alpine AS development +FROM node:18 -# Set the working directory in the container WORKDIR /app -# Copy the package.json and package-lock.json files COPY package*.json ./ -# Install dependencies RUN npm install -# Copy the rest of the application code COPY . . -# Built the app to /dist folder -RUN npm run build +EXPOSE 3004 -# Expose the port the app runs on -EXPOSE 4000 - -################ -## PRODUCTION ## -################ -FROM node:18-alpine AS production - -# Set node environment to production -ARG NODE_ENV=production -ENV NODE_ENV=${NODE_ENV} - -# Set the working directory in the container -WORKDIR /app - -# Copy only the necessary files from the previous build stage -COPY --from=development /peerprep/app/dist ./dist -COPY package*.json ./ - -# Install production dependencies only -RUN npm ci --only=production - -# Expose the port the app runs on -EXPOSE 4000 - -# Run the main file -CMD ["node", "dist/main"] \ No newline at end of file +CMD ["node", "dist/main.js"] \ No newline at end of file diff --git a/backend/matching-service/src/app.controller.spec.ts b/backend/matching-service/src/app.controller.spec.ts deleted file mode 100644 index a22ca32ced..0000000000 --- a/backend/matching-service/src/app.controller.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; - -describe('AppController', () => { - let appController: AppController; - - beforeEach(async () => { - const app: TestingModule = await Test.createTestingModule({ - controllers: [AppController], - providers: [AppService], - }).compile(); - - appController = app.get(AppController); - }); -}); diff --git a/backend/matching-service/src/interfaces/match-details.interface.ts b/backend/matching-service/src/interfaces/match-details.interface.ts index 8c96efa5a0..b949991e16 100644 --- a/backend/matching-service/src/interfaces/match-details.interface.ts +++ b/backend/matching-service/src/interfaces/match-details.interface.ts @@ -6,5 +6,5 @@ export interface MatchDetails { score: number; generatedTopics: string[]; generatedDifficulty: string; - selectedQuestionId: string + selectedQuestionId: string; } diff --git a/backend/matching-service/src/services/redis.service.ts b/backend/matching-service/src/services/redis.service.ts index cc54664677..13e9707c4a 100644 --- a/backend/matching-service/src/services/redis.service.ts +++ b/backend/matching-service/src/services/redis.service.ts @@ -98,15 +98,15 @@ export class RedisService { } } - async publishMatchedUsers(matchId: string, matchedUserIds: string[]): Promise { + async publishMatchedUsers( + matchId: string, + matchedUserIds: string[], + ): Promise { const message = { matchId: matchId, matchedUserIds: matchedUserIds, }; - await this.redisPublisher.publish( - 'matchChannel', - JSON.stringify(message), - ); + await this.redisPublisher.publish('matchChannel', JSON.stringify(message)); } async publishTimedOutUsers(timedOutUserIds: string[]): Promise { @@ -126,8 +126,17 @@ export class RedisService { return users.map((user) => JSON.parse(user)); } - async storeMatch(matchId: string, matchData: MatchDetails, ttl: number = 1000): Promise { - await this.redisPublisher.set(matchId, JSON.stringify(matchData), 'EX', ttl); + async storeMatch( + matchId: string, + matchData: MatchDetails, + ttl: number = 1000, + ): Promise { + await this.redisPublisher.set( + matchId, + JSON.stringify(matchData), + 'EX', + ttl, + ); } async getMatch(matchId: string): Promise { diff --git a/backend/question-service/Dockerfile b/backend/question-service/Dockerfile index f31497e3a1..b451ca96bb 100644 --- a/backend/question-service/Dockerfile +++ b/backend/question-service/Dockerfile @@ -1,47 +1,13 @@ -################# -## DEVELOPMENT ## -################# -FROM node:18-alpine AS development +FROM node:18 -# Set the working directory in the container WORKDIR /app -# Copy the package.json and package-lock.json files COPY package*.json ./ -# Install dependencies RUN npm install -# Copy the rest of the application code COPY . . -# Built the app to /dist folder -RUN npm run build +EXPOSE 3002 -# Expose the port the app runs on -EXPOSE 4000 - -################ -## PRODUCTION ## -################ -FROM node:18-alpine AS production - -# Set node environment to production -ARG NODE_ENV=production -ENV NODE_ENV=${NODE_ENV} - -# Set the working directory in the container -WORKDIR /app - -# Copy only the necessary files from the previous build stage -COPY --from=development /peerprep/app/dist ./dist -COPY package*.json ./ - -# Install production dependencies only -RUN npm ci --only=production - -# Expose the port the app runs on -EXPOSE 4000 - -# Run the main file -CMD ["node", "dist/main"] \ No newline at end of file +CMD ["node", "dist/main.js"] \ No newline at end of file diff --git a/backend/question-service/src/app.controller.spec.ts b/backend/question-service/src/app.controller.spec.ts deleted file mode 100644 index 5b28217f63..0000000000 --- a/backend/question-service/src/app.controller.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; - -describe('AppController', () => { - let appController: AppController; - - beforeEach(async () => { - const app: TestingModule = await Test.createTestingModule({ - controllers: [AppController], - providers: [AppService], - }).compile(); - - appController = app.get(AppController); - }); - - /* describe('root', () => { - it('should return "Hello World!"', () => { - expect(appController.getHello()).toBe('Hello World!'); - }); - }); */ -}); diff --git a/backend/question-service/src/app.controller.ts b/backend/question-service/src/app.controller.ts index bd3db285fd..dc554ffa7f 100644 --- a/backend/question-service/src/app.controller.ts +++ b/backend/question-service/src/app.controller.ts @@ -55,12 +55,6 @@ export class AppController { return this.appService.updateQuestion(id, updatedQuestionInfo); } - @MessagePattern({ cmd: 'update-question-testcases' }) - async updateQuestionTestCases(@Payload() data: UpdateQuestionTestCasesDto) { - const { id, testCases } = data; - return this.appService.updateQuestionTestCases(id, testCases); - } - @MessagePattern({ cmd: 'get-categories' }) async getCategories() { return this.appService.getCategories(); diff --git a/backend/question-service/src/app.service.ts b/backend/question-service/src/app.service.ts index 03e27fc228..e3d5395fd8 100644 --- a/backend/question-service/src/app.service.ts +++ b/backend/question-service/src/app.service.ts @@ -158,29 +158,6 @@ export class AppService { } } - async updateQuestionTestCases( - id: string, - testCases: TestCase[], - ): Promise { - try { - const updatedQuestion = await this.questionModel - .findOneAndUpdate( - { _id: new Types.ObjectId(id) }, - { testCases }, - { new: true }, - ) - .exec(); - - if (!updatedQuestion) { - throw new RpcException('Question not found'); - } - - return updatedQuestion; - } catch (error) { - throw new RpcException(error.message); - } - } - async getCategories(): Promise<{ categories: string[] }> { return { categories: QUESTION_CATEGORIES }; } diff --git a/backend/question-service/src/constants/question-categories.constant.ts b/backend/question-service/src/constants/question-categories.constant.ts index 4c545981dd..e5e8c33959 100644 --- a/backend/question-service/src/constants/question-categories.constant.ts +++ b/backend/question-service/src/constants/question-categories.constant.ts @@ -1,13 +1,13 @@ export const QUESTION_CATEGORIES = [ - "Array", - "Binary Search", - "Divide and Conquer", - "Dynamic Programming", - "Hash Table", - "Linked List", - "Math", - "Sliding Window", - "Stack", - "String", - "Two Sum" -] \ No newline at end of file + 'Array', + 'Binary Search', + 'Divide and Conquer', + 'Dynamic Programming', + 'Hash Table', + 'Linked List', + 'Math', + 'Sliding Window', + 'Stack', + 'String', + 'Two Sum', +]; diff --git a/backend/question-service/src/main.ts b/backend/question-service/src/main.ts index 9dde06c2e9..edba6b3b70 100644 --- a/backend/question-service/src/main.ts +++ b/backend/question-service/src/main.ts @@ -18,6 +18,7 @@ async function bootstrap() { }, }, ); + app.useGlobalPipes( new ValidationPipe({ transform: true, @@ -26,6 +27,7 @@ async function bootstrap() { forbidNonWhitelisted: true, }), ); + await app.listen(); console.log( 'Question Service is listening on port', diff --git a/backend/user-service/Dockerfile b/backend/user-service/Dockerfile index f31497e3a1..bfc002689e 100644 --- a/backend/user-service/Dockerfile +++ b/backend/user-service/Dockerfile @@ -1,47 +1,13 @@ -################# -## DEVELOPMENT ## -################# -FROM node:18-alpine AS development +FROM node:18 -# Set the working directory in the container WORKDIR /app -# Copy the package.json and package-lock.json files COPY package*.json ./ -# Install dependencies RUN npm install -# Copy the rest of the application code COPY . . -# Built the app to /dist folder -RUN npm run build +EXPOSE 3001 -# Expose the port the app runs on -EXPOSE 4000 - -################ -## PRODUCTION ## -################ -FROM node:18-alpine AS production - -# Set node environment to production -ARG NODE_ENV=production -ENV NODE_ENV=${NODE_ENV} - -# Set the working directory in the container -WORKDIR /app - -# Copy only the necessary files from the previous build stage -COPY --from=development /peerprep/app/dist ./dist -COPY package*.json ./ - -# Install production dependencies only -RUN npm ci --only=production - -# Expose the port the app runs on -EXPOSE 4000 - -# Run the main file -CMD ["node", "dist/main"] \ No newline at end of file +CMD ["node", "dist/main.js"] \ No newline at end of file diff --git a/backend/user-service/src/app.controller.spec.ts b/backend/user-service/src/app.controller.spec.ts deleted file mode 100644 index 5b28217f63..0000000000 --- a/backend/user-service/src/app.controller.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; - -describe('AppController', () => { - let appController: AppController; - - beforeEach(async () => { - const app: TestingModule = await Test.createTestingModule({ - controllers: [AppController], - providers: [AppService], - }).compile(); - - appController = app.get(AppController); - }); - - /* describe('root', () => { - it('should return "Hello World!"', () => { - expect(appController.getHello()).toBe('Hello World!'); - }); - }); */ -}); diff --git a/backend/user-service/src/app.controller.ts b/backend/user-service/src/app.controller.ts index d1479e20ec..db887cacfb 100644 --- a/backend/user-service/src/app.controller.ts +++ b/backend/user-service/src/app.controller.ts @@ -29,12 +29,12 @@ export class AppController { return this.appService.createUser(data); } - @MessagePattern({ cmd: "create-user-socials"}) + @MessagePattern({ cmd: 'create-user-socials' }) async createUserSocials(@Payload() data: CreateUserSocialsDto) { return this.appService.createUserSocials(data); } - @MessagePattern({ cmd: "update-user-profile"}) + @MessagePattern({ cmd: 'update-user-profile' }) async updateUserProfile(@Payload() data: UpdateUserPayload) { return this.appService.updateUserProfile(data); } diff --git a/backend/user-service/src/constants/account-provider.enum.ts b/backend/user-service/src/constants/account-provider.enum.ts index 3ee17560be..5cba246a70 100644 --- a/backend/user-service/src/constants/account-provider.enum.ts +++ b/backend/user-service/src/constants/account-provider.enum.ts @@ -2,4 +2,4 @@ export enum AccountProvider { LOCAL = 'local', GOOGLE = 'google', GITHUB = 'github', -} \ No newline at end of file +} diff --git a/backend/user-service/src/constants/coding-languages.enum.ts b/backend/user-service/src/constants/coding-languages.enum.ts index e4c4b79897..5f7c930f79 100644 --- a/backend/user-service/src/constants/coding-languages.enum.ts +++ b/backend/user-service/src/constants/coding-languages.enum.ts @@ -2,4 +2,4 @@ export enum Languages { PYTHON = 'Python', JAVA = 'Java', CPLUSPLUS = 'C++', -} \ No newline at end of file +} diff --git a/backend/user-service/src/constants/index.ts b/backend/user-service/src/constants/index.ts index 6a3dc4b302..70c1491360 100644 --- a/backend/user-service/src/constants/index.ts +++ b/backend/user-service/src/constants/index.ts @@ -1,4 +1,4 @@ -export {Proficiency} from './proficiency-level.enum'; -export {Languages} from './coding-languages.enum'; -export {AccountProvider} from './account-provider.enum'; -export {Role} from './role.enum'; \ No newline at end of file +export { Proficiency } from './proficiency-level.enum'; +export { Languages } from './coding-languages.enum'; +export { AccountProvider } from './account-provider.enum'; +export { Role } from './role.enum'; diff --git a/backend/user-service/src/constants/proficiency-level.enum.ts b/backend/user-service/src/constants/proficiency-level.enum.ts index d16ed94551..6b005a58eb 100644 --- a/backend/user-service/src/constants/proficiency-level.enum.ts +++ b/backend/user-service/src/constants/proficiency-level.enum.ts @@ -2,4 +2,4 @@ export enum Proficiency { BEGINNER = 'Beginner', INTERMEDIATE = 'Intermediate', ADVANCED = 'Advanced', -} \ No newline at end of file +} diff --git a/backend/user-service/src/constants/role.enum.ts b/backend/user-service/src/constants/role.enum.ts index a53c6d44e4..1a6fa9fabe 100644 --- a/backend/user-service/src/constants/role.enum.ts +++ b/backend/user-service/src/constants/role.enum.ts @@ -1,4 +1,4 @@ export enum Role { - ADMIN = 'admin', - USER = 'user', -} \ No newline at end of file + ADMIN = 'admin', + USER = 'user', +} diff --git a/backend/user-service/src/dto/update-user.dto.ts b/backend/user-service/src/dto/update-user.dto.ts index 23432ed387..4012c014c0 100644 --- a/backend/user-service/src/dto/update-user.dto.ts +++ b/backend/user-service/src/dto/update-user.dto.ts @@ -1,12 +1,17 @@ -import { IsNotEmpty, IsString, IsEnum, IsOptional, IsBoolean } from 'class-validator'; +import { + IsNotEmpty, + IsString, + IsEnum, + IsOptional, + IsBoolean, +} from 'class-validator'; import { Languages, Proficiency } from 'src/constants'; export class UpdateUserDto { - @IsString() @IsNotEmpty() username: string; - + @IsString() @IsNotEmpty() displayName: string; diff --git a/backend/user-service/src/payload/update-user.payload.ts b/backend/user-service/src/payload/update-user.payload.ts index ba2b645461..cb82884804 100644 --- a/backend/user-service/src/payload/update-user.payload.ts +++ b/backend/user-service/src/payload/update-user.payload.ts @@ -1,6 +1,6 @@ -import { UpdateUserDto } from "src/dto/update-user.dto"; +import { UpdateUserDto } from 'src/dto/update-user.dto'; export interface UpdateUserPayload { - userId: string, - updateUserDto: UpdateUserDto -} \ No newline at end of file + userId: string; + updateUserDto: UpdateUserDto; +} diff --git a/backend/y-websocket-service/Dockerfile b/backend/y-websocket-service/Dockerfile index c4b6ed873d..d998843fdb 100644 --- a/backend/y-websocket-service/Dockerfile +++ b/backend/y-websocket-service/Dockerfile @@ -1,47 +1,13 @@ -################# -## DEVELOPMENT ## -################# -FROM node:18-alpine AS development +FROM node:18 -# Set the working directory in the container WORKDIR /app -# Copy the package.json and package-lock.json files COPY package*.json ./ -# Install dependencies RUN npm install -# Copy the rest of the application code COPY . . -# Built the app to /dist folder -RUN npm run build +EXPOSE 4001 -# Expose the port the app runs on -EXPOSE 1234 - -################ -## PRODUCTION ## -################ -FROM node:18-alpine AS production - -# Set node environment to production -ARG NODE_ENV=production -ENV NODE_ENV=${NODE_ENV} - -# Set the working directory in the container -WORKDIR /app - -# Copy only the necessary files from the previous build stage -COPY --from=development /peerprep/app/dist ./dist -COPY package*.json ./ - -# Install production dependencies only -RUN npm ci --only=production - -# Expose the port the app runs on -EXPOSE 1234 - -# Run the main file -CMD ["node", "dist/main"] \ No newline at end of file +CMD ["node", "dist/main.js"] \ No newline at end of file diff --git a/frontend/.env.example b/frontend/.env.example deleted file mode 100644 index ca10184c9e..0000000000 --- a/frontend/.env.example +++ /dev/null @@ -1 +0,0 @@ -PUBLIC_API_URL=http://localhost:4000 \ No newline at end of file diff --git a/frontend/docker-compose.yml b/frontend/docker-compose.yml index fd40ac4e52..773e86d509 100644 --- a/frontend/docker-compose.yml +++ b/frontend/docker-compose.yml @@ -12,7 +12,6 @@ services: ports: - "3000:3000" environment: - - NODE_ENV=development - PUBLIC_API_URL=http://gateway-service:4000 networks: - backend_shared-network diff --git a/k8s/.DS_Store b/k8s/.DS_Store new file mode 100644 index 0000000000..8821dd782d Binary files /dev/null and b/k8s/.DS_Store differ diff --git a/k8s/.gitignore b/k8s/.gitignore new file mode 100644 index 0000000000..33a92995a7 --- /dev/null +++ b/k8s/.gitignore @@ -0,0 +1 @@ +secrets.yaml \ No newline at end of file diff --git a/k8s/auth-service/auth-configmap.yaml b/k8s/auth-service/auth-configmap.yaml new file mode 100644 index 0000000000..05d5177b0e --- /dev/null +++ b/k8s/auth-service/auth-configmap.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: auth-configmap + namespace: peerprep +data: + JWT_TOKEN_EXPIRATION: "1h" + JWT_REFRESH_TOKEN_EXPIRATION: "7d" + + GOOGLE_CALLBACK_URL: "http://localhost:4000/api/auth/google/callback" # Update this to domain later + GITHUB_CALLBACK_URL: "http://localhost:4000/api/auth/github/callback" # Update this to domain later + + NODEMAILER_GMAIL_USER: "peerprep33@gmail.com" + FRONTEND_URL: "http://localhost:3000" # Update this to domain later + + AUTH_SERVICE_HOST: "0.0.0.0" + AUTH_SERVICE_PORT: "3003" + AUTH_SERVICE_TRANSPORT: "TCP" + + USER_SERVICE_HOST: "user-service" + USER_SERVICE_PORT: "3001" + USER_SERVICE_TRANSPORT: "TCP" + + ACCESS_TOKEN_STRATEGY: "jwt" + REFRESH_TOKEN_STRATEGY: "jwt-refresh" + GOOGLE_STRATEGY: "google" + GITHUB_STRATEGY: "github" diff --git a/k8s/auth-service/auth-deployment.yaml b/k8s/auth-service/auth-deployment.yaml new file mode 100644 index 0000000000..ba47036fea --- /dev/null +++ b/k8s/auth-service/auth-deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: auth-service + namespace: peerprep + labels: + app: auth-service +spec: + replicas: 1 + selector: + matchLabels: + app: auth-service + template: + metadata: + labels: + app: auth-service + spec: + containers: + - name: auth-service + image: asia-southeast1-docker.pkg.dev/peerprep-438213/peerprep/auth-service:latest + imagePullPolicy: Always + ports: + - containerPort: 3003 + envFrom: + - secretRef: + name: peerprep-secrets + - configMapRef: + name: auth-configmap + restartPolicy: Always diff --git a/k8s/auth-service/auth-service.yaml b/k8s/auth-service/auth-service.yaml new file mode 100644 index 0000000000..ce504f9264 --- /dev/null +++ b/k8s/auth-service/auth-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: auth-service + namespace: peerprep +spec: + type: ClusterIP + ports: + - port: 3003 + targetPort: 3003 + protocol: TCP + selector: + app: auth-service diff --git a/k8s/base/ingress.yaml b/k8s/base/ingress.yaml new file mode 100644 index 0000000000..d6d69c23ed --- /dev/null +++ b/k8s/base/ingress.yaml @@ -0,0 +1,26 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: peerprep-ingress + namespace: peerprep + annotations: + kubernetes.io/ingress.global-static-ip-name: "peerprep33-ip" +spec: + ingressClassName: gce + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: gateway-service + port: + number: 4000 + - path: /yjs + pathType: Prefix + backend: + service: + name: y-websocket-service + port: + number: 4001 diff --git a/k8s/base/namespace.yaml b/k8s/base/namespace.yaml new file mode 100644 index 0000000000..a609d3759b --- /dev/null +++ b/k8s/base/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: peerprep diff --git a/k8s/base/secrets-example.yaml b/k8s/base/secrets-example.yaml new file mode 100644 index 0000000000..4a96580da9 --- /dev/null +++ b/k8s/base/secrets-example.yaml @@ -0,0 +1,16 @@ +# apiVersion: v1 +# kind: Secret +# metadata: +# name: peerprep-secrets +# namespace: peerprep +# type: Opaque +# data: +# MONGO_CONNECTION_STRING: +# JWT_SECRET: +# JWT_REFRESH_SECRET: +# GOOGLE_CLIENT_ID: +# GOOGLE_CLIENT_SECRET: +# GITHUB_CLIENT_ID: +# GITHUB_CLIENT_SECRET: +# NODEMAILER_GMAIL_PASSWORD: +# OPENAI_API_KEY: diff --git a/k8s/code-execution-service/code-execution-configmap.yaml b/k8s/code-execution-service/code-execution-configmap.yaml new file mode 100644 index 0000000000..73371b93e3 --- /dev/null +++ b/k8s/code-execution-service/code-execution-configmap.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: code-execution-configmap + namespace: peerprep +data: + CODE_EXECUTION_SERVICE_HOST: "0.0.0.0" + CODE_EXECUTION_SERVICE_PORT: "3006" + CODE_EXECUTION_SERVICE_TRANSPORT: "TCP" diff --git a/k8s/code-execution-service/code-execution-deployment.yaml b/k8s/code-execution-service/code-execution-deployment.yaml new file mode 100644 index 0000000000..4c474472f9 --- /dev/null +++ b/k8s/code-execution-service/code-execution-deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: code-execution-service + namespace: peerprep + labels: + app: code-execution-service +spec: + replicas: 1 + selector: + matchLabels: + app: code-execution-service + template: + metadata: + labels: + app: code-execution-service + spec: + containers: + - name: code-execution-service + image: asia-southeast1-docker.pkg.dev/peerprep-438213/peerprep/code-execution-service:latest + imagePullPolicy: Always + ports: + - containerPort: 3006 + envFrom: + - secretRef: + name: peerprep-secrets + - configMapRef: + name: code-execution-configmap + restartPolicy: Always diff --git a/k8s/code-execution-service/code-execution-service.yaml b/k8s/code-execution-service/code-execution-service.yaml new file mode 100644 index 0000000000..281b2e672b --- /dev/null +++ b/k8s/code-execution-service/code-execution-service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: code-execution-service + namespace: peerprep + labels: + app: code-execution-service +spec: + type: ClusterIP + ports: + - port: 3006 + targetPort: 3006 + protocol: TCP + selector: + app: code-execution-service diff --git a/k8s/collaboration-service/collaboration-configmap.yaml b/k8s/collaboration-service/collaboration-configmap.yaml new file mode 100644 index 0000000000..e0933c5b06 --- /dev/null +++ b/k8s/collaboration-service/collaboration-configmap.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: collaboration-configmap + namespace: peerprep +data: + COLLABORATION_SERVICE_HOST: "0.0.0.0" + COLLABORATION_SERVICE_PORT: "3005" + COLLABORATION_SERVICE_TRANSPORT: "TCP" + + USER_SERVICE_HOST: "user-service" + USER_SERVICE_PORT: "3001" + USER_SERVICE_TRANSPORT: "TCP" + + QUESTION_SERVICE_HOST: "question-service" + QUESTION_SERVICE_PORT: "3002" + QUESTION_SERVICE_TRANSPORT: "TCP" + + REDIS_HOST: "redis" + REDIS_PORT: "6379" diff --git a/k8s/collaboration-service/collaboration-deployment.yaml b/k8s/collaboration-service/collaboration-deployment.yaml new file mode 100644 index 0000000000..565fa2bc04 --- /dev/null +++ b/k8s/collaboration-service/collaboration-deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: collaboration-service + namespace: peerprep + labels: + app: collaboration-service +spec: + replicas: 1 + selector: + matchLabels: + app: collaboration-service + template: + metadata: + labels: + app: collaboration-service + spec: + containers: + - name: collaboration-service + image: asia-southeast1-docker.pkg.dev/peerprep-438213/peerprep/collaboration-service:latest + imagePullPolicy: Always + ports: + - containerPort: 3005 + envFrom: + - secretRef: + name: peerprep-secrets + - configMapRef: + name: collaboration-configmap + restartPolicy: Always diff --git a/k8s/collaboration-service/collaboration-service.yaml b/k8s/collaboration-service/collaboration-service.yaml new file mode 100644 index 0000000000..b9b2f2d33f --- /dev/null +++ b/k8s/collaboration-service/collaboration-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: collaboration-service + namespace: peerprep +spec: + type: ClusterIP + ports: + - port: 3005 + targetPort: 3005 + protocol: TCP + selector: + app: collaboration-service diff --git a/k8s/gateway-service/gateway-configmap.yaml b/k8s/gateway-service/gateway-configmap.yaml new file mode 100644 index 0000000000..72179d7696 --- /dev/null +++ b/k8s/gateway-service/gateway-configmap.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: gateway-configmap + namespace: peerprep +data: + FRONTEND_URL: "http://localhost:3000" + + GATEWAY_SERVICE_PORT: "4000" + + USER_SERVICE_HOST: "user-service" + USER_SERVICE_PORT: "3001" + USER_SERVICE_TRANSPORT: "TCP" + + QUESTION_SERVICE_HOST: "question-service" + QUESTION_SERVICE_PORT: "3002" + QUESTION_SERVICE_TRANSPORT: "TCP" + + AUTH_SERVICE_HOST: "auth-service" + AUTH_SERVICE_PORT: "3003" + AUTH_SERVICE_TRANSPORT: "TCP" + + MATCHING_SERVICE_HOST: "matching-service" + MATCHING_SERVICE_PORT: "3004" + MATCHING_SERVICE_TRANSPORT: "TCP" + + COLLABORATION_SERVICE_HOST: "collaboration-service" + COLLABORATION_SERVICE_PORT: "3005" + COLLABORATION_SERVICE_TRANSPORT: "TCP" + + REDIS_HOST: "redis" + REDIS_PORT: "6379" diff --git a/k8s/gateway-service/gateway-deployment.yaml b/k8s/gateway-service/gateway-deployment.yaml new file mode 100644 index 0000000000..d8db9739e5 --- /dev/null +++ b/k8s/gateway-service/gateway-deployment.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gateway-service + namespace: peerprep +spec: + replicas: 1 + selector: + matchLabels: + app: gateway-service + template: + metadata: + labels: + app: gateway-service + spec: + containers: + - name: gateway-service + image: asia-southeast1-docker.pkg.dev/peerprep-438213/peerprep/gateway-service:latest + imagePullPolicy: Always + ports: + - containerPort: 4000 + env: + - name: NODE_ENV + value: "production" + envFrom: + - secretRef: + name: peerprep-secrets + - configMapRef: + name: gateway-configmap + readinessProbe: + httpGet: + path: /api/health + port: 4000 + initialDelaySeconds: 10 + periodSeconds: 10 + resources: + requests: + memory: 128Mi + cpu: 250m + limits: + memory: 256Mi + cpu: 500m + restartPolicy: Always diff --git a/k8s/gateway-service/gateway-service.yaml b/k8s/gateway-service/gateway-service.yaml new file mode 100644 index 0000000000..61a5fd3572 --- /dev/null +++ b/k8s/gateway-service/gateway-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: gateway-service + namespace: peerprep +spec: + type: LoadBalancer + # type: NodePort + ports: + - port: 4000 + targetPort: 4000 + selector: + app: gateway-service diff --git a/k8s/matching-service/matching-configmap.yaml b/k8s/matching-service/matching-configmap.yaml new file mode 100644 index 0000000000..1e5fe2a1bf --- /dev/null +++ b/k8s/matching-service/matching-configmap.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: matching-configmap + namespace: peerprep +data: + MATCHING_SERVICE_HOST: "0.0.0.0" + MATCHING_SERVICE_PORT: "3004" + MATCHING_SERVICE_TRANSPORT: "TCP" + + QUESTION_SERVICE_HOST: "question-service" + QUESTION_SERVICE_PORT: "3002" + QUESTION_SERVICE_TRANSPORT: "TCP" + + USER_SERVICE_HOST: "user-service" + USER_SERVICE_PORT: "3001" + USER_SERVICE_TRANSPORT: "TCP" + + REDIS_HOST: "redis" + REDIS_PORT: "6379" diff --git a/k8s/matching-service/matching-deployment.yaml b/k8s/matching-service/matching-deployment.yaml new file mode 100644 index 0000000000..aa5a3efdd1 --- /dev/null +++ b/k8s/matching-service/matching-deployment.yaml @@ -0,0 +1,27 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: matching-service + namespace: peerprep +spec: + replicas: 1 + selector: + matchLabels: + app: matching-service + template: + metadata: + labels: + app: matching-service + spec: + containers: + - name: matching-service + image: asia-southeast1-docker.pkg.dev/peerprep-438213/peerprep/matching-service:latest + imagePullPolicy: Always + ports: + - containerPort: 3004 + envFrom: + - secretRef: + name: peerprep-secrets + - configMapRef: + name: matching-configmap + restartPolicy: Always diff --git a/k8s/matching-service/matching-service.yaml b/k8s/matching-service/matching-service.yaml new file mode 100644 index 0000000000..464d8c4987 --- /dev/null +++ b/k8s/matching-service/matching-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: matching-service + namespace: peerprep +spec: + type: ClusterIP + ports: + - port: 3004 + targetPort: 3004 + protocol: TCP + selector: + app: matching-service diff --git a/k8s/question-service/question-configmap.yaml b/k8s/question-service/question-configmap.yaml new file mode 100644 index 0000000000..afcbde946d --- /dev/null +++ b/k8s/question-service/question-configmap.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: question-configmap + namespace: peerprep +data: + QUESTION_SERVICE_HOST: "0.0.0.0" + QUESTION_SERVICE_PORT: "3002" + QUESTION_SERVICE_TRANSPORT: "TCP" diff --git a/k8s/question-service/question-deployment.yaml b/k8s/question-service/question-deployment.yaml new file mode 100644 index 0000000000..1e7a1d996d --- /dev/null +++ b/k8s/question-service/question-deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: question-service + namespace: peerprep + labels: + app: question-service +spec: + replicas: 1 + selector: + matchLabels: + app: question-service + template: + metadata: + labels: + app: question-service + spec: + containers: + - name: question-service + image: asia-southeast1-docker.pkg.dev/peerprep-438213/peerprep/question-service:latest + imagePullPolicy: Always + ports: + - containerPort: 3002 + envFrom: + - secretRef: + name: peerprep-secrets + - configMapRef: + name: question-configmap + restartPolicy: Always diff --git a/k8s/question-service/question-service.yaml b/k8s/question-service/question-service.yaml new file mode 100644 index 0000000000..99cede6791 --- /dev/null +++ b/k8s/question-service/question-service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: question-service + namespace: peerprep + labels: + app: question-service +spec: + type: ClusterIP + ports: + - port: 3002 + targetPort: 3002 + protocol: TCP + selector: + app: question-service diff --git a/k8s/redis/redis-deployment.yaml b/k8s/redis/redis-deployment.yaml new file mode 100644 index 0000000000..744ed48b7d --- /dev/null +++ b/k8s/redis/redis-deployment.yaml @@ -0,0 +1,46 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis + namespace: peerprep +spec: + replicas: 1 + selector: + matchLabels: + app: redis + template: + metadata: + labels: + app: redis + spec: + containers: + - name: redis + image: redis:latest + args: ["redis-server", "--appendonly", "yes"] + ports: + - containerPort: 6379 + volumeMounts: + - name: redis-data + mountPath: /data + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "256Mi" + cpu: "200m" + livenessProbe: + tcpSocket: + port: 6379 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + tcpSocket: + port: 6379 + initialDelaySeconds: 5 + periodSeconds: 10 + volumes: + - name: redis-data + persistentVolumeClaim: + claimName: redis-pvc + restartPolicy: Always diff --git a/k8s/redis/redis-pvc.yaml b/k8s/redis/redis-pvc.yaml new file mode 100644 index 0000000000..19f5d5f45b --- /dev/null +++ b/k8s/redis/redis-pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-pvc + namespace: peerprep +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/k8s/redis/redis-service.yaml b/k8s/redis/redis-service.yaml new file mode 100644 index 0000000000..89120c3f1a --- /dev/null +++ b/k8s/redis/redis-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis + namespace: peerprep +spec: + type: ClusterIP + ports: + - port: 6379 + targetPort: 6379 + protocol: TCP + selector: + app: redis diff --git a/k8s/start-k8s.sh b/k8s/start-k8s.sh new file mode 100755 index 0000000000..ff5192e87e --- /dev/null +++ b/k8s/start-k8s.sh @@ -0,0 +1,11 @@ +DIR="." + +kubectl apply -f $DIR/base/namespace.yaml +kubectl apply -f $DIR/base/secrets.yaml + +# Apply all YAML files in the k8s folder +for file in $DIR/**/*.yaml; do + kubectl apply -f $file +done + +echo "All services have been applied." diff --git a/k8s/user-service/user-configmap.yaml b/k8s/user-service/user-configmap.yaml new file mode 100644 index 0000000000..73d7845d5d --- /dev/null +++ b/k8s/user-service/user-configmap.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: user-configmap + namespace: peerprep +data: + USER_SERVICE_HOST: "0.0.0.0" + USER_SERVICE_PORT: "3001" + USER_SERVICE_TRANSPORT: "TCP" diff --git a/k8s/user-service/user-deployment.yaml b/k8s/user-service/user-deployment.yaml new file mode 100644 index 0000000000..6f69d3fda4 --- /dev/null +++ b/k8s/user-service/user-deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: user-service + namespace: peerprep + labels: + app: user-service +spec: + replicas: 1 + selector: + matchLabels: + app: user-service + template: + metadata: + labels: + app: user-service + spec: + containers: + - name: user-service + image: asia-southeast1-docker.pkg.dev/peerprep-438213/peerprep/user-service:latest + imagePullPolicy: Always + ports: + - containerPort: 3001 + envFrom: + - secretRef: + name: peerprep-secrets + - configMapRef: + name: user-configmap + restartPolicy: Always diff --git a/k8s/user-service/user-service.yaml b/k8s/user-service/user-service.yaml new file mode 100644 index 0000000000..ad680ea0c3 --- /dev/null +++ b/k8s/user-service/user-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: user-service + namespace: peerprep +spec: + type: ClusterIP + ports: + - port: 3001 + targetPort: 3001 + protocol: TCP + selector: + app: user-service diff --git a/k8s/y-websocket-service/y-websocket-configmap.yaml b/k8s/y-websocket-service/y-websocket-configmap.yaml new file mode 100644 index 0000000000..e7ffadab4c --- /dev/null +++ b/k8s/y-websocket-service/y-websocket-configmap.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: ywebsocket-configmap + namespace: peerprep +data: + Y_WEBSOCKET_PORT: "4001" + + COLLABORATION_SERVICE_HOST: "collaboration-service" + COLLABORATION_SERVICE_PORT: "3005" + COLLABORATION_SERVICE_TRANSPORT: "TCP" diff --git a/k8s/y-websocket-service/y-websocket-deployment.yaml b/k8s/y-websocket-service/y-websocket-deployment.yaml new file mode 100644 index 0000000000..a7780220e1 --- /dev/null +++ b/k8s/y-websocket-service/y-websocket-deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: y-websocket-service + namespace: peerprep + labels: + app: y-websocket-service +spec: + replicas: 1 + selector: + matchLabels: + app: y-websocket-service + template: + metadata: + labels: + app: y-websocket-service + spec: + containers: + - name: y-websocket-service + image: asia-southeast1-docker.pkg.dev/peerprep-438213/peerprep/y-websocket-service:latest + imagePullPolicy: Always + ports: + - containerPort: 4001 + envFrom: + - secretRef: + name: peerprep-secrets + - configMapRef: + name: ywebsocket-configmap + restartPolicy: Always diff --git a/k8s/y-websocket-service/y-websocket-service.yaml b/k8s/y-websocket-service/y-websocket-service.yaml new file mode 100644 index 0000000000..60bda61073 --- /dev/null +++ b/k8s/y-websocket-service/y-websocket-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: y-websocket-service + namespace: peerprep +spec: + type: LoadBalancer + ports: + - name: ws + port: 4001 + targetPort: 4001 + selector: + app: y-websocket-service