Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
07337de
WIP
AntoninMignotPilon Jun 21, 2026
39d9d06
fix(backend): rename RequestContextFilter to avoid Spring Boot bean c…
lmrt0572 Jun 21, 2026
a48102f
feat(groups): add createGroup, updateGroup, createInvitation server a…
lmrt0572 Jun 21, 2026
57934aa
feat(groups): add i18n translations for group management pages (fr + en)
lmrt0572 Jun 21, 2026
f4e792b
feat(groups): add GroupsGrid, CreateGroupModal, CreateGroupTrigger, I…
lmrt0572 Jun 21, 2026
76ab61c
feat(groups): add groups list page and group hub page
lmrt0572 Jun 21, 2026
bcbf68a
feat(groups): add Groups nav link for TEACHER+ in top-nav
lmrt0572 Jun 21, 2026
1ba4bf6
fix(groups): extract GroupCard, fix delete error handling and per-car…
lmrt0572 Jun 21, 2026
40894fa
fix(groups): optimistic invitation list update, fix stale form ref, g…
lmrt0572 Jun 21, 2026
358d95a
fix(groups): i18n modal title, add deleteBtn translation key
lmrt0572 Jun 21, 2026
fd8728f
fix(groups): consistent breadcrumb navigation across groups pages
lmrt0572 Jun 21, 2026
455d7da
refactor(groups): redesign group card with avatar, icon nav rows and …
lmrt0572 Jun 21, 2026
235a198
feat(deploy): add VPS installer, Caddy reverse proxy and prod overlay
RayaneHassani Jun 22, 2026
84285a0
fix(install): prevent early exit on first prompt under set -e
RayaneHassani Jun 23, 2026
2b88493
feat(deploy): add update.sh with DB backup and auto-rollback
RayaneHassani Jun 23, 2026
eb49177
feat(backend): expose Prometheus metrics and structured JSON logs
RayaneHassani Jun 23, 2026
25157b4
ci: add fast checks workflow with governance guards
RayaneHassani Jun 23, 2026
6bc3719
ci: add heavy security workflow (main + nightly)
RayaneHassani Jun 23, 2026
4481ae1
ci: add guarded SSH deploy, dependabot, GitLab mirror and badges
RayaneHassani Jun 23, 2026
2d52984
merge: integrate dev (settings service); drop obsolete instance.json
RayaneHassani Jun 23, 2026
ffe18b1
ci: fix backend DB service, gitleaks, lint and i18n parity
RayaneHassani Jun 23, 2026
46d30e4
ci: notify Discord with the CI pipeline result
RayaneHassani Jun 24, 2026
a91de9e
feat(monitoring): add optional observability overlay
RayaneHassani Jul 3, 2026
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
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,11 @@ AI_CONNECT_TIMEOUT_SECONDS=5
AI_TIMEOUT_SECONDS=90
AI_RATE_LIMIT_CAPACITY=5
AI_RATE_LIMIT_REFILL_PER_MINUTE=2

# Monitoring stack (docker-compose.monitoring.yml — optional overlay).
# Grafana is never public: reach it via SSH tunnel only:
# ssh -L 3000:localhost:3001 user@vps # then http://localhost:3000
# Generate a strong password once on the host:
# echo "GRAFANA_ADMIN_PASSWORD=$(openssl rand -base64 24)" >> .env
GRAFANA_ADMIN_USER=admin
GRAFANA_ADMIN_PASSWORD=change_me_strong_password
10 changes: 10 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Force LF line endings for files that run on the Linux VPS, so they
# work regardless of the contributor's OS / git autocrlf setting.
# (CRLF in a shell script breaks the shebang: "bad interpreter ^M".)
*.sh text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
Caddyfile text eol=lf
Makefile text eol=lf
Dockerfile text eol=lf
mvnw text eol=lf
49 changes: 49 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
version: 2

updates:
# ── Backend (Maven) ──────────────────────────────────────
- package-ecosystem: maven
directory: /apps/backend
schedule:
interval: weekly
open-pull-requests-limit: 5
labels: [dependencies, backend]
groups:
backend-minor-patch:
update-types: [minor, patch]

# ── Frontend (npm/pnpm) ──────────────────────────────────
- package-ecosystem: npm
directory: /apps/frontend
schedule:
interval: weekly
open-pull-requests-limit: 5
labels: [dependencies, frontend]
groups:
frontend-minor-patch:
update-types: [minor, patch]
ignore:
# Next.js is an internal fork — never auto-bump (see apps/frontend/AGENTS.md)
- dependency-name: next

# ── Docker base images ───────────────────────────────────
- package-ecosystem: docker
directory: /apps/backend
schedule:
interval: weekly
labels: [dependencies, docker]
- package-ecosystem: docker
directory: /apps/frontend
schedule:
interval: weekly
labels: [dependencies, docker]

# ── GitHub Actions ───────────────────────────────────────
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
labels: [dependencies, github-actions]
groups:
actions:
update-types: [minor, patch]
96 changes: 0 additions & 96 deletions .github/workflows/build-services.yml

This file was deleted.

217 changes: 217 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
name: CI

# Fast feedback on every push / PR to dev and main.
# Heavy security scanning lives in security.yml (main + nightly).
on:
push:
branches: [dev, main]
pull_request:
branches: [dev, main]

# Cancel superseded runs on the same ref.
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
changes:
name: Detect changed paths
runs-on: ubuntu-latest
outputs:
frontend: ${{ steps.filter.outputs.frontend }}
backend: ${{ steps.filter.outputs.backend }}
migrations: ${{ steps.filter.outputs.migrations }}
i18n: ${{ steps.filter.outputs.i18n }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3
id: filter
with:
filters: |
frontend:
- 'apps/frontend/**'
backend:
- 'apps/backend/**'
migrations:
- 'apps/backend/src/main/resources/db/migration/**'
i18n:
- 'apps/frontend/messages/**'

frontend:
name: Frontend — lint, typecheck, build
needs: changes
if: needs.changes.outputs.frontend == 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: apps/frontend
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
with:
version: '9.15.0'
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: '20'
cache: pnpm
cache-dependency-path: apps/frontend/pnpm-lock.yaml
- name: Install
run: pnpm install --frozen-lockfile
- name: Lint
run: pnpm lint
- name: Type-check
run: pnpm typecheck
- name: Build
run: pnpm build

backend:
name: Backend — compile, test, coverage
needs: changes
if: needs.changes.outputs.backend == 'true'
runs-on: ubuntu-latest
timeout-minutes: 20
defaults:
run:
working-directory: apps/backend
# Ephemeral Postgres for @SpringBootTest (context load runs Flyway against it).
# Created before the steps, reachable at localhost:5432, destroyed with the runner.
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: codestar
POSTGRES_PASSWORD: codestar
POSTGRES_DB: codestardb
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U codestar -d codestardb"
--health-interval 10s --health-timeout 5s --health-retries 5
env:
DB_URL: jdbc:postgresql://localhost:5432/codestardb
DB_USER: codestar
DB_PASSWORD: codestar
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
with:
java-version: '17'
distribution: temurin
cache: maven
- name: Make mvnw executable
run: chmod +x ./mvnw
- name: Compile
run: ./mvnw compile -B --no-transfer-progress
- name: Test + coverage
run: ./mvnw verify -B --no-transfer-progress
- name: Upload coverage report
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: jacoco-coverage
path: apps/backend/target/site/jacoco/
retention-days: 7
if-no-files-found: warn
compression-level: 6

governance:
name: Codestar governance (migrations, i18n)
needs: changes
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0 # full history so guards can diff against the base branch
- name: Flyway migration governance
if: needs.changes.outputs.migrations == 'true'
env:
BASE_REF: origin/${{ github.base_ref || 'main' }}
run: bash scripts/ci/flyway-governance.sh
- name: i18n key parity
if: needs.changes.outputs.i18n == 'true'
run: bash scripts/ci/i18n-parity.sh

secrets:
name: Secret scan (gitleaks)
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
# Run the gitleaks binary directly: the GitHub Action requires a paid
# license for organisation repos, the open-source binary does not.
- name: Run gitleaks
env:
GITLEAKS_VERSION: 8.21.2
run: |
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
| tar -xz gitleaks
./gitleaks detect --source . --redact --verbose --exit-code 1

dependency-review:
name: Dependency review
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/dependency-review-action@e58c696e52cac8e62d61cc21fda89565d71505d7 # v4.3.0
with:
fail-on-severity: high
comment-summary-in-pr: on-failure

docker:
name: Docker — compose build
needs: [frontend, backend]
if: |
always() &&
!contains(needs.*.result, 'failure') &&
!contains(needs.*.result, 'cancelled') &&
(needs.frontend.result == 'success' || needs.backend.result == 'success')
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Create env file
run: cp .env.example .env
- name: Build images
run: docker compose build

# Single required status check for branch protection.
ci-required:
name: CI required
needs: [frontend, backend, governance, secrets, docker]
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify no required job failed
run: |
results='${{ join(needs.*.result, ',') }}'
echo "Upstream results: $results"
case "$results" in
*failure*|*cancelled*) echo "A required job failed."; exit 1 ;;
*) echo "All required jobs passed (or were skipped)." ;;
esac

# Discord notification. No-ops when DISCORD_WEBHOOK_URL is unset (fork-safe).
notify:
name: Discord notification
needs: [frontend, backend, governance, secrets, docker]
if: always()
runs-on: ubuntu-latest
steps:
- uses: sarisia/actions-status-discord@eb045afee445dc055c18d3d90bd0f244fd062708 # v1
with:
webhook: ${{ secrets.DISCORD_WEBHOOK_URL }}
status: ${{ (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) && 'failure' || 'success' }}
title: "CI pipeline"
username: Codestar CI
Loading
Loading