Some checks failed
CI / lint-and-test (push) Failing after 23s
- Added *.egg-info/ to .gitignore to prevent egg metadata from being tracked. - Updated virtual environment instructions in CONTRIBUTING.md and README.md to use .venv for consistency. - Revised mkdocs.yml to include a placeholder for the repository URL when publishing. - Cleaned up pyproject.toml by removing unnecessary pylint configuration. - Enhanced import-format.md and runbook.md documentation for clarity on user roles and health check endpoints.
4.9 KiB
4.9 KiB
Runbook (operational guide)
This document covers running the application, checking health, logs, common errors, and database operations.
Starting and stopping
Local
- Start: From the repository root, with virtualenv activated:
Or after
python main.pypip install -e .:duty-teller - Stop:
Ctrl+C
Docker
-
Dev (code mounted; no rebuild needed for code changes):
docker compose -f docker-compose.dev.yml up --buildStop:
Ctrl+Cordocker compose -f docker-compose.dev.yml down. -
Prod (built image; restarts on failure):
docker compose -f docker-compose.prod.yml up -d --buildStop:
docker compose -f docker-compose.prod.yml down.
On container start, entrypoint.sh runs Alembic migrations then starts the app as user botuser. Ensure .env (or your orchestrator’s env) contains BOT_TOKEN and any required variables; see configuration.md.
Health check
- HTTP: The FastAPI app exposes
GET /health, which returns{"status": "ok"}with 200 when the app is up. Use it for readiness checks and in DockerHEALTHCHECK. - Alternatively, open the interactive API docs at
GET /docs(e.g.http://localhost:8080/docs) or call a lightweight API endpoint with valid auth.
Logs
- Local: Output goes to stdout/stderr; redirect or use your process manager’s logging (e.g. systemd, supervisord).
- Docker: Use
docker compose logs -f(with the appropriate compose file) to follow application logs. Adjust log level via Pythonloggingif needed (e.g. environment or code).
Common errors and what to check
"hash_mismatch" (403 from /api/duties or Miniapp)
- Cause: The server that serves the Mini App (e.g. production host) uses a different
BOT_TOKENthan the bot from which users open the Mini App (e.g. test vs production bot). Telegram signs initData with the bot token; if tokens differ, validation fails. - Check: Ensure the same
BOT_TOKENis set in.env(or equivalent) on the machine serving/api/dutiesas the one used by the bot instance whose menu button opens the Miniapp.
Miniapp "Open in browser" or direct link — access denied
- Cause: When users open the calendar via “Open in browser” or a direct URL, Telegram may not send
tgWebAppData(initData). The API requires initData (orMINI_APP_SKIP_AUTHin dev). - Action: Users should open the calendar via the bot’s menu button (e.g. ⋮ → "Calendar") or a Web App inline button so Telegram sends user data.
403 "Open from Telegram" / no initData
- Cause: Request to
/api/dutiesor/api/calendar-eventswithout validX-Telegram-Init-Dataheader. The API returns 403 without initData; the only bypass isMINI_APP_SKIP_AUTH=1(dev only, insecure). - Check: Ensure the Mini App is opened from Telegram (menu or inline button). For local dev without Telegram, use
MINI_APP_SKIP_AUTH=1in.env.
Mini App URL — redirect and broken auth
- Cause: If the Mini App URL is configured without a trailing slash (e.g.
https://your-domain.com/app) and the server redirects/app→/app/, the browser can drop the fragment Telegram sends, breaking authorization. - Action: Configure the bot’s menu button / Web App URL with a trailing slash, e.g.
https://your-domain.com/app/. See README “Mini App URL”.
User not in allowlist (403)
- Cause: Miniapp access is determined by roles in the database (see
can_access_miniapp_for_telegram_userin the repository). If the user has no role in the DB, the app falls back toADMIN_USERNAMESandADMIN_PHONES. A 403 means the user has neither a role granting access nor a match in the admin allowlist. - Check: Assign a role with
/set_role @username useroradmin(admin-only command), or add the user toADMIN_USERNAMES/ their phone toADMIN_PHONESin configuration.md. Ensure at least one admin exists via env so they can use/set_role.
Database and migrations
- Default DB path (SQLite):
data/duty_teller.db(relative to working directory when using defaultDATABASE_URL=sqlite:///data/duty_teller.db). In Docker, the entrypoint creates/app/dataand runs migrations there. - Migrations (Alembic): From the repository root:
Config:
alembic -c pyproject.toml upgrade headpyproject.toml→[tool.alembic]; script locationalembic/; metadata and URL fromduty_teller.configandduty_teller.db.models.Base. - Rollback: Use with care; test in a copy of the DB first. Example to go back one revision:
Always backup the database before downgrading.
alembic -c pyproject.toml downgrade -1
For full list of env vars (including DATABASE_URL), see configuration.md. For reverse proxy and Mini App URL details, see the main README.