Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AAB build and sign support for Android, compile constants support and other improvements #41

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3bd6061
Making sure we getting AndroidManifest file location exactly from con…
i-nikityuk May 25, 2022
3fa3928
Removed double signing of apk file
i-nikityuk May 25, 2022
771c0cb
Merge pull request #1 from inikityuk/bugfix/add_support_for_multiple_…
inikityuk May 26, 2022
9baee4d
Merge pull request #2 from inikityuk/bugfix/if_signing_details_provid…
inikityuk May 26, 2022
5b5c6d2
Added AAB build support
i-nikityuk May 26, 2022
7123e42
Update readme with new "key-password" option
i-nikityuk May 26, 2022
c4bc7b4
Removed "compile_constants" from options - it will be detected automa…
i-nikityuk May 26, 2022
1a2de2f
Added fallback for missing 'AndroidManifest' tag in project file
i-nikityuk May 26, 2022
1b403ff
Merge pull request #3 from inikityuk/feature/android_aab_build_support
inikityuk May 26, 2022
19771c5
Added "provision_profile_uuid" property to specify provisioning profi…
i-nikityuk May 27, 2022
51b599f
Updated readme
i-nikityuk May 27, 2022
2f0c4e0
Merge pull request #4 from inikityuk/feature/ios_added_property_to_sp…
inikityuk May 27, 2022
f81d752
Updated github readme
i-nikityuk May 27, 2022
790ce9b
Merge pull request #5 from inikityuk/feature/update_github_readme
inikityuk May 27, 2022
d2663f8
added ability to create .xcarchive on build for iOS
i-nikityuk Aug 16, 2022
f8a0cfd
Merge pull request #6 from inikityuk/feature/archive_on_build_support
inikityuk Aug 16, 2022
a0db094
Updated readme
i-nikityuk Aug 16, 2022
d9efc23
Merge pull request #7 from inikityuk/feature/archive_on_build_support
inikityuk Aug 16, 2022
e5cf1d1
Updated build command to match VS
i-nikityuk Aug 27, 2023
fa8c0d9
Updated plugin to support NET 6-7 projects
i-nikityuk Sep 12, 2023
2b8d700
Clean up
i-nikityuk Sep 13, 2023
59712a4
Updated README
i-nikityuk Sep 13, 2023
1147922
Merge pull request #8 from inikityuk/feature/NET6_build_support_update
inikityuk Sep 13, 2023
4bf1f3e
Update JDK version selection
i-nikityuk Jun 13, 2024
90b7706
Merge pull request #9 from inikityuk/feature/NET6_build_support_update
inikityuk Jun 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ A fastlane component to make Xamarin builds a breeze. Souyuz is now avaialbe as

*NOTE: While souyuz should continue working with your existing configuration just fine, consider using the Fastlane plugin.*

# inikityuk 16/08/2022
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please extract this portion to a CHANGELOG.md file?

* iOS: added ability to create *.xcarchive on build

# inikityuk 27/05/2022
### Few major changes to "Souyuz" plugin
* Android: added ability to build AAB files (including signing)
* Android: added support to projects with multiple AndroidManifest files (handy if your build configuration using different ones)
* Android: added "key-password" signing property (handy if "store password" doesn't match with "key password")
* Android/iOS: added support for compile constants (handy if you using them as switches in projects)
* iOS: added ability to specify provisioning profile to sign with
* Updated readme with most common properties and basic usage

## Using MSBuild

Since Version 0.7.0 souyuz is using `msbuild` by default, because according to Xamarin `xbuild` is deprecated and will be removed soon.
Expand Down
17 changes: 12 additions & 5 deletions fastlane-plugin-souyuz/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ platform :ios do
lane :example do
souyuz(
platform: "ios",
build_configuration: "Release",
plist_path: "./iOS/Info.plist"
build_target: ['Clean','Build'], # OPTIONAL - default to 'Build'
build_platform: "iPhone", # OPTIONAL -> One of "iPhone iPhoneSimulator AnyCPU" -> default to iOS:"iPhone", Android:"AnyCPU"
build_configuration: "Release", # OPTIONAL -> default to "Release"
plist_path: "./iOS/Info.plist",
provision_profile_uuid: "{PROVISIONING_PROFILE_TO_SIGN_WITH}", # OPTIONAL -> default to Visual Studio configuration
archive_app: true # Create *.xcarchive file, -> default to "false"
)
end
end
Expand All @@ -29,9 +33,12 @@ platform :android do
souyuz(
platform: "android",
build_configuration: "Release",
keystore_path: "{PATH_TO_YOUR_KEYSTORE}",
keystore_alias: "{ALIAS_OF_YOUR_KEYSTORE}",
keystore_password: "{YOUR_SUPER_SECRET_KEYSTORE_PASSWORD}"
build_target: ['Clean','Build'], # OPTIONAL - default to 'Build'
build_platform: "AnyCPU", # OPTIONAL -> One of "iPhone iPhoneSimulator AnyCPU" -> default to iOS:"iPhone", Android:"AnyCPU"
keystore_path: "{PATH_TO_YOUR_KEYSTORE}", # OPTIONAL - if not provided Xamarin default keystore will be used
keystore_alias: "{ALIAS_OF_YOUR_KEYSTORE}", # OPTIONAL - if not provided Xamarin default keystore will be used
keystore_password: "{YOUR_SUPER_SECRET_KEYSTORE_PASSWORD}", # OPTIONAL - if not provided Xamarin default keystore will be used
key_password: "{YOUR_SUPER_SECRET_KEY_PASSWORD}" # OPTIONAL - if not provided Xamarin default keystore will be used
)
end
end
Expand Down
3 changes: 2 additions & 1 deletion lib/souyuz.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require 'souyuz/generators/build_command_generator'
require 'souyuz/generators/zipalign_command_generator'
require 'souyuz/generators/apk_sign_command_generator'
require 'souyuz/generators/aab_sign_command_generator'
require 'souyuz/generators/zip_dsym_command_generator'
require 'souyuz/runner'
require 'souyuz/options'
Expand All @@ -24,8 +25,8 @@ class << self

def config=(value)
@config = value
DetectValues.set_additional_default_values
@cache = {}
DetectValues.set_additional_default_values
end
end

Expand Down
29 changes: 28 additions & 1 deletion lib/souyuz/detect_values.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ def self.set_additional_default_values
detect_build_tools
detect_info_plist
detect_assembly_name doc_csproj # we can only do that for android *after* we detected the android manitfest
detect_compile_constants doc_csproj # all platforms
detect_android_package_format doc_csproj

return config
end
Expand Down Expand Up @@ -75,7 +77,14 @@ def self.detect_output_path(doc_csproj)
def self.detect_manifest(doc_csproj)
return if Souyuz.config[:manifest_path] or Souyuz.config[:platform] != Platform::ANDROID

doc_node = doc_csproj.css('PropertyGroup > AndroidManifest')
configuration = Souyuz.config[:build_configuration]
platform = Souyuz.config[:build_platform]

doc_node = doc_csproj.xpath("/*[local-name()='Project']/*[local-name()='PropertyGroup'][translate(@*[local-name() = 'Condition'],'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz') = \" '$(configuration)|$(platform)' == '#{configuration.downcase}|#{platform.downcase}' \"]/*[local-name()='AndroidManifest']/text()")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be cleaned up a bit?
It looks like it is somewhat similar to Lines 172 in the same file.


# For AAB builds: "<AndroidManifest> tag might be missed, so falling back to first available value"
doc_node = doc_csproj.css('PropertyGroup > AndroidManifest').first if doc_node.empty?

Souyuz.config[:manifest_path] = abs_project_path doc_node.text
end

Expand Down Expand Up @@ -155,5 +164,23 @@ def self.abs_path(path)
path = File.expand_path(path) # absolute dir
path
end

def self.detect_compile_constants(doc_csproj)
configuration = Souyuz.config[:build_configuration]
platform = Souyuz.config[:build_platform]

compile_constants_node = doc_csproj.xpath("/*[local-name()='Project']/*[local-name()='PropertyGroup'][translate(@*[local-name() = 'Condition'],'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz') = \" '$(configuration)|$(platform)' == '#{configuration.downcase}|#{platform.downcase}' \"]/*[local-name()='DefineConstants']/text()")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

Souyuz.cache[:compile_constants] = compile_constants_node.text.gsub(";", " ")
compile_constants_node.text
end

def self.detect_android_package_format(doc_csproj)
configuration = Souyuz.config[:build_configuration]
platform = Souyuz.config[:build_platform]

android_package_format_node = doc_csproj.xpath("/*[local-name()='Project']/*[local-name()='PropertyGroup'][translate(@*[local-name() = 'Condition'],'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz') = \" '$(configuration)|$(platform)' == '#{configuration.downcase}|#{platform.downcase}' \"]/*[local-name()='AndroidPackageFormat']/text()")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

Souyuz.cache[:android_package_format] = android_package_format_node.text
android_package_format_node.text
end
end
end
44 changes: 44 additions & 0 deletions lib/souyuz/generators/aab_sign_command_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module Souyuz
# Responsible for building the aabsigner command
class AabSignCommandGenerator
class << self
def generate
android_package_path = Souyuz.cache[:build_android_package_path]
android_package_dir = File.dirname(android_package_path)
android_package_filename_with_extension = "#{File.basename(android_package_path, ".*")}-signed#{File.extname(android_package_path)}"
Souyuz.cache[:signed_android_package_path] = "#{File.join("#{android_package_dir}", "#{android_package_filename_with_extension}")}"

parts = prefix
parts += options
parts += pipe

parts
end

def prefix
[""]
end

def options
options = []
options << "jarsigner"
options << "--verbose" if $verbose
options << "-keystore \"#{Souyuz.config[:keystore_path]}\""
options << "-storepass \"#{Souyuz.config[:keystore_password]}\""
options << "-keypass \"#{Souyuz.config[:key_password]}\""
options << "-digestalg \"SHA-256\""
options << "-sigalg \"SHA256withRSA\""
options << "-signedjar \"#{Souyuz.cache[:signed_android_package_path]}\" \"#{Souyuz.cache[:build_android_package_path]}\""
options << "\"#{Souyuz.config[:keystore_alias]}\""

options
end

def pipe
pipe = []

pipe
end
end
end
end
9 changes: 6 additions & 3 deletions lib/souyuz/generators/apk_sign_command_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ module Souyuz
class ApkSignCommandGenerator
class << self
def generate
build_apk_path = Souyuz.cache[:build_apk_path]
Souyuz.cache[:signed_apk_path] = "#{build_apk_path}-signed"
android_package_path = Souyuz.cache[:build_android_package_path]
android_package_dir = File.dirname(android_package_path)
android_package_filename_with_extension = "#{File.basename(android_package_path, ".*")}-signed#{File.extname(android_package_path)}"
Souyuz.cache[:signed_android_package_path] = "#{File.join("#{android_package_dir}", "#{android_package_filename_with_extension}")}"

parts = prefix
parts << detect_apksigner_executable
Expand Down Expand Up @@ -32,7 +34,8 @@ def options
options << "--ks \"#{Souyuz.config[:keystore_path]}\""
options << "--ks-pass \"pass:#{Souyuz.config[:keystore_password]}\""
options << "--ks-key-alias \"#{Souyuz.config[:keystore_alias]}\""
options << "--out \"#{Souyuz.cache[:signed_apk_path]}\""
options << "--key-pass \"pass:#{Souyuz.config[:key_password]}\""
options << "--out \"#{Souyuz.cache[:signed_android_package_path]}\""

options
end
Expand Down
4 changes: 3 additions & 1 deletion lib/souyuz/generators/build_command_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def options
options << "-p:Configuration=#{config[:build_configuration]}" if config[:build_configuration]
options << "-p:Platform=#{config[:build_platform]}" if Souyuz.project.ios? and config[:build_platform]
options << "-p:BuildIpa=true" if Souyuz.project.ios?
options << "-p:DefineConstants=\"#{Souyuz.cache[:compile_constants]}\"" if Souyuz.cache[:compile_constants]
if config[:solution_path]
solution_dir = File.dirname(config[:solution_path])
options << "-p:SolutionDir=\"#{solution_dir}/\""
Expand All @@ -44,7 +45,8 @@ def build_targets
def targets
targets = []
targets += build_targets
targets << "-t:SignAndroidPackage" if Souyuz.project.android?
targets << "-t:SignAndroidPackage" if Souyuz.project.android? and !Souyuz.config[:keystore_path] and !Souyuz.config[:keystore_alias] and !Souyuz.config[:keystore_password]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you group those conditions to a helper method for better readability, please?

targets << "-t:Package" if Souyuz.project.android? and Souyuz.config[:keystore_path] and Souyuz.config[:keystore_alias] and Souyuz.config[:keystore_password]

targets
end
Expand Down
8 changes: 5 additions & 3 deletions lib/souyuz/generators/zipalign_command_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ module Souyuz
class ZipalignCommandGenerator
class << self
def generate
build_apk_path = Souyuz.cache[:build_apk_path]
Souyuz.cache[:aligned_apk_path] = "#{build_apk_path}-aligned"
android_package_path = Souyuz.cache[:build_android_package_path]
android_package_dir = File.dirname(android_package_path)
android_package_filename_with_extension = "#{File.basename(android_package_path, ".*")}-aligned#{File.extname(android_package_path)}"
Souyuz.cache[:aligned_apk_path] = "#{File.join("#{android_package_dir}", "#{android_package_filename_with_extension}")}"

parts = prefix
parts << zipalign_apk
parts += options
parts << build_apk_path
parts << android_package_path
parts << Souyuz.cache[:aligned_apk_path]
parts += pipe

Expand Down
33 changes: 31 additions & 2 deletions lib/souyuz/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

module Souyuz
class Options

PROVISION_FILES_DEFAULT_LOCATION = "#{Dir.home}/Library/MobileDevice/Provisioning\ Profiles/".freeze
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of this: Allow the user not to specify a provisioning profile UUID but the whole path to it. You give the user more flexibility if the profile is downloaded to the project folder for example.
Therefore we can safe us from hardcoding paths which are prone to change in future buildchain versions.

BUILD_PLATFORMS = %w(iPhone iPhoneSimulator AnyCPU).freeze

def self.available_options
[
FastlaneCore::ConfigItem.new(key: :silent,
Expand All @@ -20,7 +24,11 @@ def self.available_options
FastlaneCore::ConfigItem.new(key: :build_platform,
env_name: "SOUYUZ_BUILD_PLATFORM",
description: "Build platform value",
default_value: 'iPhone'),
default_value: 'iPhone',
is_string: true,
verify_block: proc do |value|
UI.user_error!("Unsupported build platform, use one of #{BUILD_PLATFORMS}") unless BUILD_PLATFORMS.include? value
end),
FastlaneCore::ConfigItem.new(key: :build_target,
env_name: "SOUYUZ_BUILD_TARGET",
description: "Build targets to build",
Expand Down Expand Up @@ -78,11 +86,32 @@ def self.available_options
env_name: "SOUYUZ_ANDROID_KEYSTORE_PASSWORD",
description: "Password of the keystore",
optional: true),
FastlaneCore::ConfigItem.new(key: :key_password,
env_name: "SOUYUZ_ANDROID_KEY_PASSWORD",
description: "Password of the key",
optional: true),
FastlaneCore::ConfigItem.new(key: :keystore_tsa,
default_value: 'http://timestamp.digicert.com',
env_name: "SOUYUZ_ANDROID_KEYSTORE_TSA",
description: "TSA for apksigner",
optional: true)
optional: true),
FastlaneCore::ConfigItem.new(key: :provision_profile_uuid,
env_name: "SOUYUZ_IOS_PP_UUID",
description: "UUID of provision profile in default dir",
is_string: true,
optional: true,
verify_block: proc do |uuid|
file = File.join PROVISION_FILES_DEFAULT_LOCATION, "#{uuid}.mobileprovision"
UI.user_error!('Empty input') if file.nil?
UI.user_error!("#{file} does not exist") unless File.exist? file
UI.user_error!("#{file} is not a file") unless File.file? file
# check if newer PP exist
end),
FastlaneCore::ConfigItem.new(key: :archive_app,
env_name: "SOUYUZ_CREATE_ARCHIVE",
description: "Create *.xcarchive file, only for iOS",
default_value: false,
is_string: false),
]
end
end
Expand Down
Loading