12 KiB
Building & Testing
For internal architecture/workflow guidance, use docs/README.md at the repo root. This page stays focused on contributor-facing build and test commands.
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 stats && bun install --frozen-lockfile)
(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
./submineris a stale artifact path and is rejected by verification checks. - Install targets (
make install-linux,make install-macos) copy fromdist/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 testandbun run test:fastcover config/core suites plus representative entry/runtime, Anki integration, release-workflow coverage, typecheck, and runtime-registry checks.bun run test:fullis the maintained full surface: Bun-compatiblesrc/**discovery, Bun-compatible launcher unit discovery, and the compiled/runtime compatibility lane for suites routed throughdist/**.bun run test:runtime:compatcovers the compiled/runtime slice directly:ipc,anki-jimaku-ipc,overlay-manager,config-validation,startup-config, andregistry.bun run test:envcovers environment-sensitive checks: launcher smoke/plugin verification plus the Bun source SQLite lane.bun run test:immersion:sqliteis 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 prettyruns the maintained Prettier allowlist only (format:src).bun run format:check:srcchecks the same scoped set without writing changes.bun run formatremains 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-configmake 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 + stats + 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.tsas 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 summarized in Architecture, with canonical internal guidance in
docs/architecture/README.mdat the repo root. - Linux packaged desktop launches pass
--backgroundusing electron-builderbuild.linux.executableArgsinpackage.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 |