Files
Obtainium-Emulation-Pack/CONTRIBUTING.md
Richard Macias 317effd7f7 readme refresh
2026-03-19 22:35:20 -05:00

11 KiB

Contributing

Prerequisites

  • Python 3.11+
  • just (task runner)
  • Git

Quick Start

# Clone the repository
git clone https://github.com/RJNY/Obtainium-Emulation-Pack.git
cd Obtainium-Emulation-Pack

just add-app                    # interactive CLI to add a new app
just test --verbose --apks      # verify configs resolve to real APKs (with full details)
just build                      # test, validate, normalize, and generate all output files

Project Structure

justfile                         # Primary task runner (run `just` to see commands)
utility.just                     # Private helper recipes (imported by justfile)
src/
  applications.json              # Source of truth - all app definitions
scripts/
  constants.py                   # Shared constants and Obtainium source schema
  utils.py                       # Shared utility functions and .env loader
  help_formatter.py              # Styled argparse help formatter (ANSI colors)
  validate-json.py               # Validates applications.json
  test-apps.py                   # Live-tests configs resolve to downloadable APKs
  add-app.py                     # Interactive CLI to add a new app
  generate-table.py              # Generates the README table
  generate-readme.py             # Stitches markdown files into README
  minify-json.py                 # Creates release JSON files
  normalize-json.py              # Normalize key order and backfill defaults
  process-test-results.py        # Processes scheduled test results, manages GitHub issues
  release.py                     # Automated release workflow (tag, push, gh release)
pages/
  header.md                      # README header/intro
  table.md                       # Generated - app tables (do not edit)
  faq.md                         # FAQ section
  footer.md                      # Short section linking here (stitched into README)
obtainium-emulation-pack-latest.json           # Standard release
obtainium-emulation-pack-dual-screen-latest.json # Dual-screen release

Adding a New Application

Use the interactive CLI to quickly add a new app:

just add-app

This will:

  • Prompt you for the GitHub URL
  • Auto-detect the source, author, and app name
  • Ask for the Android package ID and category
  • Generate proper Obtainium settings
  • Add the app to applications.json

Tip: To find the package ID, open the app in Obtainium - the package ID is displayed directly below the source URL (e.g., com.example.android).

After running, execute just build to regenerate all files.

Option B: Manual Add (For complex configs or non-GitHub sources)

Step 1: Export the app config from Obtainium

  1. Open Obtainium on your device
  2. Add the app you want to include (configure it how you want)
  3. Long-press the app and select "Export"
  4. Choose "Obtainium Export" format
  5. Transfer the JSON to your computer

Step 2: Add the app to applications.json

Open src/applications.json and add your app to the apps array:

{
  "id": "com.example.emulator",
  "url": "https://github.com/example/emulator",
  "author": "example",
  "name": "Example Emulator",
  "preferredApkIndex": 0,
  "additionalSettings": {
    "apkFilterRegEx": "arm64",
    "about": "Example emulator description"
  },
  "categories": ["Emulator"],
  "overrideSource": "GitHub"
}

Note: additionalSettings is a sparse JSON object - only include values that differ from the defaults. The full settings are hydrated automatically at export time. See scripts/constants.py for the schema and default values.

Step 3: Add meta fields (optional)

Add a meta object to customize how the app appears:

{
  "id": "com.example.emulator",
  "url": "https://github.com/example/emulator",
  "author": "example",
  "name": "Example Emulator",
  "preferredApkIndex": 0,
  "additionalSettings": {
    "apkFilterRegEx": "arm64",
    "about": "Example emulator description"
  },
  "categories": ["Emulator"],
  "overrideSource": "GitHub",
  "meta": {
    "nameOverride": "Example Emu",
    "urlOverride": "https://example-emu.org"
  }
}

Step 4: Validate, test, and regenerate

just test AppName --verbose --apks  # verify your app config resolves to a real APK
just validate                       # check for structural errors
just build                          # test, validate, normalize, and generate all output files

CI

Pull request / push checks

Pull requests and pushes to main are checked by GitHub Actions (ci.yml, single job):

  1. Validate - structural checks, regex syntax, source types
  2. Test - verifies all app configs resolve to real APKs
  3. Generate - normalizes, generates README, builds release JSONs
  4. Diff check - fails if generated files are out of date

All steps must pass before merging.

Scheduled tests

A separate workflow (scheduled-test.yml) runs daily at ~6 AM Central. It live-tests every app config and automatically creates GitHub issues for any failures. When a previously failing app starts passing again, the issue is auto-closed. You can dry-run this locally with just test-cron.

Pre-Commit Checklist

Before committing, run just build, then verify:

  • just test passes (all app configs resolve to downloadable APKs)
  • obtainium-emulation-pack-latest.json has been updated
  • obtainium-emulation-pack-dual-screen-latest.json has been updated
  • README.md has been updated
  • The README table shows a friendly application name (use nameOverride if not)
  • The README table links to the correct homepage (use urlOverride if not)
  • Beta apps are excluded with meta.excludeFromExport: true

Available Commands

Run just to see all available commands. Recipes with *args accept -h for help.

Command Description
just add-app Interactive CLI to add a new app
just validate Validate applications.json (structure, regex, source types)
just normalize Normalize key order and backfill defaults
just test Live-test all app configs resolve to downloadable APKs
just test AppName Live-test a single app by name (partial match)
just test --verbose --apks Live-test all apps with full APK URL details
just test-cron Dry-run the scheduled test workflow (no issues created)
just generate Generate all output files (README, release JSONs)
just generate table Generate the README table only
just generate readme Generate README (includes table)
just generate standard Generate standard release JSON only
just generate dual-screen Generate dual-screen release JSON only
just build Test, validate, normalize, and generate all output files
just release Tag, push, and create a GitHub release

Meta Field Reference

These fields in the meta object control how apps are processed:

Field Type Default Description
excludeFromExport bool false Exclude from both release JSON files. Use for beta/unstable apps.
excludeFromTable bool false Exclude from the README table.
includeInStandard bool true Include in standard release. Set false for dual-screen-only apps.
includeInDualScreen bool true Include in dual-screen release. Set false for standard-only apps.
nameOverride string null Override the display name in the README table.
urlOverride string null Override the homepage link in the README table.

Categories

Apps are organized into categories that appear as sections in the README table:

Category Description
Emulator Console/handheld emulators (Dolphin, RetroArch, PPSSPP, etc.)
Frontend Emulator launchers and game library managers (Daijisho, Pegasus)
Utilities Helper apps (Syncthing, OdinTools, LED controllers, etc.)
PC Emulation Windows/PC game layers (Winlator, etc.)
Streaming Game streaming clients (Moonlight, etc.)
Track Only Version tracking without APK downloads (drivers, meta-packages)

An app can belong to multiple categories.

Dual-Screen vs Standard

The pack supports two variants:

  • Standard (obtainium-emulation-pack-latest.json): For regular Android devices
  • Dual-Screen (obtainium-emulation-pack-dual-screen-latest.json): For dual-screen devices (AYN Thor, Anbernic RG DS, etc.)

Some apps have dual-screen-specific forks (e.g., Cemu, MelonDS). Use the includeInStandard and includeInDualScreen flags to control which variant(s) include each app.

Why this matters: Apps with the same Android package ID (id field) will conflict in Obtainium. If two apps share an ID (like standard Cemu and dual-screen Cemu), they must not both appear in the same JSON file.

Example: Standard Cemu excluded from dual-screen, dual-screen fork excluded from standard:

// Standard Cemu - exclude from dual-screen JSON
{
  "id": "info.cemu.cemu",
  "name": "Cemu",
  "url": "https://github.com/SSimco/Cemu",
  "categories": ["Emulator"],
  "meta": { "includeInDualScreen": false }
}

// Dual-screen Cemu fork - exclude from standard JSON
{
  "id": "info.cemu.cemu",
  "name": "Cemu",
  "url": "https://github.com/SapphireRhodonite/Cemu",
  "categories": ["Emulator"],
  "meta": { "includeInStandard": false }
}

Choosing the Right Category and Variant

Use this decision tree:

  1. Is this app device-specific? (e.g., AYN Thor frontend)

    • Yes: Set includeInStandard: false and use appropriate category
    • No: Continue to step 2
  2. Does this app share an ID with another app in the pack? (e.g., forks, beta builds, dual-screen variants)

    • Yes: Only one app per ID can be in each release JSON. Options:
      • Use includeInStandard/includeInDualScreen to split between variants
      • Use excludeFromExport: true on the less stable version (e.g., nightly builds)
    • No: App can be in both variants (default)
  3. Is this app stable and ready for users?

    • Yes: Include normally
    • No: Set excludeFromExport: true (still visible in table but not in release JSONs)