limrun-gradle

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Remote Gradle build

远程Gradle构建

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. Never fall back to local Gradle, a local Android SDK, or a local emulator. Your job doesn't end at a green build: get the app running or the artifact delivered, and iterate until the user is satisfied.
For iOS work, use
limrun-xcode
(native) or
limrun-expo-development
(Expo dev loop) instead of this skill.
在Limrun的远程Gradle沙箱中构建Android项目,支持任意环境(Linux、Windows、macOS、虚拟机、容器)。
lim gradle build
会将你的源码同步到远程实例,在那里运行项目自带的Gradle wrapper,并流式传输构建输出。无需再依赖本地Gradle、本地Android SDK或本地模拟器。你的工作不止于成功构建:要确保应用能运行或交付产物,持续迭代直至用户满意。
iOS相关工作请使用**
limrun-xcode
(原生项目)或
limrun-expo-development
**(Expo开发循环),而非本技能。

Auth and CLI

认证与CLI

Install if needed:
npm install --global lim
. Auth is
lim login
or
LIM_API_KEY
(it may be set outside the project, so don't ask for it just because it's missing from
.env
or the shell). 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:
bash
lim gradle --help
lim gradle build --help
如需安装,请执行:
npm install --global lim
。认证方式为
lim login
或设置
LIM_API_KEY
(该密钥可能在项目外设置,因此不要仅因
.env
或Shell中未找到就向用户索要)。CLI是权威来源:本技能中的命令均已验证,但如果某个标志报错或你需要此处未展示的标志,请查看
--help
而非猜测:
bash
lim gradle --help
lim gradle build --help

Build an APK

构建APK

Instead of
./gradlew
, build with:
bash
lim gradle build .
This creates or reuses the remembered Gradle instance, syncs the current directory, and runs
assembleDebug
by default. Pick tasks explicitly with
--task
(repeatable):
bash
lim gradle build . --task :app:assembleRelease
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):
bash
lim gradle build . --project-path android
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:
bash
lim gradle build ./my-monorepo --expo-app-dir apps/mobile
无需使用
./gradlew
,执行以下命令构建:
bash
lim gradle build .
此命令会创建或复用已保存的Gradle实例,同步当前目录,默认运行
assembleDebug
任务。可通过
--task
(可重复使用)显式指定任务:
bash
lim gradle build . --task :app:assembleRelease
当Gradle根目录嵌套且自动识别存在歧义时(例如裸React Native仓库中Gradle位于
android/
目录下;通常服务器可自行识别),使用
--project-path
bash
lim gradle build . --project-path android
Expo托管工作流项目(无
android/
目录)会被自动检测:沙箱会先安装依赖并运行
expo prebuild
,再执行Gradle构建。设置
--expo-app-dir
(适用于单体仓库)或
--abi
会强制启用该流程,若未检测到Expo应用则报错:
bash
lim gradle build ./my-monorepo --expo-app-dir apps/mobile

Run it on an emulator

在模拟器上运行

Upload the built APK as a named asset, then install it on an Android instance:
bash
lim gradle build . --upload myapp.apk
lim android create --install-asset=myapp.apk
If the create output includes a signed stream URL, share it with the user as a Markdown link, such as Live emulator. Drive the device with
lim android
commands (
screenshot
,
tap
,
type
,
element-tree
,
record
; see
lim android --help
). For rebuild iterations, patch the installed APK in place instead of recreating the instance:
bash
lim android sync ./path/to/app-debug.apk
将构建好的APK作为命名资产上传,然后安装到Android实例:
bash
lim gradle build . --upload myapp.apk
lim android create --install-asset=myapp.apk
如果创建输出包含签名流URL,请将其作为Markdown链接分享给用户,例如在线模拟器。使用
lim android
命令操作设备(
screenshot
tap
type
element-tree
record
;详见
lim android --help
)。如需重新构建迭代,可直接替换已安装的APK,无需重新创建实例:
bash
lim android sync ./path/to/app-debug.apk

Sign a release AAB

为发布版AAB签名

The default signing path needs NO credentials from the user:
bash
lim gradle build . --sign --upload myapp.aab
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.
默认签名流程无需用户提供任何凭据:
bash
lim gradle build . --sign --upload myapp.aab
首次使用时,Limrun会生成一个上传密钥库,将其作为组织针对该应用的签名密钥托管,并使用它进行签名。之后,任何机器或CI环境中对同一应用执行的
--sign
构建,都会使用同一个密钥,确保Play Store上传的签名一致。密钥名称由Android应用ID决定,该ID从
app.json
(Expo项目)或
app/build.gradle(.kts)
(原生项目)中检测;若检测失败或选择了错误的变体,请传递
--application-id <id>
--sign
会将
bundleRelease
设为默认任务,若显式指定的
--task
列表中不包含bundle任务,构建会在启动前失败。构建成功意味着AAB已携带签名(服务器会在上传前验证),因此除非用户要求,否则无需重新验证产物。
构建启动前会出现以下其中一行信息,请向用户传达其含义:
  • Signing with the organization's upload key for <app> (newly generated).
    :该应用首次构建;密钥现已为整个组织创建。
  • Signing with the organization's upload key for <app> (existing).
    :复用已托管的密钥,符合预期。

Bring your own upload key

使用自定义上传密钥

When the app already has a registered upload key (an existing Play listing), sign with the user's keystore instead:
bash
lim gradle build . \
  --keystore upload.jks --keystore-password "$KS_PASS" \
  --key-alias upload --key-password "$KEY_PASS" \
  --upload myapp.aab
All four flags travel together; the passwords can come from
LIM_KEYSTORE_PASSWORD
and
LIM_KEY_PASSWORD
instead of argv. 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.
Collect from the user:
  • the keystore file path (
    .jks
    or
    .p12
    ); never commit it or paste its bytes into files,
  • the keystore password and the key password (often the same value),
  • the key alias (
    keytool -list -keystore <file>
    shows it if unknown).
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.
若应用已有注册的上传密钥(已存在Play商店列表),请使用用户的密钥库进行签名:
bash
lim gradle build . \
  --keystore upload.jks --keystore-password "$KS_PASS" \
  --key-alias upload --key-password "$KEY_PASS" \
  --upload myapp.aab
上述四个标志需配合使用;密码也可来自
LIM_KEYSTORE_PASSWORD
LIM_KEY_PASSWORD
环境变量,而非命令行参数。添加
--save-key
可托管提供的密钥,后续构建无需再携带这些标志,只需使用简单的
--sign
即可。
--save-key
不会覆盖现有密钥:若该应用已托管了不同的密钥,会在创建任何实例前失败。
需向用户收集以下信息:
  • 密钥库文件路径(
    .jks
    .p12
    );切勿提交该文件或将其内容粘贴到其他文件中,
  • 密钥库密码和密钥密码(通常为同一值),
  • 密钥别名(若未知,可通过
    keytool -list -keystore <file>
    查看)。
使用自定义密钥流程中需识别的失败信息:
  • The organization already has a different upload key escrowed for <app>
    --save-key
    冲突。使用
    --sign
    的构建会使用已托管的密钥;若仅需本次构建使用提供的密钥签名,可移除
    --save-key
    ,或询问用户哪个密钥是真实的上传密钥。
  • Signing with your own key requires ... as well
    :自定义密钥标志组不完整;信息会列出缺失的具体标志。
  • signing <field> contains an unsupported character
    :密码或别名包含ISO-8859-1之外的字符。请使用keytool(
    -storepasswd
    -keypasswd
    -changealias
    )将其修改为Latin-1值。切勿重新生成密钥本身:这会更改上传密钥。

Publish to Play Store

发布到Play Store

You cannot run the publish itself: it is a browser flow with a Google sign-in. Prepare the artifact, then hand off:
bash
lim gradle build . --sign --upload-to-playstore --playstore-service-account sa.json --auto-version-code
--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. For the build-then-publish-via-console flow, upload the AAB as an asset instead:
bash
lim gradle build . --sign --upload <app>-v<versionCode>.aab
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.
你无法直接执行发布操作:这是一个需要Google登录的浏览器流程。请先准备好产物,再移交用户操作:
bash
lim gradle build . --sign --upload-to-playstore --playstore-service-account sa.json --auto-version-code
--auto-version-code
会让服务器在构建前从Google Play获取下一个可用的versionCode,并将其标记到工作区副本中(Expo项目为
app.json
中的
expo.android.versionCode
,原生Gradle项目为常规
app/
模块构建脚本中的
versionCode
字面量),确保重复发布不会冲突。若未使用该标志,或项目使用计算值或变体拆分的versionCode(会在请求时被拒绝),请按以下方式自行管理versionCode。对于“构建后通过控制台发布”的流程,请将AAB作为资产上传:
bash
lim gradle build . --sign --upload <app>-v<versionCode>.aab
告知用户打开https://console.limrun.com,在**Secrets**页面点击**Connect Play Console**,使用拥有应用发布权限的Google账号登录(会话仅存在于浏览器中;无任何信息被存储)。然后在Registry页面,点击已上传AAB旁的Publish to Play Store,输入包名(即应用ID)。应用列表必须已在Play Console中存在。Google Play要求使用从未使用过的versionCode:发布构建时优先使用
--auto-version-code
;若未使用,请在构建前修改
app/build.gradle(.kts)
中的
versionCode
(Expo项目为
app.json
中的
expo.android.versionCode
)。
使用
--sign
流程中需识别的失败信息:
  • Cannot determine the Android application ID for signing
    :检测未找到
    app.json
    中的android.package或
    app/build.gradle(.kts)
    中的
    applicationId
    ;请传递
    --application-id <id>
  • --sign produces a Play-ready signed AAB; include a bundle task
    :显式指定的
    --task
    列表中无bundle任务;请添加
    bundleRelease
    或移除
    --task
  • the built AAB carries no signature
    :服务器构建后检查发现bundle未签名;签名配置未生效。这并非用户代码问题;请重试,若问题持续则上报。

Gotchas

注意事项

  • Build errors are your job to fix. If a build fails, read the error output, fix the code, and rebuild. Don't ask the user to fix build errors.
  • 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.
  • 构建错误由你负责修复。若构建失败,请读取错误输出,修复代码后重新构建。不要让用户修复构建错误。
  • 实例复用基于git工作区。命令会根据当前工作目录的工作区解析已保存的实例;如需指定特定实例,请传递
    --id <gradle-instance-id>
    (来自
    lim gradle list
    )。
  • 每次Play Store上传的versionCode必须递增。发布构建时优先使用
    --auto-version-code
    。若发布被拒绝并提示版本代码已存在,请递增versionCode后重新构建并发布。若发布重试时出现该提示,说明之前的尝试已成功;请勿再次发布。
  • 应用ID检测会读取第一个未注释的
    applicationId
    。变体特定ID和动态Gradle逻辑不在其识别范围内;此类情况请使用
    --application-id
  • 密钥库密码必须非空且符合ISO-8859-1标准。空密码和Latin-1之外的字符会在请求时被拒绝,避免构建数分钟后失败。
  • 同步文件请保持体积小且避免同步构建目录。根目录下的
    build/
    .gradle
    .kotlin
    及任何
    local.properties
    文件永远不会被同步,且会遵循
    .gitignore
    文件(包括嵌套的
    .gitignore
    )。对于其他大型本地产物,可使用
    --ignore <regex>
    忽略;对于构建所需的、被git忽略的输入文件,可使用
    --include <regex>
    强制同步。