Files
adolf/apps/android/VERSIONING.md
alvis bedb527145
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Vendor OpenClaw source as Adolf fork baseline
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11),
free to diverge. Tree copied sans upstream .git; upstream remote added for
future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19.
Preserves docs/ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
2026-07-05 09:36:54 +00:00

5.3 KiB

OpenClaw Android Versioning

Android release builds use pinned app metadata instead of auto-bumping build.gradle.kts.

Version model

  • apps/android/version.json is the source of truth.
  • version is the Play versionName and uses CalVer: YYYY.M.D.
  • versionCode uses YYYYMMDDNN, where NN is a two-digit build number for that pinned app version.
  • apps/android/Config/Version.properties is generated from version.json and read by Gradle.
  • apps/android/CHANGELOG.md is the Android-only changelog and release-note source.
  • apps/android/fastlane/metadata/android/en-US/release_notes.txt is generated from the changelog.

Examples:

  • version = 2026.6.2
  • versionCode = 2026060201
  • another upload on the same release train: versionCode = 2026060202

Commands

pnpm android:version
pnpm android:version:check
pnpm android:version:sync
pnpm android:version:pin -- --from-gateway
pnpm android:version:pin -- --version 2026.6.5 --version-code 2026060501
pnpm android:release:signing:plan
MATCH_PASSWORD=<signing repo password> pnpm android:release:signing:sync:pull
pnpm android:release:preflight

Release-note resolution order

When generating apps/android/fastlane/metadata/android/en-US/release_notes.txt, the tooling reads the first available changelog section in this order:

  1. exact pinned version, for example ## 2026.6.2
  2. ## Unreleased

Recommended workflow:

  • while iterating on a Google Play release train, keep pending notes under ## Unreleased
  • before the production release, move or copy the final notes under ## <pinned version> and run sync again

Release Workflow

  1. Pin Android to the intended release version.
  2. Run pnpm android:version:sync.
  3. Update apps/android/CHANGELOG.md, then run pnpm android:version:sync again if needed.
  4. Run MATCH_PASSWORD=<signing repo password> pnpm android:release:signing:sync:pull to materialize encrypted Android signing assets from apps-signing.
  5. Run pnpm android:release:preflight to validate Play auth, signing, synced versioning, and release notes.
  6. Run ANDROID_SCREENSHOT_AVD=<avd-name> pnpm android:screenshots to refresh raw Google Play screenshots with a script-managed emulator, or run pnpm android:screenshots when exactly one ADB device is already connected.
  7. Run pnpm android:release:archive to produce the signed Play AAB and third-party APK.
  8. Run pnpm android:release:upload to upload metadata, screenshots, and the Play AAB to the configured Google Play track.
  9. Complete production rollout manually in Google Play Console when needed.

If pnpm android:release:upload fails, stop at that failure. Do not continue by uploading archived artifacts through pnpm android:release:archive, pnpm android:release:metadata, direct Fastlane lanes, Gradle release artifacts, Google Play API mutation commands, or Play Console mutation commands. Fix the failing release-lane step, then rerun pnpm android:release:upload.

The third-party flavor is archived as a signed APK for non-Play distribution. It is not uploaded by the Play release lane.

Release SHA tracking

Successful Play build uploads create a non-tag Git ref that records the source commit for the uploaded store build:

refs/openclaw/mobile-releases/android/<versionName>-<versionCode>

Example:

refs/openclaw/mobile-releases/android/2026.6.10-2026061008

These refs are intentionally outside refs/tags/* and refs/heads/*. They do not appear on GitHub release or tag pages, and they do not participate in the core OpenClaw release machinery.

pnpm android:release:upload checks the ref before uploading the Play build and records it only after upload_to_play_store succeeds. Existing refs are immutable: the same ref at the same SHA is accepted, while the same ref at a different SHA fails. GOOGLE_PLAY_VALIDATE_ONLY=1 still checks the ref but does not record it because no Play build is published.

Do not create this ref after a manual fallback upload. The ref is release-lane evidence, not a repair mechanism for a failed pnpm android:release:upload run.

Useful direct commands:

pnpm mobile:release:preflight -- --platform android --version 2026.6.10 --version-code 2026061008
pnpm mobile:release:resolve -- --platform android --version 2026.6.10 --version-code 2026061008

Signing model

apps/android/Config/ReleaseSigning.json pins the Android signing assets in the shared private apps-signing repo. The Android pipeline uses the same MATCH_PASSWORD release-owner secret as iOS, but the Android files are managed by scripts/android-release-signing.mjs instead of Fastlane match.

sync:pull decrypts the Play upload keystore and Gradle signing properties into apps/android/build/release-signing/. That directory is gitignored, and Fastlane exports the materialized values as Gradle project properties for the current release command.

If MATCH_PASSWORD is not set, the existing manual Gradle-property signing path still works: provide OPENCLAW_ANDROID_STORE_FILE, OPENCLAW_ANDROID_STORE_PASSWORD, OPENCLAW_ANDROID_KEY_ALIAS, and OPENCLAW_ANDROID_KEY_PASSWORD through your local Gradle user properties before running release tasks.

Agent-driven releases must not use those lower-level signing and upload surfaces to bypass a failed pnpm android:release:upload attempt. Report the failing step and wait for maintainer direction instead.