| Filename | Latest commit message | Latest commit date |
|---|---|---|
`docker login` selhal na "403 Request forbidden by administrative rules" — ověřuje údaje voláním POST /auth na daemonu a socket proxy má AUTH=0. Zapisuje se proto přímo do ~/.docker/config.json. Na funkčnost to nemá vliv: `docker push` i Registry v2 API (ověřovací krok) berou přihlášení z tohohle souboru, `docker login` ho jen vyplňuje. Cena je, že se správnost údajů pozná teprve při pushi (401 z registry) místo hned — proto zůstává kontrola na prázdné hodnoty. Zápis přes python3 (ne jq — v job image není), base64 s fallbackem pro BSD variantu bez -w0. Otestováno end-to-end: zapíše správný base64, dekóduje se zpět na user:pass. Předchozí běh potvrdil, že Docker už funguje (`Docker API: zápis OK`), takže tohle je poslední krok před samotným buildem. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
| .forgejo/workflows | ||
| .gitignore | ||
| README.md | ||
forgejo-workflows
Sdílená Forgejo Actions workflow pro gravela ekosystém — Java monorepa
(java-*) a projekty v Rustu a Node (rust-check, node-check).
Vzniklo proto, že java-check-main.yaml existoval ve čtyřech různých
verzích napříč pěti repozitáři — tři byly identické, jeden se lišil
věcně (wardenero potřebuje JDK 8). Každá úprava CI se musela opakovat
v každém repu zvlášť.
Workflow
java-build.yaml
Staví jen moduly, kterých se commit dotkl. Detekce běží z git diff
a zúží Gradle na konkrétní cesty; testy běží s buildem.
Parametry:
| vstup | výchozí | k čemu |
|---|---|---|
roots |
. |
kořeny se změněnými moduly, oddělené čárkou; . = celé repo jako jeden modul |
jdk8 |
false |
nainstalovat vedle JDK 21 i JDK 8 (wardenero / WebObjects) |
jvmargs |
-Xmx3g -XX:MaxMetaspaceSize=512m … |
org.gradle.jvmargs pro CI |
Runner label je natvrdo
host. Parametrizovat ho nejde: Forgejo vyhodnocujeruns-onpři plánování jobu, kdyinputsještě neexistují — výraz by se přeložil na prázdno a job by čekal na runner bez labelu.
Potřebuje (nastavuje se v repu nebo organizaci):
- secrets:
GRADLE_ENCRYPTION_KEY,IVY_PASS - vars:
IVY_USER,IVY_HOSTS,INIT_GRADLE_KTS
java-release.yaml
Volá release úlohy z kit.gradle.artifactory — posun verze, git tag,
podpis a nahrání do Forgejo řeší plugin, workflow je jen obal.
| vstup | výchozí | k čemu |
|---|---|---|
modules |
— (povinné) | Gradle cesty modulů, oddělené čárkou |
app |
— (povinné) | název aplikace z profile.yaml; úloha je <app>.release-<env>.<bump> |
env |
test |
test nebo prod |
bump |
patch |
patch, minor, nebo none (přebalení) |
jdk8 |
false |
JDK 8 vedle 21 |
jvmargs |
-Xmx3g … |
org.gradle.jvmargs |
java-docker-release.yaml
Staví a pushuje Docker image — backend přes Gradle (dockerPushAllImages
nebo :modul:dockerPushImage), SPA přes spa/docker-image.sh. S
java-release.yaml se nepřekrývá: ten vydává artefakty do Ivy/JFrog.
Spouští se jen z UI konzumenta (workflow_dispatch → workflow_call) — push
image je vědomá akce, ne důsledek commitu.
| vstup | výchozí | k čemu |
|---|---|---|
tag |
pred |
Docker tag (dockerImageTag / SPA_TAG) |
version |
— | X.Y.Z → neměnný tag navíc + git tag vX.Y.Z (jen target: all) |
additional-tags |
— | další re-tagy po pushi, bez rebuildu |
target |
all |
all, backend, nebo spa |
modules |
— | jen vybrané moduly, čárkou (cabinetry,hub-ui); backend vs. SPA se pozná příponou -ui |
push |
true |
false = jen postavit, nepushovat |
registry |
registry.maticon.cz |
registry pro ověřovací krok |
jvmargs |
-Xmx3g … |
org.gradle.jvmargs |
Navíc k běžným secrets potřebuje REGISTRY_USER (vars) + REGISTRY_PASS
(secret) na docker login a MATICON_TOKEN na push git tagu.
Docker CLI a buildx si doinstaluje sám (apk, fallback apt-get) — runner
image forgejo/runner je Alpine a Docker klienta neobsahuje, byť má
DOCKER_HOST na socket proxy.
Git tag zakládá jen target: all bez modules, a teprve po úspěšném pushi
i ověření registry. Tag je na celé repo, takže u částečného releasu by tvrdil,
že vznikly i image, které se nepostavily.
java-promote.yaml
Přenese hotový release mezi prostředími — nestaví ani nepodepisuje, do produkce jde bajtově tentýž soubor.
| vstup | výchozí | k čemu |
|---|---|---|
modules, app |
— (povinné) | jako výš |
from / to |
TEST / PROD |
zdrojové a cílové prostředí |
version |
(z gradle.properties) |
která verze se promuje |
⚠️ eToken v CI nefunguje. Klientské JARy se podepisují hardwarovým tokenem v USB, takže repo se
signing=etoken(dnes wardenero) vydává klienta lokálně; workflow zvládne jen server.
⚠️ Release potřebuje plnou historii (
fetch-depth: 0+ tagy). Plugin kontroluje, jestli verze už nevyšla, a s mělkým klonem by tag nenašel.
rust-check.yaml
Formát, testy a clippy v jednom jobu.
Oddělit clippy by se hodilo (neblokoval by testy, při selhání by bylo hned
vidět, co spadlo), ale u projektů s Tauri se za to platí instalací systémových
knihoven nadvakrát — 266 balíčků, 163 MB a ~4,5 minuty na rozbalení
a konfiguraci, protože každý job startuje v čerstvém kontejneru a stav systému
se necachuje. Clippy se bez nich neobejde: gdk-sys build skript hledá GTK
přes pkg-config už při kompilaci, takže padá i bez linkování.
Na našem runneru navíc joby běží sériově (jeden slot), takže oddělení dnes nezrychlí ani zpětnou vazbu. Až bude runner zvládat paralelizaci, rozdělení je otázka pár řádků.
| vstup | výchozí | k čemu |
|---|---|---|
exclude-packages |
(prázdné = všechny) | balíčky VYNECHANÉ z fmt a clippy, jména oddělená mezerou |
test-args |
--workspace |
argumenty pro cargo test |
clippy |
false |
spustit clippy job |
clippy-deny-warnings |
true |
-D warnings, tedy varování = chyba |
tauri |
false |
doinstalovat GTK/WebKit pro Tauri |
Vynechává se, nevyjmenovává. Seznam balíčků se odvozuje z
cargo metadata;exclude-packagesz něj jen ubírá.Cargo.tomlsmembers = ["crates/*"]totiž přidá nový crate do workspace sám a ruční výčet by na něj zapomněl — crate by se tiše nekontroloval. Překlep vexclude-packagesjob zastaví s výpisem, co ve workspace není.
Vynechává se generovaný kód: formátovat ho nemá smysl a clippy na něm vyrábí stovky varování, která nikdo nečte. Testy ho naopak pokrývají, proto zůstává
test-args: --workspace.
Toolchain se instaluje krokem (~15 s) — runner Rust mít nemusí. Verzi i komponenty bere
rustup showzrust-toolchain.toml, takže se CI a lokální vývoj nerozejdou.
node-check.yaml
Install, testy, build. Jeden job — celá sada trvá jednotky sekund a zátěž je
pnpm install, který by se v druhém jobu jen zopakoval.
| vstup | výchozí | k čemu |
|---|---|---|
node-version |
22 |
drž shodné s .nvmrc a engines.node |
pnpm-version |
— (povinné) | MUSÍ odpovídat packageManager v package.json |
test-command |
pnpm test |
z rootu; pnpm -r test v monorepu bez per-package skriptů neudělá nic |
build-filter |
(prázdné = bez buildu) | pnpm filtr, např. ./spa-apps/* |
timezone |
UTC |
zóna pro celý job |
build-filtermusí začínat./— pak ho pnpm bere jako cestu. Bez tečky je to vzor na NÁZEV balíčku, takžespa-apps/*nematchne@scope/my-appa krok projde jako zelený, aniž by se cokoli postavilo.
timezonenastav tam, kde testy pracují s časem. Runner jede v UTC, takže testy s pevným časem (otevírací doba, formátování data) vycházejí posunuté — v kravify shodily build hláškou „expected '4:00–20:00' to match /6.*22/", přestože kód byl v pořádku. Totéž zafixuj i ve vitest konfiguraci, aby lokální běh dopadl stejně.
Použití
.forgejo/workflows/build.yaml v konzumentovi:
name: Build changed modules
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:
concurrency:
group: build-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
uses: gradle/forgejo-workflows/.forgejo/workflows/java-build.yaml@main
with:
roots: 'client,libs,server'
jdk8: true
secrets: inherit
on: a concurrency: zůstávají v konzumentovi — reusable workflow je
nedědí a každé repo je může chtít jinak.
Repozitáře na jiné Forgejo instanci (git.eiger.cz — springerize, eiger) odkazují plnou URL a musí si uvést
runs-onsamy:jobs: build: runs-on: host # ← nutné, viz níž uses: https://git.maticon.cz/gradle/forgejo-workflows/.forgejo/workflows/java-build.yaml@mainDůvod je v dokumentaci Forgejo: workflow z jiné instance nepodporuje „workflow expansion", která se tím automaticky vypne. Bez ní Forgejo nepřevezme
runs-onz volaného workflow a job čeká na runner s prázdným labelem.Na téže instanci se
runs-onnaopak vynechává — expansion funguje a zobrazí joby volaného workflow zvlášť, s vlastními runnery.Vedlejší efekt vypnuté expansion: ve Forgejo UI se u cross-host volání objeví jen obalový job (
Set up job/Complete job) místo jednotlivých kroků. Build běží správně, plný výstup je uvnitřSet up job— jen se hůř hledá. Zapnout to nejde, je to automatika.Zkrácený tvar (
gradle/forgejo-workflows/…) z jiné instance nefunguje: hledá organizaci lokálně a skončí na „user does not exist".
⚠️ Organizace nesmí mít v názvu tečku. Forgejo parsuje
uses:jako<owner>/<repo>/<cesta>@<ref>a utools.gradle/...nepozná, kde končí owner — skončí to na „expanding reusable workflow failed to access user tools.gradle: user does not exist". Protogradle, netools.gradle.
⚠️
cancel-in-progress: truepatří jen do build workflow. Release se rušit nesmí: zrušení uprostřed nahrávání assetů nechá release neúplný a kvůli skip-logice na velikosti a SHA by vypadal jako hotový.
Kdo to používá
| repo | roots |
jdk8 |
|---|---|---|
| wardenero | client,libs,server |
✅ |
| tornelix | . |
❌ |
| bazaltis | . |
❌ |
| springerize ¹ | . |
❌ |
| eiger ¹ | . |
✅ |
¹ na git.eiger.cz — odkazuje plnou URL
java-docker-release:
| repo | co vydává | ref |
|---|---|---|
| bazaltis | 7 backend image + 9 SPA image | SHA (viz Změny) |
rust-check + node-check:
| repo | co |
|---|---|
| kravify | Rust workspace (Tauri) + pnpm monorepo se SPA aplikacemi |
Změny
⚠️
@mainse neprojeví hned — Forgejo si stažené workflow cachuje. Zjištěno 2026-10-01 na bazaltis: po pushi opravy sem běžel konzument dál starou verzí (poznalo se to tak, že chybová hláška neodpovídala aktuálnímu kódu). „Rerun" nepomůže — přehrává tentýž běh s původním snapshotem definice. Nový běh cache obvykle obejde, spolehlivé to ale není.Proto
java-docker-release.yamlkonzumuje bazaltis připíchnutý na commit SHA, ne@main: SHA je jiný ref, takže cache nemá co vrátit.
Push změny sem = úkol u konzumentů se SHA
Změna workflow, které konzument odkazuje přes SHA, se k němu sama nedostane —
musí se v jeho .forgejo/workflows/*.yaml SHA bumpnout:
| repo | workflow | ref |
|---|---|---|
| bazaltis | java-docker-release.yaml |
SHA — bumpovat ručně |
| ostatní | java-build.yaml, rust-check.yaml, … |
@main — propíše se samo (cache může zdržet) |
Pořadí: nejdřív push sem, pak bump u konzumenta. Opačně odkazuje konzument commit, který na remote ještě není.
Volba refu
uses: .../java-build.yaml@main # propíše se samo, cache může zdržet
uses: .../java-build.yaml@2b941f3 # reprodukovatelné, bump ručně
SHA stojí za to u workflow, které něco mění navenek (push image, git tag,
release) — tam je nechtěná změna pod rukama drahá. U *-check workflow, kde
nejhorší následek je falešně červený build, stačí @main.
Když by parametrů začalo přibývat nad rámec těch čtyř, je to signál, že se sdílení přepálilo — ne že je potřeba pátý.