fastlane-plugin-xambuild 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,69 @@
1
+ require "fastlane/plugin/xambuild/helpers/options"
2
+ require "fastlane/plugin/xambuild/helpers/platform"
3
+ require "fastlane/plugin/xambuild/helpers/manager"
4
+
5
+ module Fastlane
6
+ module Actions
7
+ module SharedValues
8
+ # for calabash
9
+ APP_BUNDLE_PATH = :APP_BUNDLE_PATH
10
+ APP_OUTPUT_PATH = :APP_OUTPUT_PATH
11
+ end
12
+
13
+ class XambuildAction < Action
14
+
15
+ def self.run(values)
16
+ values[:platform] = ::Xambuild::Platform.from_lane_context(Actions.lane_context)
17
+ ::Xambuild.config = values
18
+
19
+ if ::Xambuild.project.ios? || ::Xambuild.project.osx?
20
+ absolute_ipa_path = File.expand_path(::Xambuild::Manager.new.work(values))
21
+ absolute_app_path = File.join(values[:output_path], "#{values[:assembly_name]}.app")
22
+ absolute_dsym_path = absolute_ipa_path.gsub(".ipa", ".app.dSYM.zip")
23
+
24
+ Actions.lane_context[SharedValues::APP_OUTPUT_PATH] = absolute_app_path
25
+ Actions.lane_context[SharedValues::IPA_OUTPUT_PATH] = absolute_ipa_path
26
+ Actions.lane_context[SharedValues::DSYM_OUTPUT_PATH] = absolute_dsym_path if File.exist?(absolute_dsym_path)
27
+ ENV[SharedValues::APP_OUTPUT_PATH.to_s] = absolute_app_path
28
+ ENV[SharedValues::APP_BUNDLE_PATH.to_s] = absolute_app_path # for calabash
29
+ ENV[SharedValues::IPA_OUTPUT_PATH.to_s] = absolute_ipa_path # for deliver
30
+ ENV[SharedValues::DSYM_OUTPUT_PATH.to_s] = absolute_dsym_path if File.exist?(absolute_dsym_path)
31
+
32
+ absolute_ipa_path
33
+ elsif ::Xambuild.project.android?
34
+ if values[:keystore_path] && values[:keystore_alias]
35
+ unless values[:keystore_password]
36
+ ::Xambuild.config[:keystore_password] = ask("Password (for #{values[:keystore_alias]}): ") { |q| q.echo = "*" }
37
+ end
38
+ end
39
+ absolute_apk_path = File.expand_path(::Xambuild::Manager.new.work(values))
40
+
41
+ Actions.lane_context[SharedValues::GRADLE_BUILD_TYPE] = values[:build_configuration]
42
+ Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH] = absolute_apk_path
43
+
44
+ absolute_apk_path
45
+ end
46
+ end
47
+
48
+ def self.description
49
+ "Easily build and sign your app using `xambuild`"
50
+ end
51
+
52
+ def self.return_value
53
+ "The absolute path to the generated app file"
54
+ end
55
+
56
+ def self.author
57
+ "Jake Barnby"
58
+ end
59
+
60
+ def self.available_options
61
+ ::Xambuild::Options.available_options
62
+ end
63
+
64
+ def self.is_supported?(platform)
65
+ true
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,46 @@
1
+ require "commander"
2
+ require "fastlane"
3
+
4
+ HighLine.track_eof = false
5
+
6
+ module Xambuild
7
+ class CommandsGenerator
8
+ include Commander::Methods
9
+ UI = FastlaneCore::UI
10
+
11
+ FastlaneCore::CommanderGenerator.new.generate(Xambuild::Options.available_options)
12
+
13
+ def self.start
14
+ new.run
15
+ end
16
+
17
+ def convert_options(options)
18
+ o = options.__hash__.dup
19
+ o.delete(:verbose)
20
+ o
21
+ end
22
+
23
+ def run
24
+ program :version, Xambuild::VERSION
25
+ program :description, Xambuild::DESCRIPTION
26
+ program :help, "Author", "Jake Barnby <jakeb994@gmail.com>"
27
+ program :help_formatter, :compact
28
+
29
+ global_option("--verbose") { $verbose = true }
30
+
31
+ command :build do |c|
32
+ c.syntax = "xambuild"
33
+ c.description = "Just builds your app"
34
+ c.action do |_args, options|
35
+ config = FastlaneCore::Configuration.create(Xambuild::Options.available_options,
36
+ convert_options(options))
37
+ Xambuild::Manager.new.work(config)
38
+ end
39
+ end
40
+
41
+ default_command :build
42
+
43
+ run!
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,145 @@
1
+ require "nokogiri"
2
+ require "fastlane/plugin/xambuild/helpers/msbuild/project"
3
+ require "fastlane/plugin/xambuild/helpers/msbuild/solution_parser"
4
+
5
+ module Xambuild
6
+ class DetectValues
7
+
8
+ def self.set_additional_default_values
9
+ config = Xambuild.config
10
+
11
+ # TODO: detect_platform automatically for :platform config
12
+
13
+ if config[:platform] == Platform::ANDROID
14
+ config[:build_platform] = "AnyCPU"
15
+ end
16
+
17
+ # Detect the project
18
+ Xambuild.project = Msbuild::Project.new(config)
19
+ detect_solution
20
+ detect_project
21
+
22
+ doc_csproj = get_parser_handle config[:project_path]
23
+
24
+ detect_output_path doc_csproj
25
+ detect_manifest doc_csproj
26
+ detect_info_plist
27
+ detect_assembly_name doc_csproj
28
+
29
+ config
30
+ end
31
+
32
+ # Helper Methods
33
+
34
+ def self.detect_solution
35
+ return if Xambuild.config[:solution_path]
36
+
37
+ sln = find_file("*.sln", 3)
38
+ UI.user_error! "Not able to find solution file automatically, try to specify it via `solution_path` parameter." unless sln
39
+
40
+ Xambuild.config[:solution_path] = abs_path sln
41
+ end
42
+
43
+ def self.detect_project
44
+ return if Xambuild.config[:project_path]
45
+
46
+ path = Xambuild.config[:solution_path]
47
+ projects = Msbuild::SolutionParser.parse(path)
48
+ .get_platform Xambuild.config[:platform]
49
+
50
+ UI.user_error! "Not able to find any project in solution, that matches the platform `#{Xambuild.config[:platform]}`." unless projects.any?
51
+
52
+ project = projects.first
53
+ csproj = fix_path_relative project.project_path
54
+
55
+ UI.user_error! "Not able to find project file automatically, try to specify it via `project_path` parameter." unless csproj
56
+
57
+ Xambuild.config[:project_name] = project.project_name
58
+ Xambuild.config[:project_path] = abs_path csproj
59
+ end
60
+
61
+ def self.detect_output_path(doc_csproj)
62
+ return if Xambuild.config[:output_path]
63
+
64
+ configuration = Xambuild.config[:build_configuration]
65
+ platform = Xambuild.config[:build_platform]
66
+
67
+ 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()='OutputPath']/text()")
68
+ output_path = doc_node.text
69
+ UI.user_error! "Not able to find output path automatically, try to specify it via `output_path` parameter." unless output_path
70
+
71
+ Xambuild.config[:output_path] = abs_project_path output_path
72
+ end
73
+
74
+ def self.detect_manifest(doc_csproj)
75
+ return if Xambuild.config[:manifest_path] || (Xambuild.config[:platform] != Platform::ANDROID)
76
+
77
+ doc_node = doc_csproj.css("AndroidManifest").first
78
+
79
+ Xambuild.config[:manifest_path] = abs_project_path doc_node.text
80
+ end
81
+
82
+ def self.detect_info_plist
83
+ return if Xambuild.config[:plist_path] || (Xambuild.config[:platform] != Platform::IOS)
84
+
85
+ plist_path = find_file("Info.plist", 1)
86
+ UI.user_error! "Not able to find Info.plist automatically, try to specify it via `plist_path` parameter." unless plist_path
87
+
88
+ Xambuild.config[:plist_path] = abs_project_path plist_path
89
+ end
90
+
91
+ def self.detect_assembly_name(doc_csproj)
92
+ return if Xambuild.config[:assembly_name]
93
+
94
+ if [Platform::IOS, Platform::OSX].include? Xambuild.config[:platform]
95
+ Xambuild.config[:assembly_name] = doc_csproj.css("PropertyGroup > AssemblyName").text
96
+ elsif Xambuild.config[:platform] == Platform::ANDROID
97
+ doc = get_parser_handle Xambuild.config[:manifest_path]
98
+ Xambuild.config[:assembly_name] = doc.xpath("string(//manifest/@package)")
99
+ end
100
+ end
101
+
102
+ private_class_method
103
+
104
+ def self.find_file(query, depth)
105
+ itr = 0
106
+ files = []
107
+
108
+ loop do
109
+ files = Dir.glob(query)
110
+ query = "../#{query}"
111
+ itr += 1
112
+ break if files.any? || (itr > depth)
113
+ end
114
+
115
+ files.first
116
+ end
117
+
118
+ def self.get_parser_handle(filename)
119
+ f = File.open(filename)
120
+ doc = Nokogiri::XML(f)
121
+ f.close
122
+
123
+ doc
124
+ end
125
+
126
+ def self.fix_path_relative(path)
127
+ root = File.dirname Xambuild.config[:solution_path]
128
+ path = "#{root}/#{path}"
129
+ path
130
+ end
131
+
132
+ def self.abs_project_path(path)
133
+ path = path.tr('\\', "/")
134
+ platform_path = Xambuild.config[:project_path]
135
+ path = "#{File.dirname platform_path}/#{path}"
136
+ path
137
+ end
138
+
139
+ def self.abs_path(path)
140
+ path = path.tr('\\', "/")
141
+ path = File.expand_path(path)
142
+ path
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,53 @@
1
+ module Xambuild
2
+ class AndroidZipalignCommandGenerator
3
+ class << self
4
+ def generate
5
+ parts = prefix
6
+ parts << zipalign_apk
7
+ parts += options
8
+ parts << Xambuild.cache[:signed_apk_path]
9
+ parts << Xambuild.cache[:build_apk_path]
10
+ parts += pipe
11
+
12
+ parts
13
+ end
14
+
15
+ def detect_build_tools
16
+ UI.user_error! "Please ensure that the Android SDK is installed and the ANDROID_HOME variable is set correctly" unless ENV["ANDROID_HOME"]
17
+
18
+ buildtools = File.join(ENV["ANDROID_HOME"], "build-tools")
19
+ version = Dir.entries(buildtools).max
20
+
21
+ UI.success "Using Buildtools Version: #{version}..."
22
+
23
+ [buildtools, version]
24
+ end
25
+
26
+ def zipalign_apk
27
+ buildtools, version = detect_build_tools
28
+ zipalign = ENV["ANDROID_HOME"] ? File.join(buildtools, version, "zipalign") : "zipalign"
29
+
30
+ zipalign
31
+ end
32
+
33
+ def options
34
+ options = []
35
+ options << "-v" if $verbose
36
+ options << "-f"
37
+ options << "4"
38
+
39
+ options
40
+ end
41
+
42
+ def prefix
43
+ [""]
44
+ end
45
+
46
+ def pipe
47
+ pipe = []
48
+
49
+ pipe
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,66 @@
1
+ module Xambuild
2
+ class BuildCommandGenerator
3
+ class << self
4
+ def generate
5
+ parts = prefix
6
+ parts << compiler_bin
7
+ parts += options
8
+ parts += targets
9
+ parts += project
10
+ parts += pipe
11
+
12
+ parts
13
+ end
14
+
15
+ def prefix
16
+ [""]
17
+ end
18
+
19
+ def compiler_bin
20
+ Xambuild.config[:compiler_bin]
21
+ end
22
+
23
+ def options
24
+ config = Xambuild.config
25
+
26
+ options = []
27
+ options << config[:extra_build_options] if config[:extra_build_options]
28
+ options << "-p:Configuration=#{config[:build_configuration]}" if config[:build_configuration]
29
+ options << "-p:Platform=#{config[:build_platform]}" if Xambuild.project.ios? && config[:build_platform]
30
+ options << "-p:BuildIpa=true" if Xambuild.project.ios?
31
+ if config[:solution_path]
32
+ solution_dir = File.dirname(config[:solution_path])
33
+ options << "-p:SolutionDir=#{solution_dir}/"
34
+ end
35
+
36
+ options
37
+ end
38
+
39
+ def build_targets
40
+ Xambuild.config[:build_target].map! { |t| "-t:#{t}" }
41
+ end
42
+
43
+ def targets
44
+ targets = []
45
+ targets += build_targets
46
+ targets << "-t:SignAndroidPackage" if Xambuild.project.android?
47
+
48
+ targets
49
+ end
50
+
51
+ def project
52
+ path = []
53
+
54
+ path << Xambuild.config[:project_path]
55
+
56
+ path
57
+ end
58
+
59
+ def pipe
60
+ pipe = []
61
+
62
+ pipe
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,50 @@
1
+ module Xambuild
2
+ class JavaSignCommandGenerator
3
+ class << self
4
+ def generate
5
+ build_apk_path = Xambuild.cache[:build_apk_path]
6
+ Xambuild.cache[:signed_apk_path] = "#{build_apk_path}-unaligned"
7
+
8
+ parts = prefix
9
+ parts << detect_jarsigner_executable
10
+ parts += options
11
+ parts << build_apk_path
12
+ parts << Xambuild.config[:keystore_alias]
13
+ parts += pipe
14
+
15
+ parts
16
+ end
17
+
18
+ def prefix
19
+ [""]
20
+ end
21
+
22
+ def detect_jarsigner_executable
23
+ jarsigner = ENV["JAVA_HOME"] ? File.join(ENV["JAVA_HOME"], "bin", "jarsigner") : "jarsigner"
24
+
25
+ jarsigner
26
+ end
27
+
28
+ def options
29
+ config = Xambuild.config
30
+
31
+ options = []
32
+ options << "-verbose" if $verbose
33
+ options << "-sigalg MD5withRSA"
34
+ options << "-digestalg SHA1"
35
+ options << "-storepass \"#{config[:keystore_password]}\""
36
+ options << "-keystore \"#{config[:keystore_path]}\""
37
+ options << "-tsa #{config[:keystore_tsa]}"
38
+ options << "-signedjar \"#{Xambuild.cache[:signed_apk_path]}\""
39
+
40
+ options
41
+ end
42
+
43
+ def pipe
44
+ pipe = []
45
+
46
+ pipe
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,41 @@
1
+ module Xambuild
2
+ class ZipDsymCommandGenerator
3
+ class << self
4
+ def generate
5
+ parts = prefix
6
+ parts << detect_zip_executable
7
+ parts += options
8
+ parts += pipe
9
+
10
+ parts
11
+ end
12
+
13
+ def prefix
14
+ [""]
15
+ end
16
+
17
+ def detect_zip_executable
18
+ zip = ENV["XAMBUILD_ZIP_PATH"] || "zip"
19
+
20
+ zip
21
+ end
22
+
23
+ def options
24
+ build_dsym_path = Xambuild.cache[:build_dsym_path]
25
+
26
+ options = []
27
+ options << "-r"
28
+ options << "#{build_dsym_path}.zip"
29
+ options << build_dsym_path
30
+
31
+ options
32
+ end
33
+
34
+ def pipe
35
+ pipe = []
36
+
37
+ pipe
38
+ end
39
+ end
40
+ end
41
+ end