Add a runnable example compose stack for WarpEngine

examples/compose boots everything the engine's workflow assumes: mysql, a
minimal Rails host consuming the engine as a path gem, an SSH drop area
sharing the softwares volume with the app, and — behind the ci profile —
gitea plus woodpecker (agent attached to the stack network so pipeline
steps reach droparea/app by service name).

host_app doubles as a reference for a brand-new host: Gemfile, the two
initializers, apipie + engine mounts in routes.rb; on first boot the
entrypoint runs the install generator and db:prepare.

The README gains a detailed bring-up walkthrough: quickstart, publishing
a release by hand over scp + /update (verified end to end from a clean
slate), and the full gitea/woodpecker OAuth wiring.
This commit is contained in:
2026-08-05 06:56:12 +02:00
parent d569c3366a
commit 60e196a03e
18 changed files with 394 additions and 0 deletions
+103
View File
@@ -31,6 +31,109 @@ Repository: `https://git.teletypegames.org/tools/warp_engine`
- A relational database (developed and tested against MySQL 8)
- Optional: ActiveAdmin + Devise in the host app for the admin UI
## Example stack (docker compose)
`examples/compose` boots everything the engine's workflow assumes, end to
end: the catalog app itself, the SSH drop area the updater contract feeds
from and — behind a compose profile — a Gitea forge with Woodpecker CI, so
you can watch a pipeline publish a release into the catalog.
| Service | Role | Where |
| --- | --- | --- |
| `app` | Minimal Rails host with the engine mounted as a path gem (headless: API + updater) | `http://localhost:8080` |
| `mysql` | Catalog database | internal |
| `droparea` | SSH server where pipelines drop build artifacts; shares the `softwares` volume with `app` | `ssh drop@localhost -p 2222` |
| `gitea` | Git forge (profile `ci`) | `http://gitea:3000` |
| `woodpecker` + agent | CI wired to gitea (profile `ci`) | `http://woodpecker:8000` |
### Quickstart — catalog + drop area
```sh
cd examples/compose
cp .env.example .env # defaults work for a throwaway local demo
docker compose up --build
```
The first boot takes a few minutes: the app container bundles, runs
`rails g warp_engine:install` and `rails db:prepare`, then serves on
`http://localhost:8080`:
- `http://localhost:8080/api/software` — the (empty) catalog
- `http://localhost:8080/api/builds` — the platform build matrix
- `http://localhost:8080/api/docs` — apipie API docs
### Publish a release by hand
The updater contract needs nothing but files in the drop area and one HTTP
call, so you can play the role of the CI pipeline yourself:
```sh
# 1. Fake a build: metadata, a web build and a windows artifact, named by
# convention (the love platform requires the .html.zip web build)
cat > demo-0.1.0.metadata.json <<'JSON'
{ "name": "demo", "title": "Demo Game", "author": "You", "desc": "Hello", "license": "MIT" }
JSON
echo '<h1>demo</h1>' > index.html && zip demo-0.1.0.html.zip index.html
echo hello > game.bin && zip demo-0.1.0-win-x64.zip game.bin
# 2. Drop them (password: DROP_PASSWORD from .env, default "drop")
scp -P 2222 demo-0.1.0.* drop@localhost:drop/
# 3. Trigger the updater
curl -H "X-Update-Secret: example-update-secret" \
"http://localhost:8080/update?platform=love&name=demo&version=0.1.0"
```
`GET /api/software` now lists *Demo Game* with `html` and `win_x64` assets,
`http://localhost:8080/file/demo-0.1.0/index.html` serves the extracted web
build, and `GET /api/download?path=demo-0.1.0-win-x64.zip` serves the
artifact while logging a download record.
### Full loop — forge + CI (profile `ci`)
gitea and woodpecker address each other by service name, so let your browser
resolve those names too:
```sh
echo "127.0.0.1 gitea woodpecker" | sudo tee -a /etc/hosts
```
1. `docker compose --profile ci up -d gitea`, open `http://gitea:3000`,
finish the install wizard (SQLite is fine) and create your admin user.
2. In gitea: *Settings → Applications → Manage OAuth2 Applications*, create
an app with redirect URI `http://woodpecker:8000/authorize`; copy the
client id/secret into `WOODPECKER_GITEA_CLIENT` / `WOODPECKER_GITEA_SECRET`
in `.env`.
3. `docker compose --profile ci up -d` — then log in at
`http://woodpecker:8000` (OAuth via gitea) and enable your repository.
A pipeline publishes a release exactly like the by-hand steps above — build,
`scp` to `droparea`, call `/update`:
```yaml
# .woodpecker.yaml in a game repo hosted on the example gitea
steps:
publish:
image: alpine
environment:
DROP_PASSWORD:
from_secret: drop_password
UPDATE_SECRET:
from_secret: update_secret
commands:
- apk add --no-cache openssh-client sshpass curl zip
- # ... build your game, produce mygame-1.0.0.metadata.json + artifacts ...
- sshpass -p "$DROP_PASSWORD" scp -P 2222 -o StrictHostKeyChecking=no mygame-1.0.0.* drop@droparea:drop/
- curl -fs -H "X-Update-Secret: $UPDATE_SECRET" "http://app:3000/update?platform=love&name=mygame&version=1.0.0"
```
(The agent attaches pipeline containers to the stack network, so `droparea`
and `app` resolve. For real projects, the per-platform
[`tools/*-tools`](https://git.teletypegames.org) repos ship ready-made
Makefile + pipeline templates implementing this contract.)
Tear the stack down with `docker compose --profile ci down -v`.
## Installation
From the git repository: