From 0bb2e0efabbf4982eded1b4f839a6292d6d962a7 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 23 Aug 2026 20:09:20 +0200 Subject: [PATCH 1/5] =?UTF-8?q?Publikovat=20image=20do=20registru=20bal?= =?UTF-8?q?=C3=AD=C4=8Dk=C5=AF=20Gitey?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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í. --- .gitea/workflows/image.yml | 127 +++++++++++++++++++ README.md | 30 ++++- deploy/{compose.yaml => docker-compose.yaml} | 15 ++- 3 files changed, 158 insertions(+), 14 deletions(-) create mode 100644 .gitea/workflows/image.yml rename deploy/{compose.yaml => docker-compose.yaml} (70%) diff --git a/.gitea/workflows/image.yml b/.gitea/workflows/image.yml new file mode 100644 index 0000000..678510f --- /dev/null +++ b/.gitea/workflows/image.yml @@ -0,0 +1,127 @@ +# Postaví kontejnerový image a při vydání ho pošle do registru Gitey. +# +# Runner běží v host módu, takže tu nejsou hotové akce z marketplace a všechno +# je obyčejný shell — stejně jako v ostatních workflow tady. Docker na +# hostiteli být musí, ten se tu neinstaluje. +# +# Nad pull requesty se image staví a zkouší, ale nikam se neposílá. Dockerfile +# by se jinak rozbil až ve chvíli, kdy se tagne release. +name: image + +on: + push: + tags: ["v*"] + pull_request: + workflow_dispatch: + +env: + REGISTRY: gitea.spacilovi.eu + IMAGE: david-spacil/dice-counter + PLATFORMS: linux/amd64,linux/arm64 + ZKOUSKA_PORT: "18000" + +jobs: + image: + runs-on: homelab + + steps: + - 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 config --unset http.extraheader + git checkout -qf FETCH_HEAD + git clean -qfd + + - name: Předpoklady + run: | + command -v docker >/dev/null \ + || { echo "Docker na runneru není." >&2; exit 1; } + docker buildx version >/dev/null 2>&1 \ + || { echo "Chybí docker buildx — bez něj multiarch nejde." >&2; exit 1; } + docker version --format '{{.Server.Version}}' + + - name: QEMU pro cizí architektury + run: | + # Registruje binfmt, aby šlo na x86 stroji stavět i arm64. Všechny + # závislosti jsou čistě pythonní, takže se pod emulací nic + # nekompiluje a stavba tím prakticky netrpí. + docker run --privileged --rm tonistiigi/binfmt --install arm64 + + - name: Builder + run: | + # Výchozí ovladač Dockeru multiplatformní stavbu neumí, je potřeba + # docker-container. Krok se pouští opakovaně, tak ať nevadí, že + # builder z minula už existuje. + docker buildx create --name kostky --driver docker-container --use \ + 2>/dev/null || docker buildx use kostky + docker buildx inspect --bootstrap | head -20 + + - name: Zkouška + run: | + # Zkouší se nativní amd64: --load umí do místního Dockeru uložit jen + # jednu platformu a spustit stejně nic jiného nejde. + docker buildx build --platform linux/amd64 --load \ + -f deploy/Dockerfile \ + --build-arg VERSION="zkouska-${GITHUB_SHA:0:7}" \ + -t kostky:zkouska . + + trap 'docker rm -f kostky-zkouska >/dev/null 2>&1 || true' EXIT + + # Adresa se vnucuje, ať zkouška nezávisí na síti běhounu a dá se + # ověřit, co přesně tabule nabídne. + docker run -d --name kostky-zkouska --init \ + -p "${ZKOUSKA_PORT}:${ZKOUSKA_PORT}" -e DICE_HOST=127.0.0.1 \ + -e DICE_PORT="${ZKOUSKA_PORT}" kostky:zkouska + + for _ in $(seq 30); do + curl -sf -o /dev/null "http://127.0.0.1:${ZKOUSKA_PORT}/" && break + sleep 1 + done + + curl -sf -o /dev/null "http://127.0.0.1:${ZKOUSKA_PORT}/" || { + echo "Kontejner se nerozeběhl." >&2 + docker logs kostky-zkouska >&2 + exit 1; } + curl -sf -o /dev/null "http://127.0.0.1:${ZKOUSKA_PORT}/static/style.css" + curl -sf "http://127.0.0.1:${ZKOUSKA_PORT}/board" | grep -q "127.0.0.1:${ZKOUSKA_PORT}" + curl -sf -o /dev/null "http://127.0.0.1:${ZKOUSKA_PORT}/export" + + # Verze se musí do image opravdu dostat, ne se hlásit jako neznámá. + docker run --rm kostky:zkouska python web.py --version + ! docker run --rm kostky:zkouska python web.py --version | grep -q "neznámá" + + docker logs kostky-zkouska + echo "Image jede." + + - name: Publikace + if: startsWith(github.ref, 'refs/tags/') + env: + TOKEN: ${{ secrets.PACKAGE_TOKEN }} + VLASTNIK: ${{ github.repository_owner }} + run: | + # Automatický token Actions na balíčky nestačí — Gitea to zatím + # neumí a sama v dokumentaci odkazuje na osobní token. Ten je + # v secrets pod PACKAGE_TOKEN; jméno nesmí začínat na GITEA_, + # ten prefix si Gitea vyhrazuje. + [ -n "$TOKEN" ] || { echo "Chybí secret PACKAGE_TOKEN." >&2; exit 1; } + echo "$TOKEN" | docker login "$REGISTRY" -u "$VLASTNIK" --password-stdin + trap 'docker logout "$REGISTRY" >/dev/null 2>&1 || true' EXIT + + # Značka bez počátečního "v": v repozitáři je v1.2.0, u image se + # čekají 1.2.0. + VERZE="${GITHUB_REF_NAME#v}" + + docker buildx build --platform "$PLATFORMS" --push \ + -f deploy/Dockerfile \ + --build-arg VERSION="${GITHUB_REF_NAME}" \ + -t "$REGISTRY/$IMAGE:$VERZE" \ + -t "$REGISTRY/$IMAGE:latest" . + + echo "Publikováno: $REGISTRY/$IMAGE:$VERZE a :latest" + docker buildx imagetools inspect "$REGISTRY/$IMAGE:$VERZE" diff --git a/README.md b/README.md index 03d9048..34fbe43 100644 --- a/README.md +++ b/README.md @@ -192,13 +192,28 @@ Je idempotentní; druhé spuštění jen vymění binárku za nejnovější. ### Docker +Stačí jeden soubor, repozitář k tomu potřeba není: + ```bash -cd deploy && docker compose up -d +curl -fsSLO https://gitea.spacilovi.eu/david-spacil/dice-counter/raw/branch/main/deploy/docker-compose.yaml +docker compose up -d ``` -Staví se ze zdrojáků, takže image jde sestavit pro amd64 i arm64 a nezávisí -na tom, jestli release pro danou architekturu proběhl. Databáze leží -v pojmenovaném svazku, appka běží pod nerootovým uživatelem. +Image se stáhne hotový z registru Gitey, pro amd64 i arm64 — Docker si vybere +svoji variantu sám. Databáze leží v pojmenovaném svazku, appka běží pod +nerootovým uživatelem. + +Aktualizace na novější vydání: + +```bash +docker compose pull && docker compose up -d +``` + +Kdo si ho radši postaví ze zdrojáků, přebije ten stažený stejnou značkou: + +```bash +docker build -f deploy/Dockerfile -t gitea.spacilovi.eu/david-spacil/dice-counter:latest . +``` **Pozor na síť.** Compose schválně používá `network_mode: host`. V bridge režimu kontejner uvnitř vidí adresu jako `172.17.0.2`, tabule ji poctivě @@ -207,9 +222,9 @@ Kdo bridge potřebuje, musí nastavit `DICE_HOST` na adresu hostitele v LAN. | | LXC | Docker | |---|---|---| -| Odkud | vydaná binárka z releasu | zdrojáky | +| Odkud | vydaná binárka z releasu | image z registru | | Databáze | `/var/lib/kostky/dice.db` | svazek `kostky-data` | -| Aktualizace | `pve-kostky.sh update ` | `docker compose build --pull` | +| Aktualizace | `update` uvnitř kontejneru | `docker compose pull` | | Adresa a QR | funguje samo | potřeba síť hostitele | ## Když se telefon nepřipojí @@ -248,7 +263,7 @@ při remíze na prvním místě se hraje dál. | `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 | -| `.gitea/workflows/` | testy a linuxová binárka doma | +| `.gitea/workflows/` | testy, linuxová binárka a image doma | | `.github/workflows/` | binárky pro Windows a macOS | | `deploy/` | nasazení na server: Proxmox LXC a Docker | @@ -330,6 +345,7 @@ Otagovaný commit spustí stavbu na obou stranách: | Kde | Co staví | Workflow | |---|---|---| | vlastní runner u Gitey | Linux x86-64 | `.gitea/workflows/binarka.yml` | +| vlastní runner u Gitey | image amd64 + arm64 | `.gitea/workflows/image.yml` | | GitHub Actions | Windows, macOS ×2, Linux ARM64 | `.github/workflows/binarky.yml` | ```bash diff --git a/deploy/compose.yaml b/deploy/docker-compose.yaml similarity index 70% rename from deploy/compose.yaml rename to deploy/docker-compose.yaml index afffe17..f9e7a62 100644 --- a/deploy/compose.yaml +++ b/deploy/docker-compose.yaml @@ -1,18 +1,19 @@ # Počitadlo kostek v Dockeru. # -# cd deploy && docker compose up -d +# curl -fsSLO https://gitea.spacilovi.eu/david-spacil/dice-counter/raw/branch/main/deploy/docker-compose.yaml +# docker compose up -d +# +# Nic dalšího není potřeba — image se stáhne hotový, pro amd64 i arm64. +# Kdo si ho chce postavit ze zdrojáků, přebije ten stažený stejnou značkou: +# +# docker build -f deploy/Dockerfile -t gitea.spacilovi.eu/david-spacil/dice-counter:latest . # # Počítá se s domácí sítí. Appka nemá přihlašování, tohle ji nijak # nezabezpečuje a do internetu nepatří. services: kostky: - build: - context: .. - dockerfile: deploy/Dockerfile - args: - VERSION: ${VERSION:-vlastní sestavení} - image: kostky:latest + image: gitea.spacilovi.eu/david-spacil/dice-counter:latest container_name: kostky restart: unless-stopped -- 2.47.3 From 9283a87a1e965b9eb5098693c12cfae6ffcf5c02 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 23 Aug 2026 20:14:17 +0200 Subject: [PATCH 2/5] =?UTF-8?q?Ov=C4=9B=C5=99it=20emulaci=20d=C5=99=C3=ADv?= =?UTF-8?q?,=20ne=C5=BE=20se=20do=20stavby=20pust=C3=ADme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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á. --- .gitea/workflows/image.yml | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/image.yml b/.gitea/workflows/image.yml index 678510f..7da69d4 100644 --- a/.gitea/workflows/image.yml +++ b/.gitea/workflows/image.yml @@ -56,11 +56,26 @@ jobs: - name: Builder run: | # Výchozí ovladač Dockeru multiplatformní stavbu neumí, je potřeba - # docker-container. Krok se pouští opakovaně, tak ať nevadí, že - # builder z minula už existuje. - docker buildx create --name kostky --driver docker-container --use \ - 2>/dev/null || docker buildx use kostky - docker buildx inspect --bootstrap | head -20 + # docker-container. Staví se pokaždé načisto — builder z minulého + # běhu by si pamatoval platformy z doby před registrací emulace. + # + # Bez roury do `head`: pod pipefail by zavřená roura shodila celý + # krok dřív, než docker dopíše výstup. + docker buildx rm kostky >/dev/null 2>&1 || true + docker buildx create --name kostky --driver docker-container --use + docker buildx inspect --bootstrap + + # Kdyby arm64 v seznamu chybělo, stavba spadne až na konci a hláška + # nic neřekne. Radši to zkontrolujeme hned. + PLATFORMY=$(docker buildx inspect) + echo "$PLATFORMY" | grep -q "linux/arm64" || { + echo "Buildkit nevidí linux/arm64, i když se binfmt nainstaloval." >&2 + echo "Emulace musí být registrovaná s příznakem F, jinak si na ni" >&2 + echo "buildkit ze svého kontejneru nesáhne. Na runneru to natrvalo" >&2 + echo "vyřeší balíček qemu-user-static." >&2 + echo "--- současná registrace ---" >&2 + cat /proc/sys/fs/binfmt_misc/qemu-aarch64 >&2 2>/dev/null || echo "(žádná)" >&2 + exit 1; } - name: Zkouška run: | -- 2.47.3 From b6066e2be8397b6cf36dbb4fe8d469493745042b Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 23 Aug 2026 20:31:24 +0200 Subject: [PATCH 3/5] =?UTF-8?q?Image=20vyd=C3=A1vat=20z=20GitHubu,=20doma?= =?UTF-8?q?=20ho=20jen=20zkou=C5=A1et?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .gitea/workflows/image.yml | 95 ++++++++----------------------------- .github/workflows/image.yml | 79 ++++++++++++++++++++++++++++++ README.md | 13 +++-- 3 files changed, 108 insertions(+), 79 deletions(-) create mode 100644 .github/workflows/image.yml diff --git a/.gitea/workflows/image.yml b/.gitea/workflows/image.yml index 7da69d4..30017cc 100644 --- a/.gitea/workflows/image.yml +++ b/.gitea/workflows/image.yml @@ -1,23 +1,21 @@ -# Postaví kontejnerový image a při vydání ho pošle do registru Gitey. +# Postaví kontejnerový image a zkusí ho spustit. Nikam ho neposílá. # -# Runner běží v host módu, takže tu nejsou hotové akce z marketplace a všechno -# je obyčejný shell — stejně jako v ostatních workflow tady. Docker na -# hostiteli být musí, ten se tu neinstaluje. +# Dockerfile by se jinak rozbil až ve chvíli, kdy se tagne release — tohle ho +# ohlídá nad každým pull requestem. # -# Nad pull requesty se image staví a zkouší, ale nikam se neposílá. Dockerfile -# by se jinak rozbil až ve chvíli, kdy se tagne release. +# Publikuje se jinde: .github/workflows/image.yml. Zdejší runner běží v LXC, +# kde nejde zaregistrovat binfmt, takže arm64 by se tu postavit nedalo. +# Registrace je vlastnost jádra hostitele a to je produkční stroj, do kterého +# se kvůli počitadlu kostek vrtat nebude. +# +# Staví se nativní amd64 obyčejným `docker build`, žádný buildx ani emulace. name: image on: - push: - tags: ["v*"] pull_request: workflow_dispatch: env: - REGISTRY: gitea.spacilovi.eu - IMAGE: david-spacil/dice-counter - PLATFORMS: linux/amd64,linux/arm64 ZKOUSKA_PORT: "18000" jobs: @@ -42,53 +40,21 @@ jobs: run: | command -v docker >/dev/null \ || { echo "Docker na runneru není." >&2; exit 1; } - docker buildx version >/dev/null 2>&1 \ - || { echo "Chybí docker buildx — bez něj multiarch nejde." >&2; exit 1; } docker version --format '{{.Server.Version}}' - - name: QEMU pro cizí architektury + - name: Stavba run: | - # Registruje binfmt, aby šlo na x86 stroji stavět i arm64. Všechny - # závislosti jsou čistě pythonní, takže se pod emulací nic - # nekompiluje a stavba tím prakticky netrpí. - docker run --privileged --rm tonistiigi/binfmt --install arm64 - - - name: Builder - run: | - # Výchozí ovladač Dockeru multiplatformní stavbu neumí, je potřeba - # docker-container. Staví se pokaždé načisto — builder z minulého - # běhu by si pamatoval platformy z doby před registrací emulace. - # - # Bez roury do `head`: pod pipefail by zavřená roura shodila celý - # krok dřív, než docker dopíše výstup. - docker buildx rm kostky >/dev/null 2>&1 || true - docker buildx create --name kostky --driver docker-container --use - docker buildx inspect --bootstrap - - # Kdyby arm64 v seznamu chybělo, stavba spadne až na konci a hláška - # nic neřekne. Radši to zkontrolujeme hned. - PLATFORMY=$(docker buildx inspect) - echo "$PLATFORMY" | grep -q "linux/arm64" || { - echo "Buildkit nevidí linux/arm64, i když se binfmt nainstaloval." >&2 - echo "Emulace musí být registrovaná s příznakem F, jinak si na ni" >&2 - echo "buildkit ze svého kontejneru nesáhne. Na runneru to natrvalo" >&2 - echo "vyřeší balíček qemu-user-static." >&2 - echo "--- současná registrace ---" >&2 - cat /proc/sys/fs/binfmt_misc/qemu-aarch64 >&2 2>/dev/null || echo "(žádná)" >&2 - exit 1; } - - - name: Zkouška - run: | - # Zkouší se nativní amd64: --load umí do místního Dockeru uložit jen - # jednu platformu a spustit stejně nic jiného nejde. - docker buildx build --platform linux/amd64 --load \ - -f deploy/Dockerfile \ + docker build -f deploy/Dockerfile \ --build-arg VERSION="zkouska-${GITHUB_SHA:0:7}" \ -t kostky:zkouska . + - name: Zkouška + run: | trap 'docker rm -f kostky-zkouska >/dev/null 2>&1 || true' EXIT - # Adresa se vnucuje, ať zkouška nezávisí na síti běhounu a dá se + # Port musí být stejný uvnitř i venku: appka poslouchá na DICE_PORT, + # takže mapovat ho na jiný by znamenalo mířit do prázdna. + # Adresa se vnucuje, ať zkouška nezávisí na síti runneru a dá se # ověřit, co přesně tabule nabídne. docker run -d --name kostky-zkouska --init \ -p "${ZKOUSKA_PORT}:${ZKOUSKA_PORT}" -e DICE_HOST=127.0.0.1 \ @@ -114,29 +80,6 @@ jobs: docker logs kostky-zkouska echo "Image jede." - - name: Publikace - if: startsWith(github.ref, 'refs/tags/') - env: - TOKEN: ${{ secrets.PACKAGE_TOKEN }} - VLASTNIK: ${{ github.repository_owner }} - run: | - # Automatický token Actions na balíčky nestačí — Gitea to zatím - # neumí a sama v dokumentaci odkazuje na osobní token. Ten je - # v secrets pod PACKAGE_TOKEN; jméno nesmí začínat na GITEA_, - # ten prefix si Gitea vyhrazuje. - [ -n "$TOKEN" ] || { echo "Chybí secret PACKAGE_TOKEN." >&2; exit 1; } - echo "$TOKEN" | docker login "$REGISTRY" -u "$VLASTNIK" --password-stdin - trap 'docker logout "$REGISTRY" >/dev/null 2>&1 || true' EXIT - - # Značka bez počátečního "v": v repozitáři je v1.2.0, u image se - # čekají 1.2.0. - VERZE="${GITHUB_REF_NAME#v}" - - docker buildx build --platform "$PLATFORMS" --push \ - -f deploy/Dockerfile \ - --build-arg VERSION="${GITHUB_REF_NAME}" \ - -t "$REGISTRY/$IMAGE:$VERZE" \ - -t "$REGISTRY/$IMAGE:latest" . - - echo "Publikováno: $REGISTRY/$IMAGE:$VERZE a :latest" - docker buildx imagetools inspect "$REGISTRY/$IMAGE:$VERZE" + - name: Úklid + if: always() + run: docker rmi kostky:zkouska >/dev/null 2>&1 || true diff --git a/.github/workflows/image.yml b/.github/workflows/image.yml new file mode 100644 index 0000000..7695190 --- /dev/null +++ b/.github/workflows/image.yml @@ -0,0 +1,79 @@ +# Publikuje kontejnerový image do registru balíčků Gitey, pro amd64 i arm64. +# +# Proč zrovna odsud: domácí runner běží v LXC, kde nejde zaregistrovat binfmt +# — je to vlastnost jádra hostitele a ten je produkční. Běhouni GitHubu jsou +# plnohodnotné virtuály, kde emulace funguje bez řečí. +# +# Doma se image přesto staví a zkouší nad každým pull requestem +# (.gitea/workflows/image.yml), jen se nikam neposílá. Stejná dělba jako +# u binárek: doma se hlídá, tady se vydává. +name: image + +on: + push: + tags: ["v*"] + workflow_dispatch: + +env: + REGISTRY: gitea.spacilovi.eu + IMAGE: david-spacil/dice-counter + PLATFORMS: linux/amd64,linux/arm64 + +jobs: + publikace: + runs-on: ubuntu-latest + + steps: + # Přesná verze, ne plovoucí značka — viz binarky.yml. + - uses: actions/checkout@v7.0.1 + + - name: QEMU pro arm64 + run: | + # Bez hotové akce z marketplace, ať není co udržovat. Běhoun je + # virtuál, takže privilegovaný kontejner smí zapisovat do binfmt + # a registrace platí pro celé jádro. + docker run --privileged --rm tonistiigi/binfmt --install arm64 + + - name: Builder + run: | + # Výchozí ovladač Dockeru multiplatformní stavbu neumí. + docker buildx create --name kostky --driver docker-container --use + docker buildx inspect --bootstrap + + # Bez tohohle by stavba spadla až na konci a hláška by nic neřekla. + PLATFORMY=$(docker buildx inspect) + echo "$PLATFORMY" | grep -q "linux/arm64" || { + echo "Buildkit nevidí linux/arm64, emulace se nezaregistrovala." >&2 + exit 1; } + + - name: Publikace + env: + TOKEN: ${{ secrets.PACKAGE_TOKEN }} + # Uživatel v Gitee, ne na GitHubu. Shodou okolností je to totéž. + VLASTNIK: david-spacil + run: | + # Spouští se to i ručně, a to klidně nad větví. Bez tagu není z čeho + # udělat verzi a `:latest` by ukazoval na rozdělanou práci. + [ "$GITHUB_REF_TYPE" = tag ] || { + echo "Publikovat jde jen z tagu, tohle je ${GITHUB_REF_TYPE} ${GITHUB_REF_NAME}." >&2 + exit 1; } + + # Automatický token na balíčky nestačí ani u Gitey samotné, natož + # odsud — musí to být osobní token s oprávněním write:package. + [ -n "$TOKEN" ] || { echo "Chybí secret PACKAGE_TOKEN." >&2; exit 1; } + echo "$TOKEN" | docker login "$REGISTRY" -u "$VLASTNIK" --password-stdin + trap 'docker logout "$REGISTRY" >/dev/null 2>&1 || true' EXIT + + # Značka bez počátečního "v": v repozitáři je v1.2.0, u image se + # čeká 1.2.0. Verze vypálená do image ale zůstává s "v", ať --version + # hlásí totéž co binárky. + VERZE="${GITHUB_REF_NAME#v}" + + docker buildx build --platform "$PLATFORMS" --push \ + -f deploy/Dockerfile \ + --build-arg VERSION="${GITHUB_REF_NAME}" \ + -t "$REGISTRY/$IMAGE:$VERZE" \ + -t "$REGISTRY/$IMAGE:latest" . + + echo "Publikováno: $REGISTRY/$IMAGE:$VERZE a :latest" + docker buildx imagetools inspect "$REGISTRY/$IMAGE:$VERZE" diff --git a/README.md b/README.md index 34fbe43..9f09a25 100644 --- a/README.md +++ b/README.md @@ -263,7 +263,7 @@ při remíze na prvním místě se hraje dál. | `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 | -| `.gitea/workflows/` | testy, linuxová binárka a image doma | +| `.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 | @@ -345,8 +345,8 @@ Otagovaný commit spustí stavbu na obou stranách: | Kde | Co staví | Workflow | |---|---|---| | vlastní runner u Gitey | Linux x86-64 | `.gitea/workflows/binarka.yml` | -| vlastní runner u Gitey | image amd64 + arm64 | `.gitea/workflows/image.yml` | | GitHub Actions | Windows, macOS ×2, Linux ARM64 | `.github/workflows/binarky.yml` | +| GitHub Actions | image amd64 + arm64 | `.github/workflows/image.yml` | ```bash git tag v1.0.0 && git push origin v1.0.0 @@ -369,7 +369,14 @@ ověřit: sha256sum -c kostky-linux-x86_64.sha256 # na macOS: shasum -a 256 -c ``` -Nad pull requesty se Linux staví taky, jen se nikam nevěší. +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. + +Image se schválně nevydává doma: tamní runner běží v LXC, kde nejde +zaregistrovat emulaci pro arm64 — je to vlastnost jádra hostitele a ten je +produkční stroj. Běhouni GitHubu jsou plnohodnotné virtuály, kde to funguje +bez zásahu do čehokoli. ## Testy -- 2.47.3 From b1b7d1fad1031be256fd65fa2a2bee5149b98557 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 23 Aug 2026 20:41:03 +0200 Subject: [PATCH 4/5] =?UTF-8?q?Nezav=C3=A1d=C4=9Bt=20dal=C5=A1=C3=AD=20"ko?= =?UTF-8?q?stky"=20tam,=20kde=20na=20to=20nen=C3=AD=20d=C5=AFvod?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .gitea/workflows/image.yml | 18 +++++++++--------- .github/workflows/image.yml | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.gitea/workflows/image.yml b/.gitea/workflows/image.yml index 30017cc..a377e22 100644 --- a/.gitea/workflows/image.yml +++ b/.gitea/workflows/image.yml @@ -46,19 +46,19 @@ jobs: run: | docker build -f deploy/Dockerfile \ --build-arg VERSION="zkouska-${GITHUB_SHA:0:7}" \ - -t kostky:zkouska . + -t dice-counter:zkouska . - name: Zkouška run: | - trap 'docker rm -f kostky-zkouska >/dev/null 2>&1 || true' EXIT + trap 'docker rm -f dice-counter-zkouska >/dev/null 2>&1 || true' EXIT # Port musí být stejný uvnitř i venku: appka poslouchá na DICE_PORT, # takže mapovat ho na jiný by znamenalo mířit do prázdna. # Adresa se vnucuje, ať zkouška nezávisí na síti runneru a dá se # ověřit, co přesně tabule nabídne. - docker run -d --name kostky-zkouska --init \ + docker run -d --name dice-counter-zkouska --init \ -p "${ZKOUSKA_PORT}:${ZKOUSKA_PORT}" -e DICE_HOST=127.0.0.1 \ - -e DICE_PORT="${ZKOUSKA_PORT}" kostky:zkouska + -e DICE_PORT="${ZKOUSKA_PORT}" dice-counter:zkouska for _ in $(seq 30); do curl -sf -o /dev/null "http://127.0.0.1:${ZKOUSKA_PORT}/" && break @@ -67,19 +67,19 @@ jobs: curl -sf -o /dev/null "http://127.0.0.1:${ZKOUSKA_PORT}/" || { echo "Kontejner se nerozeběhl." >&2 - docker logs kostky-zkouska >&2 + docker logs dice-counter-zkouska >&2 exit 1; } curl -sf -o /dev/null "http://127.0.0.1:${ZKOUSKA_PORT}/static/style.css" curl -sf "http://127.0.0.1:${ZKOUSKA_PORT}/board" | grep -q "127.0.0.1:${ZKOUSKA_PORT}" curl -sf -o /dev/null "http://127.0.0.1:${ZKOUSKA_PORT}/export" # Verze se musí do image opravdu dostat, ne se hlásit jako neznámá. - docker run --rm kostky:zkouska python web.py --version - ! docker run --rm kostky:zkouska python web.py --version | grep -q "neznámá" + docker run --rm dice-counter:zkouska python web.py --version + ! docker run --rm dice-counter:zkouska python web.py --version | grep -q "neznámá" - docker logs kostky-zkouska + docker logs dice-counter-zkouska echo "Image jede." - name: Úklid if: always() - run: docker rmi kostky:zkouska >/dev/null 2>&1 || true + run: docker rmi dice-counter:zkouska >/dev/null 2>&1 || true diff --git a/.github/workflows/image.yml b/.github/workflows/image.yml index 7695190..418ae87 100644 --- a/.github/workflows/image.yml +++ b/.github/workflows/image.yml @@ -37,7 +37,7 @@ jobs: - name: Builder run: | # Výchozí ovladač Dockeru multiplatformní stavbu neumí. - docker buildx create --name kostky --driver docker-container --use + docker buildx create --name dice-counter --driver docker-container --use docker buildx inspect --bootstrap # Bez tohohle by stavba spadla až na konci a hláška by nic neřekla. -- 2.47.3 From 826f243af775eb51a1b9f9c282674899754a8850 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 23 Aug 2026 20:45:36 +0200 Subject: [PATCH 5/5] =?UTF-8?q?Sjednotit=20jm=C3=A9na=20i=20v=20dockerov?= =?UTF-8?q?=C3=A9=20cest=C4=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Služba, container_name, svazek a uživatel uvnitř image se jmenovaly kostky. Teď je nejlevnější chvíle to srovnat: compose se dá použít teprve od tohohle PR, takže svazek kostky-data zatím nikde neexistuje a není co migrovat. Po vydání by to už chtělo přesun dat. Uživateli zůstává uid 1000, takže vlastnictví souborů v /data nezávisí na jménu a bind mounty se nerozbijí. LXC strana (kostky.service, /opt/kostky, /var/lib/kostky) zůstává na #16 — tam přejmenování znamená migraci běžícím instalacím. --- deploy/Dockerfile | 10 +++++----- deploy/docker-compose.yaml | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 4342e00..317f289 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -5,7 +5,7 @@ # proběhl. Závislosti jsou zamčené v requirements.txt, takže je sestavení # opakovatelné. # -# docker build -f deploy/Dockerfile -t kostky . +# docker build -f deploy/Dockerfile -t gitea.spacilovi.eu/david-spacil/dice-counter:latest . # # Sestavuje se z kořene repozitáře, ne z deploy/. FROM python:3.11-slim @@ -13,7 +13,7 @@ FROM python:3.11-slim # Verze se jinak nemá kde vzít — v image není git ani zabalená binárka. ARG VERSION=neznámá -RUN useradd --system --uid 1000 --home-dir /app --shell /usr/sbin/nologin kostky +RUN useradd --system --uid 1000 --home-dir /app --shell /usr/sbin/nologin dice-counter WORKDIR /app @@ -29,15 +29,15 @@ RUN echo "$VERSION" > verze.txt # Adresář pro databázi musí vzniknout už tady a patřit správnému uživateli — # svazek, který Docker založí sám, by jinak patřil rootovi a appka běžící pod -# kostky by do něj nezapsala. -RUN install -d -o kostky -g kostky /data +# dice-counter by do něj nezapsala. +RUN install -d -o dice-counter -g dice-counter /data VOLUME ["/data"] ENV DICE_DB=/data/dice.db \ DICE_PORT=8000 EXPOSE 8000 -USER kostky +USER dice-counter # Bez curlu, ten ve slim image není. Stačí, že stránka odpoví — sahá i do # databáze, takže se tím kontroluje i ta. diff --git a/deploy/docker-compose.yaml b/deploy/docker-compose.yaml index f9e7a62..ec82493 100644 --- a/deploy/docker-compose.yaml +++ b/deploy/docker-compose.yaml @@ -12,9 +12,9 @@ # nezabezpečuje a do internetu nepatří. services: - kostky: + dice-counter: image: gitea.spacilovi.eu/david-spacil/dice-counter:latest - container_name: kostky + container_name: dice-counter restart: unless-stopped # Python jako PID 1 nesklízí osiřelé procesy a hůř reaguje na signály. @@ -39,8 +39,8 @@ services: DICE_DB: /data/dice.db volumes: - - kostky-data:/data + - dice-counter-data:/data volumes: # Zálohu si stáhneš rovnou z appky přes /export, takže se sem nemusí lézt. - kostky-data: + dice-counter-data: -- 2.47.3