Sjednotit pojmenování: kostky → dice-counter
binárka / linux (pull_request) Failing after 10s
image / image (pull_request) Successful in 7s
testy / pytest (3.11) (pull_request) Successful in 1s
testy / pytest (3.12) (pull_request) Successful in 1s
testy / pytest (3.13) (pull_request) Successful in 1s
testy / pytest (3.14) (pull_request) Successful in 1s
binárka / linux (pull_request) Failing after 10s
image / image (pull_request) Successful in 7s
testy / pytest (3.11) (pull_request) Successful in 1s
testy / pytest (3.12) (pull_request) Successful in 1s
testy / pytest (3.13) (pull_request) Successful in 1s
testy / pytest (3.14) (pull_request) Successful in 1s
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 <verze>" 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
This commit is contained in:
1 parent
96f2fc1028
commit
7449c01b14
13 files changed
+575
-427
No files matched your search
@@ -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" \
|
||||
|
||||
@@ -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" \
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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/
|
||||
Executable
+445
@@ -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" <<EOF
|
||||
[Unit]
|
||||
Description=Počitadlo kostek
|
||||
Documentation=$GITEA/$REPO
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$USER_NAME
|
||||
Environment=DICE_DB=$DATA_DIR/dice.db
|
||||
Environment=DICE_PORT=$PORT
|
||||
ExecStart=$HOME_DIR/dice-counter
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
# Databáze je jediné, co appka potřebuje mít zapisovatelné. StateDirectory ji
|
||||
# založí a předá správnému uživateli, takže se tu nemusí nic chownovat.
|
||||
StateDirectory=dice-counter
|
||||
ReadWritePaths=$DATA_DIR
|
||||
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
# Binárka se při každém startu rozbaluje do /tmp; tady do vlastního, ne do
|
||||
# sdíleného.
|
||||
PrivateTmp=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable --quiet --now "$SERVICE"
|
||||
ok "Služba běží"
|
||||
|
||||
# --- konzole v rozhraní Proxmoxu --------------------------------------------
|
||||
|
||||
if [ "${AUTOLOGIN:-1}" = "1" ]; then
|
||||
msg "Nastavuji konzoli"
|
||||
# Kontejner nemá root heslo, takže by se do konzole ve webu Proxmoxu
|
||||
# nedalo dostat. Autologin to řeší stejně, jako to dělají community-scripts.
|
||||
# Nová práva to nikomu nedává — kdo má web Proxmoxu, má root na uzlu tak
|
||||
# jako tak.
|
||||
mkdir -p /etc/systemd/system/container-getty@1.service.d
|
||||
cat > /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 <<UPDATE
|
||||
#!/usr/bin/env bash
|
||||
# Aktualizace počitadla na poslední vydání. Stačí napsat: update
|
||||
set -euo pipefail
|
||||
|
||||
# Nejdřív zkusíme obnovit i samotný instalátor, kdyby se mezitím zlepšil.
|
||||
# Bez sítě nebo při změněné adrese se použije ten uložený.
|
||||
NOVY=\$(mktemp)
|
||||
if curl -fsSL "$GITEA/$REPO/raw/branch/main/deploy/pve-dice-counter.sh" -o "\$NOVY" 2>/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=<jméno>; 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"
|
||||
+13
-375
@@ -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 <<EOF
|
||||
[Unit]
|
||||
Description=Počitadlo kostek
|
||||
Documentation=$GITEA/$REPO
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$USER_NAME
|
||||
Environment=DICE_DB=$DATA_DIR/dice.db
|
||||
Environment=DICE_PORT=$PORT
|
||||
ExecStart=$HOME_DIR/kostky
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
# Databáze je jediné, co appka potřebuje mít zapisovatelné. StateDirectory ji
|
||||
# založí a předá správnému uživateli, takže se tu nemusí nic chownovat.
|
||||
StateDirectory=kostky
|
||||
ReadWritePaths=$DATA_DIR
|
||||
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
# Binárka se při každém startu rozbaluje do /tmp; tady do vlastního, ne do
|
||||
# sdíleného.
|
||||
PrivateTmp=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable --quiet --now kostky
|
||||
ok "Služba běží"
|
||||
|
||||
# --- konzole v rozhraní Proxmoxu --------------------------------------------
|
||||
|
||||
if [ "${AUTOLOGIN:-1}" = "1" ]; then
|
||||
msg "Nastavuji konzoli"
|
||||
# Kontejner nemá root heslo, takže by se do konzole ve webu Proxmoxu
|
||||
# nedalo dostat. Autologin to řeší stejně, jako to dělají community-scripts.
|
||||
# Nová práva to nikomu nedává — kdo má web Proxmoxu, má root na uzlu tak
|
||||
# jako tak.
|
||||
mkdir -p /etc/systemd/system/container-getty@1.service.d
|
||||
cat > /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 <<UPDATE
|
||||
#!/usr/bin/env bash
|
||||
# Aktualizace počitadla na poslední vydání. Stačí napsat: update
|
||||
set -euo pipefail
|
||||
|
||||
# Nejdřív zkusíme obnovit i samotný instalátor, kdyby se mezitím zlepšil.
|
||||
# Bez sítě nebo při změněné adrese se použije ten uložený.
|
||||
NOVY=\$(mktemp)
|
||||
if curl -fsSL "$GITEA/$REPO/raw/branch/main/deploy/pve-kostky.sh" -o "\$NOVY" 2>/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=<jméno>; 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" "$@"
|
||||
@@ -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
|
||||
@@ -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()
|
||||
+16
-3
@@ -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()
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}{% endblock %}
|
||||
<footer class="verze">kostky {{ verze }}</footer>
|
||||
<footer class="verze">dice-counter {{ verze }}</footer>
|
||||
</body>
|
||||
</html>
|
||||
+23
-1
@@ -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):
|
||||
|
||||
+1
-1
@@ -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))
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in new issue
Block a user