Binárky pro Windows a macOS přes GitHub Actions
binárka / linux (pull_request) Successful in 11s
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 0s
binárka / linux (pull_request) Successful in 11s
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 0s
PyInstaller neumí křížovou kompilaci — binárku pro každý systém musí postavit ten systém. Vlastní runner pro Windows a hlavně pro macOS by byl nepoměr, tak si tyhle stroje půjčujeme od GitHub Actions. GitHub je jen půjčená dílna, ne druhý domov projektu: repozitář se tam z Gitey zrcadlí, hotové soubory se posílají zpátky na zdejší release přes Gitea API a stránka s releasy zůstává jedna. Linux se tam schválně nestaví; doma to jde proti glibc 2.17 a je to zároveň pojistka, kdyby GitHub vypadl. build.sh je společný pro všechny tři systémy, liší se jen tím, že Windows dává spustitelné soubory venvu do Scripts/ místo bin/. Ořezání symbolů zůstává jen Linuxu: na macOS by rozbilo podpis, který si PyInstaller sám přidává a bez kterého se binárka na Apple Silicon vůbec nespustí. Zkouška po stavbě je stejná jako u linuxové: nastartovat, stáhnout si stránku i styly a ověřit, že se založila databáze. Nepodepsané binárky si Gatekeeper ani SmartScreen nenechají líbit, tak je v README napsané, co s tím — certifikáty za tisíce ročně by na počitadlo kostek byly nesmysl. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
26338bfa29
commit
a7621bb01b
4 files changed
+219
-26
No files matched your search
@@ -0,0 +1,124 @@
|
||||
# Binárky pro Windows a macOS.
|
||||
#
|
||||
# PyInstaller neumí křížovou kompilaci: binárku pro každý systém musí postavit
|
||||
# ten systém. Kupovat kvůli tomu Mac nebo krmit Windows VM by bylo přehnané,
|
||||
# tak si tyhle stroje půjčujeme od GitHub Actions.
|
||||
#
|
||||
# GitHub je tu jen půjčená dílna, ne druhý domov projektu: repozitář se sem
|
||||
# z Gitey zrcadlí a hotové soubory se posílají zpátky na tamní release přes
|
||||
# Gitea API. Jedna stránka s releasy, ta původní.
|
||||
#
|
||||
# Linux se tu schválně nestaví — o ten se stará vlastní runner
|
||||
# (.gitea/workflows/binarka.yml) a dělá to líp, proti glibc 2.17.
|
||||
name: binárky
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
tags: ["v*"]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GITEA: https://gitea.spacilovi.eu
|
||||
GITEA_REPO: david-spacil/dice-counter
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-latest
|
||||
asset: kostky-windows-x86_64.exe
|
||||
built: dist/kostky.exe
|
||||
- os: macos-13 # poslední Intel běhoun
|
||||
asset: kostky-macos-x86_64
|
||||
built: dist/kostky
|
||||
- os: macos-latest # Apple Silicon
|
||||
asset: kostky-macos-arm64
|
||||
built: dist/kostky
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- uses: astral-sh/setup-uv@v10
|
||||
|
||||
- name: Testy
|
||||
run: uv run --with-requirements requirements.txt --no-project pytest -q
|
||||
|
||||
- name: Binárka
|
||||
run: ./build.sh
|
||||
|
||||
- name: Zkouška
|
||||
run: |
|
||||
# Binárka se musí umět rozbalit, najít šablony a začít poslouchat.
|
||||
# Adresa se vnucuje, ať zkouška nezávisí na síti běhounu.
|
||||
export DICE_HOST=127.0.0.1 DICE_PORT=8123 DICE_DB=zkouska/dice.db
|
||||
"${{ matrix.built }}" &
|
||||
|
||||
for _ in $(seq 30); do
|
||||
curl -sf -o /dev/null "http://127.0.0.1:8123/" && break
|
||||
sleep 1
|
||||
done
|
||||
|
||||
curl -sf -o /dev/null "http://127.0.0.1:8123/" || {
|
||||
echo "Server se nerozeběhl." >&2; exit 1; }
|
||||
curl -sf -o /dev/null "http://127.0.0.1:8123/static/style.css"
|
||||
curl -sf "http://127.0.0.1:8123/board" | grep -q "127.0.0.1:8123"
|
||||
test -f zkouska/dice.db
|
||||
|
||||
echo "Binárka jede."
|
||||
|
||||
- name: Na release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
env:
|
||||
TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
ASSET: ${{ matrix.asset }}
|
||||
run: |
|
||||
api="$GITEA/api/v1/repos/$GITEA_REPO"
|
||||
auth="Authorization: token $TOKEN"
|
||||
json() { uv run --no-project python -c "$@"; }
|
||||
|
||||
# Release u tagu být může, ale nemusí — dá se založit i ručně a
|
||||
# sahají na něj čtyři buildy naráz, tak se po neúspěchu ptáme znovu.
|
||||
for _ in 1 2 3; do
|
||||
id=$(curl -s -H "$auth" "$api/releases/tags/${GITHUB_REF_NAME}" \
|
||||
| json 'import json,sys; print(json.load(sys.stdin).get("id",""))')
|
||||
[ -n "$id" ] && break
|
||||
|
||||
curl -s -o /dev/null -X POST -H "$auth" -H "Content-Type: application/json" \
|
||||
-d "{\"tag_name\":\"${GITHUB_REF_NAME}\",\"name\":\"${GITHUB_REF_NAME}\"}" \
|
||||
"$api/releases"
|
||||
done
|
||||
[ -n "$id" ] || { echo "Release ${GITHUB_REF_NAME} se nepodařilo najít." >&2; exit 1; }
|
||||
|
||||
# macOS zná jen shasum, Git Bash na Windows jen sha256sum. Formát
|
||||
# výsledku je stejný, takže se dá ověřit kterýmkoli z nich.
|
||||
if command -v sha256sum >/dev/null; then
|
||||
soucet() { sha256sum "$@"; }
|
||||
else
|
||||
soucet() { shasum -a 256 "$@"; }
|
||||
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"
|
||||
|
||||
for file in "$ASSET" "$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" \
|
||||
| while read -r old; do
|
||||
curl -sf -X DELETE -H "$auth" "$api/releases/$id/assets/$old"
|
||||
done
|
||||
|
||||
curl -sf -o /dev/null -X POST -H "$auth" -F "attachment=@$file" \
|
||||
"$api/releases/$id/assets?name=$file"
|
||||
echo "$file pověšen na ${GITHUB_REF_NAME}"
|
||||
done
|
||||
@@ -8,16 +8,45 @@ ten samý Adam jako z minulého měsíce. Žádné účty, žádná hesla.
|
||||
|
||||
## Spuštění
|
||||
|
||||
Stáhni binárku z [releases](https://gitea.spacilovi.eu/david-spacil/dice-counter/releases)
|
||||
a spusť ji:
|
||||
Stáhni binárku pro svůj systém z
|
||||
[releases](https://gitea.spacilovi.eu/david-spacil/dice-counter/releases):
|
||||
|
||||
| Systém | Soubor |
|
||||
|---|---|
|
||||
| Linux (x86-64) | `kostky-linux-x86_64` |
|
||||
| macOS (Apple Silicon) | `kostky-macos-arm64` |
|
||||
| macOS (Intel) | `kostky-macos-x86_64` |
|
||||
| Windows (x86-64) | `kostky-windows-x86_64.exe` |
|
||||
|
||||
Nic se neinstaluje — Python, Flask i šablony jsou uvnitř.
|
||||
|
||||
Na Linuxu a macOS:
|
||||
|
||||
```bash
|
||||
chmod +x kostky
|
||||
./kostky
|
||||
chmod +x kostky-*
|
||||
./kostky-linux-x86_64
|
||||
```
|
||||
|
||||
Nic se neinstaluje — Python, Flask i šablony jsou uvnitř. Zatím jen pro Linux
|
||||
na x86-64; postavené proti glibc 2.17, takže jede prakticky všude.
|
||||
Na Windows stačí na `.exe` poklepat.
|
||||
|
||||
Linuxová binárka je postavená proti glibc 2.17, takže jede prakticky všude.
|
||||
|
||||
### Než to poprvé pustíš
|
||||
|
||||
Binárky nejsou podepsané — podpisové certifikáty stojí tisíce ročně a na
|
||||
počitadlo kostek by to byl nesmysl. Systémy si toho všimnou:
|
||||
|
||||
- **macOS** stažený soubor označí za karanténní a odmítne ho spustit. Buď
|
||||
značku sundej (`xattr -dr com.apple.quarantine kostky-macos-arm64`), nebo
|
||||
soubor stáhni rovnou z terminálu přes `curl -LO` — tudy se karanténa
|
||||
nenastavuje.
|
||||
- **Windows** ukáže modré okno SmartScreenu. *Další informace* →
|
||||
*Přesto spustit*. Občas si postěžuje i antivirus; u zabalených Python
|
||||
programů je to běžný falešný poplach. Při prvním spuštění se ještě zeptá
|
||||
brána firewall — bez povolení do místní sítě se telefon nepřipojí.
|
||||
|
||||
Kdo tomu nechce věřit, ověří si stažený soubor podle přiloženého součtu
|
||||
(níž) nebo si ho postaví sám — `./build.sh`, zdrojáky jsou tady celé.
|
||||
|
||||
Ze zdrojáků to je stejně krátké:
|
||||
|
||||
@@ -53,7 +82,9 @@ server vypíše při startu.
|
||||
|
||||
| Spuštěno | Databáze |
|
||||
|---|---|
|
||||
| binárkou | `~/.local/share/kostky/dice.db` |
|
||||
| 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` |
|
||||
| ze zdrojáků | `dice.db` v pracovním adresáři |
|
||||
|
||||
Binárka se při každém spuštění rozbaluje do dočasného adresáře a pouští se
|
||||
@@ -101,6 +132,8 @@ při remíze na prvním místě se hraje dál.
|
||||
| `web.py` | Flask aplikace |
|
||||
| `dice.py` | totéž v terminálu, bez ukládání |
|
||||
| `build.sh`, `kostky.spec` | stavba binárky |
|
||||
| `.gitea/workflows/` | testy a linuxová binárka doma |
|
||||
| `.github/workflows/` | binárky pro Windows a macOS |
|
||||
|
||||
Terminálová verze zůstává funkční jako záloha:
|
||||
|
||||
@@ -135,26 +168,44 @@ Staví se proti samostatnému CPythonu od `uv`, ne proti systémovému. Ten je
|
||||
slinkovaný s glibc 2.17; postavené proti Pythonu z Fedory 44 by to chtělo
|
||||
glibc 2.43 a nešlo by spustit skoro nikde — glibc drží zpětnou kompatibilitu,
|
||||
ne dopřednou. Nic z hostitele se do binárky nedostane, takže kontejner k tomu
|
||||
potřeba není. Výsledek je v `dist/kostky`.
|
||||
potřeba není. Výsledek je v `dist/`.
|
||||
|
||||
Stejný `build.sh` staví i na macOS a na Windows (v Git Bash) — jen tam bez
|
||||
té starosti o glibc. Křížem to nejde: PyInstaller balí do výsledku interpret
|
||||
a knihovny toho systému, na kterém běží, takže **binárku pro každý systém
|
||||
musí postavit ten systém.**
|
||||
|
||||
Terminálová verze součástí binárky není; ta se pouští ze zdrojáků.
|
||||
|
||||
Releasy si tohle dělají samy. Otagovaný commit spustí
|
||||
`.gitea/workflows/binarka.yml`, ta binárku postaví, projede testy, zkusí
|
||||
ji nastartovat a pověsí ji na release jako `kostky-linux-x86_64`:
|
||||
### Jak vznikají releasy
|
||||
|
||||
Otagovaný commit spustí stavbu na obou stranách:
|
||||
|
||||
| Kde | Co staví | Workflow |
|
||||
|---|---|---|
|
||||
| vlastní runner u Gitey | Linux | `.gitea/workflows/binarka.yml` |
|
||||
| GitHub Actions | Windows, macOS ×2 | `.github/workflows/binarky.yml` |
|
||||
|
||||
```bash
|
||||
git tag v1.0.0 && git push origin v1.0.0
|
||||
```
|
||||
|
||||
Vedle binárky se věší i `kostky-linux-x86_64.sha256`, takže se stažený
|
||||
soubor dá ověřit:
|
||||
GitHub je tu jen půjčená dílna. Repozitář se tam z Gitey zrcadlí
|
||||
([mirror](https://github.com/david-spacil/dice-counter)), postavené soubory
|
||||
se posílají zpátky na zdejší release přes Gitea API a projekt má pořád jednu
|
||||
stránku s releasy — tuhle. Linux se na GitHubu schválně nestaví; doma to jde
|
||||
proti staré glibc, a když GitHub vypadne, release má aspoň tu platformu,
|
||||
na které to reálně poběží.
|
||||
|
||||
Každá stavba nejdřív projede testy a zkusí hotovou binárku nastartovat, než
|
||||
ji kamkoli pověsí. Vedle každé visí i `.sha256`, takže se stažený soubor dá
|
||||
ověřit:
|
||||
|
||||
```bash
|
||||
sha256sum -c kostky-linux-x86_64.sha256
|
||||
sha256sum -c kostky-linux-x86_64.sha256 # na macOS: shasum -a 256 -c
|
||||
```
|
||||
|
||||
Stejná stavba běží i nad každým pull requestem, jen se nikam nevěší.
|
||||
Nad pull requesty se Linux staví taky, jen se nikam nevěší.
|
||||
|
||||
## Testy
|
||||
|
||||
@@ -165,5 +216,5 @@ uv run --with-requirements requirements.txt --no-project pytest
|
||||
Nebo z připraveného prostředí prostě `pytest`.
|
||||
|
||||
Nad každým pull requestem a nad `main` běží `.gitea/workflows/testy.yml` —
|
||||
84 testů na Pythonu 3.11, 3.12, 3.13 i 3.14, a k tomu skriptovaná partie
|
||||
99 testů na Pythonu 3.11, 3.12, 3.13 i 3.14, a k tomu skriptovaná partie
|
||||
v terminálové verzi, na kterou pytest nesahá.
|
||||
@@ -1,11 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
# Postaví jednosouborovou binárku pro Linux do dist/kostky.
|
||||
# Postaví jednosouborovou binárku do dist/ — pro systém, na kterém běží.
|
||||
#
|
||||
# Staví se proti samostatnému CPythonu od uv, ne proti systémovému. Ten je
|
||||
# slinkovaný s glibc 2.17, takže binárka jede i na letitých systémech.
|
||||
# Postavená proti Pythonu z Fedory 44 by chtěla glibc 2.43 a nešla by
|
||||
# spustit skoro nikde — glibc drží zpětnou kompatibilitu, ne dopřednou.
|
||||
# Nic z hostitele se do ní nedostane, takže kontejner k tomu není potřeba.
|
||||
# PyInstaller neumí křížovou kompilaci: binárku pro každý systém musí postavit
|
||||
# ten systém. Linux se staví doma na vlastním runneru, Windows a macOS na
|
||||
# půjčených strojích GitHub Actions (.github/workflows/binarky.yml).
|
||||
#
|
||||
# Staví se proti samostatnému CPythonu od uv, ne proti systémovému. Na Linuxu
|
||||
# je slinkovaný s glibc 2.17, takže binárka jede i na letitých systémech.
|
||||
# Postavená proti Pythonu z Fedory 44 by chtěla glibc 2.43 a nešla by spustit
|
||||
# skoro nikde — glibc drží zpětnou kompatibilitu, ne dopřednou. Nic z hostitele
|
||||
# se do ní nedostane, takže kontejner k tomu není potřeba.
|
||||
set -euo pipefail
|
||||
|
||||
VERSION=${VERSION:-3.11}
|
||||
@@ -13,10 +17,19 @@ BUILD=${BUILD:-.build}
|
||||
|
||||
uv python install "$VERSION"
|
||||
uv venv --quiet --managed-python --python "$VERSION" "$BUILD"
|
||||
uv pip install --quiet --python "$BUILD/bin/python" -r requirements.txt pyinstaller
|
||||
|
||||
"$BUILD/bin/pyinstaller" --clean --noconfirm \
|
||||
# Windows dává spustitelné soubory venvu do Scripts/, zbytek světa do bin/.
|
||||
python="$BUILD/bin/python"
|
||||
pyinstaller="$BUILD/bin/pyinstaller"
|
||||
if [ -d "$BUILD/Scripts" ]; then
|
||||
python="$BUILD/Scripts/python.exe"
|
||||
pyinstaller="$BUILD/Scripts/pyinstaller.exe"
|
||||
fi
|
||||
|
||||
uv pip install --quiet --python "$python" -r requirements.txt pyinstaller
|
||||
|
||||
"$pyinstaller" --clean --noconfirm \
|
||||
--distpath dist --workpath "$BUILD/work" kostky.spec
|
||||
|
||||
echo
|
||||
ls -lh dist/kostky
|
||||
ls -lh dist/
|
||||
+6
-1
@@ -5,6 +5,8 @@ Staví se přes `./build.sh`, ne ručně — ta se stará o to, aby výsledek je
|
||||
i na starších systémech, než je ten tvůj.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
analysis = Analysis(
|
||||
["web.py"],
|
||||
pathex=["."],
|
||||
@@ -21,6 +23,9 @@ exe = EXE(
|
||||
analysis.datas,
|
||||
name="kostky",
|
||||
console=True,
|
||||
strip=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
|
||||
# binárka na Apple Silicon vůbec nespustí; na Windows nedělá nic.
|
||||
strip=sys.platform == "linux",
|
||||
upx=False,
|
||||
)
|
||||
Reference in new issue
Block a user