91 lines
6.0 KiB
Markdown
91 lines
6.0 KiB
Markdown
<!-- retoor <retoor@molodetz.nl> -->
|
|
# Molodetz
|
|
|
|
Blog roll of the Molodetz community. Quiet, serif, slightly provocative. Posts are markdown in SQLite, written by retoor through an admin area. Flyers and memes are galleries. Join is a real sign-up form ("I'm in"). The whole site is in English; the old Dutch paths (`/rol`, `/standaard`, `/mensen`, `/binnen`, `/voorwaarden`) redirect with 301.
|
|
|
|
Built to the frozen DPP template (`/workspace/dpp/dptemplate.md`). See `SELECTION.md` for the module choice and `COMPLIANCE.md` for the review.
|
|
|
|
## Running
|
|
|
|
```
|
|
make install # venv in .venv, pip install -e ".[dev]", Chromium, git hooks
|
|
cp .env.example .env # only when there is no .env yet; chmod 600 .env
|
|
make dev # http://127.0.0.1:8088, reload
|
|
make prod # workers, pinned static version
|
|
```
|
|
|
|
`make install` needs a `python3` with the `venv` module (Debian/Ubuntu ship it as `python3-venv`).
|
|
|
|
Without make:
|
|
|
|
```
|
|
.venv/bin/python -m uvicorn molodetz.main:app --host 127.0.0.1 --port 8088
|
|
```
|
|
|
|
The first start creates the administrator from `MOLODETZ_ADMIN_USERNAME` / `MOLODETZ_ADMIN_EMAIL` / `MOLODETZ_ADMIN_PASSWORD` in `.env`, seeds the placeholder posts once and syncs the gallery. A one-time migration (`system.migrate.english`) translates content seeded by older Dutch versions. Log in at `/auth/login`, admin at `/admin`.
|
|
|
|
## Testing
|
|
|
|
```
|
|
make test # unit + api + e2e (Playwright, headless)
|
|
make test-headed # visible with slow motion
|
|
make check-ui # six static gates + em-dash + json_error order
|
|
make preflight # import, pyflakes, JS syntax, sqlglot lint, check-ui
|
|
make coverage
|
|
make locust-headless
|
|
```
|
|
|
|
Tests boot their own server on port 8099; set `MOLODETZ_TEST_PORT` to a free port when 8099 is taken. Browser tests wait up to 60 seconds per step and retry a stalled page load once via `goto_ready` in `tests/conftest.py`.
|
|
|
|
## Docker
|
|
|
|
```
|
|
docker compose up -d --build # staging dev server on http://127.0.0.1:19847, reload on change
|
|
docker compose -f docker-compose.test.yml up -d # public test server on http://127.0.0.1:19849
|
|
PROD_SECRET_KEY=... PROD_ADMIN_PASSWORD=... docker compose -f docker-compose.prod.yml up -d --build # production on :19848
|
|
docker compose logs -f # follow logs
|
|
docker compose down # stop
|
|
```
|
|
|
|
Each compose file is its own project (`molodetz-dev`, `molodetz-test`, `molodetz-prod`) with its own `./data/<env>` file mount, so the three never interfere. Production secrets come only from `PROD_SECRET_KEY` / `PROD_ADMIN_PASSWORD` and refuse to boot without them; `staging.app.molodetz.nl`, `molodetz-test.app.molodetz.nl`, and `molodetz.nl` proxy to `:19847`, `:19849`, and `:19848` (see `molohttp_deploy.md`).
|
|
|
|
The container runs the dev server (`uvicorn --reload`) with `./molodetz` mounted, so every saved change is live within seconds. Data lives in the file mount `./data/staging` (plain files, no named volumes anywhere). The admin account comes from `MOLODETZ_ADMIN_USERNAME` / `MOLODETZ_ADMIN_EMAIL` / `MOLODETZ_ADMIN_PASSWORD` (default password `staging-admin-pass-1`, override per shell); an empty password skips admin bootstrap. The compose port is fixed at `127.0.0.1:19847` and is what `staging.app.molodetz.nl` proxies to, so keep it stable.
|
|
|
|
```
|
|
make staging-refresh # copy the holy prod database over staging, then verify
|
|
```
|
|
|
|
Refresh snapshots `./data/production` (online backup API, production keeps running), integrity-checks the copy, stops staging, swaps the staging file mount content, restarts, and verifies health. After a refresh the staging admin password is the production one, so pass it to `make screenshots-staging STAGING_ADMIN_PASSWORD=...`.
|
|
|
|
## Screenshots
|
|
|
|
```
|
|
make screenshots # test gallery into ../static/pizdetz/test
|
|
make screenshots-staging # staging gallery into ../static/pizdetz/staging
|
|
make screenshots-production SCREENSHOTS_ADMIN_PASSWORD=... # production gallery into ../static/pizdetz/production
|
|
```
|
|
|
|
Each run captures 32 full-page desktop shots (public, docs, admin) plus a 25-cell responsive matrix (home, roll, flyers, join, docs at 1440x900, 768x1024, 390x844, 360x740, 320x568) with a horizontal-overflow check per cell, then rebuilds the hub page at `../static/pizdetz/index.html` from whichever environments exist on disk.
|
|
|
|
Rules, exactly: `test` always wipes `./data/test`, boots its own server there, and seeds one join request; `staging` and `production` shoot a live base URL and never seed. Staging logs in with `STAGING_ADMIN_PASSWORD` (default `staging-admin-pass-1`, must match the compose admin password); production has no default and fails loudly without `SCREENSHOTS_ADMIN_PASSWORD`. Any overflow is reported and exits nonzero. Override the output root with `SCREENSHOTS_DIR=...`.
|
|
|
|
## CLI
|
|
|
|
`molodetz --help`: roles, API keys, posts list/import (.md and .pdf via pypdf), join requests, backups, prunes, sql-lint, emoji regenerate.
|
|
|
|
## Data
|
|
|
|
All application data lives under `./data/<env>`, enforced in code: `molodetz/config.py` refuses to start with a `MOLODETZ_DATA_DIR` outside `./data` or a sqlite file outside the data dir.
|
|
|
|
- `development` - local `make dev` runs (see `.env`)
|
|
- `staging` - docker dev server on `:19847` (file mount)
|
|
- `production` - holy production database (file mount, docker prod on `:19848`)
|
|
- `test` - screenshot runs, wiped at the start of every run
|
|
- `.tmp-pytest-<pid>`, `.tmp-locust` - single test runs, removed afterwards
|
|
|
|
Each env dir holds `molodetz.db` (plus WAL files while running) and one subdirectory per kind: `uploads` (blobs, attachments), `backups`, `keys`, `locks`, `seo_reports`. The whole tree is git-ignored. Nothing else on the system holds application data; `molodetz/static/js/generated/EmojiMap.js` is a vendored build artifact the app only rewrites if missing.
|
|
|
|
## Operations
|
|
|
|
Production serving runs through molohttp on this box. `molohttp_deploy.md` is the operator guide: access, file owners, the backup specification, site changes, and static publishing.
|