diff --git a/.gitea/workflows/binarka.yml b/.gitea/workflows/binarka.yml index 32fa422..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 \ - ./dist/kostky > /tmp/server.log 2>&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,15 +84,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 "$XDG/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 +112,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..d5f280b --- /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é, tenhle blok 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 }}
+ 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()