A WarpEngine mountolható Rails engine, amely bármelyik Rails-appból retró szoftverkatalógust csinál. Egy játékrepó egyetlen soros
.woodpecker.yamljelölőt visz, a motor kiszolgálja a teljes CI-pipeline-t, a buildek HTTP-n töltődnek fel, egy publikálási hívás pedig upserteli a katalógust. Publikus, read-only JSON API és opcionális ActiveAdmin resource-ok is járnak hozzá. Minden osztálya, szolgáltatása és kontrollere dokumentálva van a forrásban: az API-referencia (RDoc) mindenwarp_engine-v*taggel újraépül belőle.
| Oldal | Mi az | Szerep |
|---|---|---|
| WECP — WarpEngine Catalog Protocol | Az olvasó oldali HTTP/JSON szerződés végpontonként: amivel minden katalógusolvasó beszél. | protokoll |
| WarpEngine Admin API | Az 1.0 óta: amit az admin tud, JSON API-ként, OpenAPI 3.1 leírással és MCP-szerverrel. Kikapcsolva érkezik. | protokoll |
| WarpEngine Client | Az asztali app: a katalógus kártyarácsként, telepítés, indítás, eltávolítás. Linux, macOS, Windows. | kliens |
| warpstore | A shell-szkriptes áruházmotorok közös magja: egy fájl, amely ismeri a WarpEngine-katalógust. | kliens |
| WarpEngine Batocera Store | Bármelyik WarpEngine-katalógus egy Batocera-dobozon, saját EmulationStation-menü alatt. | kliens |
| WarpEngine RetroArch Store | Bármelyik WarpEngine-katalógus RetroArch-lejátszási listaként, borítókkal. | kliens |
| TTG Batocera Store · TTG RetroArch Store | A saját két áruházunk: egy-egy konfig a fenti motorok tetején. | áruház |
| Nyilvános oldal | teletypegames.org, az első hoszt: a monorepó, amelyben a motor fejlődik, és a katalógus, amire a legtöbb olvasó mutat. | hoszt |
| Teletype Orbit | Az áruházplatform a WarpEngine-en: vásárlás, jogosultságok, kapuzott letöltések, eszközös bejelentkezés. | hoszt |
Software, Release, ReleaseAsset, ExternalLink, PlatformLink, SoftwareImage, Download. Mind soft delete-tel, download tracking-gel.WarpEngine::CI::Woodpecker néven, és ez a default; a :none kikapcsolja a CI-t, más szerver pedig a hoszt által adott objektum.POST /build/upload és POST /build/publish, shared secret-tel vagy adatbázisbeli application token-ekkel hitelesítve.Image modell, a fájljai, az /api/image/:id endpoint-ja és az admin oldala a hosztban él; az engine egy szoftvert egy képhez köt, és adapteren keresztül publikálja az URL-t. Ugyanaz a tábla ezután avatarokat vagy bármi mást is kiszolgálhat, ami a site-nak kell.rake warp_engine:builds:check szoftverenként és kiadásonként kiírja, mely assetek vannak meg, és melyeket tudná még a platform pipeline-ja leszállítani. Lásd: Mely assetek hiányoznak.INDEX.TXT-vel, olyan klienseknek, amelyek nem tudják olvasni a JSON API-t (a WARP64U C64-es programtár sima HTTP-n olvassa a C64-polcot). Az 1.7-től egy polc címenként egy mappa is lehet, abban az elrendezésben, amelyet a DOSINST olvas, így a DOS-bolt is a katalógusból épül. Lásd: Polcok.version lépést, és ahol a hoszt kéri, a végére egy forge-os release lépést, bármelyik platformon. Lásd: Lépések, amelyek minden pipeline-ban közösek.shelf, admin_api, additional_resource, ci … do platform … end); a régi |c|-s forma is működik. Lásd: Telepítés egy hosztba.v<verzió> tagjét; a tag pipeline-ja publikálja. Egy dev build az ága dev-<ág> tagjét mozgatja, így mindig az ág legfrissebb buildje van kiadva. Lásd: Verziók és kiadások.Platformonként két lista, és a különbség számít. Az elfogadott assetek az, amit a frissítő befogad egy kiadás publikálásakor (WarpEngine::Platform#expected_kinds). A pipeline ezeket építi az, amit a Woodpecker-sablonok ténylegesen elő is állítanak. Ahol eltérnek, ott a maradék kézi feltöltés.
Az 1.5 óta minden elfogadott kind ezen felül kötelező, várt vagy opcionális. Kötelező kind nélkül a publikálás 422-vel, a hiányzó kindok listájával válaszol, és nem rögzít semmit. Egy várt kind hiányozhat egy kiadásból, és az alábbi ellenőrzőlista jelzi. Egy opcionális kind jogosan hiányozhat, és nem számít hiánynak. A GET /api/builds platformonként mindhármat közli.
| Platform | Felirat | Elfogadott assetek | Kötelező | A pipeline ezeket építi |
|---|---|---|---|---|
godot |
Godot | html, win_x86, win_x64, linux_x64, mac_universal | html | mindet |
tic80 |
TIC-80 | cartridge, source, html, docs, win_x64, linux_x64, mac_x64 | cartridge | mindet |
bevy |
Bevy | html, win_x64, linux_x64, linux_arm64 | html | mindet |
love |
LÖVE | html, win_x64, linux_x64, mac_universal | html | mindet |
ebitengine |
Ebitengine | html, win_x86, win_x64, linux_x64, linux_arm64, mac_x64, mac_arm64 | html | html, win_x86, win_x64, linux_x64, linux_arm64 |
phaser |
Phaser | html | html | mindet |
c64 |
C64 | cartridge, html, win_x64, linux_x64, mac_arm64 | cartridge | mindet |
plus4 |
Plus/4 | cartridge, html, win_x64, linux_x64, mac_arm64 | cartridge | mindet |
dos |
DOS | cartridge (a telepíthető mappa zipben), win_x86 (opcionális: a Win32-es build, ami csak egyes programoknak van) | cartridge | mindet |
Az Ebitengine az egyetlen hiányosság: egy macOS-bináris osxcrosst igényel, amit a linuxos builder image nem visz, így a mac_x64 és a mac_arm64 mindig csak kézzel érkezik.
Egy kiadás akkor teljes, ha minden olyan asset-típust visz, amit a platformja pipeline-ja elő tud állítani — és semmi nem kényszeríti ki. Elbukik egy buildlépés, egy platform új célt kap, egy címet laptopról publikálnak, és a katalógus hét assetből hárommal szolgál ki egy kiadást. A motor ellenőrzőlistát szállít hozzá:
$ bin/rails warp_engine:builds:check
WarpEngine release asset coverage — latest release per software
expected: the kinds a platform's updater registers · [ ] the CI builds it · [-] the CI does not, upload it by hand
rabbitroller ebitengine v1.1.1 3/7
[x] html
[x] win_x64
[x] linux_x64
[ ] win_x86
[ ] linux_arm64
[-] mac_x64
[-] mac_arm64
The CI can build these and the release does not have them:
rabbitroller v1.1.1 (ebitengine): win_x86, linux_arm64
12 softwares, 12 releases, 61/78 assets present, 11 missing from CI-built kinds
4 softwares are missing an asset the CI builds
2 assets are expected but this CI does not build them
| Jelölés | Jelentés |
|---|---|
[x] |
a kiadásnak megvan ez az assetje |
[ ] |
a platform elvárja, és a pipeline meg is építi — valódi hiány, és ez az a sor, amivel érdemes kezdeni valamit |
[~] |
ezen a platformon opcionális (a DOS win_x86-ja): hiányzik, és nem számít hiánynak |
[-] |
elvárt, de ez a CI nem tudja megépíteni (lásd a fenti táblázatot) — kézi feltöltés, vagy semmi |
[+] |
a kiadás olyan assetet visz, amit a platform nem vár el |
A beállítások környezeti változók, így shellből komponálhatók:
| Változó | Hatás |
|---|---|
NAME=rabbitroller |
egyetlen szoftver |
PLATFORM=ebitengine |
egyetlen platform |
RELEASES=all |
minden kiadás, nem csak a szoftverenkénti legfrissebb |
ONLY=missing |
csak azok a kiadások, amelyekből hiányzik egy CI által épített asset |
STRICT=1 |
nem nulla kilépési kód, ha bármi hiányzik — ütemezett ellenőrzéshez |
A „legfrissebb" a legfrissebb nem dev- verzió — ugyanaz a szabály, amit a katalógus API is használ, amikor megnevezi egy cím legutóbbi kiadását. A számok is objektumok: a WarpEngine::AssetCoverage a #rows, #missing_rows és #totals metódusokra válaszol, a WarpEngine::AssetCoverageChecklist pedig kirendereli őket.
Mindkét hoszton elérhető: a nyilvános oldalon és a Teletype Orbitban.
Ez az API olvasó oldala — a WECP, WarpEngine Catalog Protocol. Minden végpont kérés- és válaszalakja a WECP-oldalon van; ez a tábla a térkép.
| Végpont | Mire való |
|---|---|
GET /api/service |
Mi ez a telepítés: verzió, kapuz-e a katalógus, hogyan lehet belépni, és (1.7 óta) a polcai a címeikkel. |
GET /api/software |
A katalógus kiadásokkal, assetekkel, linkekkel, letöltésszámokkal, opcionális category mezővel és egy access blokkal — egészben, vagy laponként (?page=, ?per_page=), status, platform, category, q, owner_id szűrőkkel. |
GET /api/software/facets |
Hány szoftvert mutatna az egyes státusz-, platform- és kategóriaértékek a többi szűrő mellett. |
GET /api/software/vocabulary |
A katalógus státuszai és kategóriái, címkével és sorrenddel. |
GET /api/software/highlighted |
A kiemelt cím. |
GET /api/builds |
Platformonként elvárt asset-típusok. |
GET /api/softwares/:name/builds |
Kiadásonként a meglévő és a hiányzó buildassetek. |
GET /api/image/:id |
Képek. 0.6 óta a hoszt végpontja — a motor közli a címet, a hoszt szolgálja ki. |
GET /api/download?path= |
Kiszolgál egy artifactot, és naplózza a letöltést. |
GET /file/*path |
Statikus buildkimenet (böngészőben játszható játékok, dokumentáció). |
POST /api/auth/device |
Elindít egy eszközbelépést, visszaadja a kódpárt. 404, ha nincs kliensidentitás beállítva. |
POST /api/auth/device/token |
Lekérdezi egy eszközbelépés tokenjét. |
DELETE /api/auth/token |
Visszavonja a kérésen érkező bearer tokent — kilépés. |
Minden olvasó végpont elfogad egy opcionális Authorization: Bearer … fejlécet; egyik sem követeli meg. A token csak azt változtatja meg, amit a hozzáférési szabályzattól kérdezünk. Az anonim hívó támogatott hívó.
Minden válasz visz egy WarpEngine-Version fejlécet, amely az akció lefutása előtt kerül rá — így a hibaválaszokon is rajta van, és egy kliens plusz kérés nélkül tud a motorverzió szerint ágazni.
$ curl -sI https://teletypegames.org/api/software | grep -i warpengine
WarpEngine-Version: 0.13.1
A hosztalkalmazás saját végpontjai (például az áruház-nyilvántartás) nem viszik — azok nem részei a motornak.
| Végpont | Mire való |
|---|---|
POST /build/upload |
Egy artifact (multipart file, opcionális sha256). X-Update-Secret kell hozzá. |
POST /build/publish |
A feltöltött artifactok regisztrálása kiadásként. X-Update-Secret kell hozzá. Az 1.9 óta a már kiadott legújabbnál régebbi verzióra 409-et ad. |
POST /build/config |
Woodpecker-konfigurációs kiterjesztés; a pipeline-YAML-t szolgálja ki. Aláírás-ellenőrzött (RFC 9421, ed25519). |
GET /build/config?platform= |
A generált YAML nyilvános előnézete. |
Két seam került be a 0.5.0-ban, mindkettő a storage adapter mintájára: dokumentált contract, a régi viselkedéssel azonos default, és egyetlen config kulcs a cseréjéhez. Ha egyiket sem állítod be, semmi nem változik.
c.access_policy = MyStore::AccessPolicy.new # :open (alapérték) = a katalógus, ahogy volt
A szabályzat három kérdésre válaszol:
| Metódus | Kérdés |
|---|---|
visible_software_scope |
mely címeket listázza a GET /api/software |
access_for |
mit tudunk meg egy kliensként az egyes címekről |
authorize_download |
átadható-e ez az artifact |
Az authorize_download kérdést az /api/download és a /file/* is felteszi, mielőtt bármit kiszolgálna, így egy hosztnak már nem kell árnyékolnia ezeket az útvonalakat.
Minden katalógusbejegyzés visz egy access blokkot, a nyílt szabályzat alatt is — egy kliensnek soha nem kell találgatnia, hogy a katalógus hallgat-e, vagy a cím egyszerűen nincs kapuzva:
"access": { "gated": true, "entitled": false,
"price": { "amountCents": 1490, "currency": "EUR" },
"purchaseUrl": "https://shop.example/games/slug",
"webUrl": "https://shop.example/play/slug" }
A mezőnevek szándékosan általánosak, mert egy kliens több katalógust olvas.
Ha a policy exception-t dob, az elutasításnak számít: üres katalógus, megtagadott letöltés, logolva. Egy artifactot soha nem szabad azért kiszolgálni, mert a gatekeeper crashelt.
Egy desktop kliensnek nincs cookie jar-ja és nincs böngésző session-je, ezért az engine login form helyett a device authorization grant-et (RFC 8628) használja.
c.access_token_owner_class = "User" # nil (alapérték): sehol nincs belépés
c.identity_verification_url = "/devices" # a te oldalad, ahol valaki beírja a kódot
c.subject_resolver = ->(request) { request.env["warden"]&.user } # böngésző felismerése
POST-ol az /api/auth/device végpontra, és megmutatja a userCode értéket;WarpEngine::DeviceGrantService#approve(user_code:, subject:) metódust — a jóváhagyáshoz session és HTML kell, ami nem az engine dolga;A token egy WarpEngine::ApplicationToken a catalog scope-pal, így a publish és a kliens credential-ök egyetlen táblában is szétválaszthatók maradnak. A subject_resolver fedi le a másik esetet: egy böngésző session-t visz, nem bearer token-t, és enélkül egy gated áruház a saját bejelentkezett látogatóit utasítaná vissza.
Ha az access_token_owner_class nincs beállítva, az /api/auth/* 404-et ad, az /api/service pedig auth: null-t jelent, így a kliens nem kínál sign-in-t.
A kép nem katalógusfogalom — ugyanaz a képtár szolgálja ki a borítókat,
a képernyőképeket és az avatarokat —, ezért a 0.6.0-tól a motoré csak a kapcsolat
(SoftwareImage: sorrendezett, egy alapértelmezett), miközben a modell, a fájlok, a
végpont és az adminoldal a hoszté. A rails g warp_engine:install
kiír egy működő készletet (app/models/image.rb, app/controllers/api/images_controller.rb,
egy create_images migrációt), a motor pedig adapteren keresztül éri el:
c.image_class_name = "Image" # alapérték
c.image_adapter = MyLibrary.new # vagy cseréld le teljesen az adaptert
| Metódus | Mire használjuk |
|---|---|
model_name / model |
az az osztály, amelyhez a SoftwareImage#image tartozik |
url_for(image_id) |
az imageUrl és az images[].url a katalógus JSON-jában, valamint az adminelőnézetek |
select_options |
a képválasztó a szoftverűrlapon |
build_from_upload(upload) |
„új kép feltöltése" ugyanezen az űrlapon |
label_for(record), available?(record) |
az admin felirata és a „megvan-e a fájl" ellenőrzés |
Az alapértelmezett adapter az /api/image/<id> címet publikálja — azt, amit a kliensek
mindig is használtak —, ezért a generált útvonal pontosan ezt szolgálja ki. Az
images tábla nem költözött: a motor egyszerűen abbahagyta a létrehozását, és a
software_images.image_id továbbra is ugyanazokra a sorokra mutat.
Egy játékrepónak nincs saját pipeline-ja. A Woodpecker minden pipeline-indításkor POST-olja az egysoros jelölőt a /build/config végpontra, és visszakapja a teljes YAML-t.
.woodpecker.yaml fájljában csak a platform: van (és a name:, ha a szoftvernév eltér a repó nevétől).POST /build/config végpontra.lib/warp_engine/ci/woodpecker/platforms/<platform>/pipeline.yaml.erb sablont a beállított builder image-dzsel — a YAML-nyelvjárás a szolgáltatóé, tehát az adapterrel együtt él. Az 1.1-től a segédlépések (version, lint, minify, docs, upload, publish) a platform tools image-ében futnak, ha van ilyen, és semmit nem telepítenek; nélküle alpine-ban futnak, és minden futáskor apk add-dal (vagy luarocks install-lal) rakják fel, ami kell nekik.Egy repó úgy lép ki ebből, hogy valódi pipeline-YAML-t commitol: a nem jelölő konfiguráció 204 No Content választ kap, és változatlanul fut.
# .woodpecker.yaml
platform: godot
name: mygame # opcionális, alapból a repó neve
// metadata.json — a TIC-80-on kívül minden platformon ugyanez
{
"name": "mygame",
"version": "1.0.0",
"title": "My Godot Game",
"author": "You",
"desc": "A cool game",
"license": "MIT",
"category": "puzzle"
}
A category opcionális szabad szöveg, amely szerint egy kliens csoportosíthatja a címeket — puzzle, action, demo. A 0.12-től a Software rekordra és a GET /api/software válaszába kerül; a WarpEngine Client kategória-tengelyt rajzol a szűrőjébe, amint egy katalógus publikál ilyet. A site és a repo is opcionális, belőlük külső link lesz.
| Platform | Forráselvárások | Mit épít a pipeline |
|---|---|---|
godot |
exportbeállítások: Web, Windows x86, Windows x64, Linux x64, Mac universal | godot --headless --export-release előbeállításonként |
bevy |
szabványos Cargo-projekt; az assets/ a natív binárisok mellé kerül becsomagolva |
WASM, linux-x64, win-x64 (mingw) |
love |
szabványos LÖVE-projekt | love.js webes build, Windows exe, Linux AppImage, univerzális macOS .app |
ebitengine |
szabványos Go-projekt | WASM, win x86/x64, linux x64, mac x64/arm64 |
phaser |
JS-fájlok a src/ alatt |
szintaxisellenőrzés, a Phaser-runtime letöltése, webes zip |
c64 |
main.asm, vagy build: make mellett egy Makefile |
ACME-fordítás .prg kazettává (vagy make <name>.prg, a builder image-ben cc65 is van), majd commodore-pack az exporter image-ben: EmulatorJS webes build a vice_x64sc core-ral és yapeSDL-csomagok linux-x64, win-x64 és mac-arm64 célra |
plus4 |
ugyanaz, mint a c64 |
ugyanaz, mint a c64, a vice_xplus4 core-ral és Plus/4 módú yapeSDL-lel |
dos |
SOURCE/build.sh, a tesztek, és a metadata.json dos szakasza (lásd: DOS) |
a dos-builder image parancsai (dos-tools): minden eseményre a build és a tesztek; tagre a telepíthető mappa zipje (és a Win32-esé) és a forge-kiadás; az FTP-bolt a DOS-polc, a katalógusból épül |
tic80 |
<name>.inc, amely felsorolja az inc/ alatti darabokat |
összefűzés, luacheck, minifikálás, LDoc, HTML + kazetta + natív binárisok |
A TIC-80-nak nem kell metadata.json — a metaadat a Lua-fejléc:
-- title: My TIC Game
-- name: mygame
-- author: You
-- desc: A TIC-80 game
-- category: puzzle
-- version: 1.0.0
function TIC() end
| Kulcs | Kötelező | Leírás |
|---|---|---|
platform |
igen | godot, tic80, bevy, love, ebitengine, phaser, c64, plus4, dos, vagy egy a hoszt által felvett platform |
name |
nem | Szoftvernév; alapból a repó neve |
release |
nem | tag (az 1.9 óta alapértelmezés): a build minden eseményre fut, a push a tag lépéssel zárul, a kiadási lépések (package, upload, publish, release) csak tagre futnak. push: az 1.9 előtti működés, minden push publikál, és nincs tagelés. Egy platform megkövetelheti a taget (release_rule "tag" a szolgáltatásában), és akkor a jelölő nem választhatja a push-t: a DOS ilyen platform |
build |
nem | make a c64-en és a plus4-en: make <name>.prg az ACME-s main.asm helyett, C-ben írt programhoz (a WARP64U így épül) |
Minden más kulcs egy olyan opció, amit a platform sablonja olvashat: csak betű, szám és _ . -, a többi kimarad. A repó többi .woodpecker/*.yaml fájlja változatlanul visszamegy, így a repó a generált mellett megtarthatja a saját workflow-ját (tesztek, deploy).
curl "https://your-host/build/config?platform=godot"
A GET /api/software borítékban válaszol — api (a JSON-alak saját verziója, 2), page, perPage, total, totalPages, nextPage és softwares. page nélkül a teljes katalógus jön vissza ebben a borítékban, amit minden 2-es API előtti olvasó a softwares alatt talál meg; page-gel egy lap per_page elemmel (catalog_page_size, ha nincs megadva, legfeljebb catalog_max_page_size). A szűrők a lapozás előtt szűkítik a katalógust; a hozzáférési szabályzat mindkettő előtt dönt a láthatóságról.
A státuszok és a kategóriák adatbázisbeli szótár — WarpEngine::SoftwareStatus és WarpEngine::SoftwareCategory, adminban szerkeszthető —, nem kódba írt lista. Egy szoftver status-a ismert kulcs kell legyen: a migráció a négyet seedeli, és a 0.13.1-től a modell maga teszi vissza őket egy üres táblába az első használatnál — egy db:schema:load-dal, nem migrációval épült adatbázisban, ami minden teszt-adatbázis, különben nem lenne egy sor sem. Egy publish által hozott, még el nem nevezett kategória a kulcsával mint címkével és needs_review jelzéssel kerül a szótárba. A GET /api/software/vocabulary mindkettőt publikálja, az oldal katalógusa és a WarpEngine Client ebből veszi a címkéket.
Minden generált pipeline egyetlen Woodpecker-secretet vár, az application_token értéket, amelyet X-Update-Secret fejlécként küld a /build/upload és a /build/publish végpontokra.
A tag lépés (1.9) a gitea_token secrettel ír tageket: ez egy Forgejo-token, írásjoggal a repóhoz (GitLabon egy TAG_TOKEN CI/CD-változó, api jogú access token). A teletypegames.org-on ez globális Woodpecker-secret, így egy új repónak ehhez nem kell semmi.
A verziózás mindenhol ugyanaz, mert az 1.7 óta a version lépést maga az engine adja hozzá (lásd lent).
Az 1.7 óta ezek a lépések egyik sablonban sincsenek benne; az engine minden renderelt pipeline-hoz hozzáadja őket:
version, elsőként. A verzió a metadata.json fájlból jön (TIC-80 esetén a Lua-fejléc -- version: sorából). Tagnél egy verziótagnek (v1.2.3 vagy 1.2.3) egyeznie kell vele, és ha a forrás nem nevez meg verziót, a tag a verzió; ha nem egyezik, a pipeline elbukik. A repó alapágán kívül dev-<version>-<branch> lesz belőle, pl. dev-1.0.0-my-feature, és ugyanígy egy dev-<ág> tagen; verzió nélkül a build dev-<commit>, ami sosem a legfrissebb. Az 1.9 óta az alapág a repó saját alapága (CI_REPO_DEFAULT_BRANCH), így egy develop alapágú repó a develop-ról ad ki; korábban ez a main vagy a master volt.tag (1.9), a push utáni build végén, hacsak a jelölő nem mondja, hogy release: push: új verziót tagel, vagy áthelyezi az ág dev tagjét. Lásd: Verziók és kiadások.release, utolsóként, verziótagre (dev- tagre nem készül), ha a hoszt a platform bejegyzésében forge_release: true-t állít (bármelyik platform kaphatja): a tag Gitea/Forgejo-kiadása (GitLabon GitLab-kiadás), a cím és a tag nevével, a RELEASE_NOTES.md szövegével, a gitea_token secrettel. Azokat a fájlokat csatolja, amelyeket a build a .release-assets-ben felsorolt, különben a feltöltési lépés által feltöltötteket. A teletypegames.org-on csak a dos-nál van bekapcsolva.Az 1.9.1 óta egy generált Woodpecker-pipeline a release kivételével minden eseményre elindul (egy workflow-szintű when, amely elmarad, ha a sablonnak van sajátja): egy dev tag áthelyezésekor a Forgejo a tag mellett release eseményt is küld, és ez ugyanazt a commitot még egyszer lebuildelte.
Minden sablon ugyanúgy nevezi a lépéseit: amelyik a fájlokat a /build/upload-ra küldi, az az upload (a c64, a plus4, az ebitengine és a dos az 1.7 előtt artifact-nak hívta), amelyik a /build/publish-t hívja, az a publish. A c64-en és a plus4-en csak a ténylegesen elkészült lejátszók töltődnek fel; a LÖVE már nem tölt fel .love.zip-et.
Az 1.9 óta senki nem tagel és senki nem publikál kézzel: mindenről a forrásban lévő verzió dönt.
metadata.json version mezője, TIC-80-on a -- version: sor. Az emelése maga a kiadás.tag lépés v<verzió> taget tesz a pusholt commitra (a forge API-ján). Ez a tag saját pipeline-t indít, amely feltölt és publikál; ahol a platformon forge_release van, forge-kiadás is készül.version lépés elbuktatja a pipeline-t, a tag lépés pedig a már létező taget nem bántja./build/publish 409-et ad a már kiadott legújabbnál régebbi verzióra (Gem::Version szerint): az lenne a legfrissebb kiadás, és visszahozná a régi metaadatait. Ugyanaz a verzió újra, egy újabb, vagy bármilyen dev- verzió átmegy.dev-<verzió>-<ág>; ha a forrásban nincs verzió, dev-<commit>. Egy ilyen buildnél a tag lépés áthelyezi az ág dev-<ág> tagjét a pusholt commitra (először létrehozza), és a tag pipeline-ja publikálja a dev buildet, felülírva az előző azonos nevűt. Egy dev verzió sosem egy cím legfrissebb kiadása, és nem készül belőle forge-kiadás.release: push minden pushra, tag nélkül publikál, ahogy az 1.9 előtt. A DOS nem léphet ki.Minden engine-nel épülő teletypegames.org-os repó korábbi verziói 2026-10-27-én egy menetben megkapták a tagjeiket (script/backfill_version_tags.rb a monorepóban: minden verzió tagje azon az első alapági commiton, amelyben megjelent), így a tagek egy repó teljes történetét mutatják.
Az 1.5 óta a sablonokban nincs egyetlen hoszt címe sem. Ami hosztonként más, azt a CI adapter platforms: beállításában a platform bejegyzése hordozza:
web_shell: — az oldal, amelybe egy bevy-, ebitengine- vagy phaser-féle böngészős build kerül. URL-lel a pipeline letölti; anélkül a repó saját web/index.html-jét veszi.bundle_id_prefix: — a LÖVE macOS-alkalmazás bundle-azonosítója <prefix>.<name> (alapból org.warpengine).exporter: — a c64-en és a plus4-en az az image, amelyben a commodore-pack <c64|plus4> <name> <version> van; ez a PRG mellé megírja a böngészős és a három natív lejátszót.A mi hosztjaink a Teletype Games értékeit állítják be, így a pipeline-jaik ugyanúgy renderelődnek, mint korábban.
A hoszt az initializerben vehet fel platformot — egy szolgáltatásosztállyal, a CI által épített kindokkal és CI-adapterenként egy pipeline-sablonnal:
c.register_platform "amiga",
service: "AmigaPlatform",
built_kinds: %w[cartridge],
templates: { woodpecker: Rails.root.join("ci/amiga.woodpecker.yaml.erb") }
A szolgáltatás a WarpEngine::Platforms::Updatable-t és a kindjai build-concernjeit húzza be, és megnevezi magát (platform "amiga", label "Amiga", required_kinds "cartridge"). Innentől ugyanolyan platform, mint a többi: szoftver lehet rajta, a publikálás az ő szolgáltatását futtatja, az admin listázza, a configuration extension az ő sablonját rendereli. Ami korábban a rögzített listát olvasta, az most a WarpEngine::Platform.names-t.
A polc (1.2 óta) egy mappa, amelyet az engine szinkronban tart a katalógussal: egy platformhoz minden nyilvános cím legfrissebb kiadása rögzített, verzió nélküli néven, plusz egy INDEX.TXT (file|version|size|crc32|title|author|description, ASCII, soronként legfeljebb 255 bájt). Azoknak a klienseknek szól, amelyek nem tudják HTTPS-en olvasni a JSON API-t. A c.shelves adja meg a platformot, a kindot, az útvonalat, a kiterjesztést és a névhosszt; a :local storage adapter kell hozzá. A fájlt a szoftver shelf_name-je nevezi meg (a metadata.json-ból, az adminból vagy az Admin API-ból). A polc minden publikáláskor és a címei minden változásakor újraépül, az index cserélődik utoljára; a rake warp_engine:shelves:check és a warp_engine:shelves:sync kézzel ellenőrzi és újraépíti.
Az 1.7 óta egy polc layout: "folders" is lehet: címenként egy mappa, abban az elrendezésben, amelyet a DOSINST olvas. Az engine kicsomagolja a kiadási zip legfelső mappáját, kihagyja belőle a metaadat dos szakaszának settings fájljait (így egy frissítés megtartja a telepített program beállításait), és két fájlt ír minden mappába: INFO.INI ([program] a name, description, version és platform — DOS vagy WIN32 — kulcsokkal, CRLF) és FILES.LST (crc32 size path, CRLF). A kind lista is lehet: a DOS-polcon a cartridge és a win_x86 van, így például a DOSINST-nek egy DOSINST és egy DOSINSTW mappája van. Csak azokat a mappákat törli valaha, amelyeket a polc INDEX.TXT-je felsorolt, így egy kézzel odatett mappa (például egy tesztprogram) megmarad.
A polcnak urls mezője is van, hogy a hoszt hol szolgálja ki, és a GET /api/service a shelves alatt listázza a polcokat (platform, kindok, elrendezés, index, címek). A kiszolgálás továbbra is a hoszt dolga: az engine megírja a mappát, saját FTP- vagy HTTP-szervert nem futtat.
A teletypegames.org három polcot tart, ezeket az FTP-szerver szolgálja ki FTP-n és sima HTTP-n:
| Polc | Mappa | Elrendezés | Cím |
|---|---|---|---|
| C64 | shelves/C64 |
lapos | ftp://ftp.teletypegames.org/C64, http://archive.teletypegames.org/C64 |
| Plus/4 | shelves/PLUS4 |
lapos | ftp://ftp.teletypegames.org/PLUS4, http://archive.teletypegames.org/PLUS4 |
| DOS | shelves/APPS |
mappás | ftp://ftp.teletypegames.org/APPS, http://archive.teletypegames.org/APPS |
Csak ott aktív, ahol az adapternek van url és api_token értéke (WarpEngine.ci.configured?). Addig az adminoldalak elrejtik magukat.
Pipeline rekordokba, név alapján párosítja az egyes repókat egy Software rekorddal, és örökli annak platformját. A Woodpeckerből eltűnt repók deaktiválódnak. A linkek kézzel szerkeszthetők maradnak.application_token secretet a tulajdonos repóira (korlátozás nélküli tokenek esetén minden aktív repóra); a törlés eltávolítja; a Rotate létrehoz egy cserét, mindenhova kiosztja, és egy lépésben visszavonja a régit.A PAT-nak Woodpecker-példányadminhoz kell tartoznia — a repók listázása csak admin által hívható végpont, minden más 403 User not authorized választ ad. Vedd fel a felhasználót a WOODPECKER_ADMIN listába, majd lépj ki és vissza: az adminjelző a bejelentkezéskor íródik, a szerver újraindítása nem elég.
Az X-Update-Secret kétféle hitelesítő adat egyikét viszi, amit az application_token_source választ ki. A módok kizárják egymást.
| Mód | Hitelesítő adat |
|---|---|
:env (alapérték) |
a közös titok az update_secret értékben; ha nincs beállítva, minden kérés elutasításra kerül |
:database |
WarpEngine::ApplicationToken rekordok: tulajdonos (pl. AdminUser), jogosultságok (update a publikáláshoz, upload a feltöltéshez), opcionális lejárat. Az adminban jönnek létre; a nyílt token egyszer jelenik meg, csak a SHA256-lenyomata tárolódik. A last_used_at követi a használatot. |
Cutover warning: a
:databasemódra váltás azonnal érvényteleníti a shared secret-et. Előbb hozd létre a token-eket.
# Gemfile — gitből:
gem "warp_engine", git: "https://git.teletypegames.org/engines/warp_engine.git"
# ...vagy a Forgejo rubygems-regiszteréből (taggelt kiadások):
source "https://git.teletypegames.org/api/packages/engines/rubygems" do
gem "warp_engine"
end
rails g warp_engine:install # initializer, képtár, migrációk
rails db:migrate
# config/routes.rb
namespace :api do
get "image/:id", to: "images#show" # a képtár a tiéd (lásd lentebb)
end
# a mount maradjon az utolsó, hogy a hoszt saját útvonalai nyerjenek
mount WarpEngine::Engine => "/"
A generátor kiírja a config/initializers/warp_engine.rb fájlt. Az 1.8 óta ez egy paraméter nélküli blokk, beállításonként egy sorral:
Rails.application.config.to_prepare do
WarpEngine.configure do
file_container_path ENV.fetch("FILE_CONTAINER_PATH", "/softwares")
# The image library is the host's; "Image" is the adapter's default.
# image_class "Media::Picture"
# image_adapter MyImageLibrary.new
update_secret ENV["UPDATE_SECRET"]
# application_tokens from: :database, owner: "AdminUser"
# One adapter carries the whole CI side: server, recipes, signing key.
ci :woodpecker do
url ENV["WOODPECKER_URL"]
api_token ENV["WOODPECKER_API_TOKEN"]
repo_owner ENV["WOODPECKER_REPO_OWNER"]
public_key_url "https://ci.example.org/api/signature/public-key"
update_server "https://catalog.example.org"
tools "registry.example/ci-tools:1.0" # every platform's, unless it names its own (1.1)
platform :godot, builder: "registry.example/godot-builder:4.6"
platform :tic80, builder: "registry.example/tic80-builder:1.0"
platform :bevy, builder: "registry.example/bevy-builder:1.0"
platform :love, builder: "registry.example/love-builder:1.0"
platform :ebitengine, builder: "registry.example/ebitengine-builder:1.0"
platform :phaser, builder: "registry.example/phaser-builder:1.0"
platform :c64, builder: "registry.example/c64-builder:1.0", exporter: "registry.example/commodore-player:1.0"
platform :plus4, builder: "registry.example/plus4-builder:1.0", exporter: "registry.example/commodore-player:1.0"
end
# max_upload_size 500 * 1024 * 1024
# enforce_software_ownership true
end
end
A blokk a shelf …, az admin_api do … end és az additional_resource … do … end sort is ismeri (engedélyezett attribútumok, az adminűrlap, és egy string/integer/… sorokból épülő, camelCase api_schema). Ismeretlen beállítás vagy kulcs megállítja az indulást. A beállítások neve az alábbi táblázaté, kivéve az image_class (image_class_name), az application_tokens from:, owner: (a két application_token_* kulcs) és a ci (ci_adapter) sort. Az 1.8 előtti WarpEngine.configure do |c| c.site_url = … end forma is működik; mindkettő ugyanazt a konfigurációt írja.
| Kulcs | Alapérték | Leírás |
|---|---|---|
file_container_path |
ENV["FILE_CONTAINER_PATH"] vagy /softwares |
Hol tárolódnak a buildartifactok |
update_secret |
ENV["UPDATE_SECRET"] |
Közös titok a /build/* végpontokhoz |
application_token_source |
:env |
:env vagy :database, kizárólagosan |
application_token_owner_class |
nil |
Tulajdonosmodell a :database módhoz |
max_upload_size |
500 MB | Korlát a /build/upload végponthoz |
enforce_software_ownership |
false |
Adatbázistoken-tulajdonos szerinti elszigetelés |
ci_adapter |
:woodpecker |
Melyik CI-szerver építi a játékokat; a :none kikapcsolja a CI-t, vagy egy hosztobjektum |
image_class_name |
"Image" |
A képtár mögötti hosztmodell |
image_adapter |
nil |
Lecseréli az alapértelmezett hosztmodell-adaptert |
access_policy |
:open |
Hozzáférési szabályzat objektum |
access_token_owner_class |
nil |
Felhasználómodell az eszközbelépéshez; nil = nincs belépés |
admin_api.* |
enabled = false |
Az Admin API és az MCP-szervere (1.0) |
Egy platform-spec három image-et kaphat. A builder futtatja a build lépéseket. Az exporter egy második image, amelyben egy sablon lépést futtathat — a c64 és a plus4 pipeline itt csomagolja a .prg-t a böngészős és a natív lejátszókba. A tools (1.1, opcionális) a segédlépéseké: version, lint, minify, docs, upload, publish. Nélküle ezek alpine-ban futnak, és minden futáskor apk add-dal felrakják a git, jq, curl, zip és lua5.4 csomagot, a tic80-nál luarocks install-lal a luacheck-et és az ldoc-ot is; vele semmit nem telepítenek, tehát az image-ben ezeknek már benne kell lenniük, a Lua 5.4-gyel lua néven. A DSL-ben a ci blokk tools sora minden platform alapértéke. Az upload és a publish lépés megkapja az application_token secretet, ezért a tools image-re digest szerint hivatkozz. A teletypegames.org így adja minden platformnak a build/ci-tools image-ét.
Az ActiveAdmin-példány a hoszté (hitelesítés, téma, útvonalak); a WarpEngine hozzáfűzi az erőforrásait az ActiveAdmin.application.load_paths listához. Egy új hosztnak két dolog kell:
/admin/files?picker=1&field=<dom_id>) az active_admin.js fájljában;"#{WarpEngine::Engine.root}/app/controllers/**/*.rb" bejegyzés az api_controllers_matcher beállításban.Az 1.0 óta ugyanezek az erőforrások JSON API-ként is elérhetők — lásd WarpEngine Admin API. Az adminoldalak és az API ugyanazokat a service-eket hívják (ApplicationTokenService, DownloadStatsService, FileManagerService), így a kettő nem tud elcsúszni egymástól.
deleted_at oszlop, és kept / discarded scope. A 0.10 óta nincs default_scope, egy lekérdezés tehát magától nem szűr — a hoszt WarpEngine::Software.kept-et kér, és aki 0.9-ről vagy régebbiről frissít, .kept-et tesz oda, ahol a default scope-ra épített.ActiveSupport.on_load(:warp_engine_<model>).bundle install
bundle exec rake app:db:prepare RAILS_ENV=test
bundle exec rspec