mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-24 10:58:37 +00:00
android: add play release upload lane
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -83,6 +83,12 @@ apps/ios/fastlane/screenshots/
|
||||
apps/ios/fastlane/test_output/
|
||||
apps/ios/fastlane/logs/
|
||||
apps/ios/fastlane/.env
|
||||
apps/android/fastlane/report.xml
|
||||
apps/android/fastlane/Preview.html
|
||||
apps/android/fastlane/test_output/
|
||||
apps/android/fastlane/logs/
|
||||
apps/android/fastlane/.env
|
||||
apps/android/fastlane/metadata/android/**/images/
|
||||
|
||||
# fastlane build artifacts (local)
|
||||
apps/ios/*.ipa
|
||||
|
||||
@@ -60,6 +60,8 @@ pnpm android:version:pin -- --version 2026.6.5 --version-code 2026060501
|
||||
|
||||
`pnpm android:bundle:release` is an alias for the same archive helper.
|
||||
|
||||
See `apps/android/VERSIONING.md` and `apps/android/fastlane/SETUP.md` for the release workflow.
|
||||
|
||||
Flavor-specific direct Gradle tasks:
|
||||
|
||||
```bash
|
||||
|
||||
37
apps/android/VERSIONING.md
Normal file
37
apps/android/VERSIONING.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# 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.
|
||||
|
||||
Examples:
|
||||
|
||||
- `version = 2026.6.2`
|
||||
- `versionCode = 2026060201`
|
||||
- another upload on the same release train: `versionCode = 2026060202`
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
## Release Workflow
|
||||
|
||||
1. Pin Android to the intended release version.
|
||||
2. Run `pnpm android:version:sync`.
|
||||
3. Update `apps/android/fastlane/metadata/android/en-US/release_notes.txt`.
|
||||
4. Run `pnpm android:release:archive` to produce the signed Play AAB and third-party APK.
|
||||
5. Run `pnpm android:release:upload` to upload metadata and the Play AAB to Google Play internal testing.
|
||||
6. Promote to production manually in Google Play Console.
|
||||
|
||||
The third-party flavor is archived as a signed APK for non-Play distribution. It is not uploaded by the Play release lane.
|
||||
20
apps/android/fastlane/.env.example
Normal file
20
apps/android/fastlane/.env.example
Normal file
@@ -0,0 +1,20 @@
|
||||
# Google Play API key (pick one approach)
|
||||
#
|
||||
# Recommended local path:
|
||||
# GOOGLE_PLAY_JSON_KEY=/absolute/path/to/google-play-service-account.json
|
||||
#
|
||||
# Or raw JSON content for CI:
|
||||
# GOOGLE_PLAY_JSON_KEY_DATA={"type":"service_account",...}
|
||||
|
||||
# Optional app targeting
|
||||
# GOOGLE_PLAY_PACKAGE_NAME=ai.openclaw.app
|
||||
|
||||
# Release target
|
||||
# GOOGLE_PLAY_TRACK=internal
|
||||
# GOOGLE_PLAY_RELEASE_STATUS=completed
|
||||
# GOOGLE_PLAY_VALIDATE_ONLY=1
|
||||
|
||||
# Metadata toggles
|
||||
# SUPPLY_UPLOAD_METADATA=1
|
||||
# SUPPLY_UPLOAD_IMAGES=1
|
||||
# SUPPLY_UPLOAD_SCREENSHOTS=1
|
||||
3
apps/android/fastlane/Appfile
Normal file
3
apps/android/fastlane/Appfile
Normal file
@@ -0,0 +1,3 @@
|
||||
package_name(ENV["GOOGLE_PLAY_PACKAGE_NAME"] || "ai.openclaw.app")
|
||||
|
||||
json_key_file(ENV["GOOGLE_PLAY_JSON_KEY"]) if ENV["GOOGLE_PLAY_JSON_KEY"]
|
||||
255
apps/android/fastlane/Fastfile
Normal file
255
apps/android/fastlane/Fastfile
Normal file
@@ -0,0 +1,255 @@
|
||||
require "fileutils"
|
||||
require "json"
|
||||
require "open3"
|
||||
require "shellwords"
|
||||
require "tempfile"
|
||||
|
||||
default_platform(:android)
|
||||
|
||||
DEFAULT_PLAY_PACKAGE_NAME = "ai.openclaw.app"
|
||||
DEFAULT_PLAY_TRACK = "internal"
|
||||
DEFAULT_PLAY_RELEASE_STATUS = "completed"
|
||||
|
||||
def load_env_file(path)
|
||||
return unless File.exist?(path)
|
||||
|
||||
File.foreach(path) do |line|
|
||||
stripped = line.strip
|
||||
next if stripped.empty? || stripped.start_with?("#")
|
||||
|
||||
key, value = stripped.split("=", 2)
|
||||
next if key.nil? || key.empty? || value.nil?
|
||||
|
||||
ENV[key] = value if ENV[key].nil? || ENV[key].strip.empty?
|
||||
end
|
||||
end
|
||||
|
||||
def env_present?(value)
|
||||
!value.nil? && !value.strip.empty?
|
||||
end
|
||||
|
||||
def android_root
|
||||
File.expand_path("..", __dir__)
|
||||
end
|
||||
|
||||
def repo_root
|
||||
File.expand_path("../..", android_root)
|
||||
end
|
||||
|
||||
def shell_join(args)
|
||||
args.shelljoin
|
||||
end
|
||||
|
||||
def play_package_name
|
||||
raw = ENV["GOOGLE_PLAY_PACKAGE_NAME"].to_s.strip
|
||||
raw.empty? ? DEFAULT_PLAY_PACKAGE_NAME : raw
|
||||
end
|
||||
|
||||
def play_track
|
||||
raw = ENV["GOOGLE_PLAY_TRACK"].to_s.strip
|
||||
raw.empty? ? DEFAULT_PLAY_TRACK : raw
|
||||
end
|
||||
|
||||
def play_release_status
|
||||
raw = ENV["GOOGLE_PLAY_RELEASE_STATUS"].to_s.strip
|
||||
raw.empty? ? DEFAULT_PLAY_RELEASE_STATUS : raw
|
||||
end
|
||||
|
||||
def play_validate_only?
|
||||
ENV["GOOGLE_PLAY_VALIDATE_ONLY"] == "1"
|
||||
end
|
||||
|
||||
def play_metadata_upload_requested?
|
||||
ENV["SUPPLY_UPLOAD_METADATA"] == "1"
|
||||
end
|
||||
|
||||
def play_screenshot_upload_requested?
|
||||
ENV["SUPPLY_UPLOAD_SCREENSHOTS"] == "1"
|
||||
end
|
||||
|
||||
def play_image_upload_requested?
|
||||
ENV["SUPPLY_UPLOAD_IMAGES"] == "1"
|
||||
end
|
||||
|
||||
def play_auth_options
|
||||
json_key = ENV["GOOGLE_PLAY_JSON_KEY"].to_s.strip
|
||||
json_key = ENV["SUPPLY_JSON_KEY"].to_s.strip if json_key.empty?
|
||||
json_key = ENV["GOOGLE_PLAY_JSON_KEY_PATH"].to_s.strip if json_key.empty?
|
||||
return { json_key: json_key } unless json_key.empty?
|
||||
|
||||
json_key_data = ENV["GOOGLE_PLAY_JSON_KEY_DATA"].to_s.strip
|
||||
json_key_data = ENV["SUPPLY_JSON_KEY_DATA"].to_s.strip if json_key_data.empty?
|
||||
return { json_key_data: json_key_data } unless json_key_data.empty?
|
||||
|
||||
UI.user_error!("Missing Google Play API credentials. Set GOOGLE_PLAY_JSON_KEY or GOOGLE_PLAY_JSON_KEY_DATA.")
|
||||
end
|
||||
|
||||
def with_play_json_key_file
|
||||
auth = play_auth_options
|
||||
if auth[:json_key]
|
||||
yield auth[:json_key]
|
||||
return
|
||||
end
|
||||
|
||||
Tempfile.create(["openclaw-google-play", ".json"]) do |file|
|
||||
file.write(auth.fetch(:json_key_data))
|
||||
file.flush
|
||||
yield file.path
|
||||
end
|
||||
end
|
||||
|
||||
def read_android_version_metadata
|
||||
stdout, stderr, status = Open3.capture3(
|
||||
"node",
|
||||
"--import",
|
||||
"tsx",
|
||||
File.join(repo_root, "scripts", "android-version.ts"),
|
||||
"--json"
|
||||
)
|
||||
unless status.success?
|
||||
detail = stderr.to_s.strip
|
||||
detail = stdout.to_s.strip if detail.empty?
|
||||
UI.user_error!("Failed to read Android version metadata: #{detail}")
|
||||
end
|
||||
|
||||
parsed = JSON.parse(stdout)
|
||||
version = parsed.fetch("canonicalVersion").to_s
|
||||
version_code = parsed.fetch("versionCode").to_i
|
||||
UI.user_error!("Android version helper returned incomplete metadata.") if version.empty? || version_code <= 0
|
||||
|
||||
{ version: version, version_code: version_code }
|
||||
rescue JSON::ParserError => e
|
||||
UI.user_error!("Invalid JSON from Android version helper: #{e.message}")
|
||||
end
|
||||
|
||||
def sync_android_versioning!
|
||||
sh(shell_join(["node", "--import", "tsx", File.join(repo_root, "scripts", "android-sync-versioning.ts"), "--check"]))
|
||||
end
|
||||
|
||||
def android_release_notes_path
|
||||
File.join(__dir__, "metadata", "android", "en-US", "release_notes.txt")
|
||||
end
|
||||
|
||||
def android_changelog_path(version_code)
|
||||
File.join(__dir__, "metadata", "android", "en-US", "changelogs", "#{version_code}.txt")
|
||||
end
|
||||
|
||||
def sync_android_changelog!(version_code)
|
||||
release_notes_path = android_release_notes_path
|
||||
UI.user_error!("Missing Android release notes at #{release_notes_path}.") unless File.exist?(release_notes_path)
|
||||
|
||||
changelog_path = android_changelog_path(version_code)
|
||||
FileUtils.mkdir_p(File.dirname(changelog_path))
|
||||
File.write(changelog_path, File.read(release_notes_path))
|
||||
changelog_path
|
||||
end
|
||||
|
||||
def play_metadata_path
|
||||
File.join(__dir__, "metadata", "android")
|
||||
end
|
||||
|
||||
def play_screenshot_paths
|
||||
Dir[File.join(play_metadata_path, "**", "images", "**", "*.png")]
|
||||
end
|
||||
|
||||
def validate_android_screenshots!
|
||||
return unless play_screenshot_upload_requested?
|
||||
|
||||
if play_screenshot_paths.empty?
|
||||
UI.user_error!("SUPPLY_UPLOAD_SCREENSHOTS=1 but no PNG screenshots were found under apps/android/fastlane/metadata/android/*/images.")
|
||||
end
|
||||
end
|
||||
|
||||
def release_artifact_path(version)
|
||||
File.join(android_root, "build", "release-artifacts", "openclaw-#{version}-play-release.aab")
|
||||
end
|
||||
|
||||
def build_release_artifacts!
|
||||
sh(shell_join(["bun", File.join(android_root, "scripts", "build-release-artifacts.ts")]))
|
||||
end
|
||||
|
||||
def upload_play_store_metadata!(version_metadata)
|
||||
validate_android_screenshots!
|
||||
sync_android_changelog!(version_metadata.fetch(:version_code))
|
||||
|
||||
upload_to_play_store(
|
||||
**play_auth_options,
|
||||
package_name: play_package_name,
|
||||
metadata_path: play_metadata_path,
|
||||
skip_upload_apk: true,
|
||||
skip_upload_aab: true,
|
||||
skip_upload_metadata: !play_metadata_upload_requested?,
|
||||
skip_upload_changelogs: false,
|
||||
skip_upload_images: !play_image_upload_requested?,
|
||||
skip_upload_screenshots: !play_screenshot_upload_requested?,
|
||||
validate_only: play_validate_only?
|
||||
)
|
||||
end
|
||||
|
||||
def upload_play_store_build!(version_metadata)
|
||||
artifact_path = release_artifact_path(version_metadata.fetch(:version))
|
||||
UI.user_error!("Missing Play release artifact at #{artifact_path}. Run pnpm android:release:archive first.") unless File.exist?(artifact_path)
|
||||
|
||||
upload_to_play_store(
|
||||
**play_auth_options,
|
||||
package_name: play_package_name,
|
||||
aab: artifact_path,
|
||||
track: play_track,
|
||||
release_status: play_release_status,
|
||||
metadata_path: play_metadata_path,
|
||||
skip_upload_apk: true,
|
||||
skip_upload_metadata: true,
|
||||
skip_upload_changelogs: false,
|
||||
skip_upload_images: true,
|
||||
skip_upload_screenshots: true,
|
||||
validate_only: play_validate_only?
|
||||
)
|
||||
end
|
||||
|
||||
load_env_file(File.join(__dir__, ".env"))
|
||||
|
||||
platform :android do
|
||||
desc "Validate Google Play API credentials"
|
||||
lane :auth_check do
|
||||
with_play_json_key_file do |json_key_path|
|
||||
validate_play_store_json_key(json_key: json_key_path)
|
||||
end
|
||||
UI.success("Google Play API credentials are valid.")
|
||||
end
|
||||
|
||||
desc "Upload Google Play metadata, changelog, and optional screenshots"
|
||||
lane :metadata do
|
||||
sync_android_versioning!
|
||||
version_metadata = read_android_version_metadata
|
||||
ENV["SUPPLY_UPLOAD_METADATA"] = "1" unless ENV.key?("SUPPLY_UPLOAD_METADATA")
|
||||
upload_play_store_metadata!(version_metadata)
|
||||
UI.success("Uploaded Android Play metadata for #{version_metadata[:version]} (#{version_metadata[:version_code]}).")
|
||||
end
|
||||
|
||||
desc "Build signed Android release artifacts locally without uploading"
|
||||
lane :play_store_archive do
|
||||
sync_android_versioning!
|
||||
build_release_artifacts!
|
||||
end
|
||||
|
||||
desc "Upload the signed Play AAB to Google Play"
|
||||
lane :play_store do
|
||||
sync_android_versioning!
|
||||
version_metadata = read_android_version_metadata
|
||||
upload_play_store_build!(version_metadata)
|
||||
UI.success("Uploaded Android Play build to #{play_track}: version=#{version_metadata[:version]} code=#{version_metadata[:version_code]}")
|
||||
end
|
||||
|
||||
desc "Upload Android metadata, archive release artifacts, then upload the Play AAB"
|
||||
lane :release_upload do
|
||||
auth_check
|
||||
sync_android_versioning!
|
||||
version_metadata = read_android_version_metadata
|
||||
ENV["SUPPLY_UPLOAD_METADATA"] = "1"
|
||||
upload_play_store_metadata!(version_metadata)
|
||||
build_release_artifacts!
|
||||
upload_play_store_build!(version_metadata)
|
||||
UI.success("Uploaded Android Play build to #{play_track}: version=#{version_metadata[:version]} code=#{version_metadata[:version_code]}")
|
||||
UI.important("Production promotion remains manual in Google Play Console.")
|
||||
end
|
||||
end
|
||||
67
apps/android/fastlane/SETUP.md
Normal file
67
apps/android/fastlane/SETUP.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# fastlane setup (OpenClaw Android)
|
||||
|
||||
Install:
|
||||
|
||||
```bash
|
||||
brew install fastlane
|
||||
```
|
||||
|
||||
Create a Google Play service account JSON key with Google Play Developer API access, then grant that service account access to the OpenClaw app in Play Console.
|
||||
|
||||
Recommended local auth:
|
||||
|
||||
```bash
|
||||
GOOGLE_PLAY_JSON_KEY=/absolute/path/to/google-play-service-account.json
|
||||
```
|
||||
|
||||
Optional app targeting:
|
||||
|
||||
```bash
|
||||
GOOGLE_PLAY_PACKAGE_NAME=ai.openclaw.app
|
||||
```
|
||||
|
||||
Validate auth:
|
||||
|
||||
```bash
|
||||
cd apps/android
|
||||
fastlane android auth_check
|
||||
```
|
||||
|
||||
Archive locally without upload:
|
||||
|
||||
```bash
|
||||
pnpm android:release:archive
|
||||
```
|
||||
|
||||
Upload metadata, release notes, and the Play AAB to the internal testing track:
|
||||
|
||||
```bash
|
||||
pnpm android:release:upload
|
||||
```
|
||||
|
||||
Direct Fastlane entry point:
|
||||
|
||||
```bash
|
||||
cd apps/android
|
||||
fastlane android release_upload
|
||||
```
|
||||
|
||||
Release rules:
|
||||
|
||||
- `apps/android/version.json` is the pinned Android release version source.
|
||||
- `apps/android/Config/Version.properties` is generated from that source and read by Gradle.
|
||||
- Supported pinned Android versions use CalVer: `YYYY.M.D`.
|
||||
- `versionCode` uses `YYYYMMDDNN`, where `NN` is a two-digit build number for the pinned version.
|
||||
- `pnpm android:version:pin -- --from-gateway` promotes the current root gateway version into the pinned Android release version.
|
||||
- `pnpm android:version:pin -- --version 2026.6.5 --version-code 2026060502` increments another build on the same Android release train.
|
||||
- `pnpm android:version:sync` updates generated version artifacts.
|
||||
- `pnpm android:version:check` validates checked-in Android version artifacts.
|
||||
- `pnpm android:release:archive` builds the signed Play AAB and third-party APK into `apps/android/build/release-artifacts/`.
|
||||
- `pnpm android:release:upload` uploads the Play AAB to the configured Google Play track. The default track is `internal`.
|
||||
- Production promotion remains manual in Google Play Console.
|
||||
|
||||
Screenshots:
|
||||
|
||||
- Android metadata can upload raw Play screenshots when PNGs exist under `apps/android/fastlane/metadata/android/<locale>/images/`.
|
||||
- Set `SUPPLY_UPLOAD_SCREENSHOTS=1` to include those screenshots in `fastlane android metadata`.
|
||||
- Do not commit generated screenshot captures unless they become intentional store metadata assets.
|
||||
@@ -0,0 +1,3 @@
|
||||
OpenClaw is now available on Android.
|
||||
|
||||
Connect to your OpenClaw Gateway to chat with your assistant, use realtime Talk mode, review approvals, and bring Android device capabilities like camera, location, screen, and notifications into your private automation workflows.
|
||||
@@ -0,0 +1,18 @@
|
||||
OpenClaw is a personal AI assistant you run on your own devices.
|
||||
|
||||
Pair this Android app with your OpenClaw Gateway to use your phone as a secure node for chat, voice, approvals, and device-aware automation.
|
||||
|
||||
What you can do:
|
||||
- Pair with your private OpenClaw Gateway by QR code or setup code
|
||||
- Chat with your assistant from Android
|
||||
- Use realtime Talk mode and push-to-talk
|
||||
- Review Gateway action approvals from your phone
|
||||
- Enable device capabilities such as camera, screen, location, and notifications when you choose
|
||||
- Receive push wakes and node status updates for connected workflows
|
||||
|
||||
OpenClaw is local-first: you control your gateway, keys, configuration, and permissions. Device access is managed by Android permissions and can be enabled only for the capabilities you want to use.
|
||||
|
||||
Getting started:
|
||||
1) Set up your OpenClaw Gateway
|
||||
2) Open the Android app and pair with your gateway
|
||||
3) Start using chat, Talk mode, approvals, and automations from your phone
|
||||
@@ -0,0 +1,3 @@
|
||||
OpenClaw is now available on Android.
|
||||
|
||||
Connect to your OpenClaw Gateway to chat with your assistant, use realtime Talk mode, review approvals, and bring Android device capabilities like camera, location, screen, and notifications into your private automation workflows.
|
||||
@@ -0,0 +1 @@
|
||||
Personal AI on your Android devices
|
||||
1
apps/android/fastlane/metadata/android/en-US/title.txt
Normal file
1
apps/android/fastlane/metadata/android/en-US/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
OpenClaw
|
||||
@@ -1440,7 +1440,11 @@
|
||||
"android:lint:android": "node scripts/run-android-gradle.mjs :app:lintDebug",
|
||||
"android:run": "node scripts/run-android-gradle.mjs :app:installPlayDebug -- adb shell am start -n ai.openclaw.app/.MainActivity",
|
||||
"android:run:third-party": "node scripts/run-android-gradle.mjs :app:installThirdPartyDebug -- adb shell am start -n ai.openclaw.app/.MainActivity",
|
||||
"android:release": "bash scripts/android-release.sh",
|
||||
"android:release:archive": "bun apps/android/scripts/build-release-artifacts.ts",
|
||||
"android:release:auth:check": "bash -lc 'source ./scripts/lib/android-fastlane.sh && cd apps/android && run_android_fastlane android auth_check'",
|
||||
"android:release:metadata": "bash -lc 'source ./scripts/lib/android-fastlane.sh && cd apps/android && run_android_fastlane android metadata'",
|
||||
"android:release:upload": "bash scripts/android-release-upload.sh",
|
||||
"android:test": "node scripts/run-android-gradle.mjs :app:testPlayDebugUnitTest",
|
||||
"android:test:integration": "node scripts/run-with-env.mjs OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_ANDROID_NODE=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.live.config.ts src/gateway/android-node.capabilities.live.test.ts",
|
||||
"android:test:third-party": "node scripts/run-android-gradle.mjs :app:testThirdPartyDebugUnitTest",
|
||||
|
||||
38
scripts/android-release-upload.sh
Normal file
38
scripts/android-release-upload.sh
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
scripts/android-release-upload.sh
|
||||
|
||||
Uploads Android Play metadata, builds signed release artifacts, and uploads the
|
||||
Play AAB to Google Play internal testing by default. This does not promote the
|
||||
build to production.
|
||||
EOF
|
||||
}
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "${ROOT_DIR}/scripts/lib/android-fastlane.sh"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--)
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1" >&2
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
(
|
||||
cd "${ROOT_DIR}/apps/android"
|
||||
run_android_fastlane android release_upload
|
||||
)
|
||||
5
scripts/android-release.sh
Normal file
5
scripts/android-release.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
exec bash "${ROOT_DIR}/scripts/android-release-upload.sh" "$@"
|
||||
21
scripts/lib/android-fastlane.sh
Normal file
21
scripts/lib/android-fastlane.sh
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
run_android_fastlane() {
|
||||
if command -v fastlane >/dev/null 2>&1 && fastlane --version >/dev/null 2>&1; then
|
||||
fastlane "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
if command -v rbenv >/dev/null 2>&1; then
|
||||
local version=""
|
||||
while IFS= read -r version; do
|
||||
if RBENV_VERSION="${version}" rbenv which fastlane >/dev/null 2>&1; then
|
||||
RBENV_VERSION="${version}" rbenv exec fastlane "$@"
|
||||
return
|
||||
fi
|
||||
done < <(rbenv versions --bare)
|
||||
fi
|
||||
|
||||
echo "fastlane not found. Install fastlane or select a Ruby version that has the fastlane gem." >&2
|
||||
return 127
|
||||
}
|
||||
Reference in New Issue
Block a user