Skip to content

Contributing

Keep changes small, testable, and inside existing trust boundaries. Read repository rules before changing download, verification, signing, caching, or release behavior.

Development setup

Requirements:

  • Python 3.11–3.13
  • Java 21+
  • current uv
  • Git
bash
git clone https://github.com/Villoh/morphe-builder
cd morphe-builder
uv sync --locked
uv run morphe-builder --help

Project layout:

PathPurpose
src/morphe_builder/CLI, configuration, download, verification, build, and release code.
tests/Standard-library unittest suite and static fixtures.
docs/User, security, architecture, and release documentation.
.github/workflows/CI, security, build, release, and PyPI automation.
morphe.tomlCommitted example and release build matrix.

docs/plan/ contains ignored local plans and handoffs. Never commit it.

Make a change

  1. Read the complete flow touched by the change and every caller of shared code.
  2. Reuse existing helpers and standard library before adding code or dependencies.
  3. Keep goopdl behind its subprocess CLI boundary.
  4. Add one focused regression test for non-trivial logic.
  5. Update documentation when behavior, configuration, output, security, or workflow changes.
  6. Run required checks.

Avoid speculative interfaces, provider abstractions without a second implementation, compatibility layers without an active caller, and broad refactors mixed with behavior changes.

Tests

Required before commit or pull request:

bash
uv run python -m unittest discover -s tests
uv lock --check

CI also compiles source and tests:

bash
uv run python -m compileall -q src tests

Tests use Python standard-library unittest. Add the smallest check that fails without the logic change. Live Google Play tests must remain opt-in and require MORPHE_LIVE_TEST_PACKAGE; normal CI must not need credentials or network access to Google Play.

Dependencies

Prefer Python standard library. New runtime dependencies need a concrete requirement not covered by existing code or installed packages.

goopdl is security-sensitive and must remain exactly pinned in both pyproject.toml and uv.lock. Morphe Builder invokes its public CLI through subprocess, never private Python internals.

After dependency changes:

bash
uv lock
uv lock --check

Review generated lock changes before commit.

Security invariants

Never weaken these to make a test or provider pass:

  • downloaded artifacts remain untrusted until manifest, hash, package, version, architecture, split, and signer checks pass
  • original verified split APKs remain unchanged
  • integrity and signer failures remain terminal
  • outputs publish atomically and never overwrite existing trusted artifacts
  • passwords and tokens never enter argv, logs, provenance, committed files, or shared caches
  • archive path, size, entry-count, and compression limits remain enforced
  • private keystores remain outside repository

Do not commit auth tokens, cookies, token caches, downloaded APKs, authenticated URLs, private keystores, or secret-bearing fixtures.

See security for threat model and explicit non-goals.

Documentation

Topic documentation belongs in docs/. Keep README.md as project overview and quick entry point rather than duplicating complete reference material.

Install and preview VitePress locally:

bash
npm ci
npm run docs:dev

Build same static site produced by CI:

bash
npm run docs:build
npm run docs:preview

When adding or renaming a page:

  1. Update documentation index.
  2. Update root README.md when page belongs in public documentation table.
  3. Update docs/.vitepress/config.mts when navigation changes.
  4. Keep relative links valid on GitHub and VitePress.
  5. Run npm run docs:build.

Documentation should describe current behavior. Deferred work belongs in roadmap, not reference pages.

Commits

Use Conventional Commits 1.0.0:

text
<type>[optional scope]: <description>

Examples:

text
feat(download): support separate ARMv7 output
fix(verify): reject truncated split APK
docs: add architecture overview

Common types: feat, fix, docs, test, refactor, build, ci, chore, perf, and revert.

Breaking changes use ! or a BREAKING CHANGE: footer. Keep unrelated changes in separate commits.

Pull requests

A pull request should state:

  • problem and chosen minimal fix
  • security or compatibility impact
  • tests run
  • documentation changed
  • live validation performed, when relevant

Do not claim device compatibility from static verification alone. Record device, Android version, architecture, install result, and launch result for runtime validation.

Released under the MIT License.