feat(renderer): deploy the renderer next to the bot in compose

The bot now reaches the renderer at http://renderer:3000/api/gif on the
compose network instead of a separately deployed service. Both share
WHEELOFNAMES_API_TOKEN. CI runs the renderer's lint, typecheck, tests,
render smoke, and image build.
This commit is contained in:
tiennm99 committed 2026-10-03 11:16:54 +07:00
1 parent de46809c96
commit 2bb5108151
12 files changed
+84 -63

No files matched your search

+1
View File
@@ -6,3 +6,4 @@ docs
LICENSE
Dockerfile
.dockerignore
renderer
+37
View File
@@ -63,3 +63,40 @@ jobs:
- name: docker build
run: docker build -t miti99bot .
renderer:
runs-on: ubuntu-latest
defaults:
run:
working-directory: renderer
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: renderer/package-lock.json
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm test
- name: Install Remotion browser runtime libraries
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
libnspr4 \
libnss3 \
libgtk-3-0 \
libgbm1 \
libasound2t64 \
libxshmfence1 \
fonts-noto
- run: npm run browser:ensure
- run: npm run render:smoke
- run: npm run api:smoke
- name: docker build
run: docker build -t miti99bot-renderer .
+31 -2
View File
@@ -14,8 +14,12 @@ services:
MODULES: ${MODULES} # CSV; empty = all modules
OWNER_ID: ${OWNER_ID} # Telegram user id for owner-only commands
ADMIN_IDS: ${ADMIN_IDS} # CSV of admin Telegram user ids
WHEELOFNAMES_API_URL: ${WHEELOFNAMES_API_URL:-} # Optional full /api/gif endpoint (/gacha uses /api/gacha)
WHEELOFNAMES_API_TOKEN: ${WHEELOFNAMES_API_TOKEN:-} # Optional bearer token for that service
# The bundled renderer service below draws /wheelofnames, /gacha and
# /genshin. The URL is fixed to its in-network address so a stale
# platform-level value cannot point the bot elsewhere; /gacha and
# /genshin derive their endpoints from it.
WHEELOFNAMES_API_URL: http://renderer:3000/api/gif
WHEELOFNAMES_API_TOKEN: ${WHEELOFNAMES_API_TOKEN:-} # Shared bearer token; the renderer uses it as API_TOKEN
# SOURCE_COMMIT is intentionally not declared here. Coolify provides it
# at runtime via its generated env file; declaring it here with Compose
# interpolation can override the runtime value with an empty string.
@@ -37,3 +41,28 @@ services:
# defined here. Configure that monitor against GET / instead
# (returns text/plain "miti99bot ok"). Note: a plain / check does not verify
# Mongo connectivity — see docs/deploy-coolify-selfhosted.md.
# Animation renderer (Node + Remotion + headless Chrome) from renderer/.
# Internal only: the bot reaches it over the compose network, so it has no
# published port and no public domain. Without WHEELOFNAMES_API_TOKEN it
# refuses to start in production, and the bot falls back to text replies.
renderer:
build:
context: ./renderer
restart: unless-stopped
environment:
NODE_ENV: production
HOST: 0.0.0.0
PORT: "3000"
API_TOKEN: ${WHEELOFNAMES_API_TOKEN:-}
MAX_CONCURRENT_RENDERS: ${MAX_CONCURRENT_RENDERS:-1}
RENDER_TIMEOUT_MS: ${RENDER_TIMEOUT_MS:-15000}
MAX_OPTIONS: ${MAX_OPTIONS:-32}
MAX_OPTION_CHARS: ${MAX_OPTION_CHARS:-40}
expose:
- "3000"
healthcheck:
test: ["CMD-SHELL", "node -e \"fetch('http://127.0.0.1:3000/api/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""]
interval: 30s
timeout: 5s
retries: 3
-34
View File
@@ -1,34 +0,0 @@
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm test
- name: Install Remotion browser runtime libraries
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
libnspr4 \
libnss3 \
libgtk-3-0 \
libgbm1 \
libasound2t64 \
libxshmfence1 \
fonts-noto
- run: npm run browser:ensure
- run: npm run render:smoke
- run: npm run api:smoke
+3 -1
View File
@@ -1,5 +1,7 @@
# wheelofnames
# renderer
Part of miti99bot: the service behind `/wheelofnames`, `/gacha`, and
`/genshin`, deployed by the root `compose.yml` as the `renderer` service.
Self-hosted API that renders wheel-of-names GIF animations and Genshin-style
meteor wish MP4 animations with Remotion, and card-pack gacha wish MP4
animations with pack-cards.
-21
View File
@@ -1,21 +0,0 @@
services:
wheelofnames:
build: .
environment:
NODE_ENV: "${NODE_ENV:-production}"
HOST: "${HOST:-0.0.0.0}"
PORT: "${PORT:-3000}"
API_TOKEN: "${API_TOKEN:-change-me}"
MAX_CONCURRENT_RENDERS: "${MAX_CONCURRENT_RENDERS:-1}"
RENDER_TIMEOUT_MS: "${RENDER_TIMEOUT_MS:-15000}"
MAX_OPTIONS: "${MAX_OPTIONS:-32}"
MAX_OPTION_CHARS: "${MAX_OPTION_CHARS:-40}"
# Coolify routes to the container port over its proxy network, so the host
# port stays unpublished there. Uncomment for a standalone `docker compose up`.
# ports:
# - "${PORT:-3000}:${PORT:-3000}"
healthcheck:
test: ["CMD-SHELL", "node -e \"fetch('http://127.0.0.1:${PORT:-3000}/api/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""]
interval: 30s
timeout: 5s
retries: 3
+9 -2
View File
@@ -1,5 +1,12 @@
# Deployment
## miti99bot compose
The root `compose.yml` builds this folder as the `renderer` service and points
the bot at it over the compose network. Only `WHEELOFNAMES_API_TOKEN` needs a
value there; it becomes `API_TOKEN` below. The rest of this page covers running
the service on its own.
## Recommendation
Use a self-hosted/container runtime for v1. Static-only hosts are not enough
@@ -33,8 +40,8 @@ MAX_OPTION_CHARS=40
API_TOKEN=change-me
```
`compose.yml` forwards these values from the shell with `${VAR:-default}`
fallbacks, so unset or empty shell variables use the defaults above.
The root `compose.yml` forwards the tuning values with `${VAR:-default}`
fallbacks, so unset or empty variables use the defaults above.
Start with 1-2 vCPU and 1-2 GB RAM. Increase only after render benchmarks show
the service is CPU-bound or concurrency-limited.
+2 -2
View File
@@ -1,11 +1,11 @@
{
"name": "wheelofnames",
"name": "miti99bot-renderer",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wheelofnames",
"name": "miti99bot-renderer",
"version": "0.1.0",
"dependencies": {
"@remotion/bundler": "4.0.485",
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "wheelofnames",
"name": "miti99bot-renderer",
"version": "0.1.0",
"private": true,
"type": "module",