diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml new file mode 100644 index 0000000..e8d68fa --- /dev/null +++ b/.github/workflows/docker-release.yml @@ -0,0 +1,69 @@ +name: Docker Release +on: + release: + types: [published] + +env: + DOCKER_PLATFORMS: | + linux/amd64 + linux/arm64 + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Extract version and tags + run: | + if [[ "$GITHUB_REF_TYPE" == "tag" ]]; then + VERSION=${GITHUB_REF_NAME#v} + echo "VERSION=$VERSION" >> $GITHUB_ENV + + # Extract major.minor (ex: 1.2.3 -> 1.2) + MAJOR_MINOR=$(echo $VERSION | cut -d. -f1,2) + echo "MAJOR_MINOR=$MAJOR_MINOR" >> $GITHUB_ENV + else + echo "VERSION=latest" >> $GITHUB_ENV + echo "MAJOR_MINOR=latest" >> $GITHUB_ENV + fi + + - name: Extract repository name (lowercase) + run: echo "REPO_NAME=$(basename ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: ${{ env.DOCKER_PLATFORMS }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + version: latest + install: true + platforms: ${{ env.DOCKER_PLATFORMS }} + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + platforms: ${{ env.DOCKER_PLATFORMS }} + push: true + tags: | + ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}:${{ env.VERSION }} + ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}:${{ env.MAJOR_MINOR }} + ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}:latest + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + BUILDKIT_INLINE_CACHE=1 diff --git a/.gitignore b/.gitignore index 7af7f04..ed1665d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /node_modules -.env \ No newline at end of file +.env +.secrets +release.json \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 92e640c..02bec79 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:24-alpine AS base +FROM node:22-alpine AS base # Enable and prepare pnpm via Corepack RUN corepack enable && corepack prepare pnpm@latest --activate @@ -37,7 +37,7 @@ WORKDIR /app/packages/socket RUN if [ -f "tsconfig.json" ]; then pnpm build; fi # ----- RUNNER ----- -FROM node:24-alpine AS runner +FROM node:22-alpine AS runner WORKDIR /app # Create a non-root user for better security diff --git a/README.md b/README.md index 93772a0..250b303 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@


- +

+ Visitor Badge + Docker Pulls +

## 🧩 What is this project? @@ -12,93 +15,144 @@ Rahoot is a straightforward and open-source clone of the Kahoot! platform, allow ## ⚙️ Prerequisites -- Node.js version 20 or higher +Choose one of the following deployment methods: + +### Without Docker + +- Node.js : version 20 or higher +- PNPM : Learn more about [here](https://pnpm.io/) + +### With Docker + +- Docker and Docker Compose ## 📖 Getting Started -1. #### Clone the GitHub repository of your project. - ```bash - git clone https://github.com/Ralex91/Rahoot.git - cd ./Rahoot - ``` -2. #### Install the dependencies using your preferred package manager +Choose your deployment method: - ```bash - npm install - ``` +### 🐳 Using Docker (Recommended) -
-
+Using Docker Compose (recommended): -## 📦 Running the Application in Production Mode: - -1. #### Check websocket connfiguration in [config.mjs](config.mjs) - - If you want the client to connect directly to the websocket server, edit the [config.mjs](config.mjs) file and change the localhost to your public IP address. - - ```js - export const WEBSOCKET_PUBLIC_URL = "http://1.2.3.4:3100/" - export const WEBSOCKET_SERVER_PORT = 3100 - - // Rest of the config ... - ``` - -2. #### Start the application - - ```bash - npm run all - ``` - -## ⚙️ Running the Application in Development Mode: +You can find the docker compose configuration in the repository: +[docker-compose.yml](/compose.yml) ```bash -npm run all-dev +docker compose up -d ``` -## 🔧 Configuration +Or using Docker directly: -Configuration can be found in [config.mjs](config.mjs) +```bash +docker run -d \ + -p 3000:3000 \ + -p 3001:3001 \ + -v ./config:/app/config \ + -e WEB_ORIGIN=http://localhost:3000 \ + -e SOCKET_URL=http://localhost:3001 \ + ralex91/rahoot:latest +``` -```js -const QUIZZ_CONFIG = { - password: "PASSWORD", // Manager password - subject: "Adobe", // Subject of the quiz - questions: [ - { // Example question - question: "What is good answer ?", // Question - answers: [ // Possible answers - "No", - "Yes", - "No", - "No", - ], - image: - "https://images.unsplash.com/....", // Image URL (optional) - solution: 1, // Index of the correct answer (index starts at 0) - cooldown: 5, // Show question cooldown in seconds - time: 15, // Time to answer in seconds - }, - ... - ], +The application will be available at: + +- Web Interface: http://localhost:3000 +- WebSocket Server: ws://localhost:3001 + +### 🛠️ Without Docker + +1. Clone the repository: + +```bash +git clone https://github.com/Ralex91/Rahoot.git +cd ./Rahoot +``` + +2. Install dependencies: + +```bash +pnpm install +``` + +3. Change the environment variables in the `.env` file + +4. Build and start the application: + +```bash +# Development mode +pnpm run dev + +# Production mode +pnpm run build +pnpm start +``` + +## ⚙️ Configuration + +The configuration is split into two main parts: + +### 1. Game Configuration (`config/game.json`) + +Main game settings: + +```json +{ + "managerPassword": "PASSWORD", + "music": true } ``` -## 🤔 How to use +Options: -- Go to [https://localhost:3000/manager](https://localhost:3000/manager) enter manager password. +- `managerPassword`: The master password for accessing the manager interface +- `music`: Enable/disable game music -- Share link [https://localhost:3000/](https://localhost:3000/) and code on manager screen with your friends and get ready to play. +### 2. Quiz Configuration (`config/quizz/*.json`) -- Once everyone is ready, start the game with button on the top left of the screen of manager. +Create your quiz files in the `config/quizz/` directory. You can have multiple quiz files and select which one to use when starting a game. + +Example quiz configuration (`config/quizz/example.json`): + +```json +{ + "subject": "Example Quiz", + "questions": [ + { + "question": "What is the correct answer?", + "answers": ["No", "Yes", "No", "No"], + "image": "https://images.unsplash.com/....", + "solution": 1, + "cooldown": 5, + "time": 15 + } + ] +} +``` + +Quiz Options: + +- `subject`: Title/topic of the quiz +- `questions`: Array of question objects containing: + - `question`: The question text + - `answers`: Array of possible answers (2-4 options) + - `image`: Optional URL for question image + - `solution`: Index of correct answer (0-based) + - `cooldown`: Time in seconds before showing the question + - `time`: Time in seconds allowed to answer + +## 🎮 How to Play + +1. Access the manager interface at http://localhost:3000/manager +2. Enter the manager password (defined in quiz config) +3. Share the game URL (http://localhost:3000) and room code with participants +4. Wait for players to join +5. Click the start button to begin the game ## 📝 Contributing -- Create a fork +1. Fork the repository +2. Create a new branch (e.g., `feat/my-feature`) +3. Make your changes +4. Create a pull request +5. Wait for review and merge -- Create work branch (Example: githubUsername/featureName). - -- Commit and push your changes in the work branch. - -- Open a pull request. - -- Your pull request would be merged and changes will be reflected in the main repository. +For bug reports or feature requests, please [create an issue](https://github.com/Ralex91/Rahoot/issues). diff --git a/compose.yml b/compose.yml index 46701b8..8db2259 100644 --- a/compose.yml +++ b/compose.yml @@ -2,7 +2,7 @@ version: "3.8" services: rahoot: - image: rahoot + image: ralex91/rahoot:latest ports: - "3000:3000" - "3001:3001" diff --git a/packages/web/src/app/game/manager/[gameId]/page.tsx b/packages/web/src/app/game/manager/[gameId]/page.tsx index b00d291..24bcddd 100644 --- a/packages/web/src/app/game/manager/[gameId]/page.tsx +++ b/packages/web/src/app/game/manager/[gameId]/page.tsx @@ -40,7 +40,6 @@ export default function ManagerGame() { useEvent( "manager:successReconnect", ({ gameId, status, players, currentQuestion }) => { - console.log("manager:successReconnect", gameId) setGameId(gameId) setStatus(status.name, status.data) setPlayers(players) diff --git a/packages/web/src/components/game/states/Podium.tsx b/packages/web/src/components/game/states/Podium.tsx index 7e4ed7c..8934713 100644 --- a/packages/web/src/components/game/states/Podium.tsx +++ b/packages/web/src/components/game/states/Podium.tsx @@ -39,8 +39,6 @@ export default function Podium({ data: { subject, top } }: Props) { }) useEffect(() => { - console.log(apparition) - switch (apparition) { case 4: sfxRoolStop()