mattermost-mobile/fastlane/Fastfile
Saturnino Abril f05faaa949
E2E: Initial Detox setup for Mobile UI automation (#4535)
* initial Detox setup for mobile UI automation

* fix iOS allow permission on opening the app, add npm script to root folder, fix test when using longer site URL and add detox dependency to root for android build dependency

* remove detox proguardFile

* update packages and emulator

* change folder build on local and CI

* add test to post a message, ability to have test in isolation, server API commands, server config, dependency updates and update folder structure

* update snapshot

* update detox and do clean up

* update dependencies
2020-08-29 07:18:41 +08:00

921 lines
31 KiB
Ruby

fastlane_version '2.71.0'
fastlane_require 'aws-sdk-s3'
fastlane_require 'erb'
fastlane_require 'json'
fastlane_require 'pathname'
skip_docs
configured = false
is_build_pr = false
# Executes before anything else use to setup the script
before_all do
is_build_pr = ENV['BUILD_PR'] == 'true'
if is_build_pr && ENV['CIRCLECI'] == 'true'
ENV['BRANCH_TO_BUILD'] = ENV['CIRCLE_BRANCH']
end
if ENV['CIRCLECI'] != 'true'
# Raises an error is git is not clean
if ENV['COMMIT_CHANGES_TO_GIT'] == 'true'
ensure_git_status_clean
end
# Block to ensure we are on the right branch
branch = ENV['BRANCH_TO_BUILD'] || ENV['GIT_BRANCH']
begin
ensure_git_branch(
branch: branch
)
rescue
sh "git checkout #{branch}"
UI.success("Using branch \"#{branch}\"")
end
# If we are going to commit changes to git create a separate branch
# so no changes are done in the branch that is being built
if ENV['COMMIT_CHANGES_TO_GIT'] == 'true'
local_branch = ENV['GIT_LOCAL_BRANCH'] || 'build'
sh "git checkout -b #{local_branch}"
UI.success("Creating branch \"#{local_branch}\"")
end
end
end
after_all do |lane|
if ENV['CIRCLECI'] != 'true'
if lane.to_s == 'build'
submit_to_store
end
if ENV['RESET_GIT_BRANCH'] == 'true'
branch = ENV['BRANCH_TO_BUILD'] || 'master'
package_id = ENV['MAIN_APP_IDENTIFIER'] || 'com.mattermost.rnbeta'
beta_dir = '../android/app/src/main/java/com/mattermost/rnbeta'
release_dir = "../android/app/src/main/java/#{package_id.gsub '.', '/'}"
if beta_dir != release_dir
sh "rm -rf #{release_dir}"
end
reset_git_repo(
force: true,
skip_clean: true
)
sh "git checkout #{branch}"
if ENV['COMMIT_CHANGES_TO_GIT'] == 'true'
local_branch = ENV['GIT_LOCAL_BRANCH'] || 'build'
sh "git branch -D #{local_branch}"
UI.success("Deleted working branch \"#{local_branch}\"")
if lane.to_s == 'build_pr'
sh 'git checkout master'
## Remove the branch for the PR
sh "git branch -D #{branch}"
UI.success("Deleted PR branch \"#{branch}\"")
end
end
end
end
end
desc 'Increment version number for both Android and iOS'
lane :set_app_version do
version_number = ENV['VERSION_NUMBER']
unless version_number.nil? || version_number.empty?
package = load_config_json('../package.json')
package['version'] = version_number
save_config_json('../package.json', package)
lock = load_config_json('../package-lock.json')
lock['version'] = version_number
save_config_json('../package-lock.json', lock)
android_set_version_name(
gradle_file: './android/app/build.gradle',
version_name: version_number
)
increment_version_number(
xcodeproj: './ios/Mattermost.xcodeproj',
version_number: version_number
)
if ENV['COMMIT_CHANGES_TO_GIT'] == 'true'
msg = ENV['INCREMENT_VERSION_NUMBER_MESSAGE'] || 'Bump app version number to '
commit_message = "#{msg} #{version_number.to_s}"
build_folder_path = Dir[File.expand_path('..')].first
repo_path = (sh "git -C #{build_folder_path} rev-parse --show-toplevel").strip
git_dirty_files = (sh "git -C #{repo_path} diff --name-only HEAD").split(" ").join(' ')
unless git_dirty_files.empty?
sh "git -C #{repo_path} commit -m \"#{commit_message}\" #{git_dirty_files}"
UI.success("Successfully committed \"#{git_dirty_files}\" 💾.")
end
end
end
end
desc 'Increments the build number for both Android and iOS'
lane :set_app_build_number do
## set the build number for both platforms
# use the one for iOS if no env variable set
if ENV['INCREMENT_BUILD_NUMBER'] === 'true'
build_number = ENV['BUILD_NUMBER'] || (get_build_number(xcodeproj: './ios/Mattermost.xcodeproj').to_i + 1)
increment_build_number(
xcodeproj: './ios/Mattermost.xcodeproj',
build_number: build_number
)
android_set_version_code(
gradle_file: './android/app/build.gradle',
version_code: build_number
)
if ENV['COMMIT_CHANGES_TO_GIT'] == 'true'
msg = ENV['INCREMENT_BUILD_NUMBER_MESSAGE'] || 'Bump app build number to '
commit_message = "#{msg} #{build_number.to_s}"
build_folder_path = Dir[File.expand_path('..')].first
repo_path = (sh "git -C #{build_folder_path} rev-parse --show-toplevel").strip
git_dirty_files = (sh "git -C #{repo_path} diff --name-only HEAD").split(" ").join(' ')
unless git_dirty_files.empty?
sh "git -C #{repo_path} commit -m \"#{commit_message}\" #{git_dirty_files}"
UI.success("Successfully committed \"#{git_dirty_files}\" 💾.")
end
end
end
end
desc 'Configure the app before building'
lane :configure do
json = load_config_json('../dist/assets/config.json')
# Set the Segment API Key
unless ENV['RUDDER_API_KEY'].nil? || ENV['RUDDER_API_KEY'].empty?
json['RudderApiKey'] = ENV['RUDDER_API_KEY']
end
# Configure Sentry if enabled
if ENV['SENTRY_ENABLED'] == 'true'
json['SentryEnabled'] = true
json['SentryOrg'] = ENV['SENTRY_ORG']
json['SentryProjectIos'] = ENV['SENTRY_PROJECT_IOS']
json['SentryProjectAndroid'] = ENV['SENTRY_PROJECT_ANDROID']
json['SentryDsnIos'] = ENV['SENTRY_DSN_IOS']
json['SentryDsnAndroid'] = ENV['SENTRY_DSN_ANDROID']
end
# Save the config.json file
save_config_json('../dist/assets/config.json', json)
configured = true
end
desc 'Build the app for Android and iOS'
lane :build do |options|
configure
set_app_version
set_app_build_number
# Build the android app
self.runner.current_platform = :android
build
# Build the ios app
self.runner.current_platform = :ios
build
end
desc 'Upload file to s3'
lane :upload_file_to_s3 do |options|
os_type = options[:os_type]
file = options[:file]
file_plist = ""
if file.nil? || file.empty?
app_name = ENV['APP_NAME'] || 'Mattermost Beta'
filename = app_name.gsub(" ", "_")
if os_type == 'Android'
file = "#{filename}.apk"
elsif os_type == 'iOS'
file = "#{filename}.ipa"
file_plist = "#{filename}.plist"
end
end
build_folder_path = Dir[File.expand_path('..')].first
file_path = "#{build_folder_path}/#{file}"
unless ENV['AWS_BUCKET_NAME'].nil? || ENV['AWS_BUCKET_NAME'].empty? || ENV['AWS_REGION'].nil? || ENV['AWS_REGION'].empty? || file_path.nil?
s3_region = ENV['AWS_REGION']
s3_bucket = ENV['AWS_BUCKET_NAME']
s3_folder = ''
version_number = ''
build_number = ''
if is_build_pr
s3_folder = "#{ENV['AWS_FOLDER_NAME']}/#{ENV['BRANCH_TO_BUILD']}"
else
if os_type == 'Android'
version_number = android_get_version_name(gradle_file: './android/app/build.gradle')
build_number = android_get_version_code(gradle_file: './android/app/build.gradle')
elsif os_type == 'iOS'
version_number = get_version_number(xcodeproj: './ios/Mattermost.xcodeproj', target: 'Mattermost')
build_number = get_build_number(xcodeproj: './ios/Mattermost.xcodeproj')
end
s3_folder = "#{ENV['AWS_FOLDER_NAME']}/#{version_number}/#{build_number}"
end
s3 = Aws::S3::Resource.new(region: s3_region)
file_obj = s3.bucket(s3_bucket).object("#{s3_folder}/#{file}")
file_obj.upload_file("#{file_path}")
if is_build_pr
if os_type == 'Android'
install_url = "https://#{s3_bucket}/#{s3_folder}/#{file}"
elsif os_type == 'iOS'
current_build_number = get_build_number(xcodeproj: './ios/Mattermost.xcodeproj')
plist_template = File.read('plist.erb')
plist_body = ERB.new(plist_template).result(binding)
plist_obj = s3.bucket(s3_bucket).object("#{s3_folder}/#{file_plist}")
plist_obj.put(body: plist_body)
install_url = "itms-services://?action=download-manifest&url=https://#{s3_bucket}/#{s3_folder}/#{file_plist}"
end
qa_build_message({
:os_type => os_type,
:install_url => install_url
})
end
public_link = "https://#{s3_bucket}/#{s3_folder}/#{file}"
if file == 'Mattermost-simulator-x86_64.app.zip'
pretext = '#### New iOS build for VM/Simulator'
msg = "Download link: #{public_link}"
send_message_to_mattermost({
:version_number => version_number,
:build_number => build_number,
:pretext => pretext,
:title => '',
:thumb_url => 'https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iOS/move-to-ios-icon.png',
:msg => msg,
:default_payloads => [],
:success => true,
})
end
UI.success("S3 bucket @#{s3_bucket}, object @#{s3_folder}/#{file}")
UI.success("S3 public path: #{public_link}")
end
end
desc 'Create GitHub release'
lane :github do
tag = ENV['CIRCLE_TAG'] || ENV['TAG']
if tag
version = android_get_version_name(gradle_file: './android/app/build.gradle')
build = android_get_version_code(gradle_file: './android/app/build.gradle')
changelog = File.read("metadata/changelog")
changelog.concat("* Android [Mattermost.apk](https://releases.mattermost.com/mattermost-mobile/#{version}/#{build}/Mattermost.apk)\n")
changelog.concat("* iOS [Mattermost.ipa](https://releases.mattermost.com/mattermost-mobile/#{version}/#{build}/Mattermost.ipa)")
github_release = set_github_release(
repository_name: "mattermost/mattermost-mobile",
api_token: ENV["GITHUB_TOKEN"],
name: "Mobile Version #{version}",
tag_name: tag,
description: changelog,
upload_assets: ["./Mattermost-unsigned.ipa", "./Mattermost-unsigned.apk"],
is_draft: true
)
end
end
platform :ios do
before_all do
if ENV['CIRCLECI'] == 'true'
setup_circle_ci
end
end
desc 'Get iOS adhoc profiles'
lane :adhoc do
if ENV['MATCH_TYPE'] != 'adhoc' && !ENV['MATCH_PASSWORD'].nil? && !ENV['MATCH_PASSWORD'].empty?
match(
type: 'adhoc'
)
end
end
desc 'Build iOS app'
lane :build do
unless configured
configure
end
update_identifiers
replace_assets
build_ios
upload_file_to_s3({:os_type => "iOS"})
end
desc 'Build an unsigned ipa'
lane :unsigned do
UI.success('Building unsigned iOS app')
ENV['APP_NAME'] = 'Mattermost'
ENV['REPLACE_ASSETS'] = 'true'
ENV['BUILD_FOR_RELEASE'] = 'true'
ENV['APP_SCHEME'] = 'mattermost-mobile'
update_identifiers
replace_assets
sh 'mkdir -p ../build-ios'
sh 'cd ../ios/ && xcodebuild -workspace Mattermost.xcworkspace/ -scheme Mattermost -sdk iphoneos -configuration Release -parallelizeTargets -resultBundlePath ../build-ios/result -derivedDataPath ../build-ios/ CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO'
sh 'cd ../build-ios/ && mkdir -p Payload && cp -R Build/Products/Release-iphoneos/Mattermost.app Payload/ && zip -r Mattermost-unsigned.ipa Payload/'
sh 'mv ../build-ios/Mattermost-unsigned.ipa ../'
sh 'rm -rf ../build-ios/'
end
lane :simulator do
UI.success('Building iOS app for simulator')
ENV['APP_NAME'] = 'Mattermost'
ENV['REPLACE_ASSETS'] = 'true'
ENV['BUILD_FOR_RELEASE'] = 'true'
ENV['APP_SCHEME'] = 'mattermost-mobile'
update_identifiers
replace_assets
sh 'cd ../ios && xcodebuild -workspace Mattermost.xcworkspace -scheme Mattermost -arch x86_64 -sdk iphonesimulator -configuration Release -parallelizeTargets -derivedDataPath ../build-ios ENABLE_BITCODE=NO CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ENABLE_BITCODE=NO'
data_path = 'ios'
if ENV['CIRCLECI'] == 'true'
data_path = 'build-ios'
end
sh "cd ../#{data_path}/Build/Products/Release-iphonesimulator && zip -r Mattermost-simulator-x86_64.app.zip Mattermost.app"
sh "mv ../#{data_path}/Build/Products/Release-iphonesimulator/Mattermost-simulator-x86_64.app.zip ../"
upload_file_to_s3({
:os_type => "iOS",
:file => "Mattermost-simulator-x86_64.app.zip"
})
end
lane :update_identifiers do
# Set the name for the app
app_name = ENV['APP_NAME'] || 'Mattermost Beta'
update_info_plist(
xcodeproj: './ios/Mattermost.xcodeproj',
plist_path: 'Mattermost/Info.plist',
display_name: app_name
)
# Set the notification service extension bundle identifier
notification_bundle_id = ENV['NOTIFICATION_SERVICE_IDENTIFIER'] || 'com.mattermost.rnbeta.NotificationService'
update_app_identifier(
xcodeproj: './ios/Mattermost.xcodeproj',
plist_path: 'NotificationService/Info.plist',
app_identifier: notification_bundle_id
)
find_replace_string(
path_to_file: './ios/Mattermost.xcodeproj/project.pbxproj',
old_string: 'com.mattermost.rnbeta.NotificationService',
new_string: notification_bundle_id
)
# Set the share extension bundle identifier
extension_bundle_id = ENV['EXTENSION_APP_IDENTIFIER'] || 'com.mattermost.rnbeta.MattermostShare'
update_app_identifier(
xcodeproj: './ios/Mattermost.xcodeproj',
plist_path: 'MattermostShare/Info.plist',
app_identifier: extension_bundle_id
)
find_replace_string(
path_to_file: './ios/Mattermost.xcodeproj/project.pbxproj',
old_string: 'com.mattermost.rnbeta.MattermostShare',
new_string: extension_bundle_id
)
# Set the app bundle id
app_bundle_id = ENV['MAIN_APP_IDENTIFIER'] || 'com.mattermost.rnbeta'
update_app_identifier(
xcodeproj: './ios/Mattermost.xcodeproj',
plist_path: 'Mattermost/Info.plist',
app_identifier: app_bundle_id
)
find_replace_string(
path_to_file: './ios/Mattermost.xcodeproj/project.pbxproj',
old_string: 'com.mattermost.rnbeta',
new_string: app_bundle_id
)
# Set the deep link prefix
app_scheme = ENV['APP_SCHEME'] || 'mattermost'
update_info_plist(
xcodeproj: './ios/Mattermost.xcodeproj',
plist_path: 'Mattermost/Info.plist',
block: proc do |plist|
urlScheme = plist["CFBundleURLTypes"].find{|scheme| scheme["CFBundleURLName"] == "com.mattermost"}
urlScheme[:CFBundleURLSchemes] = [app_scheme]
end
)
# If set update the development team
unless ENV['FASTLANE_TEAM_ID'].nil? || ENV['FASTLANE_TEAM_ID'].empty?
update_project_team(
path: './ios/Mattermost.xcodeproj',
teamid: ENV['FASTLANE_TEAM_ID']
)
end
# Set the ICloud container
icloud_container = ENV['IOS_ICLOUD_CONTAINER'] || 'iCloud.com.mattermost.rnbeta'
update_icloud_container_identifiers(
entitlements_file: './ios/Mattermost/Mattermost.entitlements',
icloud_container_identifiers: [icloud_container]
)
# Set the app group id to share data between the app and the extension
app_group_id = ENV['IOS_APP_GROUP'] || 'group.com.mattermost.rnbeta'
update_app_group_identifiers(
entitlements_file: './ios/Mattermost/Mattermost.entitlements',
app_group_identifiers: [app_group_id]
)
find_replace_string(
path_to_file: './ios/UploadAttachments/UploadAttachments/MMMConstants.m',
old_string: 'group.com.mattermost.rnbeta',
new_string: app_group_id
)
find_replace_string(
path_to_file: './node_modules/react-native-mmkv-storage/ios/MMKVStorage.m',
old_string: 'group.com.mattermost.rnbeta',
new_string: app_group_id
)
update_app_group_identifiers(
entitlements_file: './ios/MattermostShare/MattermostShare.entitlements',
app_group_identifiers: [app_group_id]
)
update_app_group_identifiers(
entitlements_file: './ios/NotificationService/NotificationService.entitlements',
app_group_identifiers: [app_group_id]
)
# Sync the provisioning profiles using match
if ENV['SYNC_PROVISIONING_PROFILES'] == 'true' && !ENV['MATCH_PASSWORD'].nil? && !ENV['MATCH_PASSWORD'].empty?
match(type: ENV['MATCH_TYPE'] || 'adhoc')
end
end
lane :replace_assets do
if ENV['REPLACE_ASSETS'] == 'true'
sh 'cp -R ../dist/assets/release/icons/ios/* ../ios/Mattermost/Images.xcassets/AppIcon.appiconset/'
sh 'cp -R ../dist/assets/release/splash_screen/ios/* ../ios/SplashScreenResource/'
end
end
lane :deploy do |options|
ipa_path = options[:file]
unless ipa_path.nil?
submit_to_testflight(ipa_path)
end
end
error do |lane, exception|
version = get_version_number(xcodeproj: './ios/Mattermost.xcodeproj', target: 'Mattermost')
build_number = get_build_number(xcodeproj: './ios/Mattermost.xcodeproj')
send_message_to_mattermost({
:version_number => version,
:build_number => build_number,
:pretext => '',
:title => 'Unsuccessful Build',
:thumb_url => 'https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iOS/move-to-ios-icon.png',
:msg => exception.message,
:default_payloads => [:lane],
:success => false
})
end
def setup_code_signing
update_code_signing_settings(
use_automatic_signing: false,
path: './ios/Mattermost.xcodeproj'
)
ENV['MATCH_APP_IDENTIFIER'].split(',').each do |id|
target = 'Mattermost'
if id.include? 'NotificationService'
target = 'NotificationService'
elsif id.include? 'MattermostShare'
target = 'MattermostShare'
end
profile = "sigh_#{id}_#{ENV['MATCH_TYPE']}"
config_mode = ENV['BUILD_FOR_RELEASE'] == 'true' ? 'Release' : 'Debug'
update_project_provisioning(
xcodeproj: './ios/Mattermost.xcodeproj',
profile: ENV["#{profile}_profile-path"], # optional if you use sigh
target_filter: ".*#{target}$", # matches name or type of a target
build_configuration: config_mode,
code_signing_identity: 'iPhone Distribution' # optionally specify the codesigning identity
)
end
end
def build_ios
app_name = ENV['APP_NAME'] || 'Mattermost Beta'
app_name_sub = app_name.gsub(" ", "_")
config_mode = ENV['BUILD_FOR_RELEASE'] == 'true' ? 'Release' : 'Debug'
method = ENV['IOS_BUILD_EXPORT_METHOD'].nil? || ENV['IOS_BUILD_EXPORT_METHOD'].empty? ? 'ad-hoc' : ENV['IOS_BUILD_EXPORT_METHOD']
setup_code_signing
gym(
clean: true,
scheme: 'Mattermost',
configuration: config_mode,
workspace: './ios/Mattermost.xcworkspace',
export_method: method,
skip_profile_detection: true,
output_name: "#{app_name_sub}.ipa",
export_xcargs: "-allowProvisioningUpdates",
export_options: {
signingStyle: 'manual',
iCloudContainerEnvironment: 'Production'
}
)
end
end
platform :android do
desc 'Build Android app'
lane :build do
unless configured
configure
end
configure_telemetry_android
update_identifiers
replace_assets
link_sentry_android
build_android
move_apk_to_root
upload_file_to_s3({:os_type => "Android"})
end
desc 'Build an unsigned apk'
lane :unsigned do
UI.success('Building unsigned Android app')
ENV['APP_NAME'] = 'Mattermost'
ENV['REPLACE_ASSETS'] = 'true'
ENV['BUILD_FOR_RELEASE'] = 'true'
ENV['APP_SCHEME'] = 'mattermost-mobile'
update_identifiers
replace_assets
gradle(
task: 'assemble',
build_type: 'Unsigned',
project_dir: 'android/'
)
sh "mv #{lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]} #{Pathname.new(File.expand_path(File.dirname(__FILE__))).parent.to_s}/Mattermost-unsigned.apk"
end
desc 'Update config and module/listener for Android telemetry'
lane :configure_telemetry_android do
if ENV['TELEMETRY_ENABLED'] == 'true' && ENV['TELEMETRY_URL'] != '' && ENV['TELEMETRY_API_KEY'] != ''
# Update telemetry config
json = load_config_json('../dist/assets/config.json')
json['TelemetryEnabled'] = true
json['TelemetryUrl'] = ENV['TELEMETRY_URL']
json['TelemetryApiKey'] = ENV['TELEMETRY_API_KEY']
save_config_json('../dist/assets/config.json', json)
beta_dir = './android/app/src/main/java/com/mattermost/rnbeta/'
# Listen to telemetry react markers
find_replace_string(
path_to_file: "#{beta_dir}MainApplication.java",
old_string: '// addReactMarkerListener();',
new_string: 'addReactMarkerListener();'
)
end
end
lane :update_identifiers do
# Set the name for the app
app_name = ENV['APP_NAME'] || 'Mattermost Beta'
sh "echo '#{app_name}' > ../fastlane/metadata/android/en-US/title.txt"
android_change_string_app_name(
newName: app_name,
stringsFile: './android/app/src/main/res/values/strings.xml'
)
package_id = ENV['MAIN_APP_IDENTIFIER'] || 'com.mattermost.rnbeta'
android_change_package_identifier(newIdentifier: package_id, manifest: './android/app/src/main/AndroidManifest.xml')
android_update_application_id(app_folder_name: 'android/app', application_id: package_id)
app_scheme = ENV['APP_SCHEME'] || 'mattermost'
find_replace_string(
path_to_file: "./android/app/src/main/AndroidManifest.xml",
old_string: 'scheme="mattermost"',
new_string: "scheme=\'#{app_scheme}\'"
)
beta_dir = './android/app/src/main/java/com/mattermost/rnbeta/'
release_dir = "./android/app/src/main/java/#{package_id.gsub '.', '/'}/"
if ENV['BUILD_FOR_RELEASE'] == 'true'
find_replace_string(
path_to_file: "#{beta_dir}MainApplication.java",
old_string: 'return BuildConfig.DEBUG;',
new_string: 'return false;'
)
end
if release_dir != beta_dir
unless Dir.exist?(".#{release_dir}")
FileUtils.mkdir_p ".#{release_dir}"
end
sh "mv .#{beta_dir}* .#{release_dir}"
find_replace_string(
path_to_file: './android/app/BUCK',
old_string: 'package com.mattermost.rnbeta;',
new_string: "package #{package_id};"
)
Dir.glob(".#{release_dir}*.java") do |item|
find_replace_string(
path_to_file: item[1..-1],
old_string: 'package com.mattermost.rnbeta;',
new_string: "package #{package_id};"
)
end
Dir.glob('../android/app/src/main/java/com/mattermost/share/*.java') do |item|
find_replace_string(
path_to_file: item[1..-1],
old_string: 'import com.mattermost.rnbeta.MainApplication;',
new_string: "import #{package_id}.MainApplication;"
)
end
end
end
lane :replace_assets do
if ENV['REPLACE_ASSETS'] == 'true'
sh 'cp -R ../dist/assets/release/icons/android/* ../android/app/src/main/res/'
sh 'cp -R ../dist/assets/release/splash_screen/android/* ../android/app/src/main/res/'
end
end
lane :deploy do |options|
apk_path = options[:file]
unless apk_path.nil?
submit_to_google_play(apk_path)
end
end
error do |lane, exception|
build_number = android_get_version_code(
gradle_file: './android/app/build.gradle'
)
version_number = android_get_version_name(
gradle_file: './android/app/build.gradle'
)
send_message_to_mattermost({
:version_number => version_number,
:build_number => build_number,
:pretext => '',
:title => 'Unsuccessful Build',
:thumb_url => 'https://lh3.ggpht.com/XL0CrI8skkxnboGct-duyg-bZ_MxJDTrjczyjdU8OP2PM1dmj7SP4jL1K8JQeMIB3AM=w300',
:msg => exception.message,
:default_payloads => [:lane],
:success => false,
})
end
def build_android
config_mode = ENV['BUILD_FOR_RELEASE'] == 'true' ? 'Release' : 'Debug'
gradle(
task: 'app:assemble',
build_type: config_mode,
project_dir: 'android/'
)
end
def move_apk_to_root
app_name = ENV['APP_NAME'] || 'Mattermost Beta'
app_name_sub = app_name.gsub(" ", "_")
new_apk_path = "#{Pathname.new(File.expand_path(File.dirname(__FILE__))).parent.to_s}/#{app_name_sub}.apk"
apk_path = lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]
unless apk_path.nil?
sh "mv #{apk_path} #{new_apk_path}"
lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH] = new_apk_path
end
end
def link_sentry_android
if ENV['SENTRY_ENABLED'] == 'true'
url = 'https://sentry.io'
File.open('../android/sentry.properties', 'w+') do |f|
UI.message('Creating sentry.properties from environment')
f.write(
"defaults.url=#{url}\n"\
"defaults.org=#{ENV['SENTRY_ORG']}\n"\
"defaults.project=#{ENV['SENTRY_PROJECT_ANDROID']}\n"\
"auth.token=#{ENV['SENTRY_AUTH_TOKEN']}\n"
)
end
else
UI.message('Not creating sentry.properties because Sentry is disabled')
end
end
end
def load_config_json(json_path)
config_file = File.read(json_path)
JSON.parse(config_file)
end
def save_config_json(json_path, json)
File.open(json_path, 'w') do |f|
f.write(JSON.pretty_generate(json))
f.write("\n")
end
end
def send_message_to_mattermost(options)
unless ENV['MATTERMOST_WEBHOOK_URL'].nil? || ENV['MATTERMOST_WEBHOOK_URL'].empty?
mattermost(
pretext: options[:pretext],
message: options[:msg],
default_payloads: options[:default_payloads],
username: 'Fastlane',
icon_url: 'https://mattermost-plugin-media.s3.amazonaws.com/fastlane.png',
payload: {},
attachment_properties: {
title: options[:title],
thumb_url: options[:thumb_url],
fields: [{
title: 'Version',
value: options[:version_number],
short: true
},
{
title: 'Build Number',
value: options[:build_number],
short: true
}]
},
success: options[:success]
)
end
end
def submit_to_testflight(ipa_path)
app_name = ENV['APP_NAME'] || 'Mattermost Beta'
app_name_sub = app_name.gsub(" ", "_")
if(File.file?(ipa_path))
UI.success("ipa file #{ipa_path}")
pilot(
ipa: ipa_path
)
else
UI.user_error! "ipa file does not exist #{ipa_path}"
return
end
version_number = get_version_number(xcodeproj: './ios/Mattermost.xcodeproj', target: 'Mattermost')
build_number = get_build_number(xcodeproj: './ios/Mattermost.xcodeproj')
s3_folder = "#{ENV['AWS_FOLDER_NAME']}/#{version_number}/#{build_number}"
public_link = "https://#{ENV['AWS_BUCKET_NAME']}/#{s3_folder}/#{app_name_sub}.ipa"
# Send a build message to Mattermost
pretext = '#### New iOS released ready to be published'
msg = "Release has been cut and is on TestFlight ready to be published.\nDownload link: #{public_link}"
if ENV['BETA_BUILD'] == 'true'
pretext = '#### New iOS beta published to TestFlight'
msg = "Sign up as a beta tester [here](https://testflight.apple.com/join/Q7Rx7K9P).\nDownload link: #{public_link}"
end
send_message_to_mattermost({
:version_number => version_number,
:build_number => build_number,
:pretext => pretext,
:title => '',
:thumb_url => 'https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iOS/move-to-ios-icon.png',
:msg => msg,
:default_payloads => [],
:success => true,
})
end
def submit_to_google_play(apk_path)
app_name = ENV['APP_NAME'] || 'Mattermost Beta'
app_name_sub = app_name.gsub(" ", "_")
if(File.file?(apk_path))
UI.success("apk file #{apk_path}")
unless ENV['SUPPLY_JSON_KEY'].nil? || ENV['SUPPLY_JSON_KEY'].empty?
supply(
track: ENV['SUPPLY_TRACK'] || 'alpha',
apk: apk_path
)
end
else
UI.user_error! "apk file does not exist #{apk_path}"
return
end
version_number = android_get_version_name(gradle_file: './android/app/build.gradle')
build_number = android_get_version_code(gradle_file: './android/app/build.gradle')
s3_folder = "#{ENV['AWS_FOLDER_NAME']}/#{version_number}/#{build_number}"
public_link = "https://#{ENV['AWS_BUCKET_NAME']}/#{s3_folder}/#{app_name_sub}.apk"
# Send a build message to Mattermost
pretext = '#### New Android released ready to be published'
msg = "Release has been cut and is on the Beta track ready to be published.\nDownload link: #{public_link}"
if ENV['BETA_BUILD'] == 'true'
pretext = '#### New Android beta published to Google Play'
msg = "Sign up as a beta tester [here](https://play.google.com/apps/testing/com.mattermost.rnbeta).\nDownload link: #{public_link}"
end
send_message_to_mattermost({
:version_number => version_number,
:build_number => build_number,
:pretext => pretext,
:title => '',
:thumb_url => 'https://lh3.ggpht.com/XL0CrI8skkxnboGct-duyg-bZ_MxJDTrjczyjdU8OP2PM1dmj7SP4jL1K8JQeMIB3AM=w300',
:msg => msg,
:default_payloads => [],
:success => true,
})
end
def submit_to_store
apk_path = lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]
ipa_path = lane_context[SharedValues::IPA_OUTPUT_PATH]
# Submit to Google Play if required
if !apk_path.nil? && ENV['SUBMIT_ANDROID_TO_GOOGLE_PLAY'] == 'true'
submit_to_google_play(apk_path)
end
# Submit to TestFlight if required
if !ipa_path.nil? && ENV['SUBMIT_IOS_TO_TESTFLIGHT'] == 'true'
submit_to_testflight(ipa_path)
end
end
def qa_build_message(options)
abbreviated_commit_hash = last_git_commit[:abbreviated_commit_hash]
os_type = options[:os_type]
install_url = options[:install_url]
unless ENV['MATTERMOST_WEBHOOK_URL'].nil? || ENV['MATTERMOST_WEBHOOK_URL'].empty?
os_type = options[:os_type]
if os_type == 'Android'
msg = "QA build [#{abbreviated_commit_hash}](https://github.com/mattermost/mattermost-mobile/commit/#{abbreviated_commit_hash}) — [Android APK Link](#{install_url})"
mattermost(message: msg, username: 'Fastlane', icon_url: 'https://lh3.ggpht.com/XL0CrI8skkxnboGct-duyg-bZ_MxJDTrjczyjdU8OP2PM1dmj7SP4jL1K8JQeMIB3AM=w300')
elsif os_type == 'iOS'
msg = "QA build [#{abbreviated_commit_hash}](https://github.com/mattermost/mattermost-mobile/commit/#{abbreviated_commit_hash}) — [iOS pList Link](#{install_url})"
mattermost(message: msg, username: 'Fastlane', icon_url: 'https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iOS/move-to-ios-icon.png')
end
else
UI.success("PR Built for #{os_type}: #{install_url}")
end
end