Point the service at registry.ginnoir.com/ginnoir/romhacks-orchestrator:latest (built by the workflow added in60121a5, verified pullable on valhalla) and drop the `build:` context that Portainer never honoured. This unfreezes stack 28, which has been stuck at847edffsince 2026-06-24: the containers kept running, so nothing alerted, but no commit had deployed in two months. README: document that Portainer builds nothing here, and that re-adding a `build:` would deadlock the stack again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
100 lines
4.7 KiB
YAML
100 lines
4.7 KiB
YAML
# romhacks stack — automated Pokémon rom-hack ingestion from a Discord server's
|
|
# per-generation threads into the RomM library.
|
|
#
|
|
# FLOW
|
|
# romhacks (orchestrator) jdownloader (jlesage) RomM (roms stack)
|
|
# ┌───────────────────────┐ ┌──────────────────┐ ┌──────────────┐
|
|
# │ DiscordChatExporter ──▶│ JSON │ FolderWatch picks│ files │ scans │
|
|
# │ parse links + art ───▶│ crawljob│ up .crawljob, │ ───────▶ │ /storage1/ │
|
|
# │ stage metadata ───▶│ ──────▶ │ resolves ~all │ │ Emulation │
|
|
# └───────────────────────┘ │ hosts, downloads │ └──────────────┘
|
|
# └──────────────────┘
|
|
#
|
|
# WHY THIS SHAPE
|
|
# - Member-only access => no official Discord bot is possible. DiscordChatExporter
|
|
# (DCE) does a READ-ONLY export with a USER token. Self-token use violates
|
|
# Discord ToS, so this is wired for an ALT account (see stack.env) to isolate
|
|
# ban risk from the main account.
|
|
# - The download links span many file hosts (Mega/Drive/MediaFire/Pixeldrain/...),
|
|
# so JDownloader2 (jlesage image) does the actual fetching — it auto-resolves
|
|
# hundreds of hosts and handles waits/captcha via its noVNC UI.
|
|
# - DCE `--media` downloads the inline thread images (box art / screenshots); the
|
|
# orchestrator stages those + the thread blurb as metadata for a later RomM
|
|
# custom-cover hand-off (dovetails with the deck-sgdb art pipeline).
|
|
#
|
|
# INERT BY DEFAULT. Does nothing until armed: DISCORD_TOKEN/GUILD_ID are empty and
|
|
# DRY_RUN=true, so even if deployed it idles and never enqueues a download. See
|
|
# README.md for the arming checklist.
|
|
#
|
|
# BAKED IMAGE (not bind) for the orchestrator: Portainer git-stack checkouts do NOT
|
|
# reliably materialize sibling repo files at relative FILE bind paths (Docker then
|
|
# auto-creates a directory — see the `share` stack note). So the orchestrator's
|
|
# scripts + channels.json are baked into an image built from ./orchestrator.
|
|
#
|
|
# That image is built by Gitea Actions and pushed to the self-hosted registry —
|
|
# NOT by a compose `build:` context. Portainer's git auto-update only ever runs
|
|
# `docker compose pull`, never `build`, so a `build:` + local-only `image:` name
|
|
# froze this stack: every poll died on "pull access denied for
|
|
# homelab/romhacks-orchestrator" and the stack never advanced past its last good
|
|
# commit. Same pattern as famapp. See .gitea/workflows/build-romhacks-orchestrator.yml.
|
|
# Editing channels.json or the scripts => push => the workflow rebuilds :latest,
|
|
# and watchtower/the next redeploy picks it up.
|
|
#
|
|
# Tiered binds: working state (exports/state/crawljobs + JD config) -> /config
|
|
# (SSD); bulk output + art -> /storage1/labdata/romhacks (ZFS, root-auto-created).
|
|
#
|
|
# Only jdownloader joins `edge` (Caddy proxies its noVNC UI, internal-only).
|
|
|
|
services:
|
|
romhacks:
|
|
image: registry.ginnoir.com/ginnoir/romhacks-orchestrator:latest
|
|
pull_policy: always
|
|
container_name: romhacks
|
|
restart: unless-stopped
|
|
networks: [romhacks]
|
|
env_file:
|
|
- stack.env
|
|
environment:
|
|
# Hand-off paths. /data is the single parent mount so incoming->library
|
|
# moves are instant renames (not cross-device copies); /emulation is the
|
|
# RomM Structure-A roms parent so console hacks land in roms/<platform>/.
|
|
- METADATA_DIR=/data/metadata
|
|
- INCOMING_DIR=/data/incoming
|
|
- LIBRARY_DIR=/data/library
|
|
- EMULATION_DIR=/emulation
|
|
- HANDOFF_STATE=/state/handled.json
|
|
volumes:
|
|
- /config/romhacks/exports:/exports
|
|
- /config/romhacks/state:/state
|
|
- /config/romhacks/crawljobs:/crawljobs
|
|
- /storage1/labdata/romhacks:/data
|
|
- /storage1/Emulation/roms:/emulation
|
|
|
|
jdownloader:
|
|
image: jlesage/jdownloader-2:latest
|
|
container_name: jdownloader
|
|
restart: unless-stopped
|
|
networks: [romhacks, edge]
|
|
env_file:
|
|
- stack.env
|
|
environment:
|
|
# root so it can write to the ZFS-tier /output bind (dirs auto-created as root)
|
|
- USER_ID=0
|
|
- GROUP_ID=0
|
|
volumes:
|
|
- /config/romhacks/jd:/config
|
|
# shared with the orchestrator: it drops .crawljob files here; the JD
|
|
# FolderWatch extension must be enabled + pointed at /watch (one-time, README).
|
|
- /config/romhacks/crawljobs:/watch
|
|
- /storage1/labdata/romhacks/incoming:/output
|
|
ports:
|
|
- "8998:5800"
|
|
|
|
networks:
|
|
romhacks:
|
|
name: romhacks
|
|
driver: bridge
|
|
edge:
|
|
name: edge
|
|
external: true
|