Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: ci
on:
push:
branches: [ "main" ]
pull_request:
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.22"
- name: Test all services
run: |
for d in services/*; do
echo "==> Testing $d"
(cd "$d" && go test ./...)
done

docker-build:
runs-on: ubuntu-latest
needs: build-and-test
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Build images (no push)
run: |
for d in services/*; do
name=$(basename "$d")
docker build -t peerprep/$name:ci "$d"
done
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Binaries
*.exe
*.exe~
*.dll
*.so
*.dylib
*.test
*.out
bin/
dist/

# Go
vendor/
**/*.local
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/QUdQy4ix)
# CS3219 Project (PeerPrep) - AY2526S1
## Group: Gxx
## Group: G21

## Quick start (local)

```bash
docker compose -f deploy/docker-compose.yaml up --build
```

Services:
- user: http://localhost:8081
- question: http://localhost:8082
- match: http://localhost:8083
- collab: http://localhost:8084

MongoDB: mongodb://localhost:27017
Redis: redis://localhost:6379

## Structure
- services/<svc> : Go microservice with chi router and health endpoints
- deploy/docker-compose.yaml : local dev
- .github/workflows/ci.yml : minimal CI (test + build)


### Note:
- You are required to develop individual microservices within separate folders within this repository.
Expand Down
45 changes: 45 additions & 0 deletions deploy/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
services:
mongo:
image: mongo:7
ports: ["27017:27017"]
volumes: [mongo-data:/data/db]
redis:
image: redis:7
ports: ["6379:6379"]

user:
build: ../services/user
environment:
- PORT=8080
- MONGO_URI=mongodb://mongo:27017
- JWT_PUBLIC_KEY=dev
depends_on: [mongo]
ports: ["8081:8080"]

question:
build: ../services/question
environment:
- PORT=8080
- MONGO_URI=mongodb://mongo:27017
depends_on: [mongo]
ports: ["8082:8080"]

match:
build: ../services/match
environment:
- PORT=8080
- REDIS_URL=redis://redis:6379
- MONGO_URI=mongodb://mongo:27017
depends_on: [redis, mongo]
ports: ["8083:8080"]

collab:
build: ../services/collab
environment:
- PORT=8080
- MONGO_URI=mongodb://mongo:27017
depends_on: [mongo]
ports: ["8084:8080"]

volumes:
mongo-data:
14 changes: 14 additions & 0 deletions services/collab/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.git
.gitignore
.vscode
.idea

bin
dist
*.out
*.test

.DS_Store

node_modules
venv
18 changes: 18 additions & 0 deletions services/collab/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM golang:1.22 AS build
WORKDIR /app

COPY go.mod ./
RUN go mod download

COPY . .
RUN go mod tidy

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /out/app ./cmd/server

FROM gcr.io/distroless/base-debian12
WORKDIR /
COPY --from=build /out/app /app
USER 65532:65532
ENV PORT=8080
EXPOSE 8080
ENTRYPOINT ["/app"]
41 changes: 41 additions & 0 deletions services/collab/cmd/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"log"
"net/http"
"os"
"time"

"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"go.uber.org/zap"
)

func registerRoutes(r *chi.Mux, logger *zap.Logger) {
// F4.* stubs
r.Post("/api/v1/session/start", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"status":"session_started_stub"}`))
})
r.Post("/api/v1/session/end", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"status":"session_ended_stub"}`))
})
}

func main() {
logger, _ := zap.NewProduction()
defer logger.Sync()

r := chi.NewRouter()
r.Use(middleware.RequestID, middleware.RealIP, middleware.Logger, middleware.Recoverer, middleware.Timeout(60*time.Second))

r.Get("/healthz", func(w http.ResponseWriter, _ *http.Request) { w.Write([]byte("ok")) })
registerRoutes(r, logger)

port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
addr := ":" + port
log.Printf("collab-svc listening on %s", addr)
log.Fatal(http.ListenAndServe(addr, r))
}
10 changes: 10 additions & 0 deletions services/collab/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module peerprep/collab

go 1.22

require (
github.com/go-chi/chi/v5 v5.0.12
go.uber.org/zap v1.27.0
)

require go.uber.org/multierr v1.10.0 // indirect
16 changes: 16 additions & 0 deletions services/collab/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
14 changes: 14 additions & 0 deletions services/match/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.git
.gitignore
.vscode
.idea

bin
dist
*.out
*.test

.DS_Store

node_modules
venv
18 changes: 18 additions & 0 deletions services/match/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM golang:1.22 AS build
WORKDIR /app

COPY go.mod ./
RUN go mod download

COPY . .
RUN go mod tidy

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /out/app ./cmd/server

FROM gcr.io/distroless/base-debian12
WORKDIR /
COPY --from=build /out/app /app
USER 65532:65532
ENV PORT=8080
EXPOSE 8080
ENTRYPOINT ["/app"]
56 changes: 56 additions & 0 deletions services/match/cmd/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package main

import (
"log"
"net/http"
"os"
"time"

"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/gorilla/websocket"
"go.uber.org/zap"
)

var upgrader = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}

func registerRoutes(r *chi.Mux, logger *zap.Logger) {
// F2.* stubs
r.Post("/api/v1/match/request", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusAccepted)
w.Write([]byte(`{"status":"enqueued_stub"}`))
})
r.Delete("/api/v1/match/request", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"status":"cancelled_stub"}`))
})
r.Get("/api/v1/match/counters", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"waiting":0}`))
})
r.Get("/ws", func(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
defer conn.Close()
conn.WriteJSON(map[string]any{"type": "waiting_count_update", "waiting": 0})
})
}

func main() {
logger, _ := zap.NewProduction()
defer logger.Sync()

r := chi.NewRouter()
r.Use(middleware.RequestID, middleware.RealIP, middleware.Logger, middleware.Recoverer, middleware.Timeout(60*time.Second))

r.Get("/healthz", func(w http.ResponseWriter, _ *http.Request) { w.Write([]byte("ok")) })
registerRoutes(r, logger)

port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
addr := ":" + port
log.Printf("match-svc listening on %s", addr)
log.Fatal(http.ListenAndServe(addr, r))
}
10 changes: 10 additions & 0 deletions services/match/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module peerprep/match

go 1.22

require (
github.com/go-chi/chi/v5 v5.0.12
go.uber.org/zap v1.27.0
)

require go.uber.org/multierr v1.10.0 // indirect
16 changes: 16 additions & 0 deletions services/match/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
14 changes: 14 additions & 0 deletions services/question/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.git
.gitignore
.vscode
.idea

bin
dist
*.out
*.test

.DS_Store

node_modules
venv
18 changes: 18 additions & 0 deletions services/question/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM golang:1.22 AS build
WORKDIR /app

COPY go.mod ./
RUN go mod download

COPY . .
RUN go mod tidy

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /out/app ./cmd/server

FROM gcr.io/distroless/base-debian12
WORKDIR /
COPY --from=build /out/app /app
USER 65532:65532
ENV PORT=8080
EXPOSE 8080
ENTRYPOINT ["/app"]
Loading