From 2bb51081519fe96c670c51a138a00e07ccccd478 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Sat, 3 Oct 2026 11:16:54 +0700 Subject: [PATCH] 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. --- .dockerignore | 1 + .github/workflows/ci.yml | 37 +++++++++++++++++++ compose.yml | 33 ++++++++++++++++- ...t-additive-blend-and-full-card-coverage.md | 0 ...61001-1656-open-source-gacha-candidates.md | 0 ...-261001-1703-code-built-gacha-animation.md | 0 renderer/.github/workflows/ci.yml | 34 ----------------- renderer/README.md | 4 +- renderer/compose.yml | 21 ----------- renderer/docs/deployment.md | 11 +++++- renderer/package-lock.json | 4 +- renderer/package.json | 2 +- 12 files changed, 84 insertions(+), 63 deletions(-) rename {renderer/plans => plans}/journals/2026-10-02-gacha-glint-additive-blend-and-full-card-coverage.md (100%) rename {renderer/plans => plans}/reports/researcher-261001-1656-open-source-gacha-candidates.md (100%) rename {renderer/plans => plans}/reports/researcher-261001-1703-code-built-gacha-animation.md (100%) delete mode 100644 renderer/.github/workflows/ci.yml delete mode 100644 renderer/compose.yml diff --git a/.dockerignore b/.dockerignore index f4daf06..99a97dc 100644 --- a/.dockerignore +++ b/.dockerignore @@ -6,3 +6,4 @@ docs LICENSE Dockerfile .dockerignore +renderer diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ba2432..48bf68b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 . diff --git a/compose.yml b/compose.yml index fadb23b..b430389 100644 --- a/compose.yml +++ b/compose.yml @@ -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 diff --git a/renderer/plans/journals/2026-10-02-gacha-glint-additive-blend-and-full-card-coverage.md b/plans/journals/2026-10-02-gacha-glint-additive-blend-and-full-card-coverage.md similarity index 100% rename from renderer/plans/journals/2026-10-02-gacha-glint-additive-blend-and-full-card-coverage.md rename to plans/journals/2026-10-02-gacha-glint-additive-blend-and-full-card-coverage.md diff --git a/renderer/plans/reports/researcher-261001-1656-open-source-gacha-candidates.md b/plans/reports/researcher-261001-1656-open-source-gacha-candidates.md similarity index 100% rename from renderer/plans/reports/researcher-261001-1656-open-source-gacha-candidates.md rename to plans/reports/researcher-261001-1656-open-source-gacha-candidates.md diff --git a/renderer/plans/reports/researcher-261001-1703-code-built-gacha-animation.md b/plans/reports/researcher-261001-1703-code-built-gacha-animation.md similarity index 100% rename from renderer/plans/reports/researcher-261001-1703-code-built-gacha-animation.md rename to plans/reports/researcher-261001-1703-code-built-gacha-animation.md diff --git a/renderer/.github/workflows/ci.yml b/renderer/.github/workflows/ci.yml deleted file mode 100644 index 29a5ea5..0000000 --- a/renderer/.github/workflows/ci.yml +++ /dev/null @@ -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 diff --git a/renderer/README.md b/renderer/README.md index a37dd5b..f5f9f3f 100644 --- a/renderer/README.md +++ b/renderer/README.md @@ -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. diff --git a/renderer/compose.yml b/renderer/compose.yml deleted file mode 100644 index 87db31f..0000000 --- a/renderer/compose.yml +++ /dev/null @@ -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 diff --git a/renderer/docs/deployment.md b/renderer/docs/deployment.md index ad1c464..07c9ac5 100644 --- a/renderer/docs/deployment.md +++ b/renderer/docs/deployment.md @@ -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. diff --git a/renderer/package-lock.json b/renderer/package-lock.json index a3295e1..969553f 100644 --- a/renderer/package-lock.json +++ b/renderer/package-lock.json @@ -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", diff --git a/renderer/package.json b/renderer/package.json index b92d336..b43c8ce 100644 --- a/renderer/package.json +++ b/renderer/package.json @@ -1,5 +1,5 @@ { - "name": "wheelofnames", + "name": "miti99bot-renderer", "version": "0.1.0", "private": true, "type": "module",