From 7449c01b14875d240ae1612074011472e58d43a3 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 23 Aug 2026 22:29:58 +0200 Subject: [PATCH 1/3] =?UTF-8?q?Sjednotit=20pojmenov=C3=A1n=C3=AD:=20kostky?= =?UTF-8?q?=20=E2=86=92=20dice-counter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Projekt se jmenuje dice-counter, ale skoro všude vystupoval jako kostky. Tohle je první ze dvou kroků podle #16: nová jména se zavádějí vedle starých, aby běžící instalace nic nerozbilo. Nově: binárka a spec dice-counter.spec, dist/dice-counter přílohy releasu dice-counter-linux-x86_64 a spol. služba v LXC dice-counter.service cesty v LXC /opt/dice-counter, /var/lib/dice-counter uživatel dice-counter hostname LXC dice-counter instalátor deploy/pve-dice-counter.sh datový adresář ~/.local/share/dice-counter a obdoby co appka hlásí "dice-counter " v banneru i v patičce Stará jména zatím fungují dál: - Přílohy se na release věší pod oběma jmény. - Instalátor umí stáhnout i kostky-*, takže starší vydání jdou nainstalovat pořád. - deploy/pve-kostky.sh zůstává jako přesměrování — příkaz `update` v už založených kontejnerech chodí pro instalátor právě tam. - Kontejnery z dřívějška se při aktualizaci přestěhují samy: služba se přejmenuje a databáze se přesune do /var/lib/dice-counter, takže o historii her nikdo nepřijde. - Binárka sáhne po ~/.local/share/kostky/dice.db, dokud nová databáze neexistuje. Při zkoušení přechodu vyplavala chyba, která tu byla už předtím: příkaz `update` si nový instalátor uloží do $HOME_DIR/install.sh a odtud ho pustí, takže `install -m 755 "$0" "$HOME_DIR/install.sh"` kopírovalo soubor sám na sebe. install to odmítne, se `set -e` spadl celý update. Ošetřeno testem `-ef`. Ověřeno v debianím kontejneru: přechod ze staré instalace (včetně běhu instalátoru z adresáře, který se během něj maže), čistá instalace, běh proti releasu, kde je jen stará příloha, a druhé spuštění za sebou. Refs #16 --- .gitea/workflows/binarka.yml | 21 +- .github/workflows/binarky.yml | 34 ++- README.md | 55 ++-- build.sh | 2 +- deploy/pve-dice-counter.sh | 445 +++++++++++++++++++++++++++++++ deploy/pve-kostky.sh | 388 +-------------------------- kostky.spec => dice-counter.spec | 2 +- dice.py | 2 +- storage.py | 19 +- templates/base.html | 2 +- tests/test_storage.py | 24 +- version.py | 2 +- web.py | 6 +- 13 files changed, 575 insertions(+), 427 deletions(-) create mode 100755 deploy/pve-dice-counter.sh rename kostky.spec => dice-counter.spec (97%) diff --git a/.gitea/workflows/binarka.yml b/.gitea/workflows/binarka.yml index 32fa422..c78ffa9 100644 --- a/.gitea/workflows/binarka.yml +++ b/.gitea/workflows/binarka.yml @@ -67,7 +67,7 @@ jobs: - name: Zkouška run: | XDG_DATA_HOME=/tmp/zkouska DICE_PORT=8321 DICE_HOST=127.0.0.1 \ - ./dist/kostky > /tmp/server.log 2>&1 & + ./dist/dice-counter > /tmp/server.log 2>&1 & server=$! trap 'kill $server 2>/dev/null || true' EXIT @@ -79,15 +79,18 @@ jobs: curl -sf -o /dev/null http://127.0.0.1:8321/ curl -sf -o /dev/null http://127.0.0.1:8321/static/style.css curl -sf -o /dev/null http://127.0.0.1:8321/board - test -f /tmp/zkouska/kostky/dice.db - ./dist/kostky --version + test -f /tmp/zkouska/dice-counter/dice.db + ./dist/dice-counter --version cat /tmp/server.log - name: Na release if: startsWith(github.ref, 'refs/tags/') env: TOKEN: ${{ secrets.GITHUB_TOKEN }} - ASSET: kostky-linux-x86_64 + ASSET: dice-counter-linux-x86_64 + # Instalátory z dřívějška si chodí pro staré jméno. Až budou + # přemigrované, přestane se pod ním věšet. + STARY_ASSET: kostky-linux-x86_64 run: | api="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" auth="Authorization: token ${TOKEN}" @@ -104,11 +107,13 @@ jobs: fi # Součet se počítá nad jménem, pod kterým se soubor stahuje, aby - # šel ověřit rovnou: sha256sum -c kostky-linux-x86_64.sha256 - cp dist/kostky "$ASSET" - sha256sum "$ASSET" | tee "$ASSET.sha256" + # šel ověřit rovnou: sha256sum -c dice-counter-linux-x86_64.sha256 + for jmeno in "$ASSET" "$STARY_ASSET"; do + cp dist/dice-counter "$jmeno" + sha256sum "$jmeno" | tee "$jmeno.sha256" + done - for file in "$ASSET" "$ASSET.sha256"; do + for file in "$ASSET" "$ASSET.sha256" "$STARY_ASSET" "$STARY_ASSET.sha256"; do # Aby se dal build zopakovat, stará příloha stejného jména jde pryč. curl -s -H "$auth" "$api/releases/$id/assets" \ | python3 -c 'import json,sys; [print(a["id"]) for a in json.load(sys.stdin) if a["name"] == sys.argv[1]]' "$file" \ diff --git a/.github/workflows/binarky.yml b/.github/workflows/binarky.yml index 32ac091..e845a90 100644 --- a/.github/workflows/binarky.yml +++ b/.github/workflows/binarky.yml @@ -29,19 +29,26 @@ jobs: strategy: fail-fast: false matrix: + # `stary` je jméno, pod kterým se příloha věšela do vydání 1.2.x. + # Instalátory z té doby si chodí pro něj, tak se pověsí obojí. + # Až budou přemigrované, sloupec zmizí. include: - os: windows-latest - asset: kostky-windows-x86_64.exe - built: dist/kostky.exe + asset: dice-counter-windows-x86_64.exe + stary: kostky-windows-x86_64.exe + built: dist/dice-counter.exe - os: macos-15-intel # Intel; macos-13 GitHub zrušil - asset: kostky-macos-x86_64 - built: dist/kostky + asset: dice-counter-macos-x86_64 + stary: kostky-macos-x86_64 + built: dist/dice-counter - os: macos-latest # Apple Silicon - asset: kostky-macos-arm64 - built: dist/kostky + asset: dice-counter-macos-arm64 + stary: kostky-macos-arm64 + built: dist/dice-counter - os: ubuntu-24.04-arm # pro Raspberry Pi a spol. - asset: kostky-linux-arm64 - built: dist/kostky + asset: dice-counter-linux-arm64 + stary: kostky-linux-arm64 + built: dist/dice-counter runs-on: ${{ matrix.os }} defaults: @@ -97,6 +104,7 @@ jobs: env: TOKEN: ${{ secrets.GITEA_TOKEN }} ASSET: ${{ matrix.asset }} + STARY_ASSET: ${{ matrix.stary }} run: | api="$GITEA/api/v1/repos/$GITEA_REPO" auth="Authorization: token $TOKEN" @@ -124,11 +132,13 @@ jobs: fi # Součet se počítá nad jménem, pod kterým se soubor stahuje, aby - # šel ověřit rovnou: shasum -a 256 -c kostky-macos-arm64.sha256 - cp "${{ matrix.built }}" "$ASSET" - soucet "$ASSET" | tee "$ASSET.sha256" + # šel ověřit rovnou: shasum -a 256 -c dice-counter-macos-arm64.sha256 + for jmeno in "$ASSET" "$STARY_ASSET"; do + cp "${{ matrix.built }}" "$jmeno" + soucet "$jmeno" | tee "$jmeno.sha256" + done - for file in "$ASSET" "$ASSET.sha256"; do + for file in "$ASSET" "$ASSET.sha256" "$STARY_ASSET" "$STARY_ASSET.sha256"; do # Aby se dal build zopakovat, stará příloha stejného jména jde pryč. curl -s -H "$auth" "$api/releases/$id/assets" \ | json 'import json,sys; [print(a["id"]) for a in json.load(sys.stdin) if a["name"] == sys.argv[1]]' "$file" \ diff --git a/README.md b/README.md index 9f09a25..66782e4 100644 --- a/README.md +++ b/README.md @@ -13,19 +13,19 @@ Stáhni binárku pro svůj systém z | Systém | Soubor | |---|---| -| Linux (x86-64) | `kostky-linux-x86_64` | -| Linux (ARM64) | `kostky-linux-arm64` | -| macOS (Apple Silicon) | `kostky-macos-arm64` | -| macOS (Intel) | `kostky-macos-x86_64` | -| Windows (x86-64) | `kostky-windows-x86_64.exe` | +| 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: ```bash -chmod +x kostky-* -./kostky-linux-x86_64 +chmod +x dice-counter-* +./dice-counter-linux-x86_64 ``` Na Windows stačí na `.exe` poklepat. @@ -38,7 +38,7 @@ Binárky nejsou podepsané — podpisové certifikáty stojí tisíce ročně a 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 kostky-macos-arm64`), nebo + 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* → @@ -60,7 +60,7 @@ 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ý: ``` -Kostky v1.1.0 +dice-counter v1.2.2 Počitadlo je dostupné na: → http://10.186.234.182:8000 místní síť @@ -68,7 +68,7 @@ Počitadlo je dostupné na: http://172.17.0.1:8000 virtuální síť ``` -Kterou verzi máš, řekne i `kostky --version`; visí taky v patičce každé +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 @@ -88,11 +88,15 @@ server vypíše při startu. | Spuštěno | Databáze | |---|---| -| binárkou na Linuxu | `~/.local/share/kostky/dice.db` | -| binárkou na macOS | `~/Library/Application Support/kostky/dice.db` | -| binárkou na Windows | `%LOCALAPPDATA%\kostky\dice.db` | +| 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 @@ -129,7 +133,7 @@ nastaví ho, stáhne poslední vydanou binárku, ověří kontrolní součet a z službu: ```bash -bash -c "$(curl -fsSL https://gitea.spacilovi.eu/david-spacil/dice-counter/raw/branch/main/deploy/pve-kostky.sh)" +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 @@ -143,7 +147,7 @@ MEMORY=1024 STORAGE=local-zfs PORT=8080 bash -c "$(curl -fsSL ...)" | Proměnná | Výchozí | |---|---| | `CTID` | první volné číslo | -| `CT_HOSTNAME` | `kostky` | +| `CT_HOSTNAME` | `dice-counter` | | `CORES`, `MEMORY`, `DISK` | `1`, `512`, `4` | | `STORAGE` | první aktivní úložiště pro kontejnery | | `TEMPLATE_STORAGE`, `BRIDGE` | `local`, `vmbr0` | @@ -170,6 +174,13 @@ Obojí vymění binárku za poslední vydání a službu restartuje; databáze z 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 @@ -185,7 +196,7 @@ přes rouru z curlu na disku hostitele žádný druhý soubor není. O Proxmoxu neví, takže se dá použít i v kontejneru, který sis založil sám: ```bash -bash pve-kostky.sh instalator > install.sh +bash pve-dice-counter.sh instalator > install.sh ``` Je idempotentní; druhé spuštění jen vymění binárku za nejnovější. @@ -223,7 +234,7 @@ 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/kostky/dice.db` | svazek `kostky-data` | +| 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 | @@ -262,7 +273,7 @@ při remíze na prvním místě se hraje dál. | `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`, `kostky.spec` | stavba 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 | @@ -321,7 +332,7 @@ srovnat. ``` 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`, `kostky.spec` ji +`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`. @@ -366,9 +377,13 @@ ji kamkoli pověsí. Vedle každé visí i `.sha256`, takže se stažený soubor ověřit: ```bash -sha256sum -c kostky-linux-x86_64.sha256 # na macOS: shasum -a 256 -c +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. diff --git a/build.sh b/build.sh index e41ba97..f31d10d 100755 --- a/build.sh +++ b/build.sh @@ -38,7 +38,7 @@ fi uv pip install --quiet --python "$python" -r requirements-build.txt "$pyinstaller" --clean --noconfirm \ - --distpath dist --workpath "$BUILD/work" kostky.spec + --distpath dist --workpath "$BUILD/work" dice-counter.spec echo ls -lh dist/ diff --git a/deploy/pve-dice-counter.sh b/deploy/pve-dice-counter.sh new file mode 100755 index 0000000..5cb7314 --- /dev/null +++ b/deploy/pve-dice-counter.sh @@ -0,0 +1,445 @@ +#!/usr/bin/env bash +# Založí na Proxmoxu LXC kontejner s počitadlem kostek. +# +# Pouští se v terminálu uzlu Proxmoxu jako root, jedním příkazem: +# +# bash -c "$(curl -fsSL https://gitea.spacilovi.eu/david-spacil/dice-counter/raw/branch/main/deploy/pve-dice-counter.sh)" +# +# Aktualizace stávajícího kontejneru na novější vydání: +# +# CTID=123 MODE=update bash -c "$(curl -fsSL .../pve-dice-counter.sh)" +# +# Ze staženého souboru jde i obojí postaru: `bash pve-dice-counter.sh` a +# `bash pve-dice-counter.sh update 123`. +# +# Podoba je odkoukaná od community-scripts.org, ale nic z jejich frameworku +# se tu nestahuje — jejich build.func si instalační skript hledá natvrdo ve +# vlastním repozitáři, takže mimo něj nefunguje. +# +# Počítá se s domácí sítí. Appka nemá přihlašování a tenhle skript ji nijak +# nezabezpečuje; do internetu ji nepouštěj. +set -euo pipefail + +APP="dice-counter" +GITEA="${GITEA:-https://gitea.spacilovi.eu}" +REPO="${REPO:-david-spacil/dice-counter}" + +# Výchozí hodnoty. Všechny se dají přebít proměnnou prostředí, třeba: +# MEMORY=1024 STORAGE=local-zfs bash -c "$(curl -fsSL ...)" +CT_HOSTNAME="${CT_HOSTNAME:-dice-counter}" +CORES="${CORES:-1}" +MEMORY="${MEMORY:-512}" +DISK="${DISK:-4}" +STORAGE="${STORAGE:-}" +TEMPLATE_STORAGE="${TEMPLATE_STORAGE:-local}" +BRIDGE="${BRIDGE:-vmbr0}" +PORT="${PORT:-8000}" +UNPRIVILEGED="${UNPRIVILEGED:-1}" +OSVERSION="${OSVERSION:-13}" +NESTING="${NESTING:-1}" +AUTOLOGIN="${AUTOLOGIN:-1}" # konzole ve webu Proxmoxu bez hesla +VERSION="${VERSION:-}" # prázdné = poslední vydání + +# --- výpisy ------------------------------------------------------------------ + +# Bez tohohle Ctrl+C zabije jen rozdělaný podproces a skript jede vesele dál +# — třeba rovnou zakládat kontejner, na který se čekat nemá. +trap 'echo; echo -e "\e[1;31m ✗\e[0m Přerušeno." >&2; exit 130' INT TERM + +msg() { echo -e "\e[1;34m →\e[0m $*"; } +ok() { echo -e "\e[1;32m ✓\e[0m $*"; } +die() { echo -e "\e[1;31m ✗\e[0m $*" >&2; exit 1; } + +header() { + echo + echo -e "\e[1;36m $APP\e[0m — počitadlo kostek do LXC" + echo -e " \e[2m$GITEA/$REPO\e[0m" + echo +} + +# --- instalátor, který poběží uvnitř kontejneru ------------------------------ +# +# Je tu jako text schválně. Skript se pouští i rourou z curlu, kdy na disku +# hostitele žádný soubor není a nebylo by co poslat dovnitř. Uvozovky kolem +# 'INSTALL' jsou podstatné: nic z toho se tady nesmí rozvinout, všechny +# proměnné patří až tomu, co poběží v kontejneru. +# +# Vypsat se dá i samostatně: `bash pve-dice-counter.sh instalator > install.sh`, +# což se hodí, když chceš appku dostat do kontejneru, který sis založil sám. +installer() { +cat <<'INSTALL' +#!/usr/bin/env bash +# Instalace počitadla uvnitř kontejneru. O Proxmoxu nic neví, takže se dá +# pustit v jakémkoli Debianu. Je idempotentní — druhé spuštění jen vymění +# binárku za nejnovější. +set -euo pipefail + +GITEA="${GITEA:-https://gitea.spacilovi.eu}" +REPO="${REPO:-david-spacil/dice-counter}" +PORT="${PORT:-8000}" +VERSION="${VERSION:-}" + +USER_NAME=dice-counter +HOME_DIR=/opt/dice-counter +DATA_DIR=/var/lib/dice-counter +SERVICE=dice-counter + +# Do vydání 1.2.x se všechno jmenovalo kostky. Instalace z té doby se při +# aktualizaci přestěhují; až budou přemigrované, tyhle tři řádky zmizí. +STARY_USER=kostky +STARY_HOME=/opt/kostky +STARY_DATA=/var/lib/kostky +STARA_SLUZBA=kostky + +msg() { echo -e "\e[1;34m →\e[0m $*"; } +ok() { echo -e "\e[1;32m ✓\e[0m $*"; } +die() { echo -e "\e[1;31m ✗\e[0m $*" >&2; exit 1; } + +case "$(dpkg --print-architecture)" in + amd64) PLATFORMA=linux-x86_64 ;; + arm64) PLATFORMA=linux-arm64 ;; + *) die "Pro architekturu $(dpkg --print-architecture) binárka není." ;; +esac + +msg "Doinstalovávám, co je potřeba ke stažení" +export DEBIAN_FRONTEND=noninteractive +apt-get update -qq +apt-get install -y -qq curl ca-certificates >/dev/null +ok "Základ je hotový" + +if [ -z "$VERSION" ]; then + msg "Zjišťuji poslední vydanou verzi" + # Jen tag; adresa přílohy se z něj složí, takže tu nepotřebujeme jq. + VERSION=$(curl -fsSL "$GITEA/api/v1/repos/$REPO/releases/latest" \ + | grep -o '"tag_name":[[:space:]]*"[^"]*"' | head -1 | cut -d'"' -f4) + [ -n "$VERSION" ] || die "Nepodařilo se zjistit poslední verzi z $GITEA." +fi +ok "Instaluje se $VERSION pro $PLATFORMA" + +BASE="$GITEA/$REPO/releases/download/$VERSION" +TMP=$(mktemp -d) +trap 'rm -rf "$TMP"' EXIT + +msg "Stahuji binárku" +# Do vydání 1.2.x se přílohy jmenovaly kostky-*. Starší vydání se tak dají +# nainstalovat dál; až stará jména z releasů zmizí, zůstane jen to první. +ASSET="" +for jmeno in "dice-counter-$PLATFORMA" "kostky-$PLATFORMA"; do + curl -fsSL -o "$TMP/$jmeno" "$BASE/$jmeno" 2>/dev/null && { ASSET="$jmeno"; break; } +done +[ -n "$ASSET" ] \ + || die "Binárka pro $PLATFORMA ve vydání $VERSION není. Pro tuhle architekturu možná ještě nevyšla." + +curl -fsSL -o "$TMP/$ASSET.sha256" "$BASE/$ASSET.sha256" \ + || die "Chybí kontrolní součet — radši nic neinstaluju." + +msg "Ověřuji kontrolní součet" +( cd "$TMP" && sha256sum -c "$ASSET.sha256" >/dev/null ) \ + || die "Kontrolní součet nesedí. Stažený soubor zahazuju." +ok "Součet sedí" + +id -u "$USER_NAME" >/dev/null 2>&1 \ + || useradd --system --home-dir "$HOME_DIR" --shell /usr/sbin/nologin "$USER_NAME" + +install -d -o root -g root -m 755 "$HOME_DIR" + +# Instalace z doby, kdy se všechno jmenovalo kostky, se tady převezme. Bez +# přestěhování databáze by po aktualizaci zmizela historie her, takže se to +# nedá odbýt smazáním staré služby. +# +# Starý domovský adresář se maže až úplně na konci skriptu: při aktualizaci +# běžícího kontejneru se instalátor pouští právě z něj a `$0` z něj ještě +# potřebujeme zkopírovat na nové místo. +if [ -f "/etc/systemd/system/$STARA_SLUZBA.service" ] \ + || [ -d "$STARY_HOME" ] || [ -d "$STARY_DATA" ]; then + msg "Našel jsem instalaci pod starým jménem, stěhuji ji" + + systemctl is-active --quiet "$STARA_SLUZBA" && systemctl stop "$STARA_SLUZBA" + systemctl disable --quiet "$STARA_SLUZBA" 2>/dev/null || true + rm -f "/etc/systemd/system/$STARA_SLUZBA.service" + systemctl daemon-reload + + # Když nový adresář z nějakého důvodu už existuje, starý se nechá být. + # Přepsat cizí databázi je horší než nechat po sobě adresář navíc. + if [ -d "$STARY_DATA" ] && [ ! -e "$DATA_DIR" ]; then + mv "$STARY_DATA" "$DATA_DIR" + ok "Databáze přestěhována do $DATA_DIR" + elif [ -d "$STARY_DATA" ]; then + msg "$DATA_DIR už existuje, $STARY_DATA nechávám na místě" + fi + + id -u "$STARY_USER" >/dev/null 2>&1 && userdel "$STARY_USER" 2>/dev/null || true +fi + +# Po stěhování patří soubory uživateli, který už neexistuje. StateDirectory +# to u založeného adresáře nedorovná, tak se to udělá rovnou tady. +[ -d "$DATA_DIR" ] && chown -R "$USER_NAME:$USER_NAME" "$DATA_DIR" + +# Zastavit se dá jen to, co běží — při první instalaci služba ještě není. +if systemctl is-active --quiet "$SERVICE"; then + systemctl stop "$SERVICE" +fi + +install -o root -g root -m 755 "$TMP/$ASSET" "$HOME_DIR/dice-counter" +echo "$VERSION" > "$HOME_DIR/verze" +ok "Binárka je na místě" + +msg "Zapisuji službu" +cat > "/etc/systemd/system/$SERVICE.service" < /etc/systemd/system/container-getty@1.service.d/override.conf <<'GETTY' +[Service] +ExecStart= +ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 $TERM +GETTY + systemctl daemon-reload + systemctl restart container-getty@1.service 2>/dev/null || true + ok "Konzole se přihlásí sama" +fi + +# --- příkaz update ---------------------------------------------------------- + +# Instalátor si necháme, ať je z čeho aktualizovat. Když se skript pouští +# rourou, soubor neexistuje a zůstane ten z minula. +# +# `-ef` je tu nutnost, ne opatrnost: příkaz `update` si nový instalátor uloží +# rovnou sem a odsud ho pustí, takže `$0` a cíl jsou tentýž soubor. `install` +# na to řekne "are the same file", skončí chybou a se `set -e` by celý update +# spadl dřív, než by stihl cokoli udělat. +if [ -f "$0" ] && ! [ "$0" -ef "$HOME_DIR/install.sh" ]; then + install -m 755 "$0" "$HOME_DIR/install.sh" +fi + +cat > /usr/bin/update </dev/null \\ + && bash "\$NOVY" instalator > "\$NOVY.in" 2>/dev/null \\ + && bash -n "\$NOVY.in" 2>/dev/null; then + install -m 755 "\$NOVY.in" "$HOME_DIR/install.sh" +fi +rm -f "\$NOVY" "\$NOVY.in" + +exec env PORT="$PORT" GITEA="$GITEA" REPO="$REPO" bash "$HOME_DIR/install.sh" +UPDATE +chmod 755 /usr/bin/update +ok "Aktualizovat půjde příkazem: update" + +# Teď už je `$0` zkopírovaný na nové místo a starý domov nikdo nepotřebuje. +# Bash si drží otevřený popisovač na skript, takže smazat se dá i ten, který +# se zrovna vykonává. +if [ -d "$STARY_HOME" ]; then + rm -rf "$STARY_HOME" + ok "Staré $STARY_HOME uklizeno" +fi + +msg "Čekám, až začne odpovídat" +for _ in $(seq 30); do + curl -fsS -o /dev/null "http://127.0.0.1:$PORT/" 2>/dev/null && break + sleep 1 +done +curl -fsS -o /dev/null "http://127.0.0.1:$PORT/" \ + || die "Služba nastartovala, ale neodpovídá. Mrkni na journalctl -u $SERVICE." + +# Verzi bereme ze souboru, ne z binárky. Starší vydání --version neumí +# a místo výpisu by nastartovala server, který by tenhle skript zavěsil. +ok "Počitadlo $(cat "$HOME_DIR/verze") odpovídá na portu $PORT" +INSTALL +} + +# --- společné části ---------------------------------------------------------- + +install_into() { + local ctid="$1" tmp + tmp=$(mktemp) + installer > "$tmp" + + msg "Posílám instalátor do kontejneru $ctid" + pct push "$ctid" "$tmp" /root/dice-counter-install.sh --perms 0755 + rm -f "$tmp" + + pct exec "$ctid" -- env PORT="$PORT" GITEA="$GITEA" REPO="$REPO" \ + VERSION="$VERSION" AUTOLOGIN="$AUTOLOGIN" bash /root/dice-counter-install.sh +} + +address_of() { + pct exec "$1" -- hostname -I 2>/dev/null | awk '{print $1}' +} + +hotovo() { + local ctid="$1" ip jmeno + ip=$(address_of "$ctid") + jmeno=$(pct config "$ctid" | awk -F': ' '/^hostname:/ {print $2}') + + echo + ok "Hotovo. Kontejner $ctid ($jmeno) běží." + echo + echo -e " Zápisník na notebook: \e[1;32mhttp://${ip}:${PORT}/board\e[0m" + echo -e " Zadávání z telefonu: \e[1;32mhttp://${ip}:${PORT}/\e[0m" + echo + echo -e " \e[2mDatabáze: /var/lib/dice-counter/dice.db (uvnitř kontejneru)" + echo -e " Aktualizace: v konzoli kontejneru napiš update" + echo -e " Log: pct exec $ctid -- journalctl -u dice-counter -f" + echo -e " Konzole: pct enter $ctid" + echo -e " Zrušit: pct stop $ctid && pct destroy $ctid\e[0m" + echo +} + +# --- co se má vlastně dělat -------------------------------------------------- +# +# Rourou z curlu se argumenty předávají mizerně, tak jde všechno i proměnnou: +# MODE=update CTID=123. Ze souboru funguje i `bash pve-dice-counter.sh update 123`. +MODE="${MODE:-${1:-create}}" +[ "$MODE" = "update" ] && CTID="${CTID:-${2:-}}" + +if [ "$MODE" = "instalator" ]; then + installer + exit 0 +fi + +command -v pct >/dev/null || die "Tohle patří na uzel Proxmoxu — pct tu není." +[ "$(id -u)" -eq 0 ] || die "Spusť to jako root." + +# --- aktualizace ------------------------------------------------------------- + +if [ "$MODE" = "update" ]; then + [ -n "${CTID:-}" ] || die "Řekni který: CTID=123 MODE=update ..." + pct status "$CTID" >/dev/null 2>&1 || die "Kontejner $CTID neexistuje." + + header + if [ "$(pct status "$CTID")" != "status: running" ]; then + msg "Startuji kontejner" + pct start "$CTID" + sleep 5 + fi + + install_into "$CTID" + hotovo "$CTID" + exit 0 +fi + +# --- nový kontejner ---------------------------------------------------------- + +header + +# Úložiště se nehádá. local-lvm na ZFS instalacích neexistuje a pct create by +# spadlo až po půlce práce, tak se radši zeptáme systému, co tu opravdu je. +if [ -z "$STORAGE" ]; then + STORAGE=$(pvesm status -content rootdir 2>/dev/null \ + | awk 'NR>1 && $3=="active" {print $1; exit}') + [ -n "$STORAGE" ] || die "Nenašel jsem úložiště pro kontejnery. Zadej STORAGE=; co máš, ukáže pvesm status." + msg "Úložiště: $STORAGE (nalezeno automaticky)" +else + pvesm status -content rootdir 2>/dev/null | awk 'NR>1 {print $1}' | grep -qx "$STORAGE" \ + || die "Úložiště $STORAGE pro kontejnery nesedí. Co máš, ukáže: pvesm status -content rootdir" + msg "Úložiště: $STORAGE" +fi + +CTID="${CTID:-$(pvesh get /cluster/nextid)}" +msg "Kontejner dostane číslo $CTID" + +# Architektura uzlu, ne první šablona v seznamu. pveam nabízí amd64 i arm64 +# vedle sebe a bez tohohle filtru by výběr padl na tu abecedně poslední. +ARCH=$(dpkg --print-architecture) +SABLONA="debian-${OSVERSION}-standard[^[:space:]]*_${ARCH}\.tar\.[a-z]*" + +msg "Hledám šablonu Debianu $OSVERSION pro $ARCH" + +# Nejdřív co už na uzlu leží — stahovat 120 MB znovu je zbytečné. +TEMPLATE=$(pveam list "$TEMPLATE_STORAGE" 2>/dev/null | grep -o "$SABLONA" | sort -V | tail -1) + +if [ -n "$TEMPLATE" ]; then + ok "Šablona $TEMPLATE (už je na uzlu)" +else + pveam update >/dev/null 2>&1 || true + TEMPLATE=$(pveam available --section system 2>/dev/null | grep -o "$SABLONA" | sort -V | tail -1) + [ -n "$TEMPLATE" ] || die "Šablona pro Debian $OSVERSION a $ARCH není k dispozici." + + msg "Stahuji $TEMPLATE (asi 120 MB, chvíli to trvá)" + pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null \ + || die "Stažení šablony selhalo." + ok "Šablona $TEMPLATE" +fi + +# Nesting: Debian 13 veze systemd 257 a ten v neprivilegovaném kontejneru bez +# něj nedostane, co potřebuje — Proxmox na to při startu sám upozorňuje. +# Stejnou výchozí hodnotu mají i community-scripts. +msg "Zakládám kontejner" +pct create "$CTID" "$TEMPLATE_STORAGE:vztmpl/$TEMPLATE" \ + --hostname "$CT_HOSTNAME" \ + --cores "$CORES" \ + --memory "$MEMORY" \ + --swap 256 \ + --rootfs "$STORAGE:$DISK" \ + --net0 "name=eth0,bridge=$BRIDGE,ip=dhcp" \ + --unprivileged "$UNPRIVILEGED" \ + --features "nesting=$NESTING" \ + --ostype debian \ + --onboot 1 \ + --description "$APP — $GITEA/$REPO" >/dev/null +ok "Kontejner $CTID založen" + +msg "Startuji" +pct start "$CTID" + +msg "Čekám na síť" +for _ in $(seq 60); do + if [ -n "$(address_of "$CTID")" ] \ + && pct exec "$CTID" -- getent hosts deb.debian.org >/dev/null 2>&1; then + break + fi + sleep 2 +done +[ -n "$(address_of "$CTID")" ] || die "Kontejner nedostal adresu. Sedí bridge $BRIDGE?" +ok "Adresa $(address_of "$CTID")" + +install_into "$CTID" +hotovo "$CTID" diff --git a/deploy/pve-kostky.sh b/deploy/pve-kostky.sh index c374108..b9ad019 100755 --- a/deploy/pve-kostky.sh +++ b/deploy/pve-kostky.sh @@ -1,385 +1,23 @@ #!/usr/bin/env bash -# Založí na Proxmoxu LXC kontejner s počitadlem kostek. +# Skript se přejmenoval na deploy/pve-dice-counter.sh. # -# Pouští se v terminálu uzlu Proxmoxu jako root, jedním příkazem: +# Tenhle soubor tu zůstává schválně. Příkaz `update` v už založených +# kontejnerech si instalátor stahuje z téhle adresy — kdyby zmizela, +# aktualizace by u nich přestala fungovat dřív, než se stihnou přemigrovat. +# Až se tak stane, zmizí i tenhle soubor. # -# bash -c "$(curl -fsSL https://gitea.spacilovi.eu/david-spacil/dice-counter/raw/branch/main/deploy/pve-kostky.sh)" -# -# Aktualizace stávajícího kontejneru na novější vydání: -# -# CTID=123 MODE=update bash -c "$(curl -fsSL .../pve-kostky.sh)" -# -# Ze staženého souboru jde i obojí postaru: `bash pve-kostky.sh` a -# `bash pve-kostky.sh update 123`. -# -# Podoba je odkoukaná od community-scripts.org, ale nic z jejich frameworku -# se tu nestahuje — jejich build.func si instalační skript hledá natvrdo ve -# vlastním repozitáři, takže mimo něj nefunguje. -# -# Počítá se s domácí sítí. Appka nemá přihlašování a tenhle skript ji nijak -# nezabezpečuje; do internetu ji nepouštěj. -set -euo pipefail - -APP="Kostky" -GITEA="${GITEA:-https://gitea.spacilovi.eu}" -REPO="${REPO:-david-spacil/dice-counter}" - -# Výchozí hodnoty. Všechny se dají přebít proměnnou prostředí, třeba: -# MEMORY=1024 STORAGE=local-zfs bash -c "$(curl -fsSL ...)" -CT_HOSTNAME="${CT_HOSTNAME:-kostky}" -CORES="${CORES:-1}" -MEMORY="${MEMORY:-512}" -DISK="${DISK:-4}" -STORAGE="${STORAGE:-}" -TEMPLATE_STORAGE="${TEMPLATE_STORAGE:-local}" -BRIDGE="${BRIDGE:-vmbr0}" -PORT="${PORT:-8000}" -UNPRIVILEGED="${UNPRIVILEGED:-1}" -OSVERSION="${OSVERSION:-13}" -NESTING="${NESTING:-1}" -AUTOLOGIN="${AUTOLOGIN:-1}" # konzole ve webu Proxmoxu bez hesla -VERSION="${VERSION:-}" # prázdné = poslední vydání - -# --- výpisy ------------------------------------------------------------------ - -# Bez tohohle Ctrl+C zabije jen rozdělaný podproces a skript jede vesele dál -# — třeba rovnou zakládat kontejner, na který se čekat nemá. -trap 'echo; echo -e "\e[1;31m ✗\e[0m Přerušeno." >&2; exit 130' INT TERM - -msg() { echo -e "\e[1;34m →\e[0m $*"; } -ok() { echo -e "\e[1;32m ✓\e[0m $*"; } -die() { echo -e "\e[1;31m ✗\e[0m $*" >&2; exit 1; } - -header() { - echo - echo -e "\e[1;36m $APP\e[0m — počitadlo kostek do LXC" - echo -e " \e[2m$GITEA/$REPO\e[0m" - echo -} - -# --- instalátor, který poběží uvnitř kontejneru ------------------------------ -# -# Je tu jako text schválně. Skript se pouští i rourou z curlu, kdy na disku -# hostitele žádný soubor není a nebylo by co poslat dovnitř. Uvozovky kolem -# 'INSTALL' jsou podstatné: nic z toho se tady nesmí rozvinout, všechny -# proměnné patří až tomu, co poběží v kontejneru. -# -# Vypsat se dá i samostatně: `bash pve-kostky.sh instalator > install.sh`, -# což se hodí, když chceš appku dostat do kontejneru, který sis založil sám. -installer() { -cat <<'INSTALL' -#!/usr/bin/env bash -# Instalace počitadla uvnitř kontejneru. O Proxmoxu nic neví, takže se dá -# pustit v jakémkoli Debianu. Je idempotentní — druhé spuštění jen vymění -# binárku za nejnovější. +# Předává se všechno beze změny, včetně argumentů a proměnných prostředí. +# Na stdout nesmí přibýt ani řádek navíc: starý `update` si sem chodí pro +# `instalator` a výstup rovnou kontroluje přes `bash -n`. set -euo pipefail GITEA="${GITEA:-https://gitea.spacilovi.eu}" REPO="${REPO:-david-spacil/dice-counter}" -PORT="${PORT:-8000}" -VERSION="${VERSION:-}" -USER_NAME=kostky -HOME_DIR=/opt/kostky -DATA_DIR=/var/lib/kostky +NOVY=$(mktemp) +trap 'rm -f "$NOVY"' EXIT -msg() { echo -e "\e[1;34m →\e[0m $*"; } -ok() { echo -e "\e[1;32m ✓\e[0m $*"; } -die() { echo -e "\e[1;31m ✗\e[0m $*" >&2; exit 1; } +curl -fsSL "$GITEA/$REPO/raw/branch/main/deploy/pve-dice-counter.sh" -o "$NOVY" \ + || { echo "Skript se přesunul do deploy/pve-dice-counter.sh, ale nejde stáhnout." >&2; exit 1; } -case "$(dpkg --print-architecture)" in - amd64) ASSET=kostky-linux-x86_64 ;; - arm64) ASSET=kostky-linux-arm64 ;; - *) die "Pro architekturu $(dpkg --print-architecture) binárka není." ;; -esac - -msg "Doinstalovávám, co je potřeba ke stažení" -export DEBIAN_FRONTEND=noninteractive -apt-get update -qq -apt-get install -y -qq curl ca-certificates >/dev/null -ok "Základ je hotový" - -if [ -z "$VERSION" ]; then - msg "Zjišťuji poslední vydanou verzi" - # Jen tag; adresa přílohy se z něj složí, takže tu nepotřebujeme jq. - VERSION=$(curl -fsSL "$GITEA/api/v1/repos/$REPO/releases/latest" \ - | grep -o '"tag_name":[[:space:]]*"[^"]*"' | head -1 | cut -d'"' -f4) - [ -n "$VERSION" ] || die "Nepodařilo se zjistit poslední verzi z $GITEA." -fi -ok "Instaluje se $VERSION ($ASSET)" - -BASE="$GITEA/$REPO/releases/download/$VERSION" -TMP=$(mktemp -d) -trap 'rm -rf "$TMP"' EXIT - -msg "Stahuji binárku" -curl -fsSL -o "$TMP/$ASSET" "$BASE/$ASSET" \ - || die "$ASSET pro $VERSION na releasu není. Vydání pro tuhle architekturu možná ještě neproběhlo." -curl -fsSL -o "$TMP/$ASSET.sha256" "$BASE/$ASSET.sha256" \ - || die "Chybí kontrolní součet — radši nic neinstaluju." - -msg "Ověřuji kontrolní součet" -( cd "$TMP" && sha256sum -c "$ASSET.sha256" >/dev/null ) \ - || die "Kontrolní součet nesedí. Stažený soubor zahazuju." -ok "Součet sedí" - -id -u "$USER_NAME" >/dev/null 2>&1 \ - || useradd --system --home-dir "$HOME_DIR" --shell /usr/sbin/nologin "$USER_NAME" - -install -d -o root -g root -m 755 "$HOME_DIR" - -# Zastavit se dá jen to, co běží — při první instalaci služba ještě není. -if systemctl is-active --quiet kostky; then - systemctl stop kostky -fi - -install -o root -g root -m 755 "$TMP/$ASSET" "$HOME_DIR/kostky" -echo "$VERSION" > "$HOME_DIR/verze" -ok "Binárka je na místě" - -msg "Zapisuji službu" -cat > /etc/systemd/system/kostky.service < /etc/systemd/system/container-getty@1.service.d/override.conf <<'GETTY' -[Service] -ExecStart= -ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 $TERM -GETTY - systemctl daemon-reload - systemctl restart container-getty@1.service 2>/dev/null || true - ok "Konzole se přihlásí sama" -fi - -# --- příkaz update ---------------------------------------------------------- - -# Instalátor si necháme, ať je z čeho aktualizovat. Když se skript pouští -# rourou, soubor neexistuje a zůstane ten z minula. -if [ -f "$0" ]; then - install -m 755 "$0" "$HOME_DIR/install.sh" -fi - -cat > /usr/bin/update </dev/null \\ - && bash "\$NOVY" instalator > "\$NOVY.in" 2>/dev/null \\ - && bash -n "\$NOVY.in" 2>/dev/null; then - install -m 755 "\$NOVY.in" "$HOME_DIR/install.sh" -fi -rm -f "\$NOVY" "\$NOVY.in" - -exec env PORT="$PORT" GITEA="$GITEA" REPO="$REPO" bash "$HOME_DIR/install.sh" -UPDATE -chmod 755 /usr/bin/update -ok "Aktualizovat půjde příkazem: update" - -msg "Čekám, až začne odpovídat" -for _ in $(seq 30); do - curl -fsS -o /dev/null "http://127.0.0.1:$PORT/" 2>/dev/null && break - sleep 1 -done -curl -fsS -o /dev/null "http://127.0.0.1:$PORT/" \ - || die "Služba nastartovala, ale neodpovídá. Mrkni na journalctl -u kostky." - -# Verzi bereme ze souboru, ne z binárky. Starší vydání --version neumí -# a místo výpisu by nastartovala server, který by tenhle skript zavěsil. -ok "Počitadlo $(cat "$HOME_DIR/verze") odpovídá na portu $PORT" -INSTALL -} - -# --- společné části ---------------------------------------------------------- - -install_into() { - local ctid="$1" tmp - tmp=$(mktemp) - installer > "$tmp" - - msg "Posílám instalátor do kontejneru $ctid" - pct push "$ctid" "$tmp" /root/kostky-install.sh --perms 0755 - rm -f "$tmp" - - pct exec "$ctid" -- env PORT="$PORT" GITEA="$GITEA" REPO="$REPO" \ - VERSION="$VERSION" AUTOLOGIN="$AUTOLOGIN" bash /root/kostky-install.sh -} - -address_of() { - pct exec "$1" -- hostname -I 2>/dev/null | awk '{print $1}' -} - -hotovo() { - local ctid="$1" ip jmeno - ip=$(address_of "$ctid") - jmeno=$(pct config "$ctid" | awk -F': ' '/^hostname:/ {print $2}') - - echo - ok "Hotovo. Kontejner $ctid ($jmeno) běží." - echo - echo -e " Zápisník na notebook: \e[1;32mhttp://${ip}:${PORT}/board\e[0m" - echo -e " Zadávání z telefonu: \e[1;32mhttp://${ip}:${PORT}/\e[0m" - echo - echo -e " \e[2mDatabáze: /var/lib/kostky/dice.db (uvnitř kontejneru)" - echo -e " Aktualizace: v konzoli kontejneru napiš update" - echo -e " Log: pct exec $ctid -- journalctl -u kostky -f" - echo -e " Konzole: pct enter $ctid" - echo -e " Zrušit: pct stop $ctid && pct destroy $ctid\e[0m" - echo -} - -# --- co se má vlastně dělat -------------------------------------------------- -# -# Rourou z curlu se argumenty předávají mizerně, tak jde všechno i proměnnou: -# MODE=update CTID=123. Ze souboru funguje i `bash pve-kostky.sh update 123`. -MODE="${MODE:-${1:-create}}" -[ "$MODE" = "update" ] && CTID="${CTID:-${2:-}}" - -if [ "$MODE" = "instalator" ]; then - installer - exit 0 -fi - -command -v pct >/dev/null || die "Tohle patří na uzel Proxmoxu — pct tu není." -[ "$(id -u)" -eq 0 ] || die "Spusť to jako root." - -# --- aktualizace ------------------------------------------------------------- - -if [ "$MODE" = "update" ]; then - [ -n "${CTID:-}" ] || die "Řekni který: CTID=123 MODE=update ..." - pct status "$CTID" >/dev/null 2>&1 || die "Kontejner $CTID neexistuje." - - header - if [ "$(pct status "$CTID")" != "status: running" ]; then - msg "Startuji kontejner" - pct start "$CTID" - sleep 5 - fi - - install_into "$CTID" - hotovo "$CTID" - exit 0 -fi - -# --- nový kontejner ---------------------------------------------------------- - -header - -# Úložiště se nehádá. local-lvm na ZFS instalacích neexistuje a pct create by -# spadlo až po půlce práce, tak se radši zeptáme systému, co tu opravdu je. -if [ -z "$STORAGE" ]; then - STORAGE=$(pvesm status -content rootdir 2>/dev/null \ - | awk 'NR>1 && $3=="active" {print $1; exit}') - [ -n "$STORAGE" ] || die "Nenašel jsem úložiště pro kontejnery. Zadej STORAGE=; co máš, ukáže pvesm status." - msg "Úložiště: $STORAGE (nalezeno automaticky)" -else - pvesm status -content rootdir 2>/dev/null | awk 'NR>1 {print $1}' | grep -qx "$STORAGE" \ - || die "Úložiště $STORAGE pro kontejnery nesedí. Co máš, ukáže: pvesm status -content rootdir" - msg "Úložiště: $STORAGE" -fi - -CTID="${CTID:-$(pvesh get /cluster/nextid)}" -msg "Kontejner dostane číslo $CTID" - -# Architektura uzlu, ne první šablona v seznamu. pveam nabízí amd64 i arm64 -# vedle sebe a bez tohohle filtru by výběr padl na tu abecedně poslední. -ARCH=$(dpkg --print-architecture) -SABLONA="debian-${OSVERSION}-standard[^[:space:]]*_${ARCH}\.tar\.[a-z]*" - -msg "Hledám šablonu Debianu $OSVERSION pro $ARCH" - -# Nejdřív co už na uzlu leží — stahovat 120 MB znovu je zbytečné. -TEMPLATE=$(pveam list "$TEMPLATE_STORAGE" 2>/dev/null | grep -o "$SABLONA" | sort -V | tail -1) - -if [ -n "$TEMPLATE" ]; then - ok "Šablona $TEMPLATE (už je na uzlu)" -else - pveam update >/dev/null 2>&1 || true - TEMPLATE=$(pveam available --section system 2>/dev/null | grep -o "$SABLONA" | sort -V | tail -1) - [ -n "$TEMPLATE" ] || die "Šablona pro Debian $OSVERSION a $ARCH není k dispozici." - - msg "Stahuji $TEMPLATE (asi 120 MB, chvíli to trvá)" - pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null \ - || die "Stažení šablony selhalo." - ok "Šablona $TEMPLATE" -fi - -# Nesting: Debian 13 veze systemd 257 a ten v neprivilegovaném kontejneru bez -# něj nedostane, co potřebuje — Proxmox na to při startu sám upozorňuje. -# Stejnou výchozí hodnotu mají i community-scripts. -msg "Zakládám kontejner" -pct create "$CTID" "$TEMPLATE_STORAGE:vztmpl/$TEMPLATE" \ - --hostname "$CT_HOSTNAME" \ - --cores "$CORES" \ - --memory "$MEMORY" \ - --swap 256 \ - --rootfs "$STORAGE:$DISK" \ - --net0 "name=eth0,bridge=$BRIDGE,ip=dhcp" \ - --unprivileged "$UNPRIVILEGED" \ - --features "nesting=$NESTING" \ - --ostype debian \ - --onboot 1 \ - --description "$APP — $GITEA/$REPO" >/dev/null -ok "Kontejner $CTID založen" - -msg "Startuji" -pct start "$CTID" - -msg "Čekám na síť" -for _ in $(seq 60); do - if [ -n "$(address_of "$CTID")" ] \ - && pct exec "$CTID" -- getent hosts deb.debian.org >/dev/null 2>&1; then - break - fi - sleep 2 -done -[ -n "$(address_of "$CTID")" ] || die "Kontejner nedostal adresu. Sedí bridge $BRIDGE?" -ok "Adresa $(address_of "$CTID")" - -install_into "$CTID" -hotovo "$CTID" +bash "$NOVY" "$@" diff --git a/kostky.spec b/dice-counter.spec similarity index 97% rename from kostky.spec rename to dice-counter.spec index cffe88e..ca1cb7f 100644 --- a/kostky.spec +++ b/dice-counter.spec @@ -28,7 +28,7 @@ exe = EXE( analysis.scripts, analysis.binaries, analysis.datas, - name="kostky", + name="dice-counter", console=True, # Ořezání symbolů šetří pár megabajtů, ale jen na Linuxu. Na macOS by # rozbilo podpis, který si PyInstaller sám přidává a bez kterého se diff --git a/dice.py b/dice.py index 433eb89..05138d4 100644 --- a/dice.py +++ b/dice.py @@ -134,7 +134,7 @@ if __name__ == "__main__": console.utf8() if {"--version", "-V"} & set(sys.argv[1:]): - print(f"kostky {version.current()}") + print(f"dice-counter {version.current()}") sys.exit(0) main() diff --git a/storage.py b/storage.py index db29428..a77eea2 100644 --- a/storage.py +++ b/storage.py @@ -27,6 +27,14 @@ def data_home() -> Path: or Path.home() / ".local" / "share") +APP_DIR = "dice-counter" + +# Do vydání 1.2.x se adresář jmenoval jinak. Kdo má databázi po staru, o ni +# přejmenováním nepřijde — použije se dál. Až se stará jména přestanou +# podporovat, zmizí i tohle. +STARY_APP_DIR = "kostky" + + def default_db() -> Path: """Kam se ukládá databáze. @@ -38,9 +46,14 @@ def default_db() -> Path: chosen = os.environ.get("DICE_DB") if chosen: return Path(chosen) - if getattr(sys, "frozen", False): - return data_home() / "kostky" / "dice.db" - return Path("dice.db") + if not getattr(sys, "frozen", False): + return Path("dice.db") + + nova = data_home() / APP_DIR / "dice.db" + stara = data_home() / STARY_APP_DIR / "dice.db" + if not nova.exists() and stara.exists(): + return stara + return nova DB_PATH = default_db() diff --git a/templates/base.html b/templates/base.html index a2ef8c5..d792baa 100644 --- a/templates/base.html +++ b/templates/base.html @@ -8,6 +8,6 @@ {% block body %}{% endblock %} -
kostky {{ verze }}
+
dice-counter {{ verze }}
diff --git a/tests/test_storage.py b/tests/test_storage.py index 34af97a..f456914 100644 --- a/tests/test_storage.py +++ b/tests/test_storage.py @@ -152,7 +152,29 @@ def test_umisteni_databaze_z_binarky(monkeypatch, tmp_path): monkeypatch.setattr(storage.sys, "platform", "linux") monkeypatch.setenv("XDG_DATA_HOME", str(tmp_path)) - assert storage.default_db() == tmp_path / "kostky" / "dice.db" + assert storage.default_db() == tmp_path / "dice-counter" / "dice.db" + + +def test_umisteni_databaze_po_starem(monkeypatch, tmp_path): + """Kdo má databázi pod starým jménem, o ni přejmenováním nepřijde.""" + monkeypatch.delenv("DICE_DB", raising=False) + monkeypatch.setattr(storage.sys, "frozen", True, raising=False) + monkeypatch.setattr(storage.sys, "platform", "linux") + monkeypatch.setenv("XDG_DATA_HOME", str(tmp_path)) + + stara = tmp_path / "kostky" / "dice.db" + stara.parent.mkdir() + stara.touch() + + assert storage.default_db() == stara + + # Jakmile nová existuje, stará se ignoruje — jinak by se dvě databáze + # přetahovaly o to, která platí. + nova = tmp_path / "dice-counter" / "dice.db" + nova.parent.mkdir() + nova.touch() + + assert storage.default_db() == nova def test_data_home_podle_systemu(monkeypatch, tmp_path): diff --git a/version.py b/version.py index 4e9715f..b560150 100644 --- a/version.py +++ b/version.py @@ -17,7 +17,7 @@ UNKNOWN = "neznámá" def bundled() -> str: """Verze vypálená do binárky při stavbě. - `build.sh` ji zapíše do souboru, `kostky.spec` ji přibalí. V binárce + `build.sh` ji zapíše do souboru, `dice-counter.spec` ji přibalí. V binárce leží vedle šablon v dočasném adresáři, na který ukazuje `sys._MEIPASS`. """ root = Path(getattr(sys, "_MEIPASS", Path(__file__).parent)) diff --git a/web.py b/web.py index 97c3475..747d7b4 100644 --- a/web.py +++ b/web.py @@ -350,7 +350,7 @@ def export(): return send_file(io.BytesIO(data), mimetype="application/vnd.sqlite3", as_attachment=True, - download_name=f"kostky-{date.today().isoformat()}.db") + download_name=f"dice-counter-{date.today().isoformat()}.db") @app.route("/stats") @@ -364,7 +364,7 @@ def hall(): def announce() -> None: """Vypíše, kde všude je počitadlo k mání, a čím je zrovna spuštěné.""" - print(f"Kostky {version.current()}\n") + print(f"dice-counter {version.current()}\n") found = net.addresses() @@ -384,7 +384,7 @@ if __name__ == "__main__": console.utf8() if {"--version", "-V"} & set(sys.argv[1:]): - print(f"kostky {version.current()}") + print(f"dice-counter {version.current()}") sys.exit(0) announce() From 6443a939556d3b296829d6700b0456066a4d189a Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 23 Aug 2026 22:32:39 +0200 Subject: [PATCH 2/3] =?UTF-8?q?Nenechat=20zkou=C5=A1ku=20bin=C3=A1rky=20vi?= =?UTF-8?q?set=20na=20zbytku=20z=20minul=C3=A9ho=20b=C4=9Bhu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .gitea/workflows/binarka.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/binarka.yml b/.gitea/workflows/binarka.yml index c78ffa9..d5e8a61 100644 --- a/.gitea/workflows/binarka.yml +++ b/.gitea/workflows/binarka.yml @@ -66,10 +66,15 @@ jobs: - name: Zkouška run: | - XDG_DATA_HOME=/tmp/zkouska DICE_PORT=8321 DICE_HOST=127.0.0.1 \ + # Vlastní adresář pro každý běh. Runner si /tmp mezi běhy drží + # a binárka umí sáhnout po databázi ve starém umístění, takže + # zbytek po dřívější zkoušce by tuhle poslal vedle. + XDG=$(mktemp -d) + + XDG_DATA_HOME="$XDG" DICE_PORT=8321 DICE_HOST=127.0.0.1 \ ./dist/dice-counter > /tmp/server.log 2>&1 & server=$! - trap 'kill $server 2>/dev/null || true' EXIT + trap 'kill $server 2>/dev/null || true; rm -rf "$XDG"' EXIT for _ in $(seq 30); do curl -sf -o /dev/null http://127.0.0.1:8321/ && break @@ -79,7 +84,7 @@ jobs: curl -sf -o /dev/null http://127.0.0.1:8321/ curl -sf -o /dev/null http://127.0.0.1:8321/static/style.css curl -sf -o /dev/null http://127.0.0.1:8321/board - test -f /tmp/zkouska/dice-counter/dice.db + test -f "$XDG/dice-counter/dice.db" ./dist/dice-counter --version cat /tmp/server.log From 182d0a3fdc2e17763a4300613f305868f6590106 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 23 Aug 2026 22:33:40 +0200 Subject: [PATCH 3/3] =?UTF-8?q?Up=C5=99esnit=20koment=C3=A1=C5=99:=20nezmi?= =?UTF-8?q?z=C3=AD=20t=C5=99i=20=C5=99=C3=A1dky,=20ale=20cel=C3=BD=20blok?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/pve-dice-counter.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/pve-dice-counter.sh b/deploy/pve-dice-counter.sh index 5cb7314..d5f280b 100755 --- a/deploy/pve-dice-counter.sh +++ b/deploy/pve-dice-counter.sh @@ -85,7 +85,7 @@ DATA_DIR=/var/lib/dice-counter SERVICE=dice-counter # Do vydání 1.2.x se všechno jmenovalo kostky. Instalace z té doby se při -# aktualizaci přestěhují; až budou přemigrované, tyhle tři řádky zmizí. +# aktualizaci přestěhují; až budou přemigrované, tenhle blok zmizí. STARY_USER=kostky STARY_HOME=/opt/kostky STARY_DATA=/var/lib/kostky