mirror of
https://github.com/selfxyz/self.git
synced 2026-01-09 22:58:20 -05:00
* update CI
* bump iOS version
* update readme
* update mobile-deploy ci
* bump version iOS
* update workflow to use workload identity federation (#933)
* update workflow to use workload identity federation
* add token permissions
* correct provider name
* chore: incrementing android build version for version 2.6.4 [github action]
---------
Co-authored-by: Self GitHub Actions <action@github.com>
* update ci
* update ci
* update ci
* update ci
* update ci
* fix ci
* fix ci
* fix ci
* remove fastlane use for android
* bump iOS build version
* update CI python script
* iterate on CI
* iterate on CI
* iterate on CI
* Dev (#941)
* SDK Go version (#920)
* feat: helper functions and constant for go-sdk
* feat: formatRevealedDataPacked in go
* chore: refactor
* feat: define struct for selfBackendVerifier
* feat: verify function for selfBackendVerifier
* feat(wip): custom hasher
* feat: SelfVerifierBacked in go
* test(wip): scope and userContextHash is failing
* test: zk proof verified
* fix: MockConfigStore getactionId function
* chore: refactor
* chore: remove abi duplicate files
* chore: move configStore to utils
* chore: modified VcAndDiscloseProof struct
* chore: more review changes
* feat: impl DefaultConfig and InMemoryConfigStore
* chore: refactor and export functions
* fix: module import and README
* chore: remove example folder
* chore: remove pointers from VerificationConfig
* chore: coderabbit review fixes
* chore: more coderabbit review fix
* chore: add license
* fix: convert attestationIdd to int
* chore: remove duplicate code
---------
Co-authored-by: ayman <aymanshaik1015@gmail.com>
* Moving proving Utils to common (#935)
* remove react dom
* moves proving utils to the common
* need to use rn components
* fix imports
* add proving-utils and dedeuplicate entry configs for esm and cjs.
* must wrap in text component
* fix metro bundling
* fix mock import
* fix builds and tests
* please save me
* solution?
* fix test
* Move proving inputs to the common package (#937)
* create ofactTree type to share
* move proving inputs from app to register inputs in common
* missed reexport
* ok
* add some validations as suggested by our ai overlords
* Fix mock passport flow (#942)
* fix dev screens
* add hint
* rename
* fix path
* fix mobile-ci path
* fix: extractMRZ (#938)
* fix: extractMRZ
* yarn nice && yarn types
* fix test: remove unused
* fix mobile ci
* add script
---------
Co-authored-by: Justin Hernandez <transphorm@gmail.com>
* Move Proving attest and cose (#950)
* moved attest and cose utils to common
with cursor converted tests in common to use vitest and converted coseVerify.test to vitest after moving from app to common
what does cryptoLoader do?
* moved away
* get buff
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* SELF-253 feat: add user email feedback (#889)
* feat: add sentry feedback
* add sentry feedback to web
* feat: add custom feedback modal & fix freeze on IOS
* yarn nice
* update lock
* feat: show feedback widget on NFC scan issues (#948)
* feat: show feedback widget on NFC scan issues
* fix ref
* clean up
* fix report issue screen
* abstract send user feedback email logic
* fixes
* change text to Report Issue
* sanitize email and track event messge
* remove unnecessary sanitization
* add sanitize error message tests
* fix tests
* save wip. almost done
* fix screen test
* fix screen test
* remove non working test
---------
Co-authored-by: Justin Hernandez <transphorm@gmail.com>
Co-authored-by: Justin Hernandez <justin.hernandez@self.xyz>
* chore: centralize license header checks (#952)
* chore: centralize license header scripts
* chore: run license header checks from root
* add header to other files
* add header to bundle
* add migration script and update check license headers
* convert license to mobile sdk
* migrate license headers
* remove headers from common; convert remaining
* fix headers
* add license header checks
* update unsupported passport screen (#953)
* update unsupported passport screen
* yarn nice
---------
Co-authored-by: Vishalkulkarni45 <109329073+Vishalkulkarni45@users.noreply.github.com>
Co-authored-by: ayman <aymanshaik1015@gmail.com>
Co-authored-by: Aaron DeRuvo <aaron.deruvo@clabs.co>
Co-authored-by: Justin Hernandez <justin.hernandez@self.xyz>
Co-authored-by: Seshanth.S🐺 <35675963+seshanthS@users.noreply.github.com>
Co-authored-by: Justin Hernandez <transphorm@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* bump version
* bump yarn.lock
* update ci (#966)
* chore: Manually bump and release v2.6.4 (#961)
* update lock files
* bump and build android
* update build artifacts
* show generate mock document button
* update lock
* fix formatting and update failing e2e test
* revert podfile
* fixes
* fix cold start of the app with deeplink
* update ci
* update ci
* Sync MARKETING_VERSION to iOS project files after version bump
* chore: incrementing android build version for version 2.6.4 [github action] (#976)
Co-authored-by: remicolin <98749896+remicolin@users.noreply.github.com>
* chore: add build dependencies step for iOS and Android in mobile deploy workflow
* chore: enhance mobile deploy workflow by adding CMake installation step
* bump android build version
* chore: incrementing android build version for version 2.6.4 [github action] (#985)
Co-authored-by: remicolin <98749896+remicolin@users.noreply.github.com>
* chore: configure Metro bundler for production compatibility in mobile deploy workflow
* chore: incrementing android build version for version 2.6.4 [github action] (#987)
Co-authored-by: remicolin <98749896+remicolin@users.noreply.github.com>
* Revert "chore: configure Metro bundler for production compatibility in mobile deploy workflow"
This reverts commit 60fc1f2580.
* reduce max old space size in mobile-deploy ci
* fix android french id card (#957)
* fix android french id card
* fix common ci cache
* feat: log apdu (#988)
---------
Co-authored-by: Justin Hernandez <transphorm@gmail.com>
Co-authored-by: Seshanth.S🐺 <35675963+seshanthS@users.noreply.github.com>
* unblock ci
* fix merge
* merge fixes
* fix tests
* make ci happy
---------
Co-authored-by: turnoffthiscomputer <colin.remi07@gmail.com>
Co-authored-by: pputman-clabs <99900942+pputman-clabs@users.noreply.github.com>
Co-authored-by: Self GitHub Actions <action@github.com>
Co-authored-by: turnoffthiscomputer <98749896+remicolin@users.noreply.github.com>
Co-authored-by: Vishalkulkarni45 <109329073+Vishalkulkarni45@users.noreply.github.com>
Co-authored-by: ayman <aymanshaik1015@gmail.com>
Co-authored-by: Aaron DeRuvo <aaron.deruvo@clabs.co>
Co-authored-by: Seshanth.S🐺 <35675963+seshanthS@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
498 lines
18 KiB
Ruby
498 lines
18 KiB
Ruby
# This file contains the fastlane.tools configuration
|
|
# You can find the documentation at https://docs.fastlane.tools
|
|
#
|
|
# For a list of all available actions, check out
|
|
# https://docs.fastlane.tools/actions
|
|
#
|
|
|
|
opt_out_usage
|
|
|
|
require "bundler/setup"
|
|
require "base64"
|
|
require "xcodeproj"
|
|
require_relative "helpers"
|
|
|
|
# load secrets before project configuration
|
|
Fastlane::Helpers.dev_load_dotenv_secrets
|
|
is_ci = Fastlane::Helpers.is_ci_environment?
|
|
local_development = !is_ci
|
|
|
|
# checks after calling Dotenv.load
|
|
android_has_permissions = false
|
|
|
|
# Project configuration
|
|
PROJECT_NAME = ENV["IOS_PROJECT_NAME"]
|
|
APP_NAME = ENV["IOS_PROJECT_NAME"] || begin
|
|
app_json_path = File.expand_path("../app.json", __dir__)
|
|
if File.exist?(app_json_path)
|
|
app_config = JSON.parse(File.read(app_json_path))
|
|
app_config["displayName"] if app_config.is_a?(Hash)
|
|
end
|
|
rescue JSON::ParserError, Errno::ENOENT
|
|
UI.important("Could not read app.json or invalid JSON format, using default app name")
|
|
nil
|
|
end || "MobileApp"
|
|
PROJECT_SCHEME = ENV["IOS_PROJECT_SCHEME"]
|
|
SIGNING_CERTIFICATE = ENV["IOS_SIGNING_CERTIFICATE"]
|
|
|
|
# Environment setup
|
|
package_version = JSON.parse(File.read("../package.json"))["version"]
|
|
# most of these values are for local development
|
|
android_aab_path = "android/app/build/outputs/bundle/release/app-release.aab"
|
|
android_gradle_file_path = "../android/app/build.gradle"
|
|
android_keystore_path = "../android/app/upload-keystore.jks"
|
|
android_play_store_json_key_path = "../android/app/play-store-key.json"
|
|
ios_connect_api_key_path = "../ios/certs/connect_api_key.p8"
|
|
ios_provisioning_profile_directory = "~/Library/MobileDevice/Provisioning\ Profiles"
|
|
ios_xcode_profile_path = "../ios/#{PROJECT_NAME}.xcodeproj"
|
|
|
|
default_platform(:ios)
|
|
|
|
platform :ios do
|
|
desc "Sync ios version"
|
|
lane :sync_version do
|
|
increment_version_number(
|
|
xcodeproj: "ios/#{PROJECT_NAME}.xcodeproj",
|
|
version_number: package_version,
|
|
)
|
|
end
|
|
|
|
desc "Push a new build to TestFlight Internal Testing"
|
|
lane :internal_test do |options|
|
|
test_mode = options[:test_mode] == true || options[:test_mode] == "true"
|
|
|
|
result = prepare_ios_build(prod_release: false)
|
|
|
|
if test_mode
|
|
UI.important("🧪 TEST MODE: Skipping TestFlight upload")
|
|
UI.success("✅ Build completed successfully!")
|
|
UI.message("📦 IPA path: #{result[:ipa_path]}")
|
|
else
|
|
upload_to_testflight(
|
|
api_key: result[:api_key],
|
|
distribute_external: true,
|
|
# Only external TestFlight groups are valid here
|
|
groups: ENV["IOS_TESTFLIGHT_GROUPS"].split(","),
|
|
changelog: "",
|
|
skip_waiting_for_build_processing: false,
|
|
) if result[:should_upload]
|
|
end
|
|
|
|
# Update deployment timestamp in version.json
|
|
if result[:should_upload]
|
|
Fastlane::Helpers.update_deployment_timestamp("ios")
|
|
end
|
|
|
|
# Notify Slack about the new build
|
|
if ENV["SLACK_CHANNEL_ID"] && !test_mode
|
|
deploy_source = Fastlane::Helpers.is_ci_environment? ? "GitHub Workflow" : "Local Deploy"
|
|
Fastlane::Helpers.upload_file_to_slack(
|
|
file_path: result[:ipa_path],
|
|
channel_id: ENV["SLACK_CHANNEL_ID"],
|
|
initial_comment: "🍎 iOS v#{package_version} (Build #{result[:build_number]}) deployed to TestFlight via #{deploy_source}",
|
|
title: "#{APP_NAME}-#{package_version}-#{result[:build_number]}.ipa",
|
|
)
|
|
elsif test_mode
|
|
UI.important("🧪 TEST MODE: Skipping Slack notification")
|
|
else
|
|
UI.important("Skipping Slack notification: SLACK_CHANNEL_ID not set.")
|
|
end
|
|
end
|
|
|
|
desc "Deploy iOS app with automatic version management"
|
|
lane :deploy_auto do |options|
|
|
deployment_track = options[:deployment_track] || "internal"
|
|
version_bump = options[:version_bump] || "build"
|
|
test_mode = options[:test_mode] == true || options[:test_mode] == "true"
|
|
|
|
UI.message("🚀 Starting iOS deployment")
|
|
UI.message(" Track: #{deployment_track}")
|
|
UI.message(" Version bump: #{version_bump}")
|
|
UI.message(" Test mode: #{test_mode}")
|
|
|
|
# Handle version bumping
|
|
if !test_mode
|
|
require_relative "helpers/version_manager"
|
|
|
|
case version_bump
|
|
when "major", "minor", "patch"
|
|
# VersionManager doesn't handle semantic versions, use npm
|
|
sh("cd .. && npm version #{version_bump} --no-git-tag-version")
|
|
UI.success("✅ Bumped #{version_bump} version")
|
|
|
|
# Sync the new version to iOS project files
|
|
sync_version
|
|
UI.success("✅ Synced MARKETING_VERSION to iOS project")
|
|
when "build"
|
|
# Build number is handled in prepare_ios_build
|
|
UI.message("📦 Build number will be incremented during build")
|
|
end
|
|
end
|
|
|
|
# Prepare and build
|
|
result = prepare_ios_build(prod_release: deployment_track == "production")
|
|
|
|
# Handle deployment based on track
|
|
if test_mode
|
|
UI.important("🧪 TEST MODE: Skipping App Store upload")
|
|
UI.success("✅ Build completed successfully!")
|
|
elsif deployment_track == "internal"
|
|
upload_to_testflight(
|
|
api_key: result[:api_key],
|
|
distribute_external: false,
|
|
skip_waiting_for_build_processing: false,
|
|
) if result[:should_upload]
|
|
elsif deployment_track == "production"
|
|
# For production, upload to TestFlight first, then promote
|
|
upload_to_testflight(
|
|
api_key: result[:api_key],
|
|
distribute_external: false,
|
|
skip_waiting_for_build_processing: true,
|
|
) if result[:should_upload]
|
|
|
|
# TODO: Add app store submission when ready
|
|
UI.important("⚠️ Production deployment uploaded to TestFlight. Manual App Store submission required.")
|
|
end
|
|
|
|
# Update deployment info
|
|
if result[:should_upload] && !test_mode
|
|
Fastlane::Helpers.update_deployment_timestamp("ios")
|
|
end
|
|
|
|
# Slack notification
|
|
if ENV["SLACK_CHANNEL_ID"] && !test_mode
|
|
deploy_source = Fastlane::Helpers.is_ci_environment? ? "GitHub Actions (Auto)" : "Local Deploy"
|
|
track_emoji = deployment_track == "production" ? "🚀" : "🧪"
|
|
|
|
Fastlane::Helpers.upload_file_to_slack(
|
|
file_path: result[:ipa_path],
|
|
channel_id: ENV["SLACK_CHANNEL_ID"],
|
|
initial_comment: "#{track_emoji} iOS v#{package_version} (Build #{result[:build_number]}) deployed to #{deployment_track} via #{deploy_source}",
|
|
title: "#{APP_NAME}-#{package_version}-#{result[:build_number]}.ipa",
|
|
)
|
|
end
|
|
end
|
|
|
|
private_lane :prepare_ios_build do |options|
|
|
if local_development
|
|
# app breaks with Xcode 16.3
|
|
xcode_select "/Applications/Xcode.app"
|
|
|
|
# Set up API key, profile, and potentially certificate for local dev
|
|
Fastlane::Helpers.ios_dev_setup_connect_api_key(ios_connect_api_key_path)
|
|
Fastlane::Helpers.ios_dev_setup_provisioning_profile(ios_provisioning_profile_directory)
|
|
Fastlane::Helpers.ios_dev_setup_certificate
|
|
else
|
|
# we need this for building ios apps in CI
|
|
# else build will hang on "[CP] Embed Pods Frameworks"
|
|
setup_ci(
|
|
keychain_name: "build.keychain",
|
|
)
|
|
end
|
|
|
|
required_env_vars = [
|
|
"IOS_APP_IDENTIFIER",
|
|
"IOS_CONNECT_API_KEY_BASE64",
|
|
"IOS_CONNECT_API_KEY_PATH",
|
|
"IOS_CONNECT_ISSUER_ID",
|
|
"IOS_CONNECT_KEY_ID",
|
|
"IOS_PROJECT_NAME",
|
|
"IOS_PROJECT_SCHEME",
|
|
"IOS_PROV_PROFILE_NAME",
|
|
"IOS_PROV_PROFILE_PATH",
|
|
"IOS_TEAM_ID",
|
|
"IOS_TEAM_NAME",
|
|
]
|
|
|
|
target_platform = options[:prod_release] ? "App Store" : "TestFlight"
|
|
should_upload = Fastlane::Helpers.should_upload_app(target_platform)
|
|
workspace_path = File.expand_path("../ios/#{PROJECT_NAME}.xcworkspace", Dir.pwd)
|
|
ios_signing_certificate_name = "iPhone Distribution: #{ENV["IOS_TEAM_NAME"]} (#{ENV["IOS_TEAM_ID"]})"
|
|
|
|
Fastlane::Helpers.verify_env_vars(required_env_vars)
|
|
|
|
# Get build number from version.json and increment it
|
|
build_number = Fastlane::Helpers.bump_ios_build_number
|
|
|
|
# Update Xcode project with new build number
|
|
increment_build_number(
|
|
build_number: build_number,
|
|
xcodeproj: "ios/#{ENV["IOS_PROJECT_NAME"]}.xcodeproj",
|
|
)
|
|
|
|
# Verify build number is higher than TestFlight
|
|
Fastlane::Helpers.ios_verify_app_store_build_number(ios_xcode_profile_path)
|
|
Fastlane::Helpers.ios_verify_provisioning_profile
|
|
|
|
api_key = app_store_connect_api_key(
|
|
key_id: ENV["IOS_CONNECT_KEY_ID"],
|
|
issuer_id: ENV["IOS_CONNECT_ISSUER_ID"],
|
|
key_filepath: ENV["IOS_CONNECT_API_KEY_PATH"],
|
|
in_house: false,
|
|
)
|
|
|
|
# Update project to use manual code signing
|
|
update_code_signing_settings(
|
|
use_automatic_signing: false,
|
|
path: "ios/#{PROJECT_NAME}.xcodeproj",
|
|
team_id: ENV["IOS_TEAM_ID"],
|
|
targets: [PROJECT_NAME],
|
|
code_sign_identity: ios_signing_certificate_name,
|
|
profile_name: ENV["IOS_PROV_PROFILE_NAME"],
|
|
bundle_identifier: ENV["IOS_APP_IDENTIFIER"],
|
|
build_configurations: ["Release"],
|
|
)
|
|
|
|
clear_derived_data
|
|
|
|
# Print final build settings before archiving
|
|
sh "xcodebuild -showBuildSettings -workspace #{workspace_path} " \
|
|
"-scheme #{PROJECT_SCHEME} -configuration Release " \
|
|
"| grep 'CODE_SIGN_STYLE\|PROVISIONING_PROFILE_SPECIFIER\|CODE_SIGN_IDENTITY\|DEVELOPMENT_TEAM' || true"
|
|
|
|
cocoapods(
|
|
podfile: "ios/Podfile",
|
|
clean_install: true,
|
|
deployment: true,
|
|
)
|
|
|
|
ipa_path = build_app({
|
|
workspace: "#{workspace_path}",
|
|
scheme: PROJECT_SCHEME,
|
|
export_method: "app-store",
|
|
output_directory: "build",
|
|
clean: true,
|
|
export_options: {
|
|
method: "app-store",
|
|
signingStyle: "manual",
|
|
provisioningProfiles: {
|
|
ENV["IOS_APP_IDENTIFIER"] => ENV["IOS_PROV_PROFILE_NAME"],
|
|
},
|
|
signingCertificate: ios_signing_certificate_name,
|
|
teamID: ENV["IOS_TEAM_ID"],
|
|
},
|
|
})
|
|
|
|
{
|
|
api_key: api_key,
|
|
build_number: build_number,
|
|
ipa_path: ipa_path,
|
|
should_upload: should_upload,
|
|
}
|
|
end
|
|
end
|
|
|
|
platform :android do
|
|
desc "Sync android version"
|
|
lane :sync_version do
|
|
android_set_version_name(
|
|
version_name: package_version,
|
|
gradle_file: android_gradle_file_path.gsub("../", ""),
|
|
)
|
|
end
|
|
|
|
desc "Push a new build to Google Play Internal Testing"
|
|
lane :internal_test do |options|
|
|
upload_android_build(track: "internal", test_mode: options[:test_mode])
|
|
end
|
|
|
|
desc "Push a new build to Google Play Store"
|
|
lane :deploy do
|
|
upload_android_build(track: "production")
|
|
end
|
|
|
|
desc "Build Android app without uploading"
|
|
lane :build_only do |options|
|
|
deployment_track = options[:deployment_track] || "internal"
|
|
version_bump = options[:version_bump] || "build"
|
|
|
|
UI.message("🔨 Building Android app (build only)")
|
|
UI.message(" Track: #{deployment_track}")
|
|
UI.message(" Version bump: #{version_bump}")
|
|
|
|
upload_android_build(options.merge(skip_upload: true))
|
|
end
|
|
|
|
desc "Deploy Android app with automatic version management"
|
|
lane :deploy_auto do |options|
|
|
deployment_track = options[:deployment_track] || "internal"
|
|
version_bump = options[:version_bump] || "build"
|
|
test_mode = options[:test_mode] == true || options[:test_mode] == "true"
|
|
|
|
UI.message("🚀 Starting Android deployment")
|
|
UI.message(" Track: #{deployment_track}")
|
|
UI.message(" Version bump: #{version_bump}")
|
|
UI.message(" Test mode: #{test_mode}")
|
|
|
|
# Handle version bumping
|
|
if !test_mode
|
|
require_relative "helpers/version_manager"
|
|
|
|
case version_bump
|
|
when "major", "minor", "patch"
|
|
# For semantic version bumps, we need to use npm version
|
|
sh("cd .. && npm version #{version_bump} --no-git-tag-version")
|
|
UI.success("✅ Bumped #{version_bump} version")
|
|
# Get the new version and sync to build.gradle
|
|
new_version = Fastlane::Helpers::VersionManager.get_current_version
|
|
android_set_version_name(
|
|
version_name: new_version,
|
|
gradle_file: android_gradle_file_path.gsub("../", ""),
|
|
)
|
|
when "build"
|
|
# Build number is automatically incremented during build
|
|
UI.message("📦 Build number will be incremented")
|
|
end
|
|
end
|
|
|
|
# Map deployment track to Play Store track
|
|
play_store_track = deployment_track == "production" ? "production" : "internal"
|
|
|
|
# Build and deploy
|
|
upload_android_build(track: play_store_track, test_mode: test_mode, deployment_track: deployment_track)
|
|
end
|
|
|
|
private_lane :upload_android_build do |options|
|
|
test_mode = options[:test_mode] == true || options[:test_mode] == "true"
|
|
skip_upload = options[:skip_upload] == true || options[:skip_upload] == "true"
|
|
if local_development
|
|
if ENV["ANDROID_KEYSTORE_PATH"].nil?
|
|
ENV["ANDROID_KEYSTORE_PATH"] = Fastlane::Helpers.android_create_keystore(android_keystore_path)
|
|
end
|
|
|
|
if ENV["ANDROID_PLAY_STORE_JSON_KEY_PATH"].nil?
|
|
ENV["ANDROID_PLAY_STORE_JSON_KEY_PATH"] = Fastlane::Helpers.android_create_play_store_key(android_play_store_json_key_path)
|
|
end
|
|
end
|
|
|
|
required_env_vars = [
|
|
"ANDROID_KEYSTORE",
|
|
"ANDROID_KEYSTORE_PASSWORD",
|
|
"ANDROID_KEYSTORE_PATH",
|
|
"ANDROID_KEY_ALIAS",
|
|
"ANDROID_KEY_PASSWORD",
|
|
"ANDROID_PACKAGE_NAME",
|
|
]
|
|
# Only require JSON key path when not running in CI (local development)
|
|
required_env_vars << "ANDROID_PLAY_STORE_JSON_KEY_PATH" if local_development
|
|
|
|
Fastlane::Helpers.verify_env_vars(required_env_vars)
|
|
|
|
# Get version code from version.json and increment it
|
|
version_code = Fastlane::Helpers.bump_android_build_number
|
|
|
|
# Update build.gradle with new version code
|
|
increment_version_code(
|
|
version_code: version_code,
|
|
gradle_file_path: android_gradle_file_path.gsub("../", ""),
|
|
)
|
|
|
|
# TODO: uncomment when we have the permissions to run this action
|
|
# Fastlane::Helpers.android_verify_version_code(android_gradle_file_path)
|
|
|
|
target_platform = options[:track] == "production" ? "Google Play" : "Internal Testing"
|
|
should_upload = Fastlane::Helpers.should_upload_app(target_platform)
|
|
|
|
# Validate JSON key only in local development; CI uses Workload Identity Federation (ADC)
|
|
if local_development
|
|
validate_play_store_json_key(
|
|
json_key: ENV["ANDROID_PLAY_STORE_JSON_KEY_PATH"],
|
|
)
|
|
end
|
|
|
|
Fastlane::Helpers.with_retry(max_retries: 3, delay: 10) do
|
|
gradle(
|
|
task: "clean bundleRelease --stacktrace --info",
|
|
project_dir: "android/",
|
|
properties: {
|
|
"MYAPP_UPLOAD_STORE_FILE" => ENV["ANDROID_KEYSTORE_PATH"],
|
|
"MYAPP_UPLOAD_STORE_PASSWORD" => ENV["ANDROID_KEYSTORE_PASSWORD"],
|
|
"MYAPP_UPLOAD_KEY_ALIAS" => ENV["ANDROID_KEY_ALIAS"],
|
|
"MYAPP_UPLOAD_KEY_PASSWORD" => ENV["ANDROID_KEY_PASSWORD"] == "EMPTY" ? "" : ENV["ANDROID_KEY_PASSWORD"],
|
|
},
|
|
)
|
|
end
|
|
|
|
if test_mode || skip_upload
|
|
if skip_upload
|
|
UI.important("🔨 BUILD ONLY: Skipping Play Store upload")
|
|
else
|
|
UI.important("🧪 TEST MODE: Skipping Play Store upload")
|
|
end
|
|
UI.success("✅ Build completed successfully!")
|
|
UI.message("📦 AAB path: #{android_aab_path}")
|
|
else
|
|
if should_upload
|
|
begin
|
|
upload_options = {
|
|
track: options[:track],
|
|
package_name: ENV["ANDROID_PACKAGE_NAME"],
|
|
skip_upload_changelogs: true,
|
|
skip_upload_images: true,
|
|
skip_upload_screenshots: true,
|
|
track_promote_release_status: "completed",
|
|
aab: android_aab_path,
|
|
}
|
|
# In local development, use the JSON key file; in CI rely on ADC
|
|
if local_development
|
|
upload_options[:json_key] = ENV["ANDROID_PLAY_STORE_JSON_KEY_PATH"]
|
|
else
|
|
# In CI, try to use ADC credentials file directly
|
|
adc_creds_path = ENV["GOOGLE_APPLICATION_CREDENTIALS"]
|
|
if adc_creds_path && File.exist?(adc_creds_path)
|
|
UI.message("🔑 Using ADC credentials file: #{adc_creds_path}")
|
|
begin
|
|
# Try passing the credentials file content as json_key_data
|
|
creds_content = File.read(adc_creds_path)
|
|
upload_options[:json_key_data] = creds_content
|
|
rescue => e
|
|
UI.error("Failed to read ADC credentials: #{e.message}")
|
|
# Fallback: let supply try to use ADC automatically
|
|
UI.message("🔄 Falling back to automatic ADC detection")
|
|
end
|
|
else
|
|
UI.error("❌ ADC credentials not found at: #{adc_creds_path}")
|
|
end
|
|
end
|
|
|
|
upload_to_play_store(upload_options)
|
|
rescue => e
|
|
if e.message.include?("forbidden") || e.message.include?("403") || e.message.include?("insufficientPermissions")
|
|
UI.error("❌ Play Store upload failed: Insufficient permissions")
|
|
UI.error("Please fix permissions in Google Play Console")
|
|
UI.important("Build saved at: #{android_aab_path}")
|
|
else
|
|
# Re-raise if it's a different error
|
|
raise e
|
|
end
|
|
end
|
|
else
|
|
UI.message("Skipping Play Store upload (should_upload: false)")
|
|
end
|
|
end
|
|
|
|
# Update deployment timestamp in version.json
|
|
if should_upload
|
|
Fastlane::Helpers.update_deployment_timestamp("android")
|
|
end
|
|
|
|
# Notify Slack about the new build
|
|
if ENV["SLACK_CHANNEL_ID"] && !test_mode
|
|
deploy_source = Fastlane::Helpers.is_ci_environment? ? "GitHub Actions (Auto)" : "Local Deploy"
|
|
deployment_track = options[:deployment_track] || options[:track]
|
|
track_emoji = deployment_track == "production" ? "🚀" : "🧪"
|
|
|
|
Fastlane::Helpers.upload_file_to_slack(
|
|
file_path: android_aab_path,
|
|
channel_id: ENV["SLACK_CHANNEL_ID"],
|
|
initial_comment: "#{track_emoji} Android v#{package_version} (Build #{version_code}) deployed to #{deployment_track || target_platform} via #{deploy_source}",
|
|
title: "#{APP_NAME}-#{package_version}-#{version_code}.aab",
|
|
)
|
|
elsif test_mode
|
|
UI.important("🧪 TEST MODE: Skipping Slack notification")
|
|
else
|
|
UI.important("Skipping Slack notification: SLACK_CHANNEL_ID not set.")
|
|
end
|
|
end
|
|
end
|