From 8aa54dc7a0b45cd16ca7bf87d24f99a769e2f9d3 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Fri, 21 Aug 2026 17:23:09 +0200 Subject: [PATCH] stavba bez kontejneru, proti Pythonu od uv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .gitea/workflows/binarka.yml | 57 ++++++++++++++++++------------------ .gitignore | 1 + README.md | 12 ++++---- build.sh | 32 ++++++++------------ 4 files changed, 47 insertions(+), 55 deletions(-) diff --git a/.gitea/workflows/binarka.yml b/.gitea/workflows/binarka.yml index ca393de..cb4d6bd 100644 --- a/.gitea/workflows/binarka.yml +++ b/.gitea/workflows/binarka.yml @@ -1,9 +1,8 @@ # Postaví binárku a pověsí ji na release. # -# Běží v kontejneru na AlmaLinux 8, ne na runneru: binárka slinkovaná proti -# novější glibc by nešla spustit na starších systémech. Záměrně bez hotových -# akcí z marketplace — na vlastním runneru odpadá starost, jestli v kontejneru -# je node. +# Runner běží v host módu, takže tu není kontejner ani hotové akce +# z marketplace — nic se nespoléhá na to, co má hostitel nainstalováno. +# O starou glibc se stará build.sh přes samostatný CPython od uv. name: binárka on: @@ -15,50 +14,50 @@ on: jobs: linux: runs-on: homelab - container: almalinux:8 steps: - - name: Nástroje - run: dnf install -y -q git python3.11 binutils - - name: Zdrojáky env: TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | git init -q . + git remote remove origin 2>/dev/null || true git remote add origin "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git" git config http.extraheader "Authorization: token ${TOKEN}" git fetch -q --depth 1 origin "${GITHUB_REF}" - git checkout -q FETCH_HEAD git config --unset http.extraheader + git checkout -qf FETCH_HEAD + git clean -qfd - - name: Prostředí + - name: uv run: | - python3.11 -m venv /tmp/build - /tmp/build/bin/pip install --quiet --upgrade pip - /tmp/build/bin/pip install --quiet -r requirements.txt pyinstaller + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + export PATH="$HOME/.local/bin:$PATH" + command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh + uv --version - name: Testy - run: /tmp/build/bin/pytest -q + run: uv run --with-requirements requirements.txt --no-project pytest -q - name: Binárka - run: | - /tmp/build/bin/pyinstaller --clean --noconfirm \ - --distpath dist --workpath /tmp/work kostky.spec - ls -lh dist/kostky + run: ./build.sh - name: Zkouška run: | - XDG_DATA_HOME=/tmp/data DICE_PORT=8321 DICE_HOST=127.0.0.1 \ + XDG_DATA_HOME=/tmp/zkouska DICE_PORT=8321 DICE_HOST=127.0.0.1 \ ./dist/kostky > /tmp/server.log 2>&1 & + server=$! + trap 'kill $server 2>/dev/null || true' EXIT + for _ in $(seq 30); do curl -sf -o /dev/null http://127.0.0.1:8321/ && break sleep 1 done + 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/data/kostky/dice.db + test -f /tmp/zkouska/kostky/dice.db cat /tmp/server.log - name: Na release @@ -70,24 +69,24 @@ jobs: api="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" auth="Authorization: token ${TOKEN}" - # Release může, ale nemusí existovat — na tag se dá kliknout ručně. - release=$(curl -s -H "$auth" "$api/releases/tags/${GITHUB_REF_NAME}") - id=$(printf '%s' "$release" | python3.11 -c \ - 'import json,sys; print(json.load(sys.stdin).get("id",""))' || true) + # Release u tagu být může, ale nemusí — dá se založit i ručně. + id=$(curl -s -H "$auth" "$api/releases/tags/${GITHUB_REF_NAME}" \ + | python3 -c 'import json,sys; print(json.load(sys.stdin).get("id",""))' || true) if [ -z "$id" ]; then id=$(curl -sf -X POST -H "$auth" -H "Content-Type: application/json" \ -d "{\"tag_name\":\"${GITHUB_REF_NAME}\",\"name\":\"${GITHUB_REF_NAME}\"}" \ - "$api/releases" | python3.11 -c \ - 'import json,sys; print(json.load(sys.stdin)["id"])') + "$api/releases" \ + | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])') fi # Aby se dal build zopakovat, stará příloha stejného jména jde pryč. - curl -s -H "$auth" "$api/releases/$id/assets" | python3.11 -c \ - 'import json,os,sys; [print(a["id"]) for a in json.load(sys.stdin) if a["name"] == os.environ["ASSET"]]' \ + curl -s -H "$auth" "$api/releases/$id/assets" \ + | python3 -c 'import json,os,sys; [print(a["id"]) for a in json.load(sys.stdin) if a["name"] == os.environ["ASSET"]]' \ | while read -r old; do curl -sf -X DELETE -H "$auth" "$api/releases/$id/assets/$old" done - curl -sf -X POST -H "$auth" -F "attachment=@dist/kostky" \ + curl -sf -o /dev/null -X POST -H "$auth" -F "attachment=@dist/kostky" \ "$api/releases/$id/assets?name=${ASSET}" + echo "$ASSET pověšen na ${GITHUB_REF_NAME}" diff --git a/.gitignore b/.gitignore index d2f10d9..a9551e5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ __pycache__/ .pytest_cache/ dist/ build/ +.build/ diff --git a/README.md b/README.md index a9fb15a..74599e8 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,7 @@ chmod +x kostky ``` Nic se neinstaluje — Python, Flask i šablony jsou uvnitř. Zatím jen pro Linux -na x86-64; postavené proti glibc 2.28, takže jede na všem od RHEL 8, -Debianu 10 a Ubuntu 20.04 výš. +na x86-64; postavené proti glibc 2.17, takže jede prakticky všude. Ze zdrojáků to je stejně krátké: @@ -132,10 +131,11 @@ python3 web.py ./build.sh ``` -Staví se v kontejneru (podman nebo docker) na AlmaLinux 8, ne na hostiteli. -Binárka slinkovaná proti glibc z Fedory 44 by nešla spustit nikde se starším -systémem — glibc drží zpětnou kompatibilitu, ne dopřednou. Výsledek je -v `dist/kostky`. +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`. Terminálová verze součástí binárky není; ta se pouští ze zdrojáků. diff --git a/build.sh b/build.sh index 7238fe5..ea0f553 100755 --- a/build.sh +++ b/build.sh @@ -1,30 +1,22 @@ #!/usr/bin/env bash # Postaví jednosouborovou binárku pro Linux do dist/kostky. # -# Staví se v kontejneru s glibc 2.28 (AlmaLinux 8), ne na hostiteli. Binárka -# slinkovaná proti glibc z Fedory 44 by nešla spustit nikde se starším -# systémem — glibc drží zpětnou kompatibilitu, ne dopřednou. Postavené na -# staré glibc poběží i na nové. +# 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. set -euo pipefail -IMAGE=${IMAGE:-docker.io/library/almalinux:8} -PYTHON=${PYTHON:-python3.11} -ENGINE=${ENGINE:-$(command -v podman || command -v docker)} +VERSION=${VERSION:-3.11} +BUILD=${BUILD:-.build} -# Rootless podman mapuje roota v kontejneru na tebe, docker ne — tam by -# dist/ zůstalo cizí. -FIXUP=":" -[[ "$ENGINE" == *docker ]] && FIXUP="chown -R $(id -u):$(id -g) dist" +uv python install "$VERSION" +uv venv --quiet --managed-python --python "$VERSION" "$BUILD" +uv pip install --quiet --python "$BUILD/bin/python" -r requirements.txt pyinstaller -"$ENGINE" run --rm -v "$PWD:/src:z" -w /src "$IMAGE" bash -euc " - dnf install -y -q python3.11 binutils - $PYTHON -m venv /tmp/build - /tmp/build/bin/pip install --quiet --upgrade pip - /tmp/build/bin/pip install --quiet flask qrcode pyinstaller - /tmp/build/bin/pyinstaller --clean --noconfirm \ - --distpath dist --workpath /tmp/work kostky.spec - $FIXUP -" +"$BUILD/bin/pyinstaller" --clean --noconfirm \ + --distpath dist --workpath "$BUILD/work" kostky.spec echo ls -lh dist/kostky