mesmerize 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mesmerize (0.0.6)
4
+ mesmerize (0.1.0)
5
5
  commander (~> 4.1.2)
6
6
  faraday (~> 0.8.0)
7
7
  faraday_middleware (~> 0.8.7)
data/bin/mesmerize CHANGED
@@ -4,7 +4,6 @@ require 'commander/import'
4
4
 
5
5
  $:.push File.expand_path("../../lib", __FILE__)
6
6
  require 'mesmerize'
7
- require 'mesmerize/commands'
8
7
 
9
8
  HighLine.track_eof = false # Fix for built-in Ruby
10
9
 
@@ -12,8 +11,10 @@ program :version, Mesmerize::VERSION
12
11
  program :description, 'A command-line interface for Mesmerize'
13
12
 
14
13
  program :help, 'Author', 'Mattt Thompson <m@mattt.me>'
15
- program :help, 'Website', 'http://mesmerizeapp.com'
14
+ program :help, 'Website', 'https://mesmerizeapp.com'
16
15
  program :help_formatter, :compact
17
16
 
18
- global_option '--verbose'
17
+ # global_option '--verbose'
19
18
  default_command :help
19
+
20
+ require 'mesmerize/commands'
@@ -66,11 +66,7 @@ module Mesmerize
66
66
  end
67
67
  end
68
68
 
69
- def post_release(app, release, file)
70
- params = {
71
- :version => release.to_s
72
- }
73
-
69
+ def post_release(app, params, file)
74
70
  @connection.post("/api/apps/#{app}/releases", params).on_complete do |env|
75
71
  if (200...300).include? env[:status]
76
72
  params = env[:body]["params"]
@@ -0,0 +1,86 @@
1
+ command :build do |c|
2
+ c.syntax = 'mesmerize build [options] [output]'
3
+ c.summary = 'Create a new build of your app'
4
+ c.description = ''
5
+
6
+ c.example 'description', 'mesmerize release 478 --tag 3.7.2 --scheme MyApp+Sparkle'
7
+ c.option '-w', '--workspace WORKSPACE', 'Workspace (.xcworkspace) file to use to build app (automatically detected in current directory)'
8
+ c.option '-p', '--project PROJECT', 'Project (.xcodeproj) file to use to build app (automatically detected in current directory, overridden by --workspace option, if passed)'
9
+ c.option '-s', '--scheme SCHEME', 'Scheme used to build app'
10
+ c.option '-q', '--quiet', 'Silence warning and success messages'
11
+
12
+ c.action do |args, options|
13
+ require_authorization!
14
+ validate_xcode_version!
15
+
16
+ begin
17
+ @xcodebuild_info = Mesmerize::XcodeBuildInfo.info
18
+
19
+ @workspace = options.workspace
20
+ @project = options.project
21
+ @scheme = options.scheme
22
+
23
+ determine_workspace_or_project! unless @workspace || @project
24
+
25
+ determine_scheme! unless @scheme
26
+ say_error "Scheme #{@scheme} not found" and abort unless @xcodebuild_info.schemes.include?(@scheme)
27
+
28
+ say_warning "Building \"#{@workspace || @project}\" with scheme \"#{@scheme}\"\n" unless options.quiet
29
+
30
+ destination = File.join("/tmp/mesmerize/", "#{@xcodebuild_info.project}-#{Time.now.to_i}")
31
+ log "xcodebuild", (@workspace || @project)
32
+
33
+ opts = []
34
+ opts << "-workspace '#{@workspace}'" if @workspace
35
+ opts << "-project '#{@project}'" if @project
36
+ opts << "-scheme '#{@scheme}'" if @scheme
37
+
38
+ ["DSTROOT", "DWARF_DSYM_FOLDER_PATH", "CONFIGURATION_BUILD_DIR"].each do |k|
39
+ opts << "#{k}=#{destination}"
40
+ end
41
+ opts << "DEPLOYMENT_LOCATION=YES"
42
+
43
+ ENV['CC'] = nil # Fix for RVM
44
+ abort unless system "xcodebuild -sdk macosx #{opts.join(' ')} clean build 1> /dev/null"
45
+
46
+ app = Dir["#{destination}/**/*.app"].detect{|app| File.basename(app, ".app") == @xcodebuild_info.project}
47
+ say_error "Could not find build product in #{destination}" and abort unless app
48
+
49
+ output = args.pop || "./"
50
+ say_error "Could not move #{app} to #{output}" and abort unless system "mv #{app} #{output}"
51
+ say_ok "#{File.basename(app)} successfully built" unless options.quiet
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def determine_workspace_or_project!
58
+ workspaces, projects = Dir["*.xcworkspace"], Dir["*.xcodeproj"]
59
+
60
+ if workspaces.empty?
61
+ if projects.empty?
62
+ say_error "No Xcode projects or workspaces found in current directory" and abort
63
+ else
64
+ if projects.length == 1
65
+ @project = projects.first
66
+ else
67
+ @project = choose "Select a project:", *projects
68
+ end
69
+ end
70
+ else
71
+ if workspaces.length == 1
72
+ @workspace = workspaces.first
73
+ else
74
+ @workspace = choose "Select a workspace:", *workspaces
75
+ end
76
+ end
77
+ end
78
+
79
+ def determine_scheme!
80
+ if @xcodebuild_info.schemes.length == 1
81
+ @scheme = @xcodebuild_info.schemes.first
82
+ else
83
+ @scheme = choose "Select a scheme:", *@xcodebuild_info.schemes
84
+ end
85
+ end
86
+ end
@@ -1,121 +1,82 @@
1
1
  command :release do |c|
2
- c.syntax = 'mesmerize release [VERSION] [options]'
2
+ c.syntax = 'mesmerize release [options]'
3
3
  c.summary = 'Release a new build of your app'
4
4
  c.description = ''
5
5
 
6
6
  c.example 'description', 'mesmerize release 478 --tag 3.7.2 --scheme MyApp+Sparkle'
7
7
  c.option '-a', '--app APP', 'Name of App'
8
- c.option '-t', '--tag TAG', 'Marketing Version Number (e.g. 3.7.2)'
8
+ c.option '-r', '--build BUILD', Integer, "Build Version Number (CFBundleVersion, e.g. 2663)"
9
+ c.option '-t', '--tag TAG', 'Marketing Version Number (CFBundleShortVersionString, e.g. 3.7.2)'
9
10
  c.option '-w', '--workspace WORKSPACE', 'Workspace (.xcworkspace) file to use to build app (automatically detected in current directory)'
10
11
  c.option '-p', '--project PROJECT', 'Project (.xcodeproj) file to use to build app (automatically detected in current directory, overridden by --workspace option, if passed)'
11
12
  c.option '-s', '--scheme SCHEME', 'Scheme used to build app'
13
+ c.option '-m', '--release-notes NOTES', 'Notes for this release'
12
14
 
13
15
  c.action do |args, options|
14
16
  require_authorization!
17
+ validate_xcode_version!
15
18
 
16
19
  begin
17
- @info = Mesmerize::XcodeBuildInfo.info
18
-
19
- @appName = options.app || @info.project
20
- @version = args.shift.to_i
21
- @tag = options.tag
22
- @workspace = options.workspace
23
- @project = options.project
24
- @scheme = options.scheme
25
-
26
- @appSlug = @appName.strip.gsub(/\s+/, '-')
27
-
28
- say "Found project \"#{@appName}\"."
29
- say "Looking up current release information..."
30
-
31
- response = client.get_app(@appSlug)
32
- if response.status == 404
33
- say_error "Could not find listing for #{@appName}." and say_error "Do `mesmerize create #{@appName}` first." and abort
34
- end
35
-
36
- @app = response.body
37
- if @version.nonzero?
38
- if @version <= @app["version"].to_i
39
- say_error "Specified release (#{@version}) must be greater than current release (#{@app["version"]})" and abort
40
- end
41
- else
42
- if @app["version"]
43
- @version = @app["version"] + 1
44
- say_warning "Bumping release to version #{@version}"
45
- elsif Mesmerize::Agvtool.vers
46
- @version = Mesmerize::Agvtool.vers + 1
47
- say_warning "Bumping release to version #{@version}"
48
- else
49
- say_error "Specify a release version" and abort
50
- end
51
- end
20
+ @xcodebuild_info = Mesmerize::XcodeBuildInfo.info
52
21
 
53
- unless @workspace || @project
54
- workspaces, projects = Dir["*.xcworkspace"], Dir["*.xcodeproj"]
55
- abort "No Xcode projects or workspaces found in current directory" if workspaces.empty? && projects.empty?
56
-
57
- case workspaces.length
58
- when 0
59
- case projects.length
60
- when 0
61
- abort "No Xcode projects or workspaces found in current directory"
62
- when 1
63
- @project = projects.first
64
- else
65
- @project = choose "Select a project:", *projects
66
- end
67
- when 1
68
- @workspace = workspaces.first
69
- else
70
- @workspace = choose "Select a workspace:", *workspaces
71
- end
72
- end
22
+ @app = options.app
23
+ @build_number = options.build
24
+ @tag = options.tag
73
25
 
74
- if @scheme and not @info.schemes.include?(@scheme)
75
- abort "Scheme #{@scheme} not found"
76
- end
26
+ @release_notes = options.release_notes
77
27
 
78
- if @scheme.nil?
79
- @scheme = choose "Select a scheme:", *@info.schemes
80
- end
28
+ determine_current_release_information!
81
29
 
82
- ENV['CC'] = nil # Fix for rvm
30
+ determine_build_number! unless @build_number
31
+ validate_build_number!
32
+
33
+ determine_tag! unless @tag
34
+ validate_tag!
83
35
 
84
- puts
85
- say "Building \"#{@workspace || @project}\" version #{@version} with scheme \"#{@scheme}\"\n"
36
+ determine_release_notes! unless @release_notes
86
37
 
87
38
  log "agvtool", "new-version"
88
- `agvtool -noscm new-version -all #{@version}`
39
+ `agvtool -noscm new-version -all #{@build_number}`
89
40
 
90
41
  if @tag
91
42
  log "agvtool", "new-marketing-version"
92
43
  `agvtool -noscm new-marketing-version #{@tag}`
93
44
  end
94
45
 
95
- [:clean, :build, :archive, :install].each do |action|
96
- log "xcodebuild", action
46
+ @filename = "#{@app["name"]}-#{@build_number}.zip"
97
47
 
98
- options = []
99
- options << "-workspace '#{@workspace}'" if @workspace
100
- options << "-project '#{@project}'" if @project
101
- options << "-scheme '#{@scheme}'" if @scheme
48
+ # Un-parsing and passing options to `build` command
49
+ cargs = options.__hash__.keep_if{|k, v| [:workspace, :project, :scheme].include?(k)}
50
+ command(:build).run(*cargs.collect{|k, v| "--#{k} #{v}"}, "-q", "#{File.basename(@filename, '.zip')}.app")
102
51
 
103
- `xcodebuild #{options.join(" ")} -sdk macosx DSTROOT='./.mesmerize' #{action}`# 1> /dev/null 2> /dev/null`
104
- end
52
+ abort unless system "zip -rmTq #{@filename} #{File.basename(@filename, '.zip')}.app"
105
53
 
54
+ log "upload", @filename
55
+
56
+ params = {
57
+ :version => @build_number.to_s,
58
+ :description => @release_notes,
59
+ :tag => @tag
60
+ }
106
61
 
107
- @filename = "#{@app['name']}-#{@version}.zip"
108
- `pushd .mesmerize/Applications; zip -r #{@filename} #{@app['name']}.app; popd`
62
+ client.post_release(@app["slug"], params, @filename) do |status, body|
63
+ case status
64
+ when 200...300, nil
65
+ log "publish appcast.xml"
109
66
 
110
- @file = ".mesmerize/Applications/" + @filename
67
+ log "delete #{@filename}"
68
+ system "rm -f #{File.basename(@filename, '.zip')}.*"
111
69
 
112
- log "upload", @filename
70
+ puts
71
+ say_ok "Successfully created release, #{@app["name"]} r#{@build_number}"
72
+
73
+ url = "https://#{@app["slug"]}.#{Mesmerize::Client::HOSTNAME}"
74
+ say "See the updated appcast at #{url}/appcast.xml"
113
75
 
114
- client.post_release(@appSlug, @version, @file) do |status, body|
115
- if (200...300).include?(status) || status.nil?
116
- say_ok "Successfully created release, #{@app['name']} r#{@version}"
76
+ puts
77
+ say "Download the latest version at #{url}/latest"
117
78
  else
118
- abort "Unable to create release"
79
+ say_error "Error creating release: #{body}" and abort
119
80
  end
120
81
  end
121
82
  rescue Mesmerize::XcodeBuildInfo::NilOutputError
@@ -124,8 +85,65 @@ command :release do |c|
124
85
  say_error "Xcode Build Error: #{e}" and abort
125
86
  rescue => e
126
87
  say_error "Error: #{e}" and abort
127
- ensure
128
- `rm -rf .mesmerize`
129
88
  end
130
89
  end
131
- end
90
+
91
+ private
92
+
93
+ def validate_xcode_version!
94
+ version = Mesmerize::XcodeBuildInfo.version
95
+ say_error "Mesmerize requires Xcode 4 (found #{version}). Please install or switch to the latest Xcode." and abort if version < "4.0.0"
96
+ end
97
+
98
+ def validate_build_number!
99
+ version = @app["version"].to_i
100
+ if version and @build_number and @build_number <= version
101
+ say_error "Specified build number (#{@build_number}) must be greater than current release (#{version})" and abort
102
+ end
103
+ end
104
+
105
+ def validate_tag!
106
+ # TODO
107
+ end
108
+
109
+ def determine_current_release_information!
110
+ name = @app || @xcodebuild_info.project
111
+
112
+ say "Found project \"#{name}\"."
113
+ say "Looking up current release information..."
114
+
115
+ response = client.get_app(name.gsub(/\s+/, '-'))
116
+ case response.status
117
+ when 200...300
118
+ @app = response.body
119
+ when 404
120
+ say_error "Could not find listing for #{name}." and say_error "Do `mesmerize create #{@app["name"]}` first." and abort
121
+ else
122
+ say_error "Error finding listing for #{name}: #{response.body}" and abort
123
+ end
124
+ end
125
+
126
+ def determine_build_number!
127
+ version = @app["version"].to_i
128
+ if version.nonzero?
129
+ @build_number = version + 1
130
+ say_warning "Bumping release to version #{@build_number}"
131
+ elsif Mesmerize::Agvtool.vers
132
+ @build_number = Mesmerize::Agvtool.vers + 1
133
+ say_warning "Bumping release to version #{@build_number}"
134
+ else
135
+ @build_number = ask_for_integer "Specify a build number (CFBundleVersion)"
136
+ end
137
+ end
138
+
139
+ def determine_tag!
140
+ @tag = Mesmerize::Agvtool.mvers
141
+ end
142
+
143
+ def determine_release_notes!
144
+ placeholder = %{What's new in this release: }
145
+
146
+ @release_notes = ask_editor placeholder
147
+ @release_notes = nil if @release_notes == placeholder
148
+ end
149
+ end
@@ -6,4 +6,5 @@ require 'commands/signup'
6
6
  require 'commands/login'
7
7
  require 'commands/logout'
8
8
  require 'commands/create'
9
- require 'commands/release'
9
+ require 'commands/build'
10
+ require 'commands/release'
@@ -2,22 +2,22 @@ require 'ostruct'
2
2
 
3
3
  module Mesmerize::XcodeBuildInfo
4
4
  class Info < OpenStruct; end
5
-
5
+
6
6
  class Error < StandardError; end
7
7
  class NilOutputError < Error; end
8
-
8
+
9
9
  class << self
10
10
  def info
11
11
  output = `xcodebuild -list 2> /dev/null`
12
12
  raise Error.new $1 if /^xcodebuild\: error\: (.+)$/ === output
13
13
  raise NilOutputError unless /\S/ === output
14
-
14
+
15
15
  lines = output.split(/\n/)
16
16
  hash = {}
17
17
  group = nil
18
-
18
+
19
19
  hash[:project] = lines.shift.match(/\"(.+)\"\:/)[1]
20
-
20
+
21
21
  lines.each do |line|
22
22
  if /\:$/ === line
23
23
  group = line.strip[0...-1].downcase.gsub(/\s+/, '-')
@@ -29,8 +29,13 @@ module Mesmerize::XcodeBuildInfo
29
29
  hash[group] << line.strip
30
30
  end
31
31
  end
32
-
32
+
33
33
  Info.new(hash)
34
34
  end
35
+
36
+ def version
37
+ output = `xcodebuild -version`
38
+ output.scan(/([\d\.?]+)/).flatten.first rescue nil
39
+ end
35
40
  end
36
41
  end
data/lib/mesmerize.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Mesmerize
2
- VERSION = '0.0.6'
2
+ VERSION = '0.1.0'
3
3
  end
4
4
 
5
5
  $:.push File.expand_path('../', __FILE__)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mesmerize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.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-06-09 00:00:00.000000000Z
12
+ date: 2012-06-18 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70335819400880 !ruby/object:Gem::Requirement
16
+ requirement: &70094542236220 !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: *70335819400880
24
+ version_requirements: *70094542236220
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70335819400320 !ruby/object:Gem::Requirement
27
+ requirement: &70094542235720 !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: *70335819400320
35
+ version_requirements: *70094542235720
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: commander
38
- requirement: &70335819399800 !ruby/object:Gem::Requirement
38
+ requirement: &70094542235260 !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: *70335819399800
46
+ version_requirements: *70094542235260
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: json
49
- requirement: &70335819399080 !ruby/object:Gem::Requirement
49
+ requirement: &70094542234800 !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: *70335819399080
57
+ version_requirements: *70094542234800
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: faraday
60
- requirement: &70335819389480 !ruby/object:Gem::Requirement
60
+ requirement: &70094542234340 !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: *70335819389480
68
+ version_requirements: *70094542234340
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: faraday_middleware
71
- requirement: &70335819388920 !ruby/object:Gem::Requirement
71
+ requirement: &70094542233880 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 0.8.7
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *70335819388920
79
+ version_requirements: *70094542233880
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: netrc
82
- requirement: &70335819388360 !ruby/object:Gem::Requirement
82
+ requirement: &70094542233420 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: 0.7.2
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *70335819388360
90
+ version_requirements: *70094542233420
91
91
  description: Command-Line Interface for Mesmerize
92
92
  email: m@mattt.me
93
93
  executables:
@@ -100,6 +100,7 @@ files:
100
100
  - ./lib/mesmerize/agvtool.rb
101
101
  - ./lib/mesmerize/authentication.rb
102
102
  - ./lib/mesmerize/client.rb
103
+ - ./lib/mesmerize/commands/build.rb
103
104
  - ./lib/mesmerize/commands/create.rb
104
105
  - ./lib/mesmerize/commands/login.rb
105
106
  - ./lib/mesmerize/commands/logout.rb
@@ -126,7 +127,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
126
127
  version: '0'
127
128
  segments:
128
129
  - 0
129
- hash: -3606515878359033241
130
+ hash: -3338072577465810837
130
131
  required_rubygems_version: !ruby/object:Gem::Requirement
131
132
  none: false
132
133
  requirements:
@@ -135,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
136
  version: '0'
136
137
  segments:
137
138
  - 0
138
- hash: -3606515878359033241
139
+ hash: -3338072577465810837
139
140
  requirements: []
140
141
  rubyforge_project:
141
142
  rubygems_version: 1.8.15