limrun-gradle

Build an Android app on a remote Gradle sandbox with `lim gradle build` instead of local Gradle or Android Studio, from any environment (Linux, Windows, macOS, VM, container). Use when the user wants to build an APK or AAB, sign a release with an upload key, or prepare a Play Store publish, for nati

By limrun-inc · 3,314 installs

npx skills add limrun-inc/skills --skill limrun-gradle

Source repository · Upstream listing

Remote Gradle build Build Android projects on Limrun's remote Gradle sandboxes, from any environment (Linux, Windows, macOS, VM, container). lim gradle build syncs your sources to a remote instance, runs the project's own Gradle wrapper there, and streams the build output. This workflow builds on the remote instance; local Gradle, a local Android SDK, and local emulators are not part of it. A finished run has the app running on a Limrun emulator or the artifact delivered. For iOS builds, use limrun xcode instead of this skill. For the Expo dev client loop (Metro, hot reload) on either platform, use limrun expo development ; it comes back here for the Android Debug build. Auth and CLI Install if needed: npm install global lim . Auth is lim login or LIM API KEY (it may already be set in the user's environment even when .env and the shell do not show it; check before asking for it). The CLI is the source of truth: the commands in this skill are verified, but if a flag errors or you need one not shown here, check help instead of guessing: Build an APK Instead of ./gradlew , build with: This creates or reuses the remembered Gradle instance, syncs the current directory, and runs assembleDebug by default. Pick tasks explicitly with task (repeatable): Use project path when the Gradle root is nested and auto discovery is ambiguous (for example a bare React Native repo where Gradle lives in android/ ; the server usually finds it on its own): Expo managed workflow projects (no android/ directory) are detected automatically: the sandbox installs dependencies and runs expo prebuild before Gradle. Setting expo app dir (monorepos) or abi forces that pipeline and errors when no Expo app is detected: For iterating on an Expo app with Metro and hot reload rather than plain builds, use limrun expo development . Private dependency credentials Copy existing credential files with additional file , also supported by sync : Remote ~/ targets the sandbox home; other destinations are workspace relative. Repeat the flags on later syncs to retain the files. Pass env for environment variables referenced by the configuration. Detached builds and logs Use detach to return once the build is accepted; a webhook is optional. logs reads the latest build without an exec ID, including persisted logs after instance deletion; add follow to wait for completion. Tool versions and shell commands After syncing, lim gradle use selects tools in the sandbox and installs missing versions. Run lim gradle tools install for synced project tool selections ([details](https://docs.limrun.com/docs/android/build with gradle)). Builds keep the project's gradlew ; Android SDK/NDK/CMake use sdkmanager . Wait for sync to succeed before executing. If you get workspace sync is still in progress , retry after sync succeeds. Download sandbox files Use lim gradle pull file <remote path [destination] id <instance ID . Paths can be absolute or relative to the synced project root. Never use build or run logs to transfer files, including text, binary, or base64 content. Wait for the command writing the file to finish. Archive directories first, and download before deleting the instance. Run it on an emulator Upload the built APK as a named asset, then install it on an Android instance: Build uploads default to a 14 day TTL: each build pushes the asset's expiry to 14 days from that upload. Pass upload ttl with a Go duration (e.g. 720h ; 1d is invalid) to change it. Share the signed stream URL from the create output with the user as a Markdown link, such as [Live emulator](<signed stream url ) . For rebuild iterations, patch the installed APK in place instead of recreating the instance: For everything else on the device (tapping, typing, element tree, screenshots, video, logcat over adb), use limrun android emulator . Sign a release AAB The default signing path needs NO credentials from the user: On first use, Limrun generates an upload keystore, escrows it as the organization's signing key for this app, and signs with it. Every later sign build of the same app, from any machine or CI, uses the same key, so Play Store uploads keep matching. The key is named by the Android application ID, detected from app.json (Expo) or app/build.gradle(.kts) ; pass application id <id when detection fails or picks the wrong flavor. sign makes bundleRelease the default task and the build fails before starting if an explicit task list contains no bundle task. A SUCCEEDED build means the AAB carries the signature (the server verifies it before upload), so don't re verify the artifact unless the user asks. Expect one of these lines before the build starts and relay its meaning: Signing with the organization's upload key for <app (newly generated). : first build of this app; the key now exists for the whole organization. Signing with the organization's upload key for <app (existing). : reusing the escrowed key, as intended. Bring your own upload key When the app already has a registered upload key (an existing Play listing), the user can sign with their own keystore instead. The keystore path, key alias and both passwords are supplied by the user on their own machine, as the keystore , key alias , keystore password and key password flags or the LIM KEYSTORE PASSWORD and LIM KEY PASSWORD environment variables ( lim gradle build help lists them). Never ask for or handle these values in the conversation; if one is missing, name the flag or variable to set. All four travel together. Add save key to escrow the provided key so later builds can drop the flags and use plain sign . save key refuses to overwrite: if a DIFFERENT key is already escrowed for the app it fails before any instance is created. The keystore file itself stays on the user's machine: never commit it or paste its bytes into files. keytool list keystore <file shows the alias when the user does not know it. Failure strings to recognize on the bring your own path: The organization already has a different upload key escrowed for <app : save key conflict. Builds with sign use the escrowed key; drop save key to sign with the provided keystore for this build only, or ask the user which key is the real upload key. Signing with your own key requires ... as well : the BYO flag group is incomplete; the message lists exactly the missing flags. signing <field contains an unsupported character : the password or alias has characters outside ISO 8859 1. Change it in place with keytool ( storepasswd , keypasswd , or changealias ) to a Latin 1 value. Never regenerate the key itself: that changes the upload key. Publish to Play Store When the user has Play credentials configured on their own machine (a service account JSON file or an access token, passed through the playstore service account or playstore access token flag), the build publishes the signed release AAB directly, no browser involved. Never ask for these credentials in the conversation: auto version code makes the server resolve the next free versionCode from Google Play before the build and stamp it into the workspace copy ( expo.android.versionCode in app.json for Expo projects, the single literal versionCode in the conventional app/ module build script for native Gradle projects), so repeat publishes never collide. Without it, or on projects with computed or flavor split versionCodes (which it rejects at request time), manage the versionCode yourself as below. Without Play credentials you cannot run the publish itself: it is a browser flow with a Google sign in. Prepare the artifact, upload it as an asset, and hand off: Tell the user to open https://console.limrun.com and, on the Secrets page, click Connect Play Console to sign in with a Google account that has release access to the app (the session lives in the browser only; nothing is stored). Then on the Registry page they click Publish to Play Store on the uploaded AAB and enter the package name (the application ID). The app listing must already exist in Play Console. Google Play requires a versionCode it has never seen: auto version code handles that on publish builds; without it, bump versionCode in app/build.gradle(.kts) (Expo: expo.android.versionCode in app.json) before the build. Failure strings to recognize on the sign path: Cannot determine the Android application ID for signing : detection found no app.json android.package and no applicationId in app/build.gradle(.kts) ; pass application id <id . sign produces a Play ready signed AAB; include a bundle task : the explicit task list has no bundle task; add bundleRelease or drop task . the built AAB carries no signature : the server's post build check found an unsigned bundle; the signing config was not applied. Not a problem in the user's code; retry, and report it if it persists. Android previews on pull requests For repeatable previews on pull requests, prefer the packaged [Android preview action](https://github.com/limrun inc/android preview action). It builds and uploads the app, updates the PR preview comment, and cleans up the builder; see the repository for inputs and workflow examples. Gotchas Build errors are part of the job. If a build fails, read the error output, fix the code, and rebuild before reporting back. A project mise file installs tools the build never uses. The first build or run in a sandbox runs mise install for every [tools] entry in the synced mise files, so a monorepo's root mise.toml full of databases and cloud CLIs slows it down or fails it. Keep using the project file when it works. If it doesn't, add a mise.limrun.toml beside it listing only the build's tools (for example node and pnpm); in that directory Limrun reads it instead of the other mise files. Instance reuse is per git worktree. Commands resolve the remembered instance from the worktree of your cwd; pass id <gradle instance id (from lim gradle list ) to target a specific one. versionCode must increase for every Play upload. Prefer auto version code on publish builds. A rejected publish saying the version code already exists means bump, rebuild, republish. If a publish RETRY reports it, the earlier attempt already succeeded; don't publish again. Application ID detection reads the first uncommented applicationId . Flavor specific IDs and dynamic Gradle logic are out of its scope; use application id there. Keystore passwords must be non empty and ISO 8859 1. Empty passwords and characters outside Latin 1 are rejected at request time instead of failing minutes into the build. Keep synced files small and out of build dirs. Root level build/ , .gradle , .kotlin and any local.properties never sync, and .gitignore files (including nested ones) are honored. Use ignore <regex for other large local artifacts and include <regex to force sync gitignored inputs the build needs.