mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 23:32:41 +00:00
Merge pull request #3498 from vector-im/ci-setup
[Internal] fastlane: code for branch switcheroo used by CI
This commit is contained in:
commit
168126ae57
4 changed files with 404 additions and 333 deletions
19
Gemfile.lock
19
Gemfile.lock
|
@ -31,10 +31,10 @@ GEM
|
|||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.3)
|
||||
claide (1.0.3)
|
||||
cocoapods (1.8.4)
|
||||
cocoapods (1.9.3)
|
||||
activesupport (>= 4.0.2, < 5)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.8.4)
|
||||
cocoapods-core (= 1.9.3)
|
||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||
cocoapods-downloader (>= 1.2.2, < 2.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
|
@ -49,15 +49,17 @@ GEM
|
|||
molinillo (~> 0.6.6)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (~> 1.4)
|
||||
xcodeproj (>= 1.11.1, < 2.0)
|
||||
cocoapods-core (1.8.4)
|
||||
xcodeproj (>= 1.14.0, < 2.0)
|
||||
cocoapods-core (1.9.3)
|
||||
activesupport (>= 4.0.2, < 6)
|
||||
algoliasearch (~> 1.0)
|
||||
concurrent-ruby (~> 1.1)
|
||||
fuzzy_match (~> 2.0.4)
|
||||
nap (~> 1.0)
|
||||
netrc (~> 0.11)
|
||||
typhoeus (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.4)
|
||||
cocoapods-downloader (1.3.0)
|
||||
cocoapods-downloader (1.4.0)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.0)
|
||||
|
@ -79,6 +81,8 @@ GEM
|
|||
dotenv (2.7.5)
|
||||
emoji_regex (1.0.1)
|
||||
escape (0.0.4)
|
||||
ethon (0.12.0)
|
||||
ffi (>= 1.3.0)
|
||||
excon (0.75.0)
|
||||
faraday (1.0.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
|
@ -127,6 +131,7 @@ GEM
|
|||
xcpretty (~> 0.3.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3)
|
||||
fastlane-plugin-versioning (0.4.3)
|
||||
ffi (1.13.1)
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
|
@ -208,6 +213,8 @@ GEM
|
|||
tty-screen (0.8.0)
|
||||
tty-spinner (0.9.3)
|
||||
tty-cursor (~> 0.7)
|
||||
typhoeus (1.4.0)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (1.2.7)
|
||||
thread_safe (~> 0.1)
|
||||
uber (0.1.0)
|
||||
|
@ -234,7 +241,7 @@ PLATFORMS
|
|||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
cocoapods (~> 1.8.3)
|
||||
cocoapods (~> 1.9.3)
|
||||
fastlane
|
||||
fastlane-plugin-versioning
|
||||
xcode-install
|
||||
|
|
162
Podfile
162
Podfile
|
@ -4,116 +4,108 @@ platform :ios, '11.0'
|
|||
# Use frameforks to allow usage of pod written in Swift (like PiwikTracker)
|
||||
use_frameworks!
|
||||
|
||||
|
||||
# Different flavours of pods to MatrixKit
|
||||
# The current MatrixKit pod version
|
||||
# Different flavours of pods to MatrixKit. Can be one of:
|
||||
# - a String indicating an official MatrixKit released version number
|
||||
# - `:local` (to use Development Pods)
|
||||
# - `{'kit branch name' => 'sdk branch name'}` to depend on specific branches of each repo
|
||||
# - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each repo. Used by Fastfile during CI
|
||||
#
|
||||
# Warning: our internal tooling depends on the name of this variable name, so be sure not to change it
|
||||
$matrixKitVersion = '0.12.9'
|
||||
# $matrixKitVersion = :local
|
||||
# $matrixKitVersion = {'develop' => 'develop'}
|
||||
|
||||
# The specific branch version (supported: develop)
|
||||
#$matrixKitVersion = 'develop'
|
||||
|
||||
# The one used for developing both MatrixSDK and MatrixKit
|
||||
# Note that MatrixSDK must be cloned into a folder called matrix-ios-sdk next to the MatrixKit folder
|
||||
#$matrixKitVersion = 'local'
|
||||
########################################
|
||||
|
||||
case $matrixKitVersion
|
||||
when :local
|
||||
$matrixKitVersionSpec = { :path => '../matrix-ios-kit/MatrixKit.podspec' }
|
||||
$matrixSDKVersionSpec = { :path => '../matrix-ios-sdk/MatrixSDK.podspec' }
|
||||
when Hash # kit branch name => sdk branch name – or {kit spec Hash} => {sdk spec Hash}
|
||||
kit_spec, sdk_spec = $matrixKitVersion.first # extract first and only key/value pair; key is kit_spec, value is sdk_spec
|
||||
kit_spec = { :git => 'https://github.com/matrix-org/matrix-ios-kit.git', :branch => kit_spec.to_s } unless kit_spec.is_a?(Hash)
|
||||
sdk_spec = { :git => 'https://github.com/matrix-org/matrix-ios-sdk.git', :branch => sdk_spec.to_s } unless sdk_spec.is_a?(Hash)
|
||||
$matrixKitVersionSpec = kit_spec
|
||||
$matrixSDKVersionSpec = sdk_spec
|
||||
when String # specific MatrixKit released version
|
||||
$matrixKitVersionSpec = $matrixKitVersion
|
||||
$matrixSDKVersionSpec = {}
|
||||
end
|
||||
|
||||
# Method to import the right MatrixKit flavour
|
||||
def import_MatrixKit
|
||||
if $matrixKitVersion == 'local'
|
||||
pod 'MatrixSDK', :path => '../matrix-ios-sdk/MatrixSDK.podspec'
|
||||
pod 'MatrixSDK/SwiftSupport', :path => '../matrix-ios-sdk/MatrixSDK.podspec'
|
||||
pod 'MatrixSDK/JingleCallStack', :path => '../matrix-ios-sdk/MatrixSDK.podspec'
|
||||
pod 'MatrixKit', :path => '../matrix-ios-kit/MatrixKit.podspec'
|
||||
else
|
||||
if $matrixKitVersion == 'develop'
|
||||
pod 'MatrixSDK', :git => 'https://github.com/matrix-org/matrix-ios-sdk.git', :branch => $matrixKitVersion
|
||||
pod 'MatrixSDK/SwiftSupport', :git => 'https://github.com/matrix-org/matrix-ios-sdk.git', :branch => $matrixKitVersion
|
||||
pod 'MatrixSDK/JingleCallStack', :git => 'https://github.com/matrix-org/matrix-ios-sdk.git', :branch => $matrixKitVersion
|
||||
pod 'MatrixKit', :git => 'https://github.com/matrix-org/matrix-ios-kit.git', :branch => $matrixKitVersion
|
||||
else
|
||||
pod 'MatrixKit', $matrixKitVersion
|
||||
pod 'MatrixSDK/SwiftSupport'
|
||||
pod 'MatrixSDK/JingleCallStack'
|
||||
end
|
||||
end
|
||||
pod 'MatrixSDK', $matrixSDKVersionSpec
|
||||
pod 'MatrixSDK/SwiftSupport', $matrixSDKVersionSpec
|
||||
pod 'MatrixSDK/JingleCallStack', $matrixSDKVersionSpec
|
||||
pod 'MatrixKit', $matrixKitVersionSpec
|
||||
end
|
||||
|
||||
# Method to import the right MatrixKit/AppExtension flavour
|
||||
def import_MatrixKitAppExtension
|
||||
if $matrixKitVersion == 'local'
|
||||
pod 'MatrixSDK', :path => '../matrix-ios-sdk/MatrixSDK.podspec'
|
||||
pod 'MatrixSDK/SwiftSupport', :path => '../matrix-ios-sdk/MatrixSDK.podspec'
|
||||
pod 'MatrixKit/AppExtension', :path => '../matrix-ios-kit/MatrixKit.podspec'
|
||||
else
|
||||
if $matrixKitVersion == 'develop'
|
||||
pod 'MatrixSDK', :git => 'https://github.com/matrix-org/matrix-ios-sdk.git', :branch => $matrixKitVersion
|
||||
pod 'MatrixSDK/SwiftSupport', :git => 'https://github.com/matrix-org/matrix-ios-sdk.git', :branch => $matrixKitVersion
|
||||
pod 'MatrixKit/AppExtension', :git => 'https://github.com/matrix-org/matrix-ios-kit.git', :branch => $matrixKitVersion
|
||||
else
|
||||
pod 'MatrixKit/AppExtension', $matrixKitVersion
|
||||
pod 'MatrixSDK/SwiftSupport'
|
||||
end
|
||||
end
|
||||
pod 'MatrixSDK', $matrixSDKVersionSpec
|
||||
pod 'MatrixSDK/SwiftSupport', $matrixSDKVersionSpec
|
||||
pod 'MatrixKit/AppExtension', $matrixKitVersionSpec
|
||||
end
|
||||
|
||||
########################################
|
||||
|
||||
abstract_target 'RiotPods' do
|
||||
|
||||
pod 'GBDeviceInfo', '~> 6.3.0'
|
||||
pod 'Reusable', '~> 4.1'
|
||||
pod 'KeychainAccess', '~> 4.2'
|
||||
pod 'GBDeviceInfo', '~> 6.3.0'
|
||||
pod 'Reusable', '~> 4.1'
|
||||
pod 'KeychainAccess', '~> 4.2'
|
||||
|
||||
# Piwik for analytics
|
||||
pod 'MatomoTracker', '~> 7.2.0'
|
||||
# Piwik for analytics
|
||||
pod 'MatomoTracker', '~> 7.2.0'
|
||||
|
||||
# Remove warnings from "bad" pods
|
||||
pod 'OLMKit', :inhibit_warnings => true
|
||||
pod 'cmark', :inhibit_warnings => true
|
||||
pod 'zxcvbn-ios'
|
||||
# Remove warnings from "bad" pods
|
||||
pod 'OLMKit', :inhibit_warnings => true
|
||||
pod 'cmark', :inhibit_warnings => true
|
||||
pod 'zxcvbn-ios'
|
||||
|
||||
# Tools
|
||||
pod 'SwiftGen', '~> 6.1'
|
||||
pod 'SwiftLint', '~> 0.36.0'
|
||||
# Tools
|
||||
pod 'SwiftGen', '~> 6.1'
|
||||
pod 'SwiftLint', '~> 0.36.0'
|
||||
|
||||
target "Riot" do
|
||||
import_MatrixKit
|
||||
pod 'DGCollectionViewLeftAlignFlowLayout', '~> 1.0.4'
|
||||
pod 'KTCenterFlowLayout', '~> 1.3.1'
|
||||
pod 'ZXingObjC', '~> 3.6.5'
|
||||
|
||||
target 'RiotTests' do
|
||||
inherit! :search_paths
|
||||
end
|
||||
end
|
||||
|
||||
target "RiotShareExtension" do
|
||||
import_MatrixKitAppExtension
|
||||
end
|
||||
target "Riot" do
|
||||
import_MatrixKit
|
||||
pod 'DGCollectionViewLeftAlignFlowLayout', '~> 1.0.4'
|
||||
pod 'KTCenterFlowLayout', '~> 1.3.1'
|
||||
pod 'ZXingObjC', '~> 3.6.5'
|
||||
|
||||
target "SiriIntents" do
|
||||
import_MatrixKitAppExtension
|
||||
target 'RiotTests' do
|
||||
inherit! :search_paths
|
||||
end
|
||||
|
||||
target "RiotNSE" do
|
||||
import_MatrixKitAppExtension
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
target "RiotShareExtension" do
|
||||
import_MatrixKitAppExtension
|
||||
end
|
||||
|
||||
target "SiriIntents" do
|
||||
import_MatrixKitAppExtension
|
||||
end
|
||||
|
||||
target "RiotNSE" do
|
||||
import_MatrixKitAppExtension
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
installer.pods_project.targets.each do |target|
|
||||
|
||||
# Disable bitcode for each pod framework
|
||||
# Because the WebRTC pod (included by the JingleCallStack pod) does not support it.
|
||||
# Plus the app does not enable it
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['ENABLE_BITCODE'] = 'NO'
|
||||
|
||||
# Force SwiftUTI Swift version to 5.0 (as there is no code changes to perform for SwiftUTI fork using Swift 4.2)
|
||||
if target.name.include? 'SwiftUTI'
|
||||
config.build_settings['SWIFT_VERSION'] = '5.0'
|
||||
end
|
||||
end
|
||||
# Disable bitcode for each pod framework
|
||||
# Because the WebRTC pod (included by the JingleCallStack pod) does not support it.
|
||||
# Plus the app does not enable it
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['ENABLE_BITCODE'] = 'NO'
|
||||
|
||||
# Force SwiftUTI Swift version to 5.0 (as there is no code changes to perform for SwiftUTI fork using Swift 4.2)
|
||||
if target.name.include? 'SwiftUTI'
|
||||
config.build_settings['SWIFT_VERSION'] = '5.0'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -44,6 +44,7 @@ PODS:
|
|||
- GZIP (1.2.3)
|
||||
- HPGrowingTextView (1.1)
|
||||
- JitsiMeetSDK (2.8.1)
|
||||
- KeychainAccess (4.2.0)
|
||||
- KTCenterFlowLayout (1.3.1)
|
||||
- libbase58 (0.1.4)
|
||||
- libPhoneNumber-iOS (0.9.15)
|
||||
|
@ -107,10 +108,12 @@ DEPENDENCIES:
|
|||
- cmark
|
||||
- DGCollectionViewLeftAlignFlowLayout (~> 1.0.4)
|
||||
- GBDeviceInfo (~> 6.3.0)
|
||||
- KeychainAccess (~> 4.2)
|
||||
- KTCenterFlowLayout (~> 1.3.1)
|
||||
- MatomoTracker (~> 7.2.0)
|
||||
- MatrixKit (= 0.12.9)
|
||||
- MatrixKit/AppExtension (= 0.12.9)
|
||||
- MatrixSDK
|
||||
- MatrixSDK/JingleCallStack
|
||||
- MatrixSDK/SwiftSupport
|
||||
- OLMKit
|
||||
|
@ -131,6 +134,7 @@ SPEC REPOS:
|
|||
- GZIP
|
||||
- HPGrowingTextView
|
||||
- JitsiMeetSDK
|
||||
- KeychainAccess
|
||||
- KTCenterFlowLayout
|
||||
- libbase58
|
||||
- libPhoneNumber-iOS
|
||||
|
@ -155,6 +159,7 @@ SPEC CHECKSUMS:
|
|||
GZIP: af5c90ef903776a7e9afe6ebebd794a84a2929d4
|
||||
HPGrowingTextView: 88a716d97fb853bcb08a4a08e4727da17efc9b19
|
||||
JitsiMeetSDK: 2984eac1343690bf1c0c72bde75b48b0148d0f79
|
||||
KeychainAccess: 3f760109aa99b05d0f231e28b22642da7153e38a
|
||||
KTCenterFlowLayout: 6e02b50ab2bd865025ae82fe266ed13b6d9eaf97
|
||||
libbase58: 7c040313537b8c44b6e2d15586af8e21f7354efd
|
||||
libPhoneNumber-iOS: 0a32a9525cf8744fe02c5206eb30d571e38f7d75
|
||||
|
@ -169,6 +174,6 @@ SPEC CHECKSUMS:
|
|||
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
|
||||
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
|
||||
|
||||
PODFILE CHECKSUM: 0f7f169726d2d7737bb2ca4020afd5534edbe9c9
|
||||
PODFILE CHECKSUM: 35c0be0ac3a1b6cfac738888f03f9be44a75f634
|
||||
|
||||
COCOAPODS: 1.9.3
|
||||
|
|
|
@ -10,267 +10,334 @@
|
|||
# https://docs.fastlane.tools/plugins/available-plugins
|
||||
#
|
||||
|
||||
fastlane_require 'dotenv'
|
||||
fastlane_require "dotenv"
|
||||
|
||||
default_platform(:ios)
|
||||
platform :ios do
|
||||
|
||||
#### Pre ####
|
||||
#### Pre ####
|
||||
|
||||
before_all do
|
||||
# Ensure used Xcode version
|
||||
xcversion(version: "~> 11.4")
|
||||
before_all do
|
||||
# Ensure used Xcode version
|
||||
xcversion(version: "~> 11.4")
|
||||
end
|
||||
|
||||
#### Public ####
|
||||
|
||||
desc "Builds an adhoc ipa"
|
||||
lane :adhoc do |options|
|
||||
options[:adhoc] = true
|
||||
build_release(options)
|
||||
end
|
||||
|
||||
desc "Builds an ipa for the App Store"
|
||||
lane :app_store do |options|
|
||||
build_release(options)
|
||||
end
|
||||
|
||||
desc "Builds the ipa for the AppStore, then uploads it"
|
||||
lane :deploy_release do |options|
|
||||
require 'date'
|
||||
build_number = DateTime.now.strftime("%Y%m%d%H%M%S")
|
||||
options = { build_number: build_number }.merge(options)
|
||||
app_store(options)
|
||||
|
||||
# We haven't yet implemented/tested deliver/upload_to_appstore properly so keep it manual for now
|
||||
UI.message("IPA is available at path '#{ENV['IPA_OUTPUT_PATH']}'. Please upload manually using Application Loader.")
|
||||
UI.confirm("Have you uploaded the IPA to the AppStore now?")
|
||||
#upload_to_appstore(
|
||||
# skip_submission: true, # Only upload the build
|
||||
# skip_waiting_for_build_processing: true # Don't wait for the build to process
|
||||
#)
|
||||
end
|
||||
|
||||
desc "Point MatrixKit and MatrixSDK to their respective release/*/release branch if they exist, develop otherwise"
|
||||
lane :point_dependencies_to_pending_releases do
|
||||
edit_podfile(branch_pattern: "release/*/release")
|
||||
end
|
||||
|
||||
desc "Point MatrixKit and MatrixSDK to the branch with the same name as the current branch if such one exist, develop otherwise"
|
||||
lane :point_dependencies_to_same_feature do
|
||||
edit_podfile(branch_pattern: git_branch)
|
||||
end
|
||||
|
||||
desc "Build the app for simulator to ensure it compiles"
|
||||
lane :build do |options|
|
||||
cocoapods
|
||||
|
||||
app_name = "Riot"
|
||||
build_app(
|
||||
clean: true,
|
||||
scheme: app_name,
|
||||
derived_data_path: "./DerivedData/",
|
||||
buildlog_path: "./DerivedData/Logs/",
|
||||
# skip_package_ipa: true,
|
||||
skip_archive: true,
|
||||
destination: "generic/platform=iOS Simulator",
|
||||
)
|
||||
end
|
||||
|
||||
#### Private ####
|
||||
|
||||
desc "Download App Store or Ad-Hoc provisioning profiles"
|
||||
private_lane :build_release do |options|
|
||||
UI.user_error!("'APPLE_ID' environment variable should be set to use this lane") unless !ENV["APPLE_ID"].to_s.empty?
|
||||
|
||||
build_number = options[:build_number]
|
||||
UI.user_error!("'build_number' parameter is missing") unless !build_number.to_s.empty?
|
||||
|
||||
# ad-hoc or app-store?
|
||||
adhoc = options.fetch(:adhoc, false)
|
||||
|
||||
# Retrieve GIT branch name
|
||||
git_branch_name = git_branch
|
||||
UI.user_error!("Unable to retrieve GIT branch name") unless !git_branch_name.to_s.empty?
|
||||
|
||||
# Fetch team id from Appfile
|
||||
team_id = CredentialsManager::AppfileConfig.try_fetch_value(:team_id)
|
||||
UI.user_error!("Fail to fetch team id from Appfile") unless !team_id.to_s.empty?
|
||||
|
||||
# Generate versioning preprocessor macros
|
||||
additional_preprocessor_definitions_hash = release_versioning_preprocessor_definitions(git_branch: git_branch_name, build_number: build_number)
|
||||
additional_preprocessor_definitions = additional_preprocessor_definitions_hash.map { |k, v| "#{k}=\"#{v}\"" }.join(" ")
|
||||
|
||||
# Generate xcodebuild additional arguments
|
||||
xcargs_hash = {
|
||||
"GCC_PREPROCESSOR_DEFINITIONS" => "$(GCC_PREPROCESSOR_DEFINITIONS) #{additional_preprocessor_definitions}",
|
||||
"-UseNewBuildSystem" => "NO",
|
||||
}
|
||||
|
||||
xcargs = xcargs_hash.map { |k, v| "#{k}=#{v.shellescape}" }.join(" ")
|
||||
|
||||
# Clear derived data
|
||||
clear_derived_data(derived_data_path: ENV["DERIVED_DATA_PATH"])
|
||||
|
||||
# Setup project provisioning profiles
|
||||
download_provisioning_profiles(adhoc: adhoc)
|
||||
disable_automatic_code_signing
|
||||
update_project_provisioning_profiles
|
||||
|
||||
# Update build number
|
||||
update_build_number(build_number: build_number)
|
||||
|
||||
# On Xcode 10 with 'Parallelize Build' option on, archive randomly fails with error title "** ARCHIVE FAILED **" for various reasons.
|
||||
# Errors only occur on CocoaPods frameworks and the observed command that failed are CodeSign, CpHeader, CpResource, SetOwnerAndGroup.
|
||||
# To make archive reliable disable 'Parallelize Build' option of scheme ENV["SCHEME"] for the moment.
|
||||
disable_parallelize_builds
|
||||
|
||||
# Perform a pod install
|
||||
cocoapods(repo_update: true)
|
||||
|
||||
# Select a config
|
||||
if adhoc
|
||||
export_method = "ad-hoc"
|
||||
main_provisioning_profile = ENV["ADHOC_MAIN_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
share_extension_provisioning_profile = ENV["ADHOC_SHARE_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
siri_intents_provisioning_profile = ENV["ADHOC_SIRI_INTENTS_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
nse_provisioning_profile = ENV["ADHOC_NSE_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
else
|
||||
export_method = "app-store"
|
||||
main_provisioning_profile = ENV["APPSTORE_MAIN_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
share_extension_provisioning_profile = ENV["APPSTORE_SHARE_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
siri_intents_provisioning_profile = ENV["APPSTORE_SIRI_INTENTS_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
nse_provisioning_profile = ENV["APPSTORE_NSE_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
end
|
||||
|
||||
#### Public ####
|
||||
# Build app and create ipa
|
||||
build_app(
|
||||
clean: true,
|
||||
scheme: ENV["SCHEME"],
|
||||
xcargs: xcargs,
|
||||
export_method: export_method,
|
||||
derived_data_path: ENV["DERIVED_DATA_PATH"],
|
||||
archive_path: ENV["ARCHIVE_PATH"],
|
||||
output_directory: ENV["BUILD_OUTPUT_DIRECTORY"],
|
||||
output_name: "#{ENV["IPA_NAME"]}.ipa",
|
||||
buildlog_path: ENV["BUILD_LOG_DIRECTORY"],
|
||||
codesigning_identity: ENV["APPSTORE_CODESIGNING_IDENTITY"],
|
||||
skip_profile_detection: true,
|
||||
export_options: {
|
||||
method: export_method,
|
||||
signingStyle: "manual",
|
||||
teamID: team_id,
|
||||
signingCertificate: ENV["APPSTORE_SIGNING_CERTIFICATE"],
|
||||
provisioningProfiles: {
|
||||
ENV["MAIN_BUNDLE_ID"] => main_provisioning_profile,
|
||||
ENV["SHARE_EXTENSION_BUNDLE_ID"] => share_extension_provisioning_profile,
|
||||
ENV["NSE_BUNDLE_ID"] => nse_provisioning_profile,
|
||||
ENV["SIRI_INTENTS_EXTENSION_BUNDLE_ID"] => siri_intents_provisioning_profile,
|
||||
},
|
||||
iCloudContainerEnvironment: "Production",
|
||||
},
|
||||
)
|
||||
end
|
||||
|
||||
desc "Builds an adhoc ipa"
|
||||
lane :adhoc do |options|
|
||||
#### Private ####
|
||||
|
||||
options[:adhoc] = true
|
||||
build_release(options)
|
||||
desc "Download App Store or Ad-Hoc provisioning profiles"
|
||||
private_lane :download_provisioning_profiles do |options|
|
||||
adhoc = options.fetch(:adhoc, false)
|
||||
|
||||
output_path = ENV["PROVISIONING_PROFILES_PATH"]
|
||||
skip_certificate_verification = false
|
||||
|
||||
main_provisioning_name = adhoc ? ENV["ADHOC_MAIN_PROVISIONING_PROFILE_SPECIFIER"] : ENV["APPSTORE_MAIN_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
share_extension_provisioning_name = adhoc ? ENV["ADHOC_SHARE_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"] : ENV["APPSTORE_SHARE_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
siri_intents_provisioning_name = adhoc ? ENV["ADHOC_SIRI_INTENTS_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"] : ENV["APPSTORE_SIRI_INTENTS_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
notification_service_extension_provisioning_name = adhoc ? ENV["ADHOC_NSE_PROVISIONING_PROFILE_SPECIFIER"] : ENV["APPSTORE_NSE_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
|
||||
# Main application
|
||||
get_provisioning_profile(
|
||||
app_identifier: ENV["MAIN_BUNDLE_ID"],
|
||||
provisioning_name: main_provisioning_name,
|
||||
ignore_profiles_with_different_name: true,
|
||||
adhoc: adhoc,
|
||||
skip_certificate_verification: skip_certificate_verification,
|
||||
output_path: output_path,
|
||||
filename: ENV["MAIN_PROVISIONING_PROFILE_FILENAME"],
|
||||
readonly: true,
|
||||
)
|
||||
# Share extension
|
||||
get_provisioning_profile(
|
||||
app_identifier: ENV["SHARE_EXTENSION_BUNDLE_ID"],
|
||||
provisioning_name: share_extension_provisioning_name,
|
||||
ignore_profiles_with_different_name: true,
|
||||
adhoc: adhoc,
|
||||
skip_certificate_verification: skip_certificate_verification,
|
||||
output_path: output_path,
|
||||
filename: ENV["SHARE_EXTENSION_PROVISIONING_PROFILE_FILENAME"],
|
||||
readonly: true,
|
||||
)
|
||||
# Siri Intents extension
|
||||
get_provisioning_profile(
|
||||
app_identifier: ENV["SIRI_INTENTS_EXTENSION_BUNDLE_ID"],
|
||||
provisioning_name: siri_intents_provisioning_name,
|
||||
ignore_profiles_with_different_name: true,
|
||||
adhoc: adhoc,
|
||||
skip_certificate_verification: skip_certificate_verification,
|
||||
output_path: output_path,
|
||||
filename: ENV["SIRI_INTENTS_EXTENSION_PROVISIONING_PROFILE_FILENAME"],
|
||||
readonly: true,
|
||||
)
|
||||
# NSE
|
||||
get_provisioning_profile(
|
||||
app_identifier: ENV["NSE_BUNDLE_ID"],
|
||||
provisioning_name: notification_service_extension_provisioning_name,
|
||||
ignore_profiles_with_different_name: true,
|
||||
adhoc: adhoc,
|
||||
skip_certificate_verification: skip_certificate_verification,
|
||||
output_path: output_path,
|
||||
filename: ENV["NSE_PROVISIONING_PROFILE_FILENAME"],
|
||||
readonly: true,
|
||||
)
|
||||
end
|
||||
|
||||
desc "Update provisioning profiles for each target"
|
||||
private_lane :update_project_provisioning_profiles do
|
||||
provisioning_profiles_path = ENV["PROVISIONING_PROFILES_PATH"]
|
||||
build_configuration = "Release"
|
||||
xcodeproj = ENV["PROJECT_PATH"]
|
||||
|
||||
# Main application
|
||||
update_project_provisioning(
|
||||
xcodeproj: xcodeproj,
|
||||
profile: "#{provisioning_profiles_path}#{ENV["MAIN_PROVISIONING_PROFILE_FILENAME"]}",
|
||||
target_filter: ENV["MAIN_TARGET"],
|
||||
build_configuration: build_configuration,
|
||||
)
|
||||
# Share extension
|
||||
update_project_provisioning(
|
||||
xcodeproj: xcodeproj,
|
||||
profile: "#{provisioning_profiles_path}#{ENV["SHARE_EXTENSION_PROVISIONING_PROFILE_FILENAME"]}",
|
||||
target_filter: ENV["SHARE_EXTENSION_TARGET"],
|
||||
build_configuration: build_configuration,
|
||||
)
|
||||
# Siri Intents extension
|
||||
update_project_provisioning(
|
||||
xcodeproj: xcodeproj,
|
||||
profile: "#{provisioning_profiles_path}#{ENV["SIRI_INTENTS_EXTENSION_PROVISIONING_PROFILE_FILENAME"]}",
|
||||
target_filter: ENV["SIRI_INTENTS_EXTENSION_TARGET"],
|
||||
build_configuration: build_configuration,
|
||||
)
|
||||
# NSE
|
||||
update_project_provisioning(
|
||||
xcodeproj: xcodeproj,
|
||||
profile: "#{provisioning_profiles_path}#{ENV["NSE_PROVISIONING_PROFILE_FILENAME"]}",
|
||||
target_filter: ENV["NSE_TARGET"],
|
||||
build_configuration: build_configuration,
|
||||
)
|
||||
end
|
||||
|
||||
desc "Update application build number for all targets"
|
||||
private_lane :update_build_number do |options|
|
||||
build_number = options[:build_number]
|
||||
|
||||
increment_build_number_in_xcodeproj(
|
||||
build_number: build_number,
|
||||
)
|
||||
end
|
||||
|
||||
desc "Returns version identifiers hash to inject in GCC_PREPROCESSOR_DEFINITIONS for release builds"
|
||||
private_lane :release_versioning_preprocessor_definitions do |options|
|
||||
preprocessor_definitions = Hash.new
|
||||
|
||||
git_branch_name = options[:git_branch]
|
||||
build_number = options[:build_number]
|
||||
|
||||
if !git_branch_name.to_s.empty?
|
||||
preprocessor_definitions["GIT_BRANCH"] = git_branch_name.sub("origin/", "").sub("heads/", "")
|
||||
end
|
||||
|
||||
desc "Builds (and upload) an ipa for the App Store"
|
||||
lane :app_store do |options|
|
||||
|
||||
build_release(options)
|
||||
|
||||
# Upload ipa to TestFlight
|
||||
#upload_to_testflight(
|
||||
# skip_submission: true, # Only upload the build
|
||||
# skip_waiting_for_build_processing: true # Don't wait for the build to process
|
||||
#)
|
||||
if !build_number.to_s.empty?
|
||||
preprocessor_definitions["BUILD_NUMBER"] = build_number
|
||||
end
|
||||
|
||||
#### Private ####
|
||||
preprocessor_definitions
|
||||
end
|
||||
|
||||
desc "Download App Store or Ad-Hoc provisioning profiles"
|
||||
private_lane :build_release do |options|
|
||||
desc "Disable 'Parallelize Build' option of build action of main scheme"
|
||||
private_lane :disable_parallelize_builds do
|
||||
project_path = "../#{ENV["PROJECT_PATH"]}"
|
||||
scheme_name = ENV["SCHEME"]
|
||||
|
||||
UI.user_error!("'APPLE_ID' environment variable should be set to use this lane") unless !ENV["APPLE_ID"].to_s.empty?
|
||||
scheme_path = Xcodeproj::XCScheme.shared_data_dir(project_path) + "#{scheme_name}.xcscheme"
|
||||
scheme = Xcodeproj::XCScheme.new(scheme_path)
|
||||
scheme.build_action.xml_element.attributes["parallelizeBuildables"] = "NO"
|
||||
scheme.save_as(project_path, scheme_name)
|
||||
end
|
||||
|
||||
build_number = options[:build_number]
|
||||
UI.user_error!("'build_number' parameter is missing") unless !build_number.to_s.empty?
|
||||
desc "Edit the Podfile in order to point MatrixKit and MatrixSDK to the appropriate branches."
|
||||
private_lane :edit_podfile do |options|
|
||||
require 'net/http'
|
||||
require 'yaml'
|
||||
|
||||
# ad-hoc or app-store?
|
||||
adhoc = options.fetch(:adhoc, false)
|
||||
branch_pattern = options[:branch_pattern]
|
||||
kit_slug = "matrix-org/matrix-ios-kit"
|
||||
sdk_slug = "matrix-org/matrix-ios-sdk"
|
||||
|
||||
# Retrieve GIT branch name
|
||||
git_branch_name = git_branch
|
||||
UI.user_error!("Unable to retrieve GIT branch name") unless !git_branch_name.to_s.empty?
|
||||
kit_branch = find_branch(kit_slug, branch_pattern) || 'develop'
|
||||
sdk_branch = find_branch(sdk_slug, branch_pattern) || 'develop'
|
||||
|
||||
# Fetch team id from Appfile
|
||||
team_id = CredentialsManager::AppfileConfig.try_fetch_value(:team_id)
|
||||
UI.user_error!("Fail to fetch team id from Appfile") unless !team_id.to_s.empty?
|
||||
UI.message("✏️ Making a local copy of MatrixKit.podspec from the \`#{kit_branch}\` branch...")
|
||||
podspec_content = Net::HTTP.get(URI("https://raw.githubusercontent.com/#{kit_slug}/#{kit_branch}/MatrixKit.podspec"))
|
||||
|
||||
# Generate versioning preprocessor macros
|
||||
additional_preprocessor_definitions_hash = release_versioning_preprocessor_definitions(git_branch: git_branch_name, build_number: build_number)
|
||||
additional_preprocessor_definitions = additional_preprocessor_definitions_hash.map { |k,v| "#{k}=\"#{v}\"" }.join(' ')
|
||||
UI.message "✏️ Editing local MatrixKit podspec to remove version constaint on 'MatrixSDK*' dependencies..."
|
||||
podspec_content.gsub!(%r{(\.dependency\s+(['"])MatrixSDK(\/[^'"]+)?\2).*$}, '\1')
|
||||
File.write('../MatrixKit.edited.podspec', podspec_content) # current dir is 'fastlane/' hence the '../'
|
||||
|
||||
# Generate xcodebuild additional arguments
|
||||
xcargs_hash = {
|
||||
'GCC_PREPROCESSOR_DEFINITIONS' => "$(GCC_PREPROCESSOR_DEFINITIONS) #{additional_preprocessor_definitions}",
|
||||
'-UseNewBuildSystem' => 'NO'
|
||||
}
|
||||
|
||||
xcargs = xcargs_hash.map { |k,v| "#{k}=#{v.shellescape}" }.join(' ')
|
||||
|
||||
# Clear derived data
|
||||
clear_derived_data(derived_data_path: ENV["DERIVED_DATA_PATH"])
|
||||
|
||||
# Setup project provisioning profiles
|
||||
download_provisioning_profiles(adhoc: adhoc)
|
||||
disable_automatic_code_signing
|
||||
update_project_provisioning_profiles
|
||||
|
||||
# Update build number
|
||||
update_build_number(build_number: build_number)
|
||||
|
||||
# On Xcode 10 with 'Parallelize Build' option on, archive randomly fails with error title "** ARCHIVE FAILED **" for various reasons.
|
||||
# Errors only occur on CocoaPods frameworks and the observed command that failed are CodeSign, CpHeader, CpResource, SetOwnerAndGroup.
|
||||
# To make archive reliable disable 'Parallelize Build' option of scheme ENV["SCHEME"] for the moment.
|
||||
disable_parallelize_builds
|
||||
|
||||
# Perform a pod install
|
||||
cocoapods(repo_update: true)
|
||||
|
||||
# Select a config
|
||||
if adhoc
|
||||
export_method = "ad-hoc"
|
||||
main_provisioning_profile = ENV["ADHOC_MAIN_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
share_extension_provisioning_profile = ENV["ADHOC_SHARE_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
siri_intents_provisioning_profile = ENV["ADHOC_SIRI_INTENTS_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
nse_provisioning_profile = ENV["ADHOC_NSE_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
else
|
||||
export_method = "app-store"
|
||||
main_provisioning_profile = ENV["APPSTORE_MAIN_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
share_extension_provisioning_profile = ENV["APPSTORE_SHARE_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
siri_intents_provisioning_profile = ENV["APPSTORE_SIRI_INTENTS_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
nse_provisioning_profile = ENV["APPSTORE_NSE_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
end
|
||||
|
||||
# Build app and create ipa
|
||||
build_app(
|
||||
clean: true,
|
||||
scheme: ENV["SCHEME"],
|
||||
xcargs: xcargs,
|
||||
export_method: export_method,
|
||||
derived_data_path: ENV["DERIVED_DATA_PATH"],
|
||||
archive_path: ENV["ARCHIVE_PATH"],
|
||||
output_directory: ENV["BUILD_OUTPUT_DIRECTORY"],
|
||||
output_name: "#{ENV['IPA_NAME']}.ipa",
|
||||
buildlog_path: ENV["BUILD_LOG_DIRECTORY"],
|
||||
codesigning_identity: ENV["APPSTORE_CODESIGNING_IDENTITY"],
|
||||
skip_profile_detection: true,
|
||||
export_options: {
|
||||
method: export_method,
|
||||
signingStyle: "manual",
|
||||
teamID: team_id,
|
||||
signingCertificate: ENV["APPSTORE_SIGNING_CERTIFICATE"],
|
||||
provisioningProfiles: {
|
||||
ENV["MAIN_BUNDLE_ID"] => main_provisioning_profile,
|
||||
ENV["SHARE_EXTENSION_BUNDLE_ID"] => share_extension_provisioning_profile,
|
||||
ENV["NSE_BUNDLE_ID"] => nse_provisioning_profile,
|
||||
ENV["SIRI_INTENTS_EXTENSION_BUNDLE_ID"] => siri_intents_provisioning_profile
|
||||
},
|
||||
iCloudContainerEnvironment: 'Production'
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
#### Private ####
|
||||
|
||||
desc "Download App Store or Ad-Hoc provisioning profiles"
|
||||
private_lane :download_provisioning_profiles do |options|
|
||||
adhoc = options.fetch(:adhoc, false)
|
||||
|
||||
output_path = ENV["PROVISIONING_PROFILES_PATH"]
|
||||
skip_certificate_verification = false
|
||||
|
||||
main_provisioning_name = adhoc ? ENV["ADHOC_MAIN_PROVISIONING_PROFILE_SPECIFIER"] : ENV["APPSTORE_MAIN_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
share_extension_provisioning_name = adhoc ? ENV["ADHOC_SHARE_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"] : ENV["APPSTORE_SHARE_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
siri_intents_provisioning_name = adhoc ? ENV["ADHOC_SIRI_INTENTS_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"] : ENV["APPSTORE_SIRI_INTENTS_EXTENSION_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
notification_service_extension_provisioning_name = adhoc ? ENV["ADHOC_NSE_PROVISIONING_PROFILE_SPECIFIER"] : ENV["APPSTORE_NSE_PROVISIONING_PROFILE_SPECIFIER"]
|
||||
|
||||
# Main application
|
||||
get_provisioning_profile(
|
||||
app_identifier: ENV["MAIN_BUNDLE_ID"],
|
||||
provisioning_name: main_provisioning_name,
|
||||
ignore_profiles_with_different_name: true,
|
||||
adhoc: adhoc,
|
||||
skip_certificate_verification: skip_certificate_verification,
|
||||
output_path: output_path,
|
||||
filename: ENV["MAIN_PROVISIONING_PROFILE_FILENAME"],
|
||||
readonly: true
|
||||
)
|
||||
# Share extension
|
||||
get_provisioning_profile(
|
||||
app_identifier: ENV["SHARE_EXTENSION_BUNDLE_ID"],
|
||||
provisioning_name: share_extension_provisioning_name,
|
||||
ignore_profiles_with_different_name: true,
|
||||
adhoc: adhoc,
|
||||
skip_certificate_verification: skip_certificate_verification,
|
||||
output_path: output_path,
|
||||
filename: ENV["SHARE_EXTENSION_PROVISIONING_PROFILE_FILENAME"],
|
||||
readonly: true
|
||||
)
|
||||
# Siri Intents extension
|
||||
get_provisioning_profile(
|
||||
app_identifier: ENV["SIRI_INTENTS_EXTENSION_BUNDLE_ID"],
|
||||
provisioning_name: siri_intents_provisioning_name,
|
||||
ignore_profiles_with_different_name: true,
|
||||
adhoc: adhoc,
|
||||
skip_certificate_verification: skip_certificate_verification,
|
||||
output_path: output_path,
|
||||
filename: ENV["SIRI_INTENTS_EXTENSION_PROVISIONING_PROFILE_FILENAME"],
|
||||
readonly: true
|
||||
)
|
||||
# NSE
|
||||
get_provisioning_profile(
|
||||
app_identifier: ENV["NSE_BUNDLE_ID"],
|
||||
provisioning_name: notification_service_extension_provisioning_name,
|
||||
ignore_profiles_with_different_name: true,
|
||||
adhoc: adhoc,
|
||||
skip_certificate_verification: skip_certificate_verification,
|
||||
output_path: output_path,
|
||||
filename: ENV["NSE_PROVISIONING_PROFILE_FILENAME"],
|
||||
readonly: true
|
||||
)
|
||||
end
|
||||
|
||||
desc "Update provisioning profiles for each target"
|
||||
private_lane :update_project_provisioning_profiles do
|
||||
provisioning_profiles_path = ENV["PROVISIONING_PROFILES_PATH"]
|
||||
build_configuration = 'Release'
|
||||
xcodeproj = ENV["PROJECT_PATH"]
|
||||
|
||||
# Main application
|
||||
update_project_provisioning(
|
||||
xcodeproj: xcodeproj,
|
||||
profile: "#{provisioning_profiles_path}#{ENV["MAIN_PROVISIONING_PROFILE_FILENAME"]}",
|
||||
target_filter: ENV["MAIN_TARGET"],
|
||||
build_configuration: build_configuration
|
||||
)
|
||||
# Share extension
|
||||
update_project_provisioning(
|
||||
xcodeproj: xcodeproj,
|
||||
profile: "#{provisioning_profiles_path}#{ENV["SHARE_EXTENSION_PROVISIONING_PROFILE_FILENAME"]}",
|
||||
target_filter: ENV["SHARE_EXTENSION_TARGET"],
|
||||
build_configuration: build_configuration
|
||||
)
|
||||
# Siri Intents extension
|
||||
update_project_provisioning(
|
||||
xcodeproj: xcodeproj,
|
||||
profile: "#{provisioning_profiles_path}#{ENV["SIRI_INTENTS_EXTENSION_PROVISIONING_PROFILE_FILENAME"]}",
|
||||
target_filter: ENV["SIRI_INTENTS_EXTENSION_TARGET"],
|
||||
build_configuration: build_configuration
|
||||
)
|
||||
# NSE
|
||||
update_project_provisioning(
|
||||
xcodeproj: xcodeproj,
|
||||
profile: "#{provisioning_profiles_path}#{ENV["NSE_PROVISIONING_PROFILE_FILENAME"]}",
|
||||
target_filter: ENV["NSE_TARGET"],
|
||||
build_configuration: build_configuration
|
||||
)
|
||||
end
|
||||
|
||||
desc "Update application build number for all targets"
|
||||
private_lane :update_build_number do |options|
|
||||
build_number = options[:build_number]
|
||||
|
||||
increment_build_number_in_xcodeproj(
|
||||
build_number: build_number
|
||||
)
|
||||
end
|
||||
|
||||
desc "Returns version identifiers hash to inject in GCC_PREPROCESSOR_DEFINITIONS for release builds"
|
||||
private_lane :release_versioning_preprocessor_definitions do |options|
|
||||
preprocessor_definitions = Hash.new
|
||||
|
||||
git_branch_name = options[:git_branch]
|
||||
build_number = options[:build_number]
|
||||
|
||||
if !git_branch_name.to_s.empty?
|
||||
preprocessor_definitions["GIT_BRANCH"] = git_branch_name.sub("origin/", "").sub("heads/", "")
|
||||
end
|
||||
|
||||
if !build_number.to_s.empty?
|
||||
preprocessor_definitions["BUILD_NUMBER"] = build_number
|
||||
end
|
||||
|
||||
preprocessor_definitions
|
||||
end
|
||||
|
||||
desc "Disable 'Parallelize Build' option of build action of main scheme"
|
||||
private_lane :disable_parallelize_builds do
|
||||
project_path = "../#{ENV["PROJECT_PATH"]}"
|
||||
scheme_name = ENV['SCHEME']
|
||||
|
||||
scheme_path = Xcodeproj::XCScheme.shared_data_dir(project_path) + "#{scheme_name}.xcscheme"
|
||||
scheme = Xcodeproj::XCScheme.new(scheme_path)
|
||||
scheme.build_action.xml_element.attributes['parallelizeBuildables'] = 'NO'
|
||||
scheme.save_as(project_path, scheme_name)
|
||||
end
|
||||
UI.message "✏️ Modify Podfile to point MatrixKit to local podspec and `MatrixSDK/*` to \`#{sdk_branch}\` branch..."
|
||||
podfile_content = File.read('../Podfile') # current dir is 'fastlane/' hence the '../'
|
||||
kit_spec = { podspec: 'MatrixKit.edited.podspec' }
|
||||
sdk_spec = { git: 'https://github.com/matrix-org/matrix-ios-sdk.git', branch: sdk_branch }
|
||||
podfile_content.gsub!(%r{^\$matrixKitVersion\s*=\s*.*$}, "$matrixKitVersion = { #{kit_spec} => #{sdk_spec} }")
|
||||
File.write('../Podfile', podfile_content)
|
||||
end
|
||||
|
||||
# Find the latest branch with the given name pattern in the given repo
|
||||
def find_branch(repo_slug, pattern)
|
||||
list = `git ls-remote --heads --sort=version:refname https://github.com/#{repo_slug} #{pattern}`
|
||||
list.split("\n")
|
||||
.map { |line| line.sub(%r{[0-9a-f]+\trefs/heads/}, '').chomp }
|
||||
.last # Latest ref found, in "version:refname" semantic order
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue