Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
fa0ffe1
fix(admin): Svelte 5 hydration + reactivity guards on 8 pages
jeremie0342 Jul 27, 2026
a1e4155
test(e2e): Playwright admin flows — Phase 1 nav-smoke + Phase 2 criti…
jeremie0342 Jul 27, 2026
3bf6586
chore(qa): bug/todo tracking + Trello sync pipeline
jeremie0342 Jul 27, 2026
60bf110
ci: add e2e-admin job pulling backend image from GHCR
jeremie0342 Jul 27, 2026
6a3181f
chore(security): bump transitive `cookie` 0.6 → 0.7.2 via override
jeremie0342 Jul 27, 2026
8b891e9
refactor(i18n): extract intlLocale helper, remove 15+ duplicate impls
jeremie0342 Jul 27, 2026
c1e8e55
test(ui): unit specs for Input, Modal, Select (20 tests)
jeremie0342 Jul 27, 2026
f5b477d
refactor(i18n): migrate all remaining inline i18n.locale strings to i…
jeremie0342 Jul 28, 2026
2cd812b
feat(defensive): global "backend unreachable" banner with auto-retry
jeremie0342 Jul 28, 2026
ce342de
refactor(e2e): route 9 admin specs through the shared e2e/setup/db he…
jeremie0342 Jul 28, 2026
57b038c
refactor(sponsored): extract decide modal into a dedicated component
jeremie0342 Jul 28, 2026
f4106a5
refactor(admin): extract 3 remaining form modals (skills, challenges,…
jeremie0342 Jul 28, 2026
12a1164
feat(admin): UI for Challenge AI variant + Fraud deep-scan endpoints
jeremie0342 Jul 28, 2026
966fb4c
fix(auth-client): align 4 auth methods to backend BE-P0-01..04 contra…
jeremie0342 Jul 28, 2026
d61ca18
chore(env): default vite proxy to production backend at api.skill-uv.com
jeremie0342 Jul 29, 2026
feceba2
chore(qa): restore original card titles so Trello sync updates in place
jeremie0342 Jul 29, 2026
b0514d8
feat(admin): consume new user-detail 2FA/passkey fields (backend comm…
jeremie0342 Jul 29, 2026
3444e1c
test(admin): flip regression guards + add community approve 400 spec
jeremie0342 Jul 29, 2026
ad830c8
chore(qa): mark 8 backend bugs as fixed with commit refs, sync Trello
jeremie0342 Jul 29, 2026
f96a28c
docs(qa): passer le tracker sur Linear + assouplir le global-setup e2e
jeremie0342 Aug 10, 2026
b16c79e
feat(admin): P26 v2 — workflow challenge complet (SKI-98, SKI-99, SKI…
jeremie0342 Aug 10, 2026
261f8c9
feat(admin): tracer les décisions validateur (SKI-99, critère traçabi…
jeremie0342 Aug 10, 2026
3d4d3d8
feat(admin): bouton de forçage d'ingestion sur la fiche projet (SKI-9…
jeremie0342 Aug 10, 2026
6c327a7
test(e2e): couvrir le workflow challenge P26 v2 (SKI-98, SKI-99, SKI-…
jeremie0342 Aug 10, 2026
3079f48
test(e2e): ajouter un préflight qui refuse un vert trompeur
jeremie0342 Aug 10, 2026
c0da61a
fix(admin): corriger ce que le premier run E2E réel a révélé
jeremie0342 Aug 11, 2026
92589a4
test(e2e): purger les fixtures en teardown, pas seulement en fin de test
jeremie0342 Aug 11, 2026
d8c8fcb
test(e2e): distinguer « tunnel fermé » de « hôte introuvable » au pré…
jeremie0342 Aug 11, 2026
7ba72bf
fix(admin): SKI-109 est livré — resserrer la fiche projet, signaler c…
jeremie0342 Aug 11, 2026
074e996
feat(admin): page /slices — retrouver une slice quel que soit son sta…
jeremie0342 Aug 11, 2026
9905173
fix(admin): trois pages de liste étaient cassées, et 10 specs réparée…
jeremie0342 Aug 11, 2026
8481eb7
fix(admin): 18 specs rouges — dont 5 pages de liste réellement cassée…
jeremie0342 Aug 11, 2026
54fe0e6
fix(admin): borner les requêtes de l'agrégat analytics, stabiliser gd…
jeremie0342 Aug 11, 2026
792f3b3
test(e2e): tunnel auto-réparant + teardown qui ne laisse plus de débris
jeremie0342 Aug 11, 2026
be951bd
feat(admin): remonter le compte d'erreurs et le cas « aucun label » d…
jeremie0342 Aug 11, 2026
8e8864c
fix(e2e): déplacer le tunnel sur 5434 et ne plus orphelin d'ssh
jeremie0342 Aug 11, 2026
3bd8c5c
fix(e2e): rendre l'arrêt du tunnel fiable sous Git Bash
jeremie0342 Aug 11, 2026
a40dd3a
feat(admin): permettre de débrancher un repo GitHub d'un projet
jeremie0342 Aug 12, 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
42 changes: 29 additions & 13 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
# Skilluv Admin — environment variables
# Copy to `.env` and adjust for local dev. Do NOT commit `.env`.
# Copy to `.env` (gitignored) and adjust for your setup.

# Internal URL of the Skilluv backend (server-side only, used by
# hooks.server.ts for SSR calls). The browser side goes through the
# `/api` proxy declared in vite.config.ts, so this value only matters
# when running under `node build` (production adapter-node output).
API_URL=http://localhost:3001/api
# ─── SSR + dev proxy ─────────────────────────────────────────────────
# Internal URL of the Skilluv backend used server-side by hooks.server.ts
# for the /auth/me call. Always ends in /api.
# Deployed backend (default recommendation):
API_URL=https://api.skill-uv.com/api
# Local Rust backend (docker stack + cargo run):
# API_URL=http://localhost:3001/api

# --- Playwright e2e (optional) ---
# Postgres URL used by `e2e/admin-back-e2e.spec.ts` to seed a test
# admin directly in DB. Leave empty to skip the e2e suite.
# SKILLUV_PG_URL=postgres://skilluv:skilluv_secret@localhost:5433/skilluv
# Where the vite dev server proxies /api/*. Must be the same host as
# API_URL minus the /api suffix.
VITE_API_PROXY_TARGET=https://api.skill-uv.com
# VITE_API_PROXY_TARGET=http://localhost:3001

# Backend URL used by the same e2e suite for the pre-flight health
# check. Skipped if unreachable.
# SKILLUV_BACKEND=http://localhost:3001
# ─── Analytics validation (P26 v2, SKI-100 section 5) ────────────────
# Dashboard Grafana qui trace les compteurs Prometheus du workflow
# challenge (ingestion, refresh externe, webhook CI, bonus merge). La page
# /validation-analytics affiche un lien vers cette URL quand elle est
# renseignée, et un rappel de configuration sinon.
# PUBLIC_GRAFANA_URL=https://grafana.skill-uv.com/d/skilluv-challenges

# ─── Playwright E2E ──────────────────────────────────────────────────
# When set, e2e/setup/bootstrap-admin.mjs and the admin-project specs
# talk to this backend + Postgres directly. Leave empty to run only the
# `public` Playwright project (no backend needed).
BACKEND_URL=https://api.skill-uv.com
# DATABASE_URL is required by the `admin` project: bootstrap-admin.mjs
# grants the admin role in SQL, and 14 of 17 admin specs seed fixtures via
# e2e/setup/db.ts. Point it at the Postgres backing whichever BACKEND_URL
# you chose — the local docker stack exposes it on 5433.
# DATABASE_URL=postgres://skilluv:CHANGE_ME@localhost:5433/skilluv
159 changes: 155 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
run: npm run build

e2e:
name: Playwright smoke tests
name: Playwright public smoke
runs-on: ubuntu-latest
needs: check
timeout-minutes: 15
Expand All @@ -54,13 +54,164 @@ jobs:
- name: Build
run: npm run build

- name: Run smoke tests
run: npm run test:e2e
- name: Run public smoke tests
run: npx playwright test --project=public

- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@v7
with:
name: playwright-report
name: playwright-public-report
path: playwright-report/
retention-days: 7

e2e-admin:
# Runs the authenticated `admin` Playwright project against a real backend
# pulled from GHCR. Requires the backend team's publish workflow to be
# merged first (see skilluv-backend PR #33). This job will stay red on
# PRs until that image is published — that's intentional; we don't skip
# tests when a dependency isn't ready, we surface the gap.
name: Playwright admin flows (needs backend image)
runs-on: ubuntu-latest
needs: check
timeout-minutes: 20

services:
postgres:
image: postgres:18.4-alpine
env:
POSTGRES_USER: skilluv
POSTGRES_PASSWORD: skilluv_secret
POSTGRES_DB: skilluv
# postgres 18+ warns when data lives at /var/lib/postgresql/data
# (the legacy mount path). Force a subdir to silence the check.
PGDATA: /var/lib/postgresql/data/pgdata
ports:
- 5433:5432
options: >-
--health-cmd "pg_isready -U skilluv"
--health-interval 5s
--health-timeout 5s
--health-retries 10

redis:
image: redis:8.8-alpine
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 5s
--health-timeout 5s
--health-retries 5

mailpit:
image: axllent/mailpit:latest
ports:
- 1025:1025
- 8025:8025
options: >-
--health-cmd "wget -q --spider http://localhost:8025 || exit 1"
--health-interval 5s
--health-timeout 5s
--health-retries 10

steps:
- uses: actions/checkout@v7

# MinIO can't be a GHA service (the image needs a `server /data` arg;
# services don't support commands). Docker-run it on host network so
# the backend (also host-net) reaches it via localhost:9000.
- name: Start MinIO
run: |
docker run -d --name minio --network host \
-e MINIO_ROOT_USER=skilluv \
-e MINIO_ROOT_PASSWORD=skilluv_secret \
minio/minio:RELEASE.2025-09-07T16-13-09Z \
server /data
for i in $(seq 1 30); do
curl -fsS http://localhost:9000/minio/health/live > /dev/null 2>&1 && \
echo "minio ready after ${i}s" && exit 0
sleep 1
done
docker logs minio
exit 1

- name: Start backend from GHCR image
env:
# `:master` is republished on every green master merge — see
# skilluv-backend/.github/workflows/ci.yml `publish` job.
BACKEND_IMAGE: ghcr.io/skilluv/skilluv-backend:master
run: |
docker pull "$BACKEND_IMAGE"
# Host network — backend reaches postgres/redis/mailpit/minio via
# the ports GHA services (and MinIO above) already bound to the
# runner. Admin origin allowlist added so the API accepts
# requests from the test's Origin: http://localhost:5174.
docker run -d --name backend --network host \
-e HOST=0.0.0.0 \
-e PORT=3001 \
-e ENVIRONMENT=dev \
-e DATABASE_URL=postgres://skilluv:skilluv_secret@localhost:5433/skilluv \
-e REDIS_URL=redis://localhost:6379 \
-e JWT_SECRET=ci-test-secret-please-rotate \
-e BASE_URL=http://localhost:3001 \
-e MINIO_ENDPOINT=http://localhost:9000 \
-e MINIO_ACCESS_KEY=skilluv \
-e MINIO_SECRET_KEY=skilluv_secret \
-e MINIO_BUCKET=avatars \
-e SMTP_HOST=localhost \
-e SMTP_PORT=1025 \
-e SMTP_TLS=none \
-e EMAIL_FROM=noreply@skilluv.test \
-e ADMIN_ORIGINS=http://localhost:5174 \
-e RUST_LOG=skilluv_backend=info,tower_http=info \
"$BACKEND_IMAGE"

- name: Wait for backend to be healthy
run: |
for i in $(seq 1 60); do
if curl -fsS http://localhost:3001/api/health > /dev/null 2>&1; then
echo "backend ready after ${i}s"
exit 0
fi
sleep 2
done
echo "backend never became healthy — dumping logs:"
docker logs backend
exit 1

- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: '24'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Install Playwright browsers
run: npx playwright install --with-deps chromium

- name: Bootstrap admin user (register + elevate + enable 2FA)
env:
BACKEND_URL: http://localhost:3001
DATABASE_URL: postgres://skilluv:skilluv_secret@localhost:5433/skilluv
run: node e2e/setup/bootstrap-admin.mjs

- name: Run admin Playwright project
env:
BACKEND_URL: http://localhost:3001
DATABASE_URL: postgres://skilluv:skilluv_secret@localhost:5433/skilluv
run: npx playwright test --project=admin

- name: Dump backend logs on failure
if: failure()
run: docker logs backend

- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v7
with:
name: playwright-admin-report
path: playwright-report/
retention-days: 7
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ playwright-report
test-results
.playwright

# E2E admin bootstrap artifacts (contain test creds + session state)
e2e/setup/admin-credentials.json
e2e/setup/admin-storage-state.json
e2e/setup/*.png

# Trello sync creds (see qa/.trello.env.example)
qa/.trello.env

# AI coding assistant caches
.claude/
.claude.*
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@

## What is Skilluv?

Skilluv is a community platform training the African OSS generation through real contributions to real open source projects. Every completed challenge produces a verifiable artifact — a merged pull request, a delivered Figma component, a submitted CVE report, a playable game build — exportable to recruiters.
Skilluv is a platform where talents in code, design, security, game
development, product, and other tech crafts grow their skills by
contributing to **real open source projects**. Every completed challenge
produces a verifiable artifact — a merged pull request, a delivered
Figma component, a submitted CVE report, a playable game build —
exportable to recruiters.

Full product vision in the [backend repository](https://github.com/skilluv/skilluv-backend).
**African-born, globally open.** Contributors and hiring companies come
from anywhere. Full product vision in the
[org profile](https://github.com/skilluv).

## What this repo contains

Expand Down Expand Up @@ -133,4 +140,4 @@ Distributed under the [GNU Affero General Public License v3.0](LICENSE) (AGPL-3.

## Origin

Skilluv is built solo by [Jeremie Zitti](https://github.com/skilluv), a Beninese engineer. Public launch: **January 2027**.
Skilluv is built solo by [Jeremie Zitti](https://github.com/skilluv), an engineer based in Benin. Public launch: **January 2027**.
Loading
Loading