Files
SubMiner/docs-site/development.md
sudacode 9c7e02cbf0 Enforce config example drift checks in CI and release
- add `verify:config-example` script with tests to fail on missing/stale generated config artifacts
- run the verification in CI and release workflows, and document it in release/docs guidance
- fix docs-site Cloudflare Pages watch path to `docs-site/*` with regression coverage
2026-03-10 20:06:41 -07:00

12 KiB

Building & Testing

Prerequisites

Setup

git clone --recurse-submodules https://github.com/ksyasuda/SubMiner.git
cd SubMiner
# if you cloned without --recurse-submodules:
git submodule update --init --recursive

bun install
(cd vendor/texthooker-ui && bun install --frozen-lockfile)

make deps is still available as a convenience wrapper around the same dependency install flow.

Building

# Main app build
bun run build

# Platform packages
bun run build:appimage      # Linux AppImage
bun run build:mac           # macOS DMG + ZIP (signed)
bun run build:mac:unsigned  # macOS DMG + ZIP (unsigned)
bun run build:win           # Windows NSIS installer + ZIP

# Optional launcher artifact only
make build-launcher
# output: dist/launcher/subminer

bun run build includes the Yomitan build step. It builds the bundled Chrome extension directly from the vendor/subminer-yomitan submodule into build/yomitan using Bun.

Launcher Artifact Workflow

  • Source of truth: launcher/*.ts
  • Generated output: dist/launcher/subminer
  • Do not hand-edit generated launcher output.
  • Repo-root ./subminer is a stale artifact path and is rejected by verification checks.
  • Install targets (make install-linux, make install-macos) copy from dist/launcher/subminer.

Verify the workflow:

make build-launcher
dist/launcher/subminer --help >/dev/null
bash scripts/verify-generated-launcher.sh

Running Locally

bun run dev    # builds + launches with --start --dev
electron . --start --dev --log-level debug   # equivalent Electron launch with verbose logging
electron . --background                       # tray/background mode, minimal default logging
make dev-start                                # build + launch via Makefile
make dev-watch                                # watch TS + renderer and launch Electron (faster edit loop)
make dev-watch-macos                          # same as dev-watch, forcing --backend macos

For mpv-plugin-driven testing without exporting SUBMINER_BINARY_PATH each run, set a one-time dev binary path in ~/.config/mpv/script-opts/subminer.conf:

binary_path=/absolute/path/to/SubMiner/scripts/subminer-dev.sh

Testing

Default lanes:

bun run test           # alias for test:fast
bun run test:fast      # default fast lane
bun run test:full      # maintained source + launcher-unit + runtime compat surface
bun run test:runtime:compat # compiled/runtime compatibility slice only
bun run test:env       # launcher/plugin + env-sensitive verification
bun run test:immersion:sqlite # SQLite persistence lane
bun run test:subtitle  # maintained alass/ffsubsync subtitle surface
  • bun run test and bun run test:fast cover config/core suites plus representative entry/runtime, Anki integration, release-workflow coverage, typecheck, and runtime-registry checks.
  • bun run test:full is the maintained full surface: Bun-compatible src/** discovery, Bun-compatible launcher unit discovery, and the compiled/runtime compatibility lane for suites routed through dist/**.
  • bun run test:runtime:compat covers the compiled/runtime slice directly: ipc, anki-jimaku-ipc, overlay-manager, config-validation, startup-config, and registry.
  • bun run test:env covers environment-sensitive checks: launcher smoke/plugin verification plus the Bun source SQLite lane.
  • bun run test:immersion:sqlite is the reproducible persistence lane when you need real DB-backed SQLite coverage under Bun.

The Bun-managed discovery lanes intentionally exclude a small compiled/runtime-focused set: src/core/services/ipc.test.ts, src/core/services/anki-jimaku-ipc.test.ts, src/core/services/overlay-manager.test.ts, src/main/config-validation.test.ts, src/main/runtime/startup-config.test.ts, and src/main/runtime/registry.test.ts. bun run test:runtime:compat keeps them in the standard workflow via dist/**.

Suggested local gate before handoff:

bun run typecheck
bun run test:fast
bun run test:env
bun run build
bun run test:smoke:dist

If you changed docs in docs-site/, also run:

bun run docs:test
bun run docs:build

Focused commands:

bun run test:config       # Source-level config schema/validation tests
bun run test:launcher     # Launcher regression tests (config discovery + command routing)
bun run test:core         # Source-level core regression tests (default lane)
bun run test:launcher:smoke:src # Launcher e2e smoke: launcher -> mpv IPC -> overlay start/stop wiring
bun run test:launcher:env:src # Launcher smoke + Lua plugin gate
bun run test:src          # Bun-managed maintained src/** discovery lane
bun run test:launcher:unit:src # Bun-managed maintained launcher unit lane
bun run test:immersion:sqlite:src # Bun source lane

Dist-level tests are now an explicit smoke lane used to validate compiled/runtime assumptions.

Launcher smoke artifacts are written to .tmp/launcher-smoke locally and uploaded by CI/release workflows when the smoke step fails.

Smoke and optional deep dist commands:

bun run build                 # compile dist artifacts
bun run test:immersion:sqlite # compile + run SQLite-backed immersion tests under Bun
bun run test:smoke:dist       # explicit smoke scope for compiled runtime
bun run test:config:dist      # optional full dist config suite
bun run test:core:dist        # optional full dist core suite

Use bun run test:immersion:sqlite when you need real DB-backed coverage for the immersion tracker.

Formatting

Use the scoped formatter for normal app-repo work:

make pretty
bun run format:check:src
  • make pretty runs the maintained Prettier allowlist only (format:src).
  • bun run format:check:src checks the same scoped set without writing changes.
  • bun run format remains the broad repo-wide Prettier command; use it intentionally.

Config Generation

# Generate default config to ~/.config/SubMiner/config.jsonc (or %APPDATA%\SubMiner\config.jsonc on Windows)
bun run electron . --generate-config

# Regenerate the repo's config.example.jsonc from centralized defaults
bun run generate:config-example

Convenience wrappers still exist:

  • make generate-config
  • make generate-example-config

Documentation Site

The docs site now lives in docs-site/ inside the main repo.

From the SubMiner app repo:

bun --cwd docs-site install
bun run docs:dev     # Dev server at http://localhost:5173
bun run docs:build   # Production build into docs-site/.vitepress/dist
bun run docs:preview # Preview built site at http://localhost:4173
bun run docs:test    # Docs regression tests

Cloudflare Pages deploy settings:

  • Git repo: ksyasuda/SubMiner
  • Root directory: docs-site
  • Build command: bun run docs:build
  • Build output directory: .vitepress/dist
  • Build watch paths: docs-site/*

Use Cloudflare's single * wildcard syntax for watch paths. docs-site/* covers nested docs-site changes in the repo; docs-site/** is not the correct Pages pattern and may skip docs-only pushes.

Makefile Reference

Run make help for a full list of targets. Key ones:

Target Description
make build Build platform package for detected OS
make build-launcher Generate Bun launcher wrapper at dist/launcher/subminer
make install Install platform artifacts (wrapper, theme, AppImage/app bundle)
make install-plugin Install mpv Lua plugin and config
make deps Install JS dependencies (root + texthooker-ui)
make pretty Run scoped Prettier formatting for maintained source/config files
make generate-config Generate default config from centralized registry
make build-linux Convenience wrapper for Linux packaging
make build-macos Convenience wrapper for signed macOS packaging
make build-macos-unsigned Convenience wrapper for unsigned macOS packaging

Contributor Notes

  • To add/change a config default, edit the matching domain file in src/config/definitions/defaults-*.ts.
  • To add/change config option metadata, edit the matching domain file in src/config/definitions/options-*.ts.
  • To add/change generated config template blocks/comments, update src/config/definitions/template-sections.ts.
  • Keep src/config/definitions.ts as the composed public API (DEFAULT_CONFIG, registries, template export) that wires domain modules together.
  • Overlay window/visibility state is owned by src/core/services/overlay-manager.ts.
  • Runtime architecture/module-boundary conventions are documented in Architecture; keep contributor changes aligned with that canonical guide.
  • Linux packaged desktop launches pass --background using electron-builder build.linux.executableArgs in package.json.
  • Prefer direct inline deps objects in src/main/ modules for simple pass-through wiring.
  • Add a helper/adapter service only when it performs meaningful adaptation, validation, or reuse (not identity mapping).

Environment Variables

Variable Description
SUBMINER_APPIMAGE_PATH Override SubMiner app binary path for launcher playback commands
SUBMINER_BINARY_PATH Alias for SUBMINER_APPIMAGE_PATH
SUBMINER_ROFI_THEME Override rofi theme path for launcher picker
SUBMINER_LOG_LEVEL Override app logger level (debug, info, warn, error)
SUBMINER_MPV_LOG Override mpv/app shared log file path
SUBMINER_WHISPER_BIN Override youtubeSubgen.whisperBin for launcher
SUBMINER_WHISPER_MODEL Override youtubeSubgen.whisperModel for launcher
SUBMINER_WHISPER_VAD_MODEL Override youtubeSubgen.whisperVadModel for launcher
SUBMINER_WHISPER_THREADS Override youtubeSubgen.whisperThreads for launcher
SUBMINER_YT_SUBGEN_OUT_DIR Override generated subtitle output directory
SUBMINER_YT_SUBGEN_AUDIO_FORMAT Override extraction format used for whisper fallback
SUBMINER_YT_SUBGEN_KEEP_TEMP Set to 1 to keep temporary subtitle-generation workspace
SUBMINER_JIMAKU_API_KEY Override Jimaku API key for launcher subtitle downloads
SUBMINER_JIMAKU_API_KEY_COMMAND Command used to resolve Jimaku API key at runtime
SUBMINER_JIMAKU_API_BASE_URL Override Jimaku API base URL
SUBMINER_JELLYFIN_ACCESS_TOKEN Override Jellyfin access token (used before stored encrypted session fallback)
SUBMINER_JELLYFIN_USER_ID Optional Jellyfin user ID override
SUBMINER_SKIP_MACOS_HELPER_BUILD Set to 1 to skip building the macOS helper binary during bun run build