joe_jenkins 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/helpers/jj_debug.rb +24 -0
- data/lib/helpers/jj_xcode.rb +186 -0
- data/lib/joe_jenkins.rb +48 -0
- metadata +65 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
class JJDebugger
|
3
|
+
|
4
|
+
|
5
|
+
def self.prettyLog(m="",count=%x[tput cols])
|
6
|
+
if(m.length > 0)
|
7
|
+
c = (count.to_i - (m.length+10))/2
|
8
|
+
c = 0 if(c < 0)
|
9
|
+
print ('*'*c)+(' '*5)+m+(' '*5)+('*'*c)+"\n"
|
10
|
+
else
|
11
|
+
print '*'*count.to_i+"\n"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.log(m)
|
16
|
+
print "\n"
|
17
|
+
1.times do self.prettyLog end
|
18
|
+
self.prettyLog(m.to_s)
|
19
|
+
1.times do self.prettyLog end
|
20
|
+
print "\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'helpers/jj_debug'
|
2
|
+
|
3
|
+
class JJXcode
|
4
|
+
attr_accessor :projectName, :projectDirectory
|
5
|
+
attr_accessor :bundleIdentifier
|
6
|
+
attr_accessor :signer
|
7
|
+
attr_accessor :profile
|
8
|
+
attr_accessor :macroFlags
|
9
|
+
|
10
|
+
attr_accessor :verbose
|
11
|
+
|
12
|
+
attr_accessor :targets
|
13
|
+
attr_accessor :configurations
|
14
|
+
attr_accessor :schemes
|
15
|
+
|
16
|
+
attr_accessor :profileDirectory
|
17
|
+
|
18
|
+
def initialize(verbose=false)
|
19
|
+
@verbose = verbose
|
20
|
+
system "clear"
|
21
|
+
@profileDirectory = "~/Library/MobileDevice/Provisioning\ Profiles/"
|
22
|
+
@projectDirectory = Dir.pwd
|
23
|
+
end
|
24
|
+
|
25
|
+
def methods()
|
26
|
+
var = Array.new
|
27
|
+
var.push "getInstalledProfiles"
|
28
|
+
var.push "listProfiles"
|
29
|
+
var.push "getTargets"
|
30
|
+
var.push "doBuild"
|
31
|
+
var.push "reSignApp"
|
32
|
+
var.push "packageApp"
|
33
|
+
|
34
|
+
var
|
35
|
+
end
|
36
|
+
|
37
|
+
def log(msg)
|
38
|
+
JJDebugger.log(msg) if @verbose
|
39
|
+
end
|
40
|
+
|
41
|
+
def getInstalledProfiles
|
42
|
+
profile_list = Array.new
|
43
|
+
Dir.glob(File.expand_path(@profileDirectory)+"/*.mobileprovision").each do |profile|
|
44
|
+
profile_list.push(profile.split("/").last.split(".").first)
|
45
|
+
end
|
46
|
+
|
47
|
+
profile_list
|
48
|
+
end
|
49
|
+
|
50
|
+
def listProfiles
|
51
|
+
log "Listing Profiles in #{File.expand_path(@profileDirectory)}"
|
52
|
+
getInstalledProfiles.each do |p|
|
53
|
+
print "Profile: #{p}\n"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def getTargets()
|
58
|
+
d = getProjectInfo()
|
59
|
+
@targets = d[:targets]
|
60
|
+
@configurations = d[:configurations]
|
61
|
+
@schemes = d[:schemes]
|
62
|
+
@targets
|
63
|
+
end
|
64
|
+
|
65
|
+
def buildDir(configuration="")
|
66
|
+
return "#{@projectDirectory}/build/#{configuration}-iphoneos/"
|
67
|
+
end
|
68
|
+
|
69
|
+
def binaryLocation(configuration="")
|
70
|
+
log buildDir(configuration)
|
71
|
+
return Dir.glob("#{buildDir(configuration)}*.app").first
|
72
|
+
end
|
73
|
+
|
74
|
+
# Do an 'xcodebuild -configuration -xcconfig' with given params
|
75
|
+
# @return The path to the .app file
|
76
|
+
|
77
|
+
def doBuild(configuration="Debug", config="")
|
78
|
+
if(config == "")
|
79
|
+
config = createXCConfig()
|
80
|
+
end
|
81
|
+
output = doXcodeCall("-configuration #{configuration}"+(config.length>0 ? " -xcconfig #{config}" : ""))
|
82
|
+
if(output.include?"BUILD SUCCEEDED")
|
83
|
+
binaryLoc = binaryLocation(configuration)
|
84
|
+
log "Build Output Here: #{binaryLoc}"
|
85
|
+
return binaryLoc
|
86
|
+
else
|
87
|
+
log "BUILD FAILED"
|
88
|
+
return nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
def reSignApp(binaryLocation,signer)
|
94
|
+
config = File.dirname(binaryLocation).split("/").last.split('-').first
|
95
|
+
entitlementsDir = Dir.glob("#{@projectDirectory}/build/*.build").first
|
96
|
+
entitlements = Dir.glob(Dir.glob(entitlementsDir+"/#{config}-iphoneos/*.build").first+"/*.xcent").first
|
97
|
+
%x[codesign -f -s "iPhone Distribution: #{signer}" #{File.expand_path(binaryLocation)} --entitlements #{File.expand_path(entitlements)}]
|
98
|
+
end
|
99
|
+
|
100
|
+
#output dir defaults to wherever the script is called from
|
101
|
+
|
102
|
+
def packageApp(binaryLocation, profile, outputLocation=File.expand_path("./"))
|
103
|
+
log "Packaging Application to IPA: #{binaryLocation}"
|
104
|
+
appName = binaryLocation.split("/").last.split(".").first
|
105
|
+
p_name = profile.split(".").first
|
106
|
+
if(!getInstalledProfiles.include?p_name)
|
107
|
+
raise ArgumentError, "Profile Not found on machine", p_name
|
108
|
+
end
|
109
|
+
profileLoc = @profileDirectory+p_name
|
110
|
+
ipaLoc = outputLocation+"/"+appName+".ipa"
|
111
|
+
log %x[xcrun -sdk iphoneos PackageApplication #{"-v" if @verbose} "#{binaryLocation}" -o "#{ipaLoc}" --embed "#{profileLoc}.mobileprovision"]
|
112
|
+
log "IPA OutputDir: #{ipaLoc}"
|
113
|
+
ipaLoc if(File.exists?ipaLoc)
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
def doXcodeCall(call="")
|
118
|
+
log("Doing Xcode call \"#{call}\"")
|
119
|
+
output = %x[cd \"#{@projectDirectory}\";xcodebuild #{call}]
|
120
|
+
log output
|
121
|
+
return output
|
122
|
+
end
|
123
|
+
|
124
|
+
def createXCConfig()
|
125
|
+
if(!@profile || !@bundleIdentifier || !@signer)
|
126
|
+
print "Error: You must specify profile, signer, and bundleIdentifier to create a valid scheme\n"
|
127
|
+
return nil
|
128
|
+
end
|
129
|
+
|
130
|
+
profile_path = File.expand_path(@profileDirectory)+"/#{@profile}.mobileprovision"
|
131
|
+
file = File.open(profile_path, "r")
|
132
|
+
fdata = file.read
|
133
|
+
file.close()
|
134
|
+
fdata[0, fdata.index('<?xml')] = ''
|
135
|
+
|
136
|
+
plist_end = fdata.index('</plist>') + 8
|
137
|
+
fdata[plist_end, fdata.length - plist_end] = ''
|
138
|
+
|
139
|
+
profileData = Plist::parse_xml(fdata)
|
140
|
+
|
141
|
+
profile_uuid = profileData['UUID']
|
142
|
+
|
143
|
+
log "Creating scheme:\nProfile: #{@profile}\nSigner: #{@signer}\nBundleIdentifier: #{@bundleIdentifier}"
|
144
|
+
data = "CODE_SIGN_IDENTITY = iPhone Distribution: #{@signer};\n"
|
145
|
+
data += "RUN_CLANG_STATIC_ANALYZER = NO;\n"
|
146
|
+
data += "PROVISIONING_PROFILE = #{profile_uuid};\n"
|
147
|
+
data += "CustomBundleID = #{@bundleIdentifier};\n"
|
148
|
+
data += "GCC_PREPROCESSOR_DEFINITIONS = #{@macroFlags};\n"
|
149
|
+
|
150
|
+
xc_s = File.new("config.xcconfig", "w")
|
151
|
+
xc_s.write(data)
|
152
|
+
xc_s.close
|
153
|
+
return "config.xcconfig"
|
154
|
+
end
|
155
|
+
|
156
|
+
def getProjectInfo()
|
157
|
+
doXcodeCall("-list")
|
158
|
+
info = Hash.new
|
159
|
+
info[:targets] = Array.new
|
160
|
+
info[:configurations] = Array.new
|
161
|
+
info[:schemes] = Array.new
|
162
|
+
|
163
|
+
t,c,s = false
|
164
|
+
data.split("\n").each do |line|
|
165
|
+
line.gsub!(' ','')
|
166
|
+
|
167
|
+
if(line == "Targets:")
|
168
|
+
t=true
|
169
|
+
elsif(line == "BuildConfigurations:")
|
170
|
+
c=true
|
171
|
+
elsif(line == "Schemes:")
|
172
|
+
s=true
|
173
|
+
elsif (t or c or s)
|
174
|
+
if(line.length > 0)
|
175
|
+
info[:targets].push line if(t)
|
176
|
+
info[:configurations].push line if(c)
|
177
|
+
info[:schemes].push line if(s)
|
178
|
+
else
|
179
|
+
t=c=s=false
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
return info
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
data/lib/joe_jenkins.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
require 'helpers/jj_xcode'
|
3
|
+
|
4
|
+
require 'zip/zip'
|
5
|
+
require 'plist'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
class JoeJenkins
|
9
|
+
|
10
|
+
attr_accessor :config
|
11
|
+
|
12
|
+
def initialize(verbose=false)
|
13
|
+
@xcode = JJXcode.new(verbose)
|
14
|
+
end
|
15
|
+
|
16
|
+
def doBuildWithConfig(config)
|
17
|
+
@config = config
|
18
|
+
|
19
|
+
@xcode.profile = config[:profile]
|
20
|
+
@xcode.signer = config[:signer]
|
21
|
+
@xcode.bundleIdentifier = config[:bundleID]
|
22
|
+
|
23
|
+
appOutputLocation = @xcode.doBuild(config[:configuration])
|
24
|
+
|
25
|
+
print "Write Config to #{@xcode.buildDir(@config[:configuration])+"/config.txt"}\n"
|
26
|
+
File.open(@xcode.buildDir(@config[:configuration])+"/config.txt", "w") do |f|
|
27
|
+
f.puts @config.to_json
|
28
|
+
end
|
29
|
+
# print "This is the output #{appOutputLocation}\n"
|
30
|
+
return appOutputLocation
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def postBuild(bc_url)
|
35
|
+
|
36
|
+
dir_to_zip = @xcode.buildDir(@config[:configuration])
|
37
|
+
output_path = Dir.pwd+"/bundle.tgz"
|
38
|
+
output = %x[cd "#{dir_to_zip}";tar -cvzf "#{output_path}" ./]
|
39
|
+
|
40
|
+
res = RestClient.post bc_url, :app => File.new(output_path)
|
41
|
+
print "\nPost complete #{res.to_str}\n<br/>"
|
42
|
+
end
|
43
|
+
|
44
|
+
def createDistributionPlist
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: joe_jenkins
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Joseph Ridenour
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2012-06-22 00:00:00 -05:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Simple builder classes for creating markup.
|
22
|
+
email: jridenour@mercury.io
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- lib/helpers/jj_debug.rb
|
31
|
+
- lib/helpers/jj_xcode.rb
|
32
|
+
- lib/joe_jenkins.rb
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: http://mercury.io
|
35
|
+
licenses: []
|
36
|
+
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options:
|
39
|
+
- --title
|
40
|
+
- Xcode Helper for helping xcode
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
segments:
|
48
|
+
- 0
|
49
|
+
version: "0"
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 1.3.6
|
61
|
+
signing_key:
|
62
|
+
specification_version: 3
|
63
|
+
summary: JoeJenkins gem is a helper for all processes of building and deploying mobile
|
64
|
+
test_files: []
|
65
|
+
|