xcodebuild_rake 2.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gemrc +1 -0
- data/.gitignore +1 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +25 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/xcodebuild_rake_init +8 -0
- data/docs/configuration.md +43 -0
- data/docs/installation.md +11 -0
- data/docs/prerequisites.md +34 -0
- data/docs/usage.md +71 -0
- data/lib/.DS_Store +0 -0
- data/lib/ExportOptions.plist +10 -0
- data/lib/model/build_configuration.rb +90 -0
- data/lib/model/release_configuration.rb +46 -0
- data/lib/model/test_destination.rb +41 -0
- data/lib/model/upload_configuration.rb +63 -0
- data/lib/modules/applause_tool.rb +18 -0
- data/lib/modules/plist.rb +31 -0
- data/lib/modules/s3.rb +19 -0
- data/lib/modules/xcode.rb +142 -0
- data/lib/modules/zip.rb +18 -0
- data/lib/tasks/applause_pod.rake +75 -0
- data/lib/tasks/framework.rake +49 -0
- data/lib/tasks/notify.rake +9 -0
- data/lib/tasks/podspec.rake +85 -0
- data/lib/tasks/testapp.rake +48 -0
- data/lib/tasks/version_number.rake +83 -0
- data/lib/xcodebuild_rake.rb +29 -0
- data/lib/xcodebuild_rake/version.rb +3 -0
- data/lib/xcodebuild_safe.sh +38 -0
- data/templates/Rakefile +54 -0
- data/templates/build.yaml +15 -0
- data/xcodebuild_rake.gemspec +32 -0
- metadata +157 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
# Copyright (c) 2017 Applause Inc. All rights reserved.
|
2
|
+
|
3
|
+
namespace :framework do
|
4
|
+
desc "Build the SDK binary"
|
5
|
+
task :build, [:setup_name] do |t, args|
|
6
|
+
setup_name = args[:setup_name]
|
7
|
+
setup = BuildConfiguration.load(setup_name)
|
8
|
+
Xcode.build_universal_framework setup_name, setup.release_configuration.output_path
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Compress SDK"
|
12
|
+
task :archive, [:setup_name] => :build do |t, args|
|
13
|
+
setup_name = args[:setup_name]
|
14
|
+
setup = BuildConfiguration.load(setup_name)
|
15
|
+
if (setup.release_configuration.plist && setup.release_configuration.output_path && setup.release_configuration.product_name)
|
16
|
+
framework_path = setup.release_configuration.output_path + '/' + setup.release_configuration.product_name + '.framework'
|
17
|
+
archived_framework_path = archived_framework_path(setup_name)
|
18
|
+
Zip.compress(framework_path, archived_framework_path)
|
19
|
+
puts "Compressed Framework path: #{archived_framework_path}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "Upload SDK to S3"
|
24
|
+
task :upload, [:setup_name] => :archive do |t, args|
|
25
|
+
setup_name = args[:setup_name]
|
26
|
+
setup = BuildConfiguration.load(setup_name)
|
27
|
+
if (setup.release_configuration.plist && setup.release_configuration.output_path && setup.release_configuration.product_name &&
|
28
|
+
setup.release_configuration.s3_upload_folder && setup.release_configuration.s3_bucket)
|
29
|
+
archived_framework_path = archived_framework_path(setup_name)
|
30
|
+
s3_upload_path = s3_upload_path(setup_name)
|
31
|
+
url = S3.upload_file(archived_framework_path, s3_upload_path, setup.release_configuration.s3_bucket)
|
32
|
+
puts "Framework S3 url: #{url}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def archived_framework_path(setup_name)
|
37
|
+
setup = BuildConfiguration.load(setup_name)
|
38
|
+
version = Plist.version(setup.release_configuration.plist)
|
39
|
+
archived_framework_path = setup.release_configuration.output_path + '/' + setup.release_configuration.product_name + '-' + version + '.zip'
|
40
|
+
return archived_framework_path
|
41
|
+
end
|
42
|
+
|
43
|
+
def s3_upload_path(setup_name)
|
44
|
+
setup = BuildConfiguration.load(setup_name)
|
45
|
+
version = Plist.version(setup.release_configuration.plist)
|
46
|
+
s3_upload_path = setup.release_configuration.s3_upload_folder + '/' + version + '/' + setup.release_configuration.product_name + '-' + version + '.zip'
|
47
|
+
return s3_upload_path
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Copyright (c) 2017 Applause Inc. All rights reserved.
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'git'
|
5
|
+
require 'cocoapods'
|
6
|
+
|
7
|
+
PODSPEC_TEMPLATE_PATH = "./Applause-Podspecs/%{pod_name}/%{pod_name}.template"
|
8
|
+
PODSPEC_PATH = "./Applause-Podspecs/%{pod_name}/%{version}/%{pod_name}.podspec"
|
9
|
+
|
10
|
+
namespace :podspec do
|
11
|
+
|
12
|
+
desc "Generates podspec for given setup name"
|
13
|
+
task :generate, [:setup_name] do |t, args|
|
14
|
+
setup_name = args[:setup_name]
|
15
|
+
setup = BuildConfiguration.load(setup_name)
|
16
|
+
version = Plist.version(setup.release_configuration.plist)
|
17
|
+
pod_name = setup.release_configuration.pod_name
|
18
|
+
template_path = PODSPEC_TEMPLATE_PATH % {pod_name: pod_name, version: version}
|
19
|
+
podspec_path = PODSPEC_PATH % {pod_name: pod_name, version: version}
|
20
|
+
podspec = generate_podspec(template_path, version)
|
21
|
+
save_podspec(podspec_path, podspec)
|
22
|
+
end
|
23
|
+
|
24
|
+
task :verify, [:setup_name] do |t, args|
|
25
|
+
pod_name, version = properties_from_setup(args[:setup_name])
|
26
|
+
podspec_path = PODSPEC_PATH % {pod_name: pod_name, version: version}
|
27
|
+
if !lint_podspec(podspec_path)
|
28
|
+
raise "*** Podspec is not valid! ***"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Generates and commits podspec for given setup name"
|
33
|
+
task :commit, [:setup_name] => :generate do |t, args|
|
34
|
+
setup_name = args[:setup_name]
|
35
|
+
setup = BuildConfiguration.load(setup_name)
|
36
|
+
version = Plist.version(setup.release_configuration.plist)
|
37
|
+
pod_name = setup.release_configuration.pod_name
|
38
|
+
podspec_path = PODSPEC_PATH % {pod_name: pod_name, version: version}
|
39
|
+
commit_message = "Generated #{pod_name} Podspec for #{version}"
|
40
|
+
commit(podspec_path, commit_message)
|
41
|
+
end
|
42
|
+
|
43
|
+
def generate_podspec(template_path, version)
|
44
|
+
template_file = File.open(template_path)
|
45
|
+
template = template_file.read
|
46
|
+
podspec = template % {version: version}
|
47
|
+
puts "New podspec:"
|
48
|
+
puts podspec
|
49
|
+
return podspec
|
50
|
+
end
|
51
|
+
|
52
|
+
def save_podspec(podspec_path, podspec_contents)
|
53
|
+
dirname = File.dirname(podspec_path)
|
54
|
+
unless File.directory?(dirname)
|
55
|
+
FileUtils.mkdir_p(dirname)
|
56
|
+
end
|
57
|
+
File.open(podspec_path, 'w') {|f|
|
58
|
+
f.write(podspec_contents)
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def lint_podspec(podspec_path)
|
63
|
+
validator = Pod::Validator.new(podspec_path, [])
|
64
|
+
valid = validator.validate
|
65
|
+
if !valid
|
66
|
+
validator.print_results
|
67
|
+
else
|
68
|
+
puts "*** Podspec is valid! ***"
|
69
|
+
end
|
70
|
+
return valid
|
71
|
+
end
|
72
|
+
|
73
|
+
def commit(file, message)
|
74
|
+
sdk_repo = Git.open('.')
|
75
|
+
sdk_repo.add(file)
|
76
|
+
sdk_repo.commit(message)
|
77
|
+
end
|
78
|
+
|
79
|
+
def properties_from_setup(setup_name)
|
80
|
+
setup = BuildConfiguration.load(setup_name)
|
81
|
+
version = Plist.version(setup.release_configuration.plist)
|
82
|
+
pod_name = setup.release_configuration.pod_name
|
83
|
+
return [pod_name, version]
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Copyright (c) 2017 Applause Inc. All rights reserved.
|
2
|
+
|
3
|
+
namespace :testapp do
|
4
|
+
desc "Updates test app application key"
|
5
|
+
task :configure, [:setup_name, :upload_configuration_name] do |t, args|
|
6
|
+
configuration = UploadConfiguration.load(args[:upload_configuration_name])
|
7
|
+
setup_name = args[:setup_name]
|
8
|
+
setup = BuildConfiguration.load(setup_name)
|
9
|
+
update_application_key(configuration.application_key, setup.release_configuration.plist)
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Builds application"
|
13
|
+
task :archive, [:setup_name, :upload_configuration_name] => :configure do |t, args|
|
14
|
+
setup_name = args[:setup_name]
|
15
|
+
setup = BuildConfiguration.load(setup_name)
|
16
|
+
output_path = setup.release_configuration.output_path
|
17
|
+
export_options_plist = setup.release_configuration.export_options_plist
|
18
|
+
if export_options_plist.nil?
|
19
|
+
Xcode.archive_and_export_ipa setup_name, output_path
|
20
|
+
else
|
21
|
+
Xcode.archive_and_export_ipa setup_name, output_path, export_options_plist
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Uploads test app to sdk.applause.com"
|
26
|
+
task :publish, [:setup_name, :upload_configuration_name] => :archive do |t, args|
|
27
|
+
upload_configuration_name = args[:upload_configuration_name]
|
28
|
+
configuration = UploadConfiguration.load(upload_configuration_name)
|
29
|
+
ipa_path = ipa_path(args[:setup_name])
|
30
|
+
ApplauseTool.upload_app(ipa_path, configuration.company_id, configuration.app_id, configuration.publish_email, configuration.service, upload_configuration_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def update_application_key(application_key, plist_path)
|
34
|
+
result = `/usr/libexec/PlistBuddy -c "Set :ATCApplicationId #{application_key}" "#{plist_path}"`
|
35
|
+
if result.length > 0
|
36
|
+
puts "Error: #{result}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def ipa_path(setup_name)
|
41
|
+
config = BuildConfiguration.load(setup_name)
|
42
|
+
file_name = config.release_configuration.product_name ? config.release_configuration.product_name : config.scheme
|
43
|
+
archive_folder = File.join(Dir.pwd, config.release_configuration.output_path)
|
44
|
+
ipa_name = file_name + ".ipa"
|
45
|
+
ipa_path = File.join(archive_folder, ipa_name)
|
46
|
+
return ipa_path
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# Copyright (c) 2017 Applause Inc. All rights reserved.
|
2
|
+
|
3
|
+
namespace :version_number do
|
4
|
+
desc "Removes suffix from version string in Info.plist file"
|
5
|
+
task :remove_suffix, [:setup_name] do |t, args|
|
6
|
+
setup_name = args[:setup_name]
|
7
|
+
setup = BuildConfiguration.load(setup_name)
|
8
|
+
plist_path = setup.release_configuration.plist
|
9
|
+
version = Plist.version(plist_path)
|
10
|
+
version_without_suffix = version_without_suffix(version)
|
11
|
+
set_version(plist_path, version_without_suffix)
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Updates build number to current commits count"
|
15
|
+
task :update_sdk_build_version, [:setup_name] do |t, args|
|
16
|
+
setup_name = args[:setup_name]
|
17
|
+
update_build_number_for_setup(setup_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Updates test apps versions and build numbers to values from SDK"
|
21
|
+
task :update_test_apps_versions, [:setup_name] do |t, args|
|
22
|
+
setup_name = args[:setup_name]
|
23
|
+
set_test_apps_versions(setup_name)
|
24
|
+
update_test_app_code_version(setup_name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def update_build_number_to_commits_count(info_plist_path)
|
28
|
+
commits_count = `git rev-list HEAD --count`.strip
|
29
|
+
result = Plist.set_build_number("#{info_plist_path}", "#{commits_count}")
|
30
|
+
if result.length > 0
|
31
|
+
puts "Error: #{result}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def update_test_app_code_version(setup_name)
|
37
|
+
setup = BuildConfiguration.load(setup_name)
|
38
|
+
plist_path = setup.release_configuration.plist
|
39
|
+
version = Plist.version(plist_path)
|
40
|
+
build_number = Plist.build_number(plist_path)
|
41
|
+
code_files = setup.release_configuration.test_apps_version_code_files
|
42
|
+
code_files.each { |file|
|
43
|
+
update_code_file_version(file, "#{version} (#{build_number})")
|
44
|
+
} unless code_files.nil?
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def update_code_file_version(file_path, version)
|
49
|
+
text = File.read(file_path)
|
50
|
+
new_contents = text.gsub("###VERSION###", version)
|
51
|
+
File.open(file_path, "w") { |file| file.puts new_contents }
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def set_test_apps_versions(setup_name)
|
56
|
+
setup = BuildConfiguration.load(setup_name)
|
57
|
+
plist_path = setup.release_configuration.plist
|
58
|
+
version = Plist.version(plist_path)
|
59
|
+
build_number = Plist.build_number(plist_path)
|
60
|
+
test_apps_plists = setup.release_configuration.test_apps_plists
|
61
|
+
test_apps_plists.each { |plist|
|
62
|
+
update_application_version(plist, version, build_number)
|
63
|
+
} unless test_apps_plists.nil?
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def update_build_number_for_setup(setup_name)
|
68
|
+
setup = BuildConfiguration.load(setup_name)
|
69
|
+
plist_path = setup.release_configuration.plist
|
70
|
+
update_build_number_to_commits_count(plist_path)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def version_without_suffix(version)
|
75
|
+
return version.split("-")[0]
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
def update_application_version(info_plist_path, version, build_number)
|
80
|
+
Plist.set_version(info_plist_path, version)
|
81
|
+
Plist.set_build_number(info_plist_path, build_number)
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Copyright (c) 2016 Applause Inc. All rights reserved.
|
2
|
+
|
3
|
+
require "xcodebuild_rake/version"
|
4
|
+
|
5
|
+
ROOT_DIR = File.dirname(__FILE__)
|
6
|
+
|
7
|
+
#Load all rake tasks
|
8
|
+
Dir.glob(File.join(ROOT_DIR, "tasks", "*.rake")) { |script|
|
9
|
+
load script
|
10
|
+
}
|
11
|
+
|
12
|
+
#Load all classes
|
13
|
+
Dir.glob(File.join(ROOT_DIR, "model", "*.rb")) { |script|
|
14
|
+
require "#{script}"
|
15
|
+
}
|
16
|
+
|
17
|
+
#Load all modules
|
18
|
+
Dir.glob(File.join(ROOT_DIR, "modules", "*.rb")) { |script|
|
19
|
+
require "#{script}"
|
20
|
+
include self.class.const_get(File.basename(script).gsub('.rb','').split("_").map{|ea| ea.capitalize}.join(""))
|
21
|
+
}
|
22
|
+
|
23
|
+
Rake::FileUtilsExt.verbose(false)
|
24
|
+
|
25
|
+
### BUILD SCRIPT FUNCTIONS ###
|
26
|
+
|
27
|
+
def display_version()
|
28
|
+
puts File.open("./xcodebuild_rake/version", "rb").read
|
29
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/bin/bash --login
|
2
|
+
|
3
|
+
# Cf. http://stackoverflow.com/questions/33041109
|
4
|
+
#
|
5
|
+
# Xcode 7 (incl. 7.0.1) seems to have a dependency on the system ruby.
|
6
|
+
# xcodebuild is screwed up by using rvm to map to another non-system
|
7
|
+
# ruby†. This script is a fix that allows you call xcodebuild in a
|
8
|
+
# "safe" rvm environment, but will not (AFAIK) affect the "external"
|
9
|
+
# rvm setting.
|
10
|
+
#
|
11
|
+
# The script is a drop in replacement for your xcodebuild call.
|
12
|
+
#
|
13
|
+
# xcodebuild arg1 ... argn
|
14
|
+
#
|
15
|
+
# would become
|
16
|
+
#
|
17
|
+
# path/to/xcbuild-safe.sh arg1 ... argn
|
18
|
+
#
|
19
|
+
# -----
|
20
|
+
# † Because, you know, that *never* happens when you are building
|
21
|
+
# Xcode projects, say with abstruse tools like Rake or CocoaPods.
|
22
|
+
|
23
|
+
# This allows you to use rvm in a script. Otherwise you get a BS
|
24
|
+
# error along the lines of "cannot use rvm as function". Jeez.
|
25
|
+
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
|
26
|
+
|
27
|
+
# Cause rvm to use system ruby. AFAIK, this is effective only for
|
28
|
+
# the scope of this script.
|
29
|
+
rvm use system
|
30
|
+
|
31
|
+
unset RUBYLIB
|
32
|
+
unset RUBYOPT
|
33
|
+
unset BUNDLE_BIN_PATH
|
34
|
+
unset _ORIGINAL_GEM_PATH
|
35
|
+
unset BUNDLE_GEMFILE
|
36
|
+
|
37
|
+
set -x # echoes commands
|
38
|
+
xcodebuild "$@" # calls xcodebuild with all the arguments passed to this
|
data/templates/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'xcodebuild_rake'
|
3
|
+
|
4
|
+
S3_BUCKET = ''
|
5
|
+
|
6
|
+
PRODUCT_NAME = 'MyProject' #Replace 'MyProject' with your project name
|
7
|
+
INFO_PLIST = File.join(PRODUCT_NAME, 'Info.plist') #If your Info property list file is named differently, or is located elswhere, add proper path here
|
8
|
+
|
9
|
+
desc 'Display build script version'
|
10
|
+
task :version do
|
11
|
+
display_version
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'Cleans the project, including the build directory'
|
15
|
+
task :clean do
|
16
|
+
Xcode.clean
|
17
|
+
rm_rf BUILD_DIR
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Builds project using "Default" setup (see build.yaml)'
|
21
|
+
task :build => :clean do
|
22
|
+
Xcode.build
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'Builds project using "Default" setup (see build.yaml) but without cleaning'
|
26
|
+
task :incremental_build do
|
27
|
+
Xcode.build
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'Executes test for the project using "Specs" setup (see build.yaml)'
|
31
|
+
task :test => :clean do
|
32
|
+
test "Specs"
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'Executes test for the project using "Specs" setup (see build.yaml) but without cleaning'
|
36
|
+
task :incremental_test do
|
37
|
+
test "Specs"
|
38
|
+
end
|
39
|
+
|
40
|
+
task :update_build_number do
|
41
|
+
version_number:update_build_number_to_commits_count INFO_PLIST
|
42
|
+
end
|
43
|
+
|
44
|
+
desc 'Archives app using "Default" (see build.yaml) - use this task for distribution'
|
45
|
+
task :archive => [:clean, :update_build_number] do
|
46
|
+
Xcode.archive
|
47
|
+
end
|
48
|
+
|
49
|
+
task :release => :archive do
|
50
|
+
config = BuildConfiguration.load('Default')
|
51
|
+
app_url, archive_url = S3.upload_archived_app "#{BUILD_DIR}/#{config.scheme}.ipa", "#{BUILD_DIR}/#{config.scheme}.xcarchive.zip", INFO_PLIST, S3_BUCKET
|
52
|
+
puts "App was uploaded: #{app_url}"
|
53
|
+
puts "App's Xcode archive was uploaded: #{archive_url}"
|
54
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'xcodebuild_rake/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "xcodebuild_rake"
|
8
|
+
spec.version = XcodebuildRake::VERSION
|
9
|
+
spec.authors = ["Łukasz Przytuła", "Aleksander Zubala"]
|
10
|
+
spec.email = ["lprzytula@applause.com", "azubala@applause.com"]
|
11
|
+
|
12
|
+
spec.summary = "Xcodebuild helpers for rake"
|
13
|
+
spec.description = "This gem contains useful helpers for building and testing iOS/watchOS/tvOS/macOS apps using rake."
|
14
|
+
spec.homepage = "https://github.com/ApplauseAQI/xcodebuild-rake"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = "bin"
|
21
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
|
27
|
+
spec.add_runtime_dependency 'xcpretty'
|
28
|
+
spec.add_runtime_dependency 'terminal-notifier', '~> 1.6.3'
|
29
|
+
spec.add_runtime_dependency 'aws-sdk', '~> 2.1.2'
|
30
|
+
|
31
|
+
spec.post_install_message = "Thanks for using xcodebuild_rake!"
|
32
|
+
end
|