shenzhen 0.1.0 → 0.2.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.
- data/Gemfile.lock +1 -1
- data/README.md +3 -4
- data/lib/shenzhen.rb +1 -1
- data/lib/shenzhen/commands.rb +1 -0
- data/lib/shenzhen/commands/build.rb +2 -2
- data/lib/shenzhen/plugins/hockeyapp.rb +126 -0
- data/shenzhen-0.1.0.gem +0 -0
- metadata +18 -16
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
# Shenzhen
|
2
2
|
**CLI for Building & Distributing iOS Apps (.ipa Files)**
|
3
3
|
|
4
|
-
Create `.ipa` files and then distribute them with [TestFlight](https://testflightapp.com/), all from the command line!
|
4
|
+
Create `.ipa` files and then distribute them with [TestFlight](https://testflightapp.com/) or [HockeyApp](http://www.hockeyapp.net), all from the command line!
|
5
5
|
|
6
6
|
Less cumbersome than clicking around in Xcode, and less hassle than rolling your own build script--Shenzhen radically improves the process of getting new builds out to testers and enterprises.
|
7
7
|
|
8
|
-
This project is starting with TestFlight, but will move to support other popular distribution methods, such as S3, CloudApp, and / or Dropbox. Suggestions (and pull requests) are very welcome.
|
9
|
-
|
10
8
|
> `shenzhen` is named for [深圳](http://en.wikipedia.org/wiki/Shenzhen), the Chinese city famous for its role as the center of manufacturing for a majority of consumer electronics, including iPhones and iPads. Its [sister project](https://github.com/mattt/cupertino)'s namesake, [Cupertino, CA](http://en.wikipedia.org/wiki/Cupertino,_California), is home to Apple, Inc.'s world headquarters.
|
11
9
|
|
12
10
|
## Installation
|
@@ -26,7 +24,8 @@ $ ipa
|
|
26
24
|
|
27
25
|
Commands:
|
28
26
|
build Create a new .ipa file for your app
|
29
|
-
distribute:testflight Distribute an .ipa file over
|
27
|
+
distribute:testflight Distribute an .ipa file over TestFlight
|
28
|
+
distribute:hockeyapp Distribute an .ipa file over HockeyApp
|
30
29
|
help Display global or [command] help documentation.
|
31
30
|
|
32
31
|
Aliases:
|
data/lib/shenzhen.rb
CHANGED
data/lib/shenzhen/commands.rb
CHANGED
@@ -48,13 +48,13 @@ command :build do |c|
|
|
48
48
|
ENV['CC'] = nil # Fix for RVM
|
49
49
|
abort unless system %{xcodebuild #{flags.join(' ')} clean build 1> /dev/null}
|
50
50
|
|
51
|
-
log "xcrun", "PackageApplication"
|
52
|
-
|
53
51
|
@xcodebuild_settings = Shenzhen::XcodeBuild.settings(flags)
|
54
52
|
@app_path = File.join(@xcodebuild_settings['BUILT_PRODUCTS_DIR'], @xcodebuild_settings['PRODUCT_NAME']) + ".app"
|
55
53
|
@dsym_path = @app_path + ".dSYM"
|
56
54
|
@dsym_filename = "#{@xcodebuild_settings['PRODUCT_NAME']}.app.dSYM"
|
57
55
|
@ipa_path = File.join(Dir.pwd, @xcodebuild_settings['PRODUCT_NAME']) + ".ipa"
|
56
|
+
|
57
|
+
log "xcrun", "PackageApplication"
|
58
58
|
abort unless system %{xcrun -sdk iphoneos PackageApplication -v "#{@app_path}" -o "#{@ipa_path}" --embed "#{@dsym_path}" 1> /dev/null}
|
59
59
|
|
60
60
|
log "zip", @dsym_filename
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'faraday'
|
3
|
+
require 'faraday_middleware'
|
4
|
+
|
5
|
+
module Shenzhen::Plugins
|
6
|
+
module HockeyApp
|
7
|
+
class Client
|
8
|
+
HOSTNAME = 'rink.hockeyapp.net'
|
9
|
+
|
10
|
+
def initialize(api_token)
|
11
|
+
@api_token = api_token
|
12
|
+
@connection = Faraday.new(:url => "https://#{HOSTNAME}") do |builder|
|
13
|
+
builder.request :multipart
|
14
|
+
builder.request :url_encoded
|
15
|
+
builder.response :json, :content_type => /\bjson$/
|
16
|
+
builder.use FaradayMiddleware::FollowRedirects
|
17
|
+
builder.adapter :net_http
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def upload_build(ipa, options)
|
22
|
+
options[:ipa] = Faraday::UploadIO.new(ipa, 'application/octet-stream')
|
23
|
+
|
24
|
+
if dsym_filename = options.delete(:dsym_filename)
|
25
|
+
options[:dsym] = Faraday::UploadIO.new(dsym_filename, 'application/octet-stream')
|
26
|
+
end
|
27
|
+
|
28
|
+
@connection.post do |req|
|
29
|
+
if options[:public_identifer].nil?
|
30
|
+
req.url("/api/2/apps/upload")
|
31
|
+
else
|
32
|
+
req.url("/api/2/apps/#{options.delete(:public_identifer)}/app_versions")
|
33
|
+
end
|
34
|
+
req.headers['X-HockeyAppToken'] = @api_token
|
35
|
+
req.body = options
|
36
|
+
end.on_complete do |env|
|
37
|
+
yield env[:status], env[:body] if block_given?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
command :'distribute:hockeyapp' do |c|
|
45
|
+
c.syntax = "ipa distribute:hockeyapp [options]"
|
46
|
+
c.summary = "Distribute an .ipa file over HockeyApp"
|
47
|
+
c.description = ""
|
48
|
+
c.option '-f', '--file FILE', ".ipa file for the build"
|
49
|
+
c.option '-d', '--dsym FILE', "zipped .dsym package for the build"
|
50
|
+
c.option '-t', '--token TOKEN', "API Token. Available at https://rink.hockeyapp.net/manage/auth_tokens"
|
51
|
+
c.option '-i', '--identifier PUBLIC_IDENTIFIER', "Public identifier of the app you are targeting, if not specified HockeyApp will use the bundle identifier to choose the right"
|
52
|
+
c.option '-m', '--notes NOTES', "Release notes for the build (Default: Textile)"
|
53
|
+
c.option '--markdown', 'Notes are written with Markdown'
|
54
|
+
c.option '--tags TAGS', "Comma separated list of tags which will receive access to the build"
|
55
|
+
c.option '--notify', "Notify permitted teammates to install the build"
|
56
|
+
c.option '--downloadOff', "Upload but don't allow download of this version just yet"
|
57
|
+
|
58
|
+
c.option '-q', '--quiet', "Silence warning and success messages"
|
59
|
+
|
60
|
+
|
61
|
+
c.action do |args, options|
|
62
|
+
determine_file! unless @file = options.file
|
63
|
+
say_error "Missing or unspecified .ipa file" and abort unless @file and File.exist?(@file)
|
64
|
+
|
65
|
+
determine_dsym! unless @dsym = options.dsym
|
66
|
+
say_error "Specified dSYM.zip file doesn't exist" if @dsym and !File.exist?(@dsym)
|
67
|
+
|
68
|
+
determine_api_token! unless @api_token = options.token
|
69
|
+
say_error "Missing API Token" and abort unless @api_token
|
70
|
+
|
71
|
+
determine_notes! unless @notes = options.notes
|
72
|
+
say_error "Missing release notes" and abort unless @notes
|
73
|
+
|
74
|
+
parameters = {}
|
75
|
+
parameters[:public_identifer] = options.identifier if options.identifier
|
76
|
+
parameters[:notes] = @notes
|
77
|
+
parameters[:notes_type] = options.markdown ? "1" : "0"
|
78
|
+
parameters[:notify] = "1" if options.notify && !options.downloadOff
|
79
|
+
parameters[:status] = options.downloadOff ? "1" : "2"
|
80
|
+
parameters[:tags] = options.tags if options.tags
|
81
|
+
parameters[:dsym_filename] = @dsym if @dsym
|
82
|
+
|
83
|
+
|
84
|
+
client = Shenzhen::Plugins::HockeyApp::Client.new(@api_token)
|
85
|
+
response = client.upload_build(@file, parameters)
|
86
|
+
case response.status
|
87
|
+
when 200...300
|
88
|
+
say_ok "Build successfully uploaded to HockeyApp"
|
89
|
+
else
|
90
|
+
say_error "Error uploading to HockeyApp: #{response.body}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def determine_api_token!
|
97
|
+
@api_token ||= ask "API Token:"
|
98
|
+
end
|
99
|
+
|
100
|
+
def determine_file!
|
101
|
+
files = Dir['*.ipa']
|
102
|
+
@file ||= case files.length
|
103
|
+
when 0 then nil
|
104
|
+
when 1 then files.first
|
105
|
+
else
|
106
|
+
@file = choose "Select an .ipa File:", *files
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def determine_dsym!
|
111
|
+
dsym_files = Dir['*.dSYM.zip']
|
112
|
+
@dsym ||= case dsym_files.length
|
113
|
+
when 0 then nil
|
114
|
+
when 1 then dsym_files.first
|
115
|
+
else
|
116
|
+
@dsym = choose "Select a .dSYM.zip file:", *dsym_files
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def determine_notes!
|
121
|
+
placeholder = %{What's new in this release: }
|
122
|
+
|
123
|
+
@notes = ask_editor placeholder
|
124
|
+
@notes = nil if @notes == placeholder
|
125
|
+
end
|
126
|
+
end
|
data/shenzhen-0.1.0.gem
ADDED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shenzhen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-12 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70170608319000 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.6.1
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70170608319000
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &70170608318420 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 0.9.2
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70170608318420
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: commander
|
38
|
-
requirement: &
|
38
|
+
requirement: &70170608317720 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 4.1.2
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70170608317720
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: json
|
49
|
-
requirement: &
|
49
|
+
requirement: &70170608317140 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 1.7.3
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70170608317140
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: faraday
|
60
|
-
requirement: &
|
60
|
+
requirement: &70170608316680 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 0.8.0
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70170608316680
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: faraday_middleware
|
71
|
-
requirement: &
|
71
|
+
requirement: &70170608316200 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
version: 0.8.7
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70170608316200
|
80
80
|
description: CLI for Building & Distributing iOS Apps (.ipa Files)
|
81
81
|
email: m@mattt.me
|
82
82
|
executables:
|
@@ -90,12 +90,14 @@ files:
|
|
90
90
|
- ./lib/shenzhen/commands/build.rb
|
91
91
|
- ./lib/shenzhen/commands/distribute.rb
|
92
92
|
- ./lib/shenzhen/commands.rb
|
93
|
+
- ./lib/shenzhen/plugins/hockeyapp.rb
|
93
94
|
- ./lib/shenzhen/plugins/testflight.rb
|
94
95
|
- ./lib/shenzhen/xcodebuild.rb
|
95
96
|
- ./lib/shenzhen.rb
|
96
97
|
- ./LICENSE
|
97
98
|
- ./Rakefile
|
98
99
|
- ./README.md
|
100
|
+
- ./shenzhen-0.1.0.gem
|
99
101
|
- ./shenzhen.gemspec
|
100
102
|
- bin/ipa
|
101
103
|
homepage: http://github.com/mattt/shenzhen
|
@@ -112,7 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
114
|
version: '0'
|
113
115
|
segments:
|
114
116
|
- 0
|
115
|
-
hash:
|
117
|
+
hash: 4537962558176197982
|
116
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
119
|
none: false
|
118
120
|
requirements:
|
@@ -121,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
123
|
version: '0'
|
122
124
|
segments:
|
123
125
|
- 0
|
124
|
-
hash:
|
126
|
+
hash: 4537962558176197982
|
125
127
|
requirements: []
|
126
128
|
rubyforge_project:
|
127
129
|
rubygems_version: 1.8.15
|