Druhý krok po #16, rovnou celý. Dvojkolejnost dávala smysl pro projekt
s neznámými uživateli; tady běží jedna instance a ta je přemigrovaná.
Pryč je:
- deploy/pve-kostky.sh (přesměrování na nový skript)
- stěhování ze starého jména v instalátoru včetně bloku STARY_*
- záložní jméno přílohy kostky-* v instalátoru
- věšení příloh pod dvěma jmény v obou workflow
- záloha na ~/.local/share/kostky/dice.db ve storage.py
- odstavce o přechodu v README
Jediné, co ve zdrojácích zůstalo, je docstring "Pravidla hry v kostky"
v core.py — to je česky pojmenovaná hra, ne identifikátor.
POZOR na pořadí: instalátor teď hledá jen dice-counter-*, a poslední
vydání (v1.2.1) má na releasu pouze kostky-*. Do otagování v1.2.2 tedy
`update` ani čerstvá instalace nemají co stáhnout. Merge a tag patří
k sobě.
Ověřeno v debianím kontejneru: čistá instalace, druhé spuštění za sebou,
a vydání bez nových jmen spadne se srozumitelnou hláškou místo toho, aby
sáhlo po starém. Binárka postavená lokálně zakládá databázi v
…/dice-counter/ a starou vedle sebe ignoruje. 118 testů.
Closes#19
Krok padl na `test -f /tmp/zkouska/dice-counter/dice.db`. Runner si /tmp
mezi běhy drží, takže tam po dřívějších stavbách zůstalo
/tmp/zkouska/kostky/dice.db — a binárka po něm nově sáhne, dokud nová
databáze neexistuje. Zkouška tedy hledala soubor, který se schválně
nezaložil.
Chová se to správně, jen se to nedá zkoušet na adresáři, do kterého si
sype každý běh. Nově dostane každý svůj vlastní přes mktemp a po sobě ho
uklidí.
Reprodukováno lokálně: se zbytkem po staru krok padne, s vlastním
adresářem projde.
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
Značka image ve zkoušce, testovací kontejner a builder buildx se jmenovaly
kostky. Všechno to vzniká a mizí uvnitř jednoho běhu CI, nikam se to
nepropisuje a nic to nestojí — jen jsem to zkopíroval ze zvyku.
Jména v docker-compose.yaml (služba, container_name, svazek kostky-data)
zůstávají; ta se dotýkají uložených dat a patří k tomu úklidu ve #16.
Domácí runner běží v LXC. binfmt_misc je vlastnost jádra hostitele a do toho
se kvůli počitadlu kostek vrtat nebude — je produkční. tonistiigi/binfmt sice
hlásil úspěch, ale na hostiteli po něm nezůstala žádná registrace, takže
buildkit arm64 mezi platformami nikdy neuvidí.
Stejná dělba jako u binárek: doma se hlídá, na GitHubu se vydává. Zdejší
workflow staví nativní amd64 obyčejným `docker build` a zkouší ho spustit nad
každým pull requestem; žádný buildx, žádná emulace, nic, co by na runneru
mohlo chybět. Publikaci multiarch image převzalo .github/workflows/image.yml,
kde jsou běhouni plnohodnotné virtuály a emulace funguje bez zásahu.
Publikovat jde nově jen z tagu. Ruční spuštění nad větví by udělalo `:latest`
ukazující na rozdělanou práci.
První běh na runneru odhalil dvě věci.
Rouru do `head` shodil pipefail: head zavřel rouru po dvaceti řádcích, docker
dostal EPIPE a krok skončil na 255, přestože se builder založil v pořádku.
Horší je, že binfmt se sice nainstaloval (installing: arm64 OK), ale buildkit
pak arm64 mezi platformami nenabídl. Emulace musí být registrovaná s příznakem
F, aby si na ni buildkit ve svém kontejneru sáhl bez interpretu v souborovém
systému; jinak vidí jen nativní platformy. Doma to tak mám z qemu-user-static
a proto tam multiarch stavba prošla.
Builder se teď staví načisto — ten z minulého běhu by si pamatoval platformy
z doby před registrací — a hned po něm se ověří, že arm64 v seznamu opravdu
je. Bez toho by stavba spadla až na konci s hláškou, ze které se nic nepozná.
Compose soubor měl v sobě build: context: .., takže si image stavěl z
lokálních zdrojáků a bez naklonovaného repozitáře byl k ničemu. Proti LXC
cestě, kde se stahuje hotová binárka, to byla nesrovnalost.
Nové workflow staví image na domácím runneru a při vydání ho pošle do
registru Gitey, pro amd64 i arm64. Compose se tím smrskl na jeden soubor,
který si člověk stáhne a rovnou spustí.
Automatický token Actions na balíčky nestačí — Gitea to zatím neumí a sama
v dokumentaci odkazuje na osobní token. Je v secrets pod PACKAGE_TOKEN;
jméno nesmí začínat na GITEA_, ten prefix si Gitea vyhrazuje.
Nad pull requesty se image staví a zkouší, ale nepublikuje. Dockerfile do
teď v CI žádné pokrytí neměl a rozbil by se až při releasu.
Image se jmenuje podle repozitáře, dice-counter. Zbytek projektu pořád mluví
o kostkách; sjednocení je na samostatné issue, protože se dotkne vydaných
binárek i běžících instalací.
Venku jsou čtyři soubory na release, tři systémy a k tomu zdrojáky. Když
někdo napíše, že mu něco nefunguje, není jak zjistit, co vlastně pustil.
Verzi zapisuje build.sh do verze.txt, kostky.spec ji přibalí a version.py ji
z rozbalené binárky přečte. Ze zdrojáků má přednost git describe, který ví
i o commitech nad tagem a o rozdělané práci. V CI se na tagu vnucuje
proměnnou, protože runner klonuje jeden commit bez značek.
Hlásí se přes --version, v úvodní hlášce serveru a v patičce každé stránky.
Zkouška v obou workflow ověří, že se do binárky opravdu dostala.
Bez zamčených verzí si každá stavba stáhne to, co je zrovna nejnovější:
binárka z dneška a binárka z příštího jara obsahují něco jiného a není jak
zjistit co. Zároveň může vydání kterékoli knihovny rozbít build, aniž by se
sáhlo na řádku kódu — a nejspíš zrovna ve chvíli, kdy se tagne release.
Volné seznamy jsou nově v `.in`, zamčené v `.txt`. Rozděleno na tři: běh,
testy a stavba. Pytest se tak přestane instalovat do prostředí, kde se
staví binárka, a PyInstaller má konečně taky zamčenou verzi — ta na podobu
výsledku sahá ze všech nejvíc.
Zůstává, že se verze píšou i v hlavičce PEP 723, jinak by přestalo fungovat
`uv run web.py`. Aby se ta dvě místa nerozešla, hlídá je test.
Věší se jako druhá příloha ve formátu sha256sum, počítaná nad jménem, pod
kterým se soubor stahuje — aby se dala ověřit rovnou přes
sha256sum -c, bez přejmenovávání.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Matice Python 3.11 až 3.14 — u projektu, který deklaruje >=3.11, se hodí
vědět, že to na všech čtyřech opravdu jede. Pythony obstará uv, na
hostiteli nemusí být žádný.
K pytestu ještě skriptovaná partie v terminálové verzi. Pytest sahá na
core.py, prompty v dice.py nikdo netestoval; tohle projde dvě nuly, třetí
s vynulováním a výhru tak, jak to odehraje člověk.
Runner sdílí pracovní adresář mezi variantami matice, proto max-parallel 1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PyInstaller hledá objdumpem, na kterých knihovnách binárka visí. Runner
v host módu ho nemá — je to jediné, co musí být na hostiteli, zbytek si
obstará uv.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Runner běží v host módu, bez dockeru, takže se v něm kontejner na AlmaLinux
spustit nedá. Ukázalo se ale, že kontejner potřeba není: stačí stavět proti
samostatnému CPythonu od uv. Ten je slinkovaný s glibc 2.17 a nic
z hostitele se do binárky nedostane — změřeno objdumpem přes všechno, co
se z ní rozbaluje. Výsledek je tedy přenositelnější než přes AlmaLinux 8
(2.28) a build.sh je o polovinu kratší.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Otagovaný commit postaví binárku na runneru, projede testy, zkusí ji
nastartovat a pověsí ji na release. Nad pull requesty běží totéž bez
posledního kroku, ať se rozbitá stavba pozná dřív než na tagu.
Staví se v kontejneru na AlmaLinux 8 ze stejného důvodu jako build.sh —
kvůli glibc. Záměrně bez hotových akcí z marketplace: na vlastním runneru
tím odpadá starost, jestli je v kontejneru node.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>