Commit Graph

14 Commits

Author SHA1 Message Date
f413ee8e4c Merge pull request 'Show the question bank as a table with a stable, right-aligned actions column' (#2) from feature/question-bank-table into master
All checks were successful
CI/CD / build-test-deploy (push) Successful in 24s
Reviewed-on: #2
2026-08-09 16:48:18 +00:00
danamir
24cce8ea71 Show the question bank as a table with a stable, right-aligned actions column
All checks were successful
CI/CD / build-test-deploy (pull_request) Successful in 1m39s
The old list showed type, text, and points inline via flexbox, with no
correct-answer info at all, and unstyled buttons that shifted position
depending on question text length. A table with a shrink-to-fit
actions column (text/kind/answer/points first, buttons last) fixes
both: correct answers are now visible, and button position no longer
depends on text length.
2026-08-09 19:03:40 +03:00
danamir
b7177c455e Fix CI/CD deploy targeting the wrong compose project
All checks were successful
CI/CD / build-test-deploy (push) Successful in 29s
COMPOSE_PROJECT_NAME was "ruvdstests" but the live stack was actually
deployed under "ruvdstest" (no trailing s) — Compose treated it as an
unrelated project and spun up a whole second stack from scratch,
colliding with the real one's host port and aborting mid-deploy
instead of updating the running containers in place.
2026-08-09 01:29:10 +03:00
38ef683b69 Merge pull request 'feature/teacher-quiz-form' (#1) from feature/teacher-quiz-form into master
Some checks failed
CI/CD / build-test-deploy (push) Failing after 31s
Reviewed-on: #1
2026-08-08 22:15:02 +00:00
danamir
8c46ef1972 Wire JWT_SECRET/POSTGRES_PASSWORD through Gitea Actions secrets
All checks were successful
CI/CD / build-test-deploy (pull_request) Successful in 4m43s
The job checks out into the runner's own workspace, not
/opt/ruvdstests where DEPLOY.md has the human create a .env file — so
docker compose here had no .env to read JWT_SECRET from and failed
outright. POSTGRES_PASSWORD would have silently fallen back to the
compose file's devpassword default instead of erroring, which on
Deploy would have broken auth against the already-initialized pgdata
volume.
2026-08-09 01:04:13 +03:00
danamir
0a1407719e Install Node.js before Checkout in the CI/CD workflow
Some checks failed
CI/CD / build-test-deploy (pull_request) Failing after 53s
Host-mode jobs execute directly on the bare runner container rather
than a per-job container, and actions/checkout is a JS action — it
needs `node` on PATH to run at all, which the runner image doesn't
ship. Failed every run with "Cannot find: node in PATH" before any
other step got a chance to install anything.
2026-08-09 01:00:12 +03:00
danamir
ef119dc0dc Show one question per card in the take-quiz screen, with prev/next arrows
Some checks failed
CI/CD / build-test-deploy (pull_request) Failing after 2s
Replaces the single long scrollable list of every question with one
card at a time plus arrow navigation, so a student's focus stays on
the current question instead of the whole quiz at once.
2026-08-09 00:55:01 +03:00
danamir
63bdd7dd74 Allow the quiz-builder picker to expand multiple topics at once
Sources could already draw from any number of topics, but the picker
UI only ever showed one topic's questions at a time, forcing a teacher
to lose their place switching between topics while assembling a quiz.
2026-08-09 00:54:45 +03:00
danamir
b5921292db Trim DEPLOY.md: reverse proxy is managed separately, out of scope here
Some checks failed
CI/CD / build-test-deploy (push) Has been cancelled
2026-08-06 14:46:58 +03:00
danamir
154411e7a4 Fix nginx crash-loop on a fully fresh docker compose up
Some checks failed
CI/CD / build-test-deploy (push) Has been cancelled
nginx resolves a plain `proxy_pass http://server:8080;` hostname once at
config-load time. On a cold `docker compose up` that creates every
container at once, the `server` container isn't always registered in
Docker's embedded DNS yet by the time the client's nginx starts — nginx
then fails immediately ("host not found in upstream") and doesn't retry,
so it just crash-loops.

Route the target through a variable instead (`set $upstream_server ...;
proxy_pass $upstream_server;`) with an explicit `resolver`, which makes
nginx resolve the hostname lazily per-request via Docker's DNS rather than
once at startup. Also add `depends_on: [server]` on the client service so
it at least doesn't start before the server container exists at all.

Verified with repeated `docker compose down && docker compose up` cycles
locally — this only reliably reproduced starting every container from
nothing simultaneously, which prior local testing hadn't actually done
(the server container had usually stayed running across rebuilds).
2026-08-06 14:44:52 +03:00
danamir
773dbb493e Add production deployment guide and harden compose for it
Some checks failed
CI/CD / build-test-deploy (push) Has been cancelled
- docker-compose.yml: bind client/server ports to 127.0.0.1 only — the
  client container is the sole intended public entry point (it proxies
  /api/* to the server itself), a host-level nginx sits in front of it in
  production. Client__Origin now configurable via CLIENT_ORIGIN env var.
- docs/DEPLOY.md: step-by-step for a fresh Linux target (Docker install,
  clone, .env secrets, nginx + certbot).
- docs/CI-CD.md: runner registration for that same target machine, in
  "host" mode so the deploy step's `docker compose up -d` acts on the
  actual running stack.
2026-08-06 14:18:22 +03:00
danamir
dfbc43a43e Make client API calls relative instead of hardcoded localhost:5144
Some checks failed
CI/CD / build-test-deploy (push) Has been cancelled
The client always called a hardcoded http://localhost:5144, which only
worked when browser and server shared the same "localhost" — breaks for
any real remote deployment, since the browser would try to reach that
port on the visitor's own machine instead of the actual server.

Now every environment routes /api/* to the server under the same origin
the page was loaded from, so the client code needs no per-environment URL:
- Docker (client container's own nginx) proxies /api/ to the server
  container.
- `npm run dev` (Vite) proxies /api to localhost:5144 via server.proxy.
- Production nginx (reverse proxy + TLS) just needs to forward everything
  to the client container, which already knows how to route /api itself.

Also incidentally removes CORS from the picture everywhere, since none of
these setups make a cross-origin request anymore.
2026-08-06 14:15:15 +03:00
danamir
74497fa747 Add Gitea Actions CI/CD workflow
Some checks failed
CI/CD / build-test-deploy (push) Has been cancelled
On every push/PR: run Domain.Tests, then docker compose build to validate
the full stack still builds. On push to master: also docker compose up -d
to redeploy. COMPOSE_PROJECT_NAME is pinned to ruvdstests so a run from a
runner-managed checkout always targets the existing stack/volumes instead
of spinning up a duplicate under a different project name.
2026-08-06 13:57:57 +03:00
danamir
942dfc9c1a Initial commit: standalone quiz-testing system
Full-stack F# (Domain/Server/Client via Fable+Elmish+Feliz), PostgreSQL
persistence via Dapper, Docker Compose deployment. Student quiz-taking flow
with time-limit enforcement and focus-loss tracking, Teacher question bank
and quiz builder with results analytics, Admin user management.
2026-08-06 12:36:16 +03:00