EN /HU | Belépés

WarpEngine

A WarpEngine mountolható Rails engine, amely bármelyik Rails-appból retró szoftverkatalógust csinál. Egy játékrepó egyetlen soros .woodpecker.yaml jelö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) minden warp_engine-v* taggel újraépül belőle.

WarpEngine-hez kapcsolódó oldalak

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

Amit kapsz

  • Katalógus domain — Software, Release, ReleaseAsset, ExternalLink, PlatformLink, SoftwareImage, Download. Mind soft delete-tel, download tracking-gel.
  • CI-pipeline-szerver — Woodpecker configuration extension. A játékrepókban csak egy platform marker van. A builder image-ek szerver oldalon élnek, így egy image bump egyszerre ér el minden repót.
  • Pluggable CI — 0.7-től minden CI-funkció egyetlen adapteren megy át. A Woodpecker az engine-nel érkezik WarpEngine::CI::Woodpecker néven, és ez a default; a :none kikapcsolja a CI-t, más szerver pedig a hoszt által adott objektum.
  • Build endpoint-ok — POST /build/upload és POST /build/publish, shared secret-tel vagy adatbázisbeli application token-ekkel hitelesítve.
  • Publikus JSON API — katalógus, kiemelt cím, platformonkénti build mátrix, download tracking, statikus fájlszerver a webes buildekhez.
  • A hoszt képtára — 0.6-tól az 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.
  • Pluggable access — a hoszt ad egy policy-t, a katalógus pedig árakat, jogosultságokat és gated download-okat kap, és ezt az API-ban is közli, így egy kliens a fizetős címet fizetősként tudja mutatni ahelyett, hogy letöltéskor bukna el. Default: a nyílt katalógus.
  • Client sign-in — RFC 8628 device authorization grant a hoszt user modelljén, böngésző nélküli klienseknek. Konfig nélkül kikapcsolva.
  • Opcionális admin — ActiveAdmin resource-ok (katalógusszerkesztő, fájlkezelő, download statisztika, application token-ek). ActiveAdmin nélkül az engine headless módban fut.
  • CI-kezelés — API token-nel az admin vezérli a CI-szervert: repo sync, pipeline history kézi trigger-rel, CI secret-ként kiosztott application token-ek.
  • Asset-ellenőrzőlista — 0.8-tól a 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.
  • Polcok — 1.2-től egy platform legfrissebb buildjei egy lapos mappában, rögzített, verzió nélküli néven, egy 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.
  • Saját platformok — 1.5-től a hoszt felvehet egy platformot a saját szolgáltatásával, kindjaival és pipeline-sablonjával; a beépítettek már nem az egyetlenek. Lásd: Saját platformok.
  • Közös verzió- és kiadási lépés — 1.7-től az engine minden generált pipeline-hoz hozzáadja a 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.
  • Konfigurációs DSL — 1.8-tól az initializer hash-ek helyett nevesített beállítások blokkja (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.
  • Kiadás a pipeline saját tagjeiből — 1.9-től a push buildel, és a forrásban megjelenő új verzió a pipeline-tól kapja meg a 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.

Támogatott platformok

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.

Mely assetek hiányoznak

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á:

TXT
$ 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.

Végpontok

Nyilvános API

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.

SH
$ 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.

Build / CI

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.

Hozzáférés és identitás

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.

Ki mit láthat és tölthet le

RUBY
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:

JSON
"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.

Client sign-in

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.

RUBY
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
  1. a kliens POST-ol az /api/auth/device végpontra, és megmutatja a userCode értéket;
  2. az ember megnyitja az ellenőrzőoldalt, és beírja azt a kódot;
  3. a hoszt oldala meghívja a WarpEngine::DeviceGrantService#approve(user_code:, subject:) metódust — a jóváhagyáshoz session és HTML kell, ami nem az engine dolga;
  4. a kliens következő lekérdezése elviszi a tokent. Pontosan egyszer adjuk át.

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éptár

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:

RUBY
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.

A Woodpecker használata a WarpEngine-nel

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.

  1. A Woodpecker úgy van beállítva, hogy a WarpEngine a konfigurációs kiterjesztése.
  2. A repó .woodpecker.yaml fájljában csak a platform: van (és a name:, ha a szoftvernév eltér a repó nevétől).
  3. Egy push elküldi a jelölőt a POST /build/config végpontra.
  4. A CI-adapter rendereli a 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.
  5. A pipeline lefut. Az 1.9 óta push után: verzió → build → tag; a lépés által készített tagre: verzió → build → feltöltés → publikálás (→ kiadás, ahol a hoszt bekapcsolja). Lásd: Verziók és kiadások.

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.

Egy játékrepó beállítása

YAML
# .woodpecker.yaml
platform: godot
name: mygame     # opcionális, alapból a repó neve
JSON
// 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:

LUA
-- title: My TIC Game
-- name: mygame
-- author: You
-- desc: A TIC-80 game
-- category: puzzle
-- version: 1.0.0
function TIC() end

A jelölő beállításai

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).

Pipeline előnézete

SH
curl "https://your-host/build/config?platform=godot"

Lapozás és szótár (0.13)

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.

Titkok és verziók

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).

Lépések, amelyek minden pipeline-ban közösek

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.

Verziók és kiadások

Az 1.9 óta senki nem tagel és senki nem publikál kézzel: mindenről a forrásban lévő verzió dönt.

  1. A verzió a forrásban van — a metadata.json version mezője, TIC-80-on a -- version: sor. Az emelése maga a kiadás.
  2. Egy új verziójú push az alapágra buildel, és a 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.
  3. Egy már tagelt verziójú push csak buildel. Verzióemelés nélküli commit nem ad ki semmit.
  4. Kézzel készített tag a korábbiak szerint működik: egyeznie kell a forrás verziójával, különben a version lépés elbuktatja a pipeline-t, a tag lépés pedig a már létező taget nem bántja.
  5. A verzió csak nőhet. A /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.
  6. A dev buildek mindig követik az ágat. Az alapágon kívül a verzió 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.
  7. Kilépés: a jelölőben a 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.

Amit egy sablon a hoszttól kap

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.

Saját platformok

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:

RUBY
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.

Polcok

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

CI-kezelés (Woodpecker API)

Csak ott aktív, ahol az adapternek van url és api_token értéke (WarpEngine.ci.configured?). Addig az adminoldalak elrejtik magukat.

  • Repószinkron — Admin → Pipelines → Sync from Woodpecker (a gomb az adapter nevét viseli). Tükrözi a repólistát 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.
  • Pipeline-ok — minden bejegyzés felsorolja a legutóbbi futásait (státusz, ág, üzenet, idő) egy kézi Trigger gombbal. A legfrissebb futás frissíti a listaoldalon gyorsítótárazott státuszt. Egy szoftver adminoldala hivatkozik a pipeline-jaira.
  • Secret-kiosztás — egy token létrehozása kiosztja az 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.

Buildhitelesítés

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 :database módra váltás azonnal érvényteleníti a shared secret-et. Előbb hozd létre a token-eket.

Telepítés egy hosztba

RUBY
# 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
SH
rails g warp_engine:install   # initializer, képtár, migrációk
rails db:migrate
RUBY
# 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:

RUBY
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.

Adminintegráció

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:

  • a fájlválasztó JS a kiadási assetek útvonalmezőihez (iframe → /admin/files?picker=1&field=<dom_id>) az active_admin.js fájljában;
  • apipie-dokumentáció esetén a "#{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.

Viselkedési megjegyzések

  • Minden modell soft delete-tel dolgozik: 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.
  • A JSON shape stabil, és bug-compatible a korábbi Go backenddel: Go-féle nulla timestamp-ek, camelCase kulcsok, legacy flat path field-ek.
  • Model extension point-ok: ActiveSupport.on_load(:warp_engine_<model>).

Tesztelés

SH
bundle install
bundle exec rake app:db:prepare RAILS_ENV=test
bundle exec rspec