Skip to content

Build with GitHub Template

This is the recommended path for users who want verified patched APKs without installing Python, Java, uv, pipx, or Morphe Builder locally. GitHub Actions runs the complete build inside hosted runners.

You only need a GitHub account and a committed morphe.toml configuration.

Template or fork

OptionUse whenTrade-off
Use this templateYou want an independent builder repository.Clean history and ownership, but no automatic upstream relationship.
ForkYou want to compare and merge later Morphe Builder changes.Keeps upstream relationship and original history.

Both options include workflows, public template keystore, configuration, and code required by the build. Neither requires local installation.

1. Create repository

From Villoh/morphe-builder:

  • select Use this template → Create a new repository, or
  • select Fork

A public repository is simplest because release assets and workflow evidence remain visible. Never commit credentials, downloaded APKs, or private signing keys even when repository is private.

Open repository Actions tab. Select I understand my workflows, go ahead and enable them if GitHub shows that prompt. Forked repositories commonly start with workflows disabled.

Before continuing: check whether Daily verified update is enabled. Public forks normally start with workflows disabled. For repositories created from template, disable scheduled workflow until first manual build has completed and its APKs have been tested. Scheduled workflow publishes changed builds automatically.

Documentation workflow always validates VitePress changes. To publish your own documentation site, select Settings → Pages → Source: GitHub Actions, then create repository variable PUBLISH_DOCUMENTATION=true.

2. Edit morphe.toml

Open morphe.toml, select edit button, and change desired application matrix. No Python code needs modification.

Each [[apps]] entry controls one app:

toml
[[apps]]
package = "com.google.android.youtube"
name = "YouTube"
slug = "youtube"
patched-package = "app.morphe.android.youtube"
version = "auto"
build-mode = "both"
arch = "both"
include-patches = ["GmsCore support", "SponsorBlock"]
exclude-patches = []

[apps.patch-options."SponsorBlock"]
toast-on-connection-error = true

[apps.google-play]
country = "US"

[apps.fallbacks]
apkmirror = ["https://www.apkmirror.com/apk/google-inc/youtube/"]

Important fields:

FieldTypical choice
packageStock Android package name.
patched-packageExpected package after non-root patching; omit if unchanged.
versionauto for first patch-compatible version, latest, or exact version.
build-modeapk, module, or both.
archarm64-v8a, arm-v7a, both, or all.
include-patchesAdditional patch names from configured bundle.
fallbacks.apkmirrorCatalog URL used when Google Play is unavailable.

Delete complete [[apps]] blocks for apps you do not want. Copy a complete block to add another app, then change package identity, patch selection, and provider URLs.

Commit changes directly to default branch or through pull request. Workflow accepts only a committed configuration file; uncommitted editor content cannot be built.

Full schema and validation rules: configuration reference.

3. Decide authentication

Secret-free first build

No secrets are required. Workflow uses:

  • public anonymous Google Play dispenser when available
  • configured verified fallback providers when Play is unavailable
  • committed public template keystore for signing

This is easiest first test. Anonymous Google Play commonly fails from GitHub-hosted runners, so each app should configure at least one fallback such as APKMirror or Uptodown.

Account-backed Google Play

For reliable direct Google Play access, create repository environment:

  1. Open Settings → Environments.
  2. Create or open environment named release.
  3. Add environment secrets:
SecretValue
GOOPDL_ACCOUNT_EMAILDedicated Google account email.
GOOPDL_AAS_TOKENPersistent token starting with aas_et/.

Both secrets must exist together. Token generation and handling: Google Play authentication.

Private signing key

Default .github/template-release.p12 is public. Anyone can sign with it. It provides update compatibility across template forks, not publisher identity.

For your own signing identity, add optional release environment secrets:

SecretValue
MORPHE_KEYSTORE_BASE64Base64-encoded PKCS12 or JKS keystore.
MORPHE_KEYSTORE_PASSWORDKeystore password. Required with private keystore.
MORPHE_KEYSTORE_ALIASAlias; defaults to morphe-builder.

Back up private keystore and password separately in encrypted storage. Losing key prevents compatible updates to installed apps.

4. Run first build

Open Actions → Manual verified build → Run workflow.

Use:

InputFirst run
configmorphe.toml
release_tagUnique future-style value, for example manual-2026-03-01-1.
publishfalse
previous_releaseLeave empty.

release_tag is required because module metadata and update URLs include it, even when first run does not publish a release.

Workflow performs:

  1. checks out committed repository
  2. installs Python, Java, uv, and locked dependencies on runner
  3. validates configuration contains no committed secrets
  4. resolves and hashes toolchain
  5. downloads and verifies stock APKs
  6. merges, patches, signs, and re-verifies output
  7. verifies release manifest and hashes
  8. uploads short-lived workflow artifact

No installation occurs on your computer.

5. Download and test artifact

Open completed workflow run and download artifact named:

text
morphe-verified-<run-id>

Artifact is retained for 14 days. It contains APKs, optional modules, provenance, release manifest, build summary, changelog, and obtainium.json.

Before publication:

  1. inspect CHANGELOG.md and release-manifest.json
  2. confirm expected apps, versions, architectures, and patches
  3. install non-root APK on matching test device
  4. launch app and test required patched behavior
  5. test root module separately when built

Static verification proves artifact consistency, not runtime behavior.

6. Publish release

After successful device validation, run Manual verified build again:

InputPublication run
configmorphe.toml
release_tagNew unused tag, for example manual-2026-03-01-2.
publishtrue
previous_releaseOptional previous published tag.

Workflow builds again from committed inputs, verifies every staged hash, creates draft release, uploads all files, checks asset count, requests attestations, and only then makes release public. Failure deletes incomplete draft.

Existing release tag is refused. Use new tag for each publication attempt.

If publication fails with GitHub token permission error, check Settings → Actions → General → Workflow permissions and organization policy. Workflow requires contents: write, id-token: write, and attestations: write.

Install through Obtainium

Each published release body links obtainium.json. Download it, then use Obtainium's Import/Export page to import it. It tracks every non-root APK in the current release matrix from this repository's future GitHub releases. Root modules are excluded.

7. Enable automatic updates

After manual workflow and signing policy are validated, enable Daily verified update from Actions tab.

Scheduled workflow runs daily at 04:17 UTC. It:

  1. resolves current configured Morphe CLI and patch bundle releases
  2. compares their tags and hashes with last published APK provenance
  3. skips unchanged toolchains
  4. invokes full verified build after change
  5. skips publication when resulting APK versions and hashes remain unchanged
  6. publishes changed verified release automatically

Forks often require scheduled workflows to be enabled manually. GitHub may disable schedules after long repository inactivity.

Automatic publication uses current committed morphe.toml, release environment secrets, and signing key. Review configuration changes before merging them into default branch.

Updating your builder

Template-created repositories have no upstream relationship. Apply upstream changes manually or create a Git remote locally when desired.

Forks can use GitHub Sync fork. Review workflow, dependency, configuration, and signing changes before merging upstream updates. Never accept conflict resolution that replaces your morphe.toml or private-secret setup without review.

Troubleshooting

Common causes:

  • Actions disabled in fork
  • invalid or uncommitted morphe.toml
  • missing provider fallback
  • only one Google account secret configured
  • invalid patch name or no shared compatible version
  • private keystore secrets incomplete
  • release tag already exists
  • workflow token lacks publication permissions

Use troubleshooting for exit-code and build-stage diagnosis. Workflow logs are redacted, but inspect them before sharing and never publish environment dumps or credentials.

Released under the MIT License.