gitea-actions 6443a93955
binárka / linux (pull_request) Successful in 10s
image / image (pull_request) Successful in 14s
testy / pytest (3.11) (pull_request) Successful in 2s
testy / pytest (3.12) (pull_request) Successful in 1s
testy / pytest (3.13) (pull_request) Successful in 0s
testy / pytest (3.14) (pull_request) Successful in 1s
Nenechat zkoušku binárky viset na zbytku z minulého běhu
Krok padl na `test -f /tmp/zkouska/dice-counter/dice.db`. Runner si /tmp
mezi běhy drží, takže tam po dřívějších stavbách zůstalo
/tmp/zkouska/kostky/dice.db — a binárka po něm nově sáhne, dokud nová
databáze neexistuje. Zkouška tedy hledala soubor, který se schválně
nezaložil.

Chová se to správně, jen se to nedá zkoušet na adresáři, do kterého si
sype každý běh. Nově dostane každý svůj vlastní přes mktemp a po sobě ho
uklidí.

Reprodukováno lokálně: se zbytkem po staru krok padne, s vlastním
adresářem projde.
2026-08-23 22:32:39 +02:00
2026-08-22 18:26:32 +02:00
2026-08-22 18:26:32 +02:00
2026-08-22 18:22:35 +02:00
2026-08-22 18:22:35 +02:00
2026-08-22 18:22:35 +02:00
2026-08-22 18:22:35 +02:00
2026-08-22 18:22:35 +02:00
2026-08-22 18:22:35 +02:00

Dice Counter

Doprovod k fyzickým kostkám: telefon zapisuje skóre, notebook ukazuje zápisník a hry se pamatují mezi večery.

Hráči se napříč hrami poznávají podle jména — Adam ze středečního večera je ten samý Adam jako z minulého měsíce. Žádné účty, žádná hesla.

Spuštění

Stáhni binárku pro svůj systém z releases:

Systém Soubor
Linux (x86-64) dice-counter-linux-x86_64
Linux (ARM64) dice-counter-linux-arm64
macOS (Apple Silicon) dice-counter-macos-arm64
macOS (Intel) dice-counter-macos-x86_64
Windows (x86-64) dice-counter-windows-x86_64.exe

Nic se neinstaluje — Python, Flask i šablony jsou uvnitř.

Na Linuxu a macOS:

chmod +x dice-counter-*
./dice-counter-linux-x86_64

Na Windows stačí na .exe poklepat.

Linuxová binárka je postavená proti glibc 2.17, takže jede prakticky všude.

Než to poprvé pustíš

Binárky nejsou podepsané — podpisové certifikáty stojí tisíce ročně a na počitadlo kostek by to byl nesmysl. Systémy si toho všimnou:

  • macOS stažený soubor označí za karanténní a odmítne ho spustit. Buď značku sundej (xattr -dr com.apple.quarantine dice-counter-macos-arm64), nebo soubor stáhni rovnou z terminálu přes curl -LO — tudy se karanténa nenastavuje.
  • Windows ukáže modré okno SmartScreenu. Další informace → Přesto spustit. Občas si postěžuje i antivirus; u zabalených Python programů je to běžný falešný poplach. Při prvním spuštění se ještě zeptá brána firewall — bez povolení do místní sítě se telefon nepřipojí.

Kdo tomu nechce věřit, ověří si stažený soubor podle přiloženého součtu (níž) nebo si ho postaví sám — ./build.sh, zdrojáky jsou tady celé.

Ze zdrojáků to je stejně krátké:

uv run web.py

Závislosti si skript nese v hlavičce (PEP 723) a uv je obstará sám.

Server vypíše všechny adresy, na kterých je dostupný:

dice-counter v1.2.2

Počitadlo je dostupné na:
 → http://10.186.234.182:8000     místní síť
   http://100.91.0.24:8000        přes Tailscale
   http://172.17.0.1:8000         virtuální síť

Kterou verzi máš, řekne i dice-counter --version; visí taky v patičce každé stránky. Když něco nefunguje, je to první věc, na kterou se zeptám.

Na notebooku otevři /board, naskenuj QR kód telefonem a hraj. Tabule nabízí i zbylé adresy — když jedna nefunguje, klikni na jinou a QR kód se přepne na ni. Zastavuje se Ctrl+C.

Proměnná K čemu je Výchozí
DICE_DB soubor s databází podle způsobu spuštění, viz níž
DICE_PORT port 8000
DICE_HOST pevná adresa; vypne hledání hledá se za běhu

Kde jsou data

Jeden soubor SQLite. Založí se sám při prvním načtení stránky, cestu k němu server vypíše při startu.

Spuštěno Databáze
binárkou na Linuxu ~/.local/share/dice-counter/dice.db
binárkou na macOS ~/Library/Application Support/dice-counter/dice.db
binárkou na Windows %LOCALAPPDATA%\dice-counter\dice.db
ze zdrojáků dice.db v pracovním adresáři

Do vydání 1.2.x se adresář jmenoval kostky. Kdo databázi po staru má, o ni nepřijde — dokud nová neexistuje, používá se dál ta stará. Přesunout se dá kdykoli ručně, přejmenováním adresáře.

Binárka se při každém spuštění rozbaluje do dočasného adresáře a pouští se odkudkoli, takže relativní cesta by databázi rozsypala po disku — proto napevno domovský adresář. Ze zdrojáků zůstává relativní, ať se dá mít víc sad vedle sebe.

Zálohovat i stěhovat jde prostým zkopírováním souboru; DICE_DB si ho najde kdekoli. Kdo ho hledat nechce — a z binárky na Windows je zalezlý — si ho stáhne ze síně slávy odkazem Stáhnout databázi (/export). Kopie se dělá přes VACUUM INTO, takže je použitelná i uprostřed rozehrané hry.

Schéma má verzi uloženou v PRAGMA user_version a storage.migrate() si databázi při každém připojení dorovná. Starší soubory z verzí, kdy se verze schématu ještě nepsala, se poznají podle nuly a orazítkují se. Databázi založenou novější verzí počitadla appka odmítne otevřít, místo aby ji tiše rozbila.

Obsluhuje to waitress — čistě pythonní WSGI server, který se zabalí do binárky stejně snadno jako zbytek. Vestavěný server Flasku by pod úvodní hlášku vysypal varování, že takhle se to nemá, a měl by pravdu.

Počítá se s domácí sítí — appka nemá přihlašování a kdokoli na stejné WiFi může zapisovat.

Nasazení na server

Kdo nechce každý večer spouštět binárku na notebooku, může to nechat běžet pořád. Obojí níž počítá jen s domácí sítí — appka nemá přihlašování a ani jedno nasazení ji nijak nezabezpečuje. Do internetu to nepatří.

Proxmox (LXC)

Jeden příkaz v terminálu uzlu Proxmoxu, jako root. Založí kontejner, nastaví ho, stáhne poslední vydanou binárku, ověří kontrolní součet a zapne službu:

bash -c "$(curl -fsSL https://gitea.spacilovi.eu/david-spacil/dice-counter/raw/branch/main/deploy/pve-dice-counter.sh)"

Na konci vypíše adresu, na které počitadlo poslouchá. Výchozí nastavení je 1 jádro, 512 MB, 4 GB disku a Debian 13; úložiště si najde samo. Přebíjí se proměnnými před příkazem:

MEMORY=1024 STORAGE=local-zfs PORT=8080 bash -c "$(curl -fsSL ...)"
Proměnná Výchozí
CTID první volné číslo
CT_HOSTNAME dice-counter
CORES, MEMORY, DISK 1, 512, 4
STORAGE první aktivní úložiště pro kontejnery
TEMPLATE_STORAGE, BRIDGE local, vmbr0
PORT 8000
UNPRIVILEGED, OSVERSION 1, 13
NESTING 1 — systemd v Debianu 13 ho potřebuje
AUTOLOGIN 1 — konzole ve webu Proxmoxu bez hesla
VERSION poslední vydání

Aktualizace na novější vydání se dá spustit dvěma způsoby. Buď zevnitř kontejneru, kde na to stačí jedno slovo:

update

Nebo z uzlu Proxmoxu tím samým příkazem s číslem kontejneru:

CTID=123 MODE=update bash -c "$(curl -fsSL ...)"

Obojí vymění binárku za poslední vydání a službu restartuje; databáze zůstává. Příkaz update si přitom obnoví i sám sebe — instalátor bere z větve main, takže jede na nejnovější verzi skriptu, ne na té, se kterou se instalovalo.

Kontejnery založené do vydání 1.2.x se při první aktualizaci přejmenují ze starého kostky: služba, uživatel i cesty dostanou nová jména a databáze se přestěhuje z /var/lib/kostky do /var/lib/dice-counter. Dělá se to samo a stačí na to obyčejný update; historie her zůstává. Původní adresa skriptu (deploy/pve-kostky.sh) proto ještě chvíli funguje — jen přesměrovává na novou.

Do konzole kontejneru se dostaneš přímo z webu Proxmoxu, žádné jméno ani heslo se nezadává — kontejner root heslo nemá a konzole se přihlašuje sama. Nová práva to nikomu nedává: kdo se dostane do webu Proxmoxu, má root na uzlu tak jako tak. Komu se to nezdá, vypne to přes AUTOLOGIN=0 a do kontejneru pak leze přes pct enter <ctid>.

Podoba je odkoukaná od community-scripts.org, ale nic z jejich frameworku se nestahuje — jejich build.func si instalační skript hledá natvrdo ve vlastním repozitáři, takže mimo něj nefunguje.

Instalátor, který běží uvnitř kontejneru, je ve skriptu vložený jako text — přes rouru z curlu na disku hostitele žádný druhý soubor není. O Proxmoxu nic neví, takže se dá použít i v kontejneru, který sis založil sám:

bash pve-dice-counter.sh instalator > install.sh

Je idempotentní; druhé spuštění jen vymění binárku za nejnovější.

Docker

Stačí jeden soubor, repozitář k tomu potřeba není:

curl -fsSLO https://gitea.spacilovi.eu/david-spacil/dice-counter/raw/branch/main/deploy/docker-compose.yaml
docker compose up -d

Image se stáhne hotový z registru Gitey, pro amd64 i arm64 — Docker si vybere svoji variantu sám. Databáze leží v pojmenovaném svazku, appka běží pod nerootovým uživatelem.

Aktualizace na novější vydání:

docker compose pull && docker compose up -d

Kdo si ho radši postaví ze zdrojáků, přebije ten stažený stejnou značkou:

docker build -f deploy/Dockerfile -t gitea.spacilovi.eu/david-spacil/dice-counter:latest .

Pozor na síť. Compose schválně používá network_mode: host. V bridge režimu kontejner uvnitř vidí adresu jako 172.17.0.2, tabule ji poctivě nabídne a vygeneruje na ni QR kód — jenže z telefonu je nedosažitelná. Kdo bridge potřebuje, musí nastavit DICE_HOST na adresu hostitele v LAN.

LXC Docker
Odkud vydaná binárka z releasu image z registru
Databáze /var/lib/dice-counter/dice.db svazek dice-counter-data
Aktualizace update uvnitř kontejneru docker compose pull
Adresa a QR funguje samo potřeba síť hostitele

Když se telefon nepřipojí

Adresy se hledají při každém načtení tabule, takže přechod z domácí WiFi na hotspot a zpátky si tabule pohlídá sama a načte se znovu.

Zbývají tři důvody, proč se telefon nedostane na notebook:

  • Telefon je na mobilních datech, notebook na WiFi. Různé sítě, nepotkají se. Připoj telefon na stejnou WiFi, nebo notebook na hotspot telefonu — to funguje taky.
  • Zapnutý hotspot na telefonu shodil jeho WiFi. Většina Androidů to dělá. Pak je řešením připojit na ten hotspot i notebook.
  • VPN nebo Tailscale exit node na telefonu posílá veškerý provoz mimo místní síť. V Tailscale to řeší přepínač „Allow local network access"; případně použij tailnet adresu notebooku, ta funguje odkudkoli.

Pravidla

Skóre se zadává ručně po tazích, hází se doopravdy. Tři nulové tahy za sebou vynulují hráči skóre; indikátor x / xx ukazuje, jak blízko k tomu je. Vítěz se vyhlašuje až po dokončeném kole, aby měli všichni stejný počet tahů — při remíze na prvním místě se hraje dál.

Co kde je

Soubor Role
core.py pravidla hry, žádný vstup ani výstup
net.py hledání adres, na kterých je počitadlo dostupné
storage.py SQLite: hráči, hry, tahy
stats.py síň slávy a kariérní statistiky
web.py Flask aplikace
dice.py totéž v terminálu, bez ukládání
console.py aby čeština prošla i windowsovou konzolí
version.py která verze to je — z gitu, nebo z binárky
build.sh, dice-counter.spec stavba binárky
.gitea/workflows/ testy, linuxová binárka a zkouška image doma
.github/workflows/ binárky pro Windows a macOS
deploy/ nasazení na server: Proxmox LXC a Docker

Terminálová verze zůstává funkční jako záloha:

uv run dice.py

Bez uv

Když uv po ruce není, jde to postaru:

python -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python web.py

Na Fedoře stačí i systémové balíčky, pak se nemusí řešit vůbec nic:

sudo dnf install python3-flask python3-qrcode python3-tabulate python3-waitress
python3 web.py

Závislosti

Verze jsou zamčené, aby binárka postavená dnes a za půl roku obsahovala totéž. Volné seznamy jsou v .in, zamčené v .txt:

Soubor K čemu
requirements.in → .txt běh aplikace
requirements-dev.in → .txt + pytest, pro testy
requirements-build.in → .txt + PyInstaller, pro stavbu binárky

Aktualizace je vědomý krok, ne vedlejší efekt toho, že něco vyšlo na PyPI:

for f in requirements requirements-dev requirements-build; do
    uv pip compile "$f.in" -o "$f.txt"
done

Verze se píšou ještě jednou v hlavičce PEP 723 na začátku web.py a dice.py, aby fungovalo uv run web.py. Že se ty dva zápisy shodují, hlídá tests/test_zavislosti.py — po každém přegenerování je potřeba hlavičky srovnat.

Vlastní binárka

./build.sh

Verzi si build.sh vezme z git describe, nebo se dá vnutit přes VERSION=v1.2.3 ./build.sh. Zapíše ji do verze.txt, dice-counter.spec ji přibalí a binárka ji pak umí ohlásit i na cizím počítači, kde žádný git není. Verzi Pythonu, proti kterému se staví, přebíjí PYTHON_VERSION.

Staví se proti samostatnému CPythonu od uv, ne proti systémovému. Ten je slinkovaný s glibc 2.17; postavené proti Pythonu z Fedory 44 by to chtělo glibc 2.43 a nešlo by spustit skoro nikde — glibc drží zpětnou kompatibilitu, ne dopřednou. Nic z hostitele se do binárky nedostane, takže kontejner k tomu potřeba není. Výsledek je v dist/.

Stejný build.sh staví i na macOS a na Windows (v Git Bash) — jen tam bez té starosti o glibc. Křížem to nejde: PyInstaller balí do výsledku interpret a knihovny toho systému, na kterém běží, takže binárku pro každý systém musí postavit ten systém.

Terminálová verze součástí binárky není; ta se pouští ze zdrojáků.

Jak vznikají releasy

Otagovaný commit spustí stavbu na obou stranách:

Kde Co staví Workflow
vlastní runner u Gitey Linux x86-64 .gitea/workflows/binarka.yml
GitHub Actions Windows, macOS ×2, Linux ARM64 .github/workflows/binarky.yml
GitHub Actions image amd64 + arm64 .github/workflows/image.yml
git tag v1.0.0 && git push origin v1.0.0

GitHub je tu jen půjčená dílna. Repozitář se tam z Gitey zrcadlí (mirror), postavené soubory se posílají zpátky na zdejší release přes Gitea API a projekt má pořád jednu stránku s releasy — tuhle. Linux na x86-64 se na GitHubu schválně nestaví; doma to jde proti staré glibc, a když GitHub vypadne, release má aspoň tu platformu, na které to reálně poběží. ARM64 je výjimka — doma na něm není na čem stavět, a hodí se pro Raspberry Pi nebo jinou malou pořád zapnutou krabičku.

Každá stavba nejdřív projede testy a zkusí hotovou binárku nastartovat, než ji kamkoli pověsí. Vedle každé visí i .sha256, takže se stažený soubor dá ověřit:

sha256sum -c dice-counter-linux-x86_64.sha256   # na macOS: shasum -a 256 -c

Do vydání 1.2.x se přílohy jmenovaly kostky-*. Ještě chvíli se budou věšet pod oběma jmény, ať fungují instalace, které si o ně říkají po staru. Až budou přemigrované, zůstane jen dice-counter-*.

Nad pull requesty se Linux staví taky, jen se nikam nevěší. Totéž platí pro kontejnerový image — doma se nad každým PR postaví a zkusí nastartovat (.gitea/workflows/image.yml), publikuje se ale až z tagu na GitHubu.

Image se schválně nevydává doma: tamní runner běží v LXC, kde nejde zaregistrovat emulaci pro arm64 — je to vlastnost jádra hostitele a ten je produkční stroj. Běhouni GitHubu jsou plnohodnotné virtuály, kde to funguje bez zásahu do čehokoli.

Testy

uv run --with-requirements requirements.txt --no-project pytest

Nebo z připraveného prostředí prostě pytest.

Nad každým pull requestem a nad main běží .gitea/workflows/testy.yml — 118 testů na Pythonu 3.11, 3.12, 3.13 i 3.14, a k tomu skriptovaná partie v terminálové verzi, na kterou pytest nesahá.

S
Description
No description provided
Readme
515 KiB
0 Stars 1 Watchers 0 Forks
2026-08-23 23:15:56 +02:00
Languages
Python 65.1%
HTML 12.4%
Shell 12.3%
CSS 8.4%
Dockerfile 1.8%