seagull 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dec044af9abfb2bf1b35d3633f422c59621d825a
4
- data.tar.gz: 181d0e91c8bbc4fb04e988fd94919db2944753b3
3
+ metadata.gz: eca246ae739c6916e531c26e71df1abd766e44db
4
+ data.tar.gz: 091a023531c9958b84c4e899d8a9b191de2697b2
5
5
  SHA512:
6
- metadata.gz: 6357bb17d446592aedfb925a28691eefcfa63295f5cb4031afce9b66345427ade30578b155567a958a05f309ef4667f81b4cc1bcfed1a136f62dadfeb555b157
7
- data.tar.gz: 632292d5442f91a05eab8f66b9c687f70da3175497c24200cf7d29438f1b387e3c9aee74a62d2077dacd6d5f3b8170fa56dc031eb05df87fb0116f18d56ae82a
6
+ metadata.gz: c9ae3d32e76a7c0b6fc4cef7d848eb0c42083b18b34fadd61f7fcb33741bc92f3548aa70629d83cf1d496285885eb190fa1272bc21d5f2ce94baf666858d12fc
7
+ data.tar.gz: 4f6de74dc40da0910ea3ec23dff467a4266da1a6c36f96c73787500be6418d498f323f58af8b9e757052ffabb13c560c05e9cfae1de92d50cd0684be7e0c696b
@@ -0,0 +1,136 @@
1
+ require 'app_conf'
2
+ require 'seagull/deployment_strategies'
3
+
4
+ module Seagull
5
+ class Configuration < AppConf
6
+ def initialize(defaults = {})
7
+ super()
8
+
9
+ # Set defaults
10
+ from_hash({
11
+ :configuration => {:debug => 'Debug', :beta => 'AdHoc', :release => 'Release'},
12
+ :build_dir => 'build',
13
+ :auto_archive => true,
14
+ :changelog_file => File.expand_path('CHANGELOG.md'),
15
+ :archive_path => File.expand_path("~/Library/Developer/Xcode/Archives"),
16
+ :ipa_path => File.expand_path("~/Library/Developer/Xcode/Archives"),
17
+ :dsym_path => File.expand_path("~/Library/Developer/Xcode/Archives"),
18
+ :xcpretty => true,
19
+ :xctool_path => "xctool",
20
+ :xcodebuild_path => "xcodebuild",
21
+ :workspace_path => nil,
22
+ :scheme => nil,
23
+ :app_name => nil,
24
+ :arch => nil,
25
+ :skip_clean => false,
26
+ :verbose => false,
27
+ :dry_run => false,
28
+
29
+ :deploy => {
30
+ :release_notes_items => 5,
31
+ },
32
+ :release_type => :beta,
33
+ :deployment_strategies => {},
34
+ })
35
+
36
+ self.load('.seagull.yml') if File.exists?(".seagull.yml")
37
+ self.from_hash(defaults)
38
+ end
39
+
40
+ # Configuration
41
+ def deployment(release_type, strategy_name, &block)
42
+ if DeploymentStrategies.valid_strategy?(strategy_name.to_sym)
43
+ deployment_strategy = DeploymentStrategies.build(strategy_name, self)
44
+
45
+ self.deployment_strategies.send("#{release_type}=", deployment_strategy)
46
+ self.deployment_strategies.send("#{release_type}").configure(&block)
47
+ else
48
+ raise "Unknown deployment strategy '#{strategy_name}'."
49
+ end
50
+ end
51
+
52
+ def deployment_strategy(type)
53
+ self.active_release_type = type
54
+ self.deployment_strategies.send(type)
55
+ end
56
+
57
+ # Accessors
58
+ def archive_name
59
+ app_name || target || scheme
60
+ end
61
+
62
+ def archive_file_name(override = {})
63
+ "#{archive_name}-#{full_version}_#{configuration.send(override.fetch(:release_type, release_type))}.xcarchive"
64
+ end
65
+
66
+ def archive_full_path(type)
67
+ File.join(archive_path, archive_file_name(release_type: type))
68
+ end
69
+
70
+ def ipa_name
71
+ app_name || target || scheme
72
+ end
73
+
74
+ def ipa_file_name(override = {})
75
+ "#{archive_name}-#{full_version}_#{configuration.send(override.fetch(:release_type, release_type))}.ipa"
76
+ end
77
+
78
+ def ipa_full_path(type)
79
+ File.join(ipa_path, ipa_file_name(release_type: type))
80
+ end
81
+
82
+ def dsym_file_name(override = {})
83
+ "#{archive_name}-#{full_version}_#{configuration.send(override.fetch(:release_type, release_type))}.dSYM.zip"
84
+ end
85
+
86
+ def dsym_full_path(type)
87
+ File.join(dsym_path, dsym_file_name(release_type: type))
88
+ end
89
+
90
+ def version_data
91
+ @version_data ||= begin
92
+ vers = %x{agvtool vers -terse|tail -1}.strip
93
+ mvers = %x{agvtool mvers -terse1|tail -1}.strip
94
+ {marketing: mvers, version: vers}
95
+ end
96
+ end
97
+
98
+ def reload_version!
99
+ @version_data = nil; version_data
100
+ end
101
+
102
+ def marketing_version
103
+ version_data[:marketing]
104
+ end
105
+
106
+ def version
107
+ version_data[:version]
108
+ end
109
+
110
+ def full_version
111
+ "#{marketing_version}.#{version}"
112
+ end
113
+
114
+ def version_tag
115
+ "v#{full_version}"
116
+ end
117
+
118
+ def build_arguments(override = {})
119
+ args = {}
120
+ if workspace
121
+ args[:workspace] = "#{workspace}.xcworkspace"
122
+ args[:scheme] = scheme
123
+ else
124
+ args[:target] = target
125
+ args[:project] = project_file_path if project_file_path
126
+ end
127
+
128
+ args[:configuration] = configuration.send(release_type)
129
+ args[:arch] = arch unless arch.nil?
130
+
131
+ args.merge!(override)
132
+
133
+ args.collect{|k,v| "-#{k} #{Shellwords.escape(v)}"}
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,37 @@
1
+ module Seagull
2
+ module DeploymentStrategies
3
+ class File < DeploymentStrategy
4
+ def extended_configuration_for_strategy
5
+ proc do
6
+ def generate_release_notes(&block)
7
+ self.release_notes = block if block
8
+ end
9
+ end
10
+ end
11
+
12
+ def prepare
13
+ end
14
+
15
+ def deploy
16
+ # Make sure destionation directoy exists
17
+ FileUtils.mkpath(@configuration.deploy.path) unless ::File.directory?(@configuration.deploy.path)
18
+
19
+ # Copy xcarchive
20
+ Dir.chdir(@configuration.archive_path) do
21
+ deploy_path = ::File.join(@configuration.deploy.path, @configuration.archive_file_name(release_type: @configuration.active_release_type) + ".zip")
22
+ FileUtils.rm deploy_path if ::File.exists?(deploy_path)
23
+ system("/usr/bin/zip --symlinks --recurse-paths #{Shellwords.escape(deploy_path)} #{Shellwords.escape(@configuration.archive_file_name(release_type: @configuration.active_release_type))}")
24
+ end
25
+
26
+ [
27
+ @configuration.ipa_full_path(@configuration.active_release_type),
28
+ @configuration.dsym_full_path(@configuration.active_release_type),
29
+ ].each do |f|
30
+ FileUtils.cp_r f, @configuration.deploy.path
31
+ end
32
+ end
33
+
34
+ private
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,61 @@
1
+ require 'tempfile'
2
+ require 'json'
3
+ require 'launchy'
4
+
5
+ module Seagull
6
+ module DeploymentStrategies
7
+ class HockeyApp < DeploymentStrategy
8
+
9
+ def defaults
10
+ {
11
+ :allow_download => true,
12
+ :notify => true,
13
+ :mandatory => false,
14
+ :tags => '',
15
+ }
16
+ end
17
+
18
+ # Nothing to prepare
19
+ def prepare
20
+ end
21
+
22
+ def deploy
23
+ # Create response file
24
+ response_file = Tempfile.new('seagull_deploy_hockey')
25
+ payload = {
26
+ status: @configuration.deploy.allow_download ? 2 : 1,
27
+ notify: @configuration.deploy.notify ? 1 : 0,
28
+ mandatory: @configuration.deploy.mandatory ? 1 : 0,
29
+ tags: @configuration.deploy.tags,
30
+ notes: release_notes,
31
+ notes_type: 1,
32
+ ipa: "@#{Shellwords.escape(@configuration.ipa_full_path(@configuration.active_release_type))}",
33
+ dsym: "@#{Shellwords.escape(@configuration.dsym_full_path(@configuration.active_release_type))}",
34
+ commit_sha: %x{git rev-parse HEAD}.strip,
35
+ repository_url: %x{git remote -v|grep fetch|awk '{print $2;}'}.strip,
36
+ }
37
+ opts = payload.collect{|k,v| "-F #{k}=#{Shellwords.escape(v)}"}.join(" ")
38
+
39
+ puts "Uploading to Hockeyapp... Please wait..."
40
+ system("curl #{opts} -o #{response_file.path} -H 'X-HockeyAppToken: #{@configuration.deploy.token}' https://rink.hockeyapp.net/api/2/apps/#{@configuration.deploy.appid}/app_versions/upload")
41
+
42
+ response_body = if response_file.size > 0
43
+ response_file.read
44
+ else
45
+ "{}"
46
+ end
47
+ response = JSON.parse(response_body)
48
+ if response['config_url']
49
+ puts "Version page: #{response['config_url']}"
50
+ Launchy.open(response['config_url'])
51
+ else
52
+ puts "FAILED to upload app"
53
+ end
54
+ ensure
55
+ response_file.unlink
56
+ end
57
+
58
+ private
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,60 @@
1
+ require 'vandamme'
2
+
3
+ module Seagull
4
+ module DeploymentStrategies
5
+ def self.valid_strategy?(strategy_name)
6
+ strategies.keys.include?(strategy_name.to_sym)
7
+ end
8
+
9
+ def self.build(strategy_name, configuration)
10
+ strategies[strategy_name.to_sym].new(configuration)
11
+ end
12
+
13
+ class DeploymentStrategy
14
+ def initialize(configuration)
15
+ @configuration = configuration
16
+
17
+ if respond_to?(:extended_configuration_for_strategy)
18
+ @configuration.instance_eval(&extended_configuration_for_strategy)
19
+ end
20
+ end
21
+
22
+ def configure(&block)
23
+ @configuration.deploy.from_hash(defaults)
24
+
25
+ yield @configuration.deploy
26
+ end
27
+
28
+ def defaults
29
+ {}
30
+ end
31
+
32
+ def prepare
33
+ puts "Nothing to prepare!"
34
+ end
35
+
36
+ def deploy
37
+ raise "NOT IMPLEMENTED"
38
+ end
39
+
40
+ def release_notes
41
+ changelog = ::File.exists?(@configuration.changelog_file) ? ::File.read(@configuration.changelog_file) : ""
42
+
43
+ parser = Vandamme::Parser.new(changelog: changelog, version_header_exp: '^\*\*?([\w\d\.-]+\.[\w\d\.-]+[a-zA-Z0-9])( \/ (\d{4}-\d{2}-\d{2}|\w+))?\*\*\n?[=-]*', format: 'markdown')
44
+ changes = parser.parse
45
+
46
+ changes.first(@configuration.deploy.release_notes_items).collect{|v, c| "**#{v}**\n\n#{c}" }.join("\n\n")
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def self.strategies
53
+ {:file => File, :hockeyapp => HockeyApp}
54
+ end
55
+ end
56
+ end
57
+
58
+ require 'seagull/deployment_strategies/file'
59
+ require 'seagull/deployment_strategies/hockey_app'
60
+
@@ -0,0 +1,207 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+ require 'vandamme'
4
+ require 'date'
5
+ require 'term/ansicolor'
6
+ require 'seagull/configuration'
7
+
8
+ module Seagull
9
+ class Tasks < ::Rake::TaskLib
10
+ def initialize(namespace = :seagull, &block)
11
+ @configuration = Configuration.new
12
+ @namespace = namespace
13
+
14
+ yield @configuration if block_given?
15
+
16
+ # Check we can find our xctool
17
+ unless File.executable?(%x{which #{@configuration.xctool_path}}.strip)
18
+ raise "xctool is required. Please install using Homebrew: brew install xctool."
19
+ end
20
+
21
+ unless File.executable?(%x{which #{@configuration.xcodebuild_path}}.strip)
22
+ raise "xcodebuild is required. Please install XCode."
23
+ end
24
+
25
+ define
26
+ end
27
+
28
+ private
29
+ def define
30
+ # Detect some defaults
31
+ namespace(@namespace) do
32
+ task :clean do
33
+ unless @configuration.skip_clean
34
+ xctool @configuration.build_arguments, "clean"
35
+ end
36
+ end
37
+
38
+ desc "Build and run tests"
39
+ task test: [] do
40
+ xctool @configuration.build_arguments(configuration: @configuration.configuration.debug, arch: 'i386', sdk: 'iphonesimulator'), "clean", "test", "-freshInstall", "-freshSimulator"
41
+ end
42
+
43
+ # File dependencies
44
+ @configuration.configuration.to_hash.each do |type, conf|
45
+ file @configuration.archive_full_path(type) do
46
+ xctool @configuration.build_arguments(configuration: conf), "archive", "-archivePath", Shellwords.escape(@configuration.archive_full_path(type))
47
+ end
48
+
49
+ file @configuration.ipa_full_path(type) => @configuration.archive_full_path(type) do
50
+ xcodebuild "-exportArchive", "-exportFormat", "ipa", "-archivePath", Shellwords.escape(@configuration.archive_full_path(type)), "-exportPath", Shellwords.escape(@configuration.ipa_full_path(type))
51
+ end
52
+
53
+ file @configuration.dsym_full_path(type) => @configuration.archive_full_path(type) do
54
+ dsym_path = File.expand_path(Dir["#{@configuration.archive_full_path(type)}/dSYMS/*"].first)
55
+ Dir.chdir dsym_path do
56
+ sh("/usr/bin/zip --symlinks --verbose --recurse-paths '#{@configuration.dsym_full_path(type)}' .")
57
+ end
58
+ end
59
+ end
60
+
61
+ ['beta', 'release'].each do |type|
62
+ namespace(type) do
63
+ desc "Archive the #{type} version as an XCArchive file"
64
+ task archive: [@configuration.archive_full_path(type)]
65
+
66
+ desc "Package the #{type} version as an IPA file"
67
+ task package: [@configuration.ipa_full_path(type), @configuration.dsym_full_path(type)]
68
+
69
+ if @configuration.deployment_strategies
70
+ desc "Prepare your app for deployment"
71
+ task prepare: ['git:verify', :package] do
72
+ @configuration.deployment_strategy(type).prepare
73
+ end
74
+
75
+ desc "Deploy the beta using your chosen deployment strategy"
76
+ task deploy: [:prepare] do
77
+ @configuration.deployment_strategy(type).deploy
78
+ end
79
+
80
+ desc "Deploy the last build"
81
+ task redeploy: [:prepre, :deploy]
82
+ end
83
+
84
+ end
85
+
86
+ desc "Build, package and deploy beta build"
87
+ task type => ["#{type}:deploy"] do
88
+ end
89
+ end
90
+
91
+ # Version control
92
+ namespace(:version) do
93
+ desc "Bumps build number"
94
+ task bump: ['git:verify:dirty'] do
95
+ sh("agvtool bump -all")
96
+ @configuration.reload_version!
97
+
98
+ # Edit changelog
99
+ Rake::Task["#{@namespace}:changelog:edit"].invoke
100
+ Rake::Task["#{@namespace}:version:commit"].invoke
101
+ Rake::Task["#{@namespace}:version:tag"].invoke
102
+ end
103
+
104
+ task :tag do
105
+ current_tag = %x{git describe --exact-match `git rev-parse HEAD` 2>/dev/null}.strip
106
+ unless current_tag == @configuration.version_tag
107
+ sh("git tag -m 'Released version #{@configuration.full_version}' -s '#{@configuration.version_tag}'")
108
+ end
109
+ end
110
+
111
+ task :commit do
112
+ ver_files = %x{git status --porcelain}.split("\n").collect{|a| Shellwords.escape(a.gsub(/[ AM\?]+ (.*)/, '\1'))}
113
+
114
+ Dir.chdir(git_directory) do
115
+ sh("git add #{ver_files.join(' ')}")
116
+ sh("git commit -m 'Bumped version to #{@configuration.full_version}' #{ver_files.join(' ')}")
117
+ end
118
+ end
119
+ end
120
+
121
+ namespace(:changelog) do
122
+ desc "Edit changelog for current version"
123
+ task :edit do
124
+ changelog = if File.exists?(@configuration.changelog_file)
125
+ File.read(@configuration.changelog_file)
126
+ else
127
+ ""
128
+ end
129
+
130
+ tag = %x{git describe --exact-match `git rev-parse HEAD` 2>/dev/null}.strip
131
+ tag_date = Date.parse(%x{git log -1 --format=%ai #{tag}})
132
+
133
+ # Parse current changelog
134
+ parser = Vandamme::Parser.new(changelog: changelog, version_header_exp: '^\*\*?([\w\d\.-]+\.[\w\d\.-]+[a-zA-Z0-9])( \/ (\d{4}-\d{2}-\d{2}|\w+))?\*\*\n?[=-]*', format: 'markdown')
135
+ changes = parser.parse
136
+
137
+ # Write entry to changelog
138
+ File.open('CHANGELOG.md', 'w') do |io|
139
+ unless @configuration.full_version
140
+ io.puts "**#{@configuration.full_version} / #{tag_date.strftime('%Y-%m-%d')}**"
141
+ io.puts ""
142
+ %w{FIXED SECURITY FEATURE ENHANCEMENT PERFORMANCE}.each do |kw|
143
+ io.puts " * **#{kw}** Describe changes here or remove if not required"
144
+ end
145
+ io.puts ""
146
+ end
147
+ io.puts changelog
148
+ end
149
+ sh("#{ENV['EDITOR']} CHANGELOG.md")
150
+ end
151
+ end
152
+
153
+ namespace(:git) do
154
+ namespace(:verify) do
155
+ # Verify GIT tag
156
+ task :tag do
157
+ current_tag = %x{git describe --exact-match `git rev-parse HEAD` 2>/dev/null}.strip
158
+ unless current_tag == @configuration.version_tag
159
+ puts ""
160
+ puts Term::ANSIColor.red("!!! Current commit is not properly tagged in GIT. Please tag and release version.")
161
+ puts ""
162
+
163
+ fail unless ENV['IGNORE_GIT_TAG']
164
+ end
165
+ end
166
+
167
+ # Verify dirty
168
+ task :dirty do
169
+ unless %x{git status -s --ignore-submodules=dirty 2> /dev/null}.empty?
170
+ puts ""
171
+ puts Term::ANSIColor.red("!!! Current GIT tree is dirty. Please commit changes before building release.")
172
+ puts ""
173
+
174
+ fail unless ENV['IGNORE_GIT_DIRTY']
175
+ end
176
+ end
177
+ end
178
+
179
+ task verify: ['verify:tag', 'verify:dirty']
180
+ end
181
+
182
+ def xctool(*args)
183
+ sh("#{@configuration.xctool_path} #{args.join(" ")}")
184
+ end
185
+
186
+ def xcodebuild(*args)
187
+ sh("#{@configuration.xcodebuild_path} #{args.join(" ")} | xcpretty -c; exit ${PIPESTATUS[0]}")
188
+ end
189
+ end
190
+ end
191
+
192
+ def git_directory
193
+ original_cwd = Dir.pwd
194
+
195
+ loop do
196
+ if File.directory?('.git')
197
+ git_dir = Dir.pwd
198
+ Dir.chdir(original_cwd) and return git_dir
199
+ end
200
+
201
+ Dir.chdir(original_cwd) and return if Pathname.new(Dir.pwd).root?
202
+
203
+ Dir.chdir('..')
204
+ end
205
+ end
206
+ end
207
+ end
@@ -1,170 +1,9 @@
1
- require 'singleton'
2
- require 'seagull/config'
3
- require 'versionomy'
4
- require 'seagull/versionomy/format_definitions/apple'
5
-
6
1
  module Seagull
7
2
  class Version
8
- include Singleton
9
-
10
- def initialize
11
- @config = Seagull::Config.instance
12
-
13
- @version = if File.exists?(@config.version.file)
14
- Versionomy.create(YAML.load_file(@config.version.file), @config.version.format)
15
- else
16
- Versionomy.create({}, @config.version.format)
17
- end
18
- end
19
-
20
- def peek(what)
21
- peek = case what
22
- when :release
23
- bump(:major)
24
- when :patch
25
- bump(:minor)
26
- when :update
27
- bump(:update)
28
- when :build
29
- bump(:build)
30
- else
31
- @version
32
- end
33
-
34
- peek.unparse
35
- end
36
-
37
- # Output marketing version
38
- def marketing
39
- case @config.version.format
40
- when :apple
41
- major, minor = if @config.versions![@version.major]
42
- @config.versions[@version.major].split('.')
43
- else
44
- [@version.major, @version.minor]
45
- end
46
- tiny = @version.convert(:standard).tiny
47
-
48
- Versionomy.create(major: major, minor: minor, tiny: tiny).unparse(:required_fields => :tiny)
49
- else
50
- @version.convert(:standard).unparse(:required_fields => [:major, :minor, :tiny])
51
- end
52
- end
53
-
54
- def bundle
55
- case @config.version.format
56
- when :apple
57
- @version.unparse
58
- else
59
- @version.convert(:standard).tiny2
60
- end
61
- end
62
-
63
- def bundle_numeric
64
- case @config.version.format
65
- when :apple
66
- @version.build
67
- else
68
- @version.convert(:standard).tiny2
69
- end
70
- end
71
-
72
- def save
73
- if File.extname(@config.version.file) == '.yml'
74
- yaml = if File.exists?(@config.version.file)
75
- YAML.load_file(@config.version.file)
76
- else
77
- {}
78
- end
79
-
80
- yaml.merge!(@version.values_hash)
81
-
82
- # Some shortcuts
83
- yaml.merge!({
84
- marketing: self.marketing,
85
- bundle: self.bundle,
86
- bundle_numeric: self.bundle_numeric,
87
- short: self.marketing,
88
- string: self.marketing,
89
- })
90
-
91
- File.open(@config.version.file, 'w') {|io| io.puts yaml.to_yaml }
92
-
93
- else
94
- File.open(@config.version.file, 'w') {|io| io.puts @version.unparse }
95
- end
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ PATCH = 0
96
6
 
97
- # Commit
98
- system "git commit #{@config.version.file} -m 'Bumped version to #{self.bundle}'"
99
- end
100
-
101
- # Accessors
102
- def build
103
- bump!(:build); self
104
- end
105
-
106
- def update
107
- bump!(:update); self
108
- end
109
-
110
- def patch
111
- bump!(:minor); self
112
- end
113
-
114
- def release(major = nil, version = nil)
115
- old_major = @version.major
116
- old_version = @config.versions![old_major.to_s]
117
-
118
- bump!(:major)
119
-
120
- major ||= @version.major
121
- version ||= Versionomy.parse(@config.versions![old_major.to_s] || "0.#{major}").bump(:minor).unparse
122
-
123
- if @config.versions![major] or @config.versions!.invert[version]
124
- raise "Version #{version} or major #{major} already exists"
125
- end
126
-
127
- @config.versions![major] = version; @config.save
128
-
129
- # Commit
130
- system "git tag 'v#{self.marketing}' -m 'Released version #{self.marketing}'"
131
-
132
- self
133
- end
134
-
135
- def bump(field)
136
- _tr = {
137
- :apple => {},
138
- :standard => {
139
- :update => :tiny, :build => :tiny2
140
- }
141
- }
142
-
143
- _field = _tr[@config.version.format][field] || field
144
-
145
- if @config.version.format == :apple and field == :update and @version.update.empty?
146
- @version.change(update: 'a')
147
- else
148
- @version.bump(field)
149
- end
150
- end
151
-
152
- def bump!(field)
153
- @version = bump(field); save; self
154
- end
155
-
156
- def to_s(format = @config.version.format)
157
- @version.convert(format).unparse
158
- end
159
-
160
- # Proxy
161
- def method_missing(m, *args, &blk)
162
- @version.send(m, *args, &blk)
163
- end
164
-
165
- def respond_to?(m)
166
- @version.respond_to?(m)
167
- end
168
-
7
+ STRING = [MAJOR, MINOR, PATCH].join('.')
169
8
  end
170
9
  end
data/lib/seagull.rb CHANGED
@@ -1,4 +1 @@
1
- require "seagull/version"
2
-
3
- module Seagull
4
- end
1
+ require 'seagull/tasks'
data/seagull.gemspec CHANGED
@@ -1,10 +1,11 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'seagull/version'
4
5
 
5
6
  Gem::Specification.new do |spec|
6
7
  spec.name = "seagull"
7
- spec.version = "0.0.1"
8
+ spec.version = Seagull::Version::STRING
8
9
  spec.authors = ["Mikko Kokkonen"]
9
10
  spec.email = ["mikko@owlforestry.com"]
10
11
  spec.description = %q{Seagull makes managing XCode projects easy as flying is for seagulls}
@@ -17,9 +18,16 @@ Gem::Specification.new do |spec|
17
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
19
  spec.require_paths = ["lib"]
19
20
 
20
- spec.add_dependency "versionomy", "~> 0.4"
21
- spec.add_dependency "thor", "~> 0.18"
22
- spec.add_dependency "hashie"
21
+ spec.add_dependency "rake", "~> 10.1"
22
+ spec.add_dependency "xcpretty", "~> 0.1.3"
23
+ spec.add_dependency "app_conf", "~> 0.4.2"
24
+ spec.add_dependency "unicode", "~> 0.4.4"
25
+ spec.add_dependency "nokogiri", "~> 1.6.1"
26
+ spec.add_dependency "vandamme", "~> 0.0.7"
27
+ spec.add_dependency "json", "~> 1.8.1"
28
+ spec.add_dependency "term-ansicolor", "~> 1.3.0"
29
+ spec.add_dependency "launchy", "~> 2.4.2"
30
+
31
+
23
32
  spec.add_development_dependency "bundler", "~> 1.3"
24
- spec.add_development_dependency "rake", "~> 10.1"
25
33
  end
metadata CHANGED
@@ -1,107 +1,174 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seagull
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikko Kokkonen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-13 00:00:00.000000000 Z
11
+ date: 2014-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: versionomy
14
+ name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.4'
19
+ version: '10.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.4'
26
+ version: '10.1'
27
27
  - !ruby/object:Gem::Dependency
28
- name: thor
28
+ name: xcpretty
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.18'
33
+ version: 0.1.3
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.18'
40
+ version: 0.1.3
41
41
  - !ruby/object:Gem::Dependency
42
- name: hashie
42
+ name: app_conf
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 0.4.2
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 0.4.2
55
55
  - !ruby/object:Gem::Dependency
56
- name: bundler
56
+ name: unicode
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.3'
62
- type: :development
61
+ version: 0.4.4
62
+ type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '1.3'
68
+ version: 0.4.4
69
69
  - !ruby/object:Gem::Dependency
70
- name: rake
70
+ name: nokogiri
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '10.1'
75
+ version: 1.6.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.6.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: vandamme
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.0.7
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.0.7
97
+ - !ruby/object:Gem::Dependency
98
+ name: json
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 1.8.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 1.8.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: term-ansicolor
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 1.3.0
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 1.3.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: launchy
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 2.4.2
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 2.4.2
139
+ - !ruby/object:Gem::Dependency
140
+ name: bundler
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '1.3'
76
146
  type: :development
77
147
  prerelease: false
78
148
  version_requirements: !ruby/object:Gem::Requirement
79
149
  requirements:
80
- - - ~>
150
+ - - "~>"
81
151
  - !ruby/object:Gem::Version
82
- version: '10.1'
152
+ version: '1.3'
83
153
  description: Seagull makes managing XCode projects easy as flying is for seagulls
84
154
  email:
85
155
  - mikko@owlforestry.com
86
- executables:
87
- - seagull
156
+ executables: []
88
157
  extensions: []
89
158
  extra_rdoc_files: []
90
159
  files:
91
- - .gitignore
160
+ - ".gitignore"
92
161
  - Gemfile
93
162
  - LICENSE.txt
94
163
  - README.md
95
164
  - Rakefile
96
- - VERSION.yml
97
- - bin/seagull
98
165
  - lib/seagull.rb
99
- - lib/seagull/cli.rb
100
- - lib/seagull/config.rb
101
- - lib/seagull/tasks/config.rb
102
- - lib/seagull/tasks/version.rb
166
+ - lib/seagull/configuration.rb
167
+ - lib/seagull/deployment_strategies.rb
168
+ - lib/seagull/deployment_strategies/file.rb
169
+ - lib/seagull/deployment_strategies/hockey_app.rb
170
+ - lib/seagull/tasks.rb
103
171
  - lib/seagull/version.rb
104
- - lib/seagull/versionomy/format_definitions/apple.rb
105
172
  - seagull.gemspec
106
173
  homepage: ''
107
174
  licenses:
@@ -113,17 +180,17 @@ require_paths:
113
180
  - lib
114
181
  required_ruby_version: !ruby/object:Gem::Requirement
115
182
  requirements:
116
- - - '>='
183
+ - - ">="
117
184
  - !ruby/object:Gem::Version
118
185
  version: '0'
119
186
  required_rubygems_version: !ruby/object:Gem::Requirement
120
187
  requirements:
121
- - - '>='
188
+ - - ">="
122
189
  - !ruby/object:Gem::Version
123
190
  version: '0'
124
191
  requirements: []
125
192
  rubyforge_project:
126
- rubygems_version: 2.0.3
193
+ rubygems_version: 2.2.0
127
194
  signing_key:
128
195
  specification_version: 4
129
196
  summary: Manage Xcode projects with total control
data/VERSION.yml DELETED
@@ -1,5 +0,0 @@
1
- ---
2
- :major: 2
3
- :minor: B
4
- :build: 1
5
- :update: a
data/bin/seagull DELETED
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
-
5
- # Do we have seagull inside bundler?
6
- if File.exists?("Gemfile") and File.read("Gemfile") =~ /#{File.basename($0)}/
7
- # Restart tool from bundle if facing load error
8
- require 'bundler'
9
- begin
10
- Bundler.require(:default)
11
- rescue LoadError
12
- exec "bundle", "exec", File.basename($0), *ARGV
13
- end
14
- end
15
-
16
- require 'seagull/cli'
17
- Seagull::CLI.start
data/lib/seagull/cli.rb DELETED
@@ -1,30 +0,0 @@
1
- require 'thor'
2
- # require 'seagull/config'
3
-
4
- module Seagull
5
- class CLI < Thor
6
- def initialize(*args)
7
- super
8
-
9
- # @config = Seagull::Config.instance
10
- end
11
-
12
- desc "debug", "Opens debug console"
13
- def debug
14
- require 'pry'
15
-
16
- binding.pry
17
- end
18
- end
19
- end
20
-
21
- #
22
- require 'seagull/tasks/config'
23
- require 'seagull/tasks/version'
24
-
25
- module Seagull
26
- class CLI
27
- register(Seagull::Tasks::Config, 'config', 'config <command>', 'Manage and display configuration settings')
28
- register(Seagull::Tasks::Version, 'version', 'version <command>', 'Version release tasks')
29
- end
30
- end
@@ -1,41 +0,0 @@
1
- require 'singleton'
2
- require 'hashie/mash'
3
- require 'yaml'
4
-
5
- module Seagull
6
- class Config
7
- include Singleton
8
-
9
- def initialize
10
- @config = Hashie::Mash.new({
11
- config: {file: '.seagull'},
12
- version: {file: 'VERSION.yml', format: :apple}
13
- })
14
-
15
- load
16
- end
17
-
18
- def load
19
- if File.exists?(@config.config.file)
20
- @config.deep_merge!(YAML.load_file(@config.config.file))
21
- end
22
- end
23
-
24
- def save
25
- File.open(@config.config.file, 'w') {|io| io.puts self.to_yaml }
26
- end
27
-
28
- def to_yaml
29
- @config.to_hash.to_yaml
30
- end
31
-
32
- # Proxy
33
- def method_missing(m, *args, &blk)
34
- @config.send(m, *args, &blk)
35
- end
36
-
37
- def respond_to?(m)
38
- @config.respond_to?(m)
39
- end
40
- end
41
- end
@@ -1,57 +0,0 @@
1
- module Seagull
2
- module Tasks
3
- class Config < Thor
4
- def initialize(*args)
5
- super
6
-
7
- @config = Seagull::Config.instance
8
- end
9
-
10
- desc "print [KEY]", "Prints current config, with optionally filtering using key"
11
- def print(key = nil)
12
- cfgs = _build_config_array(@config.to_hash)
13
-
14
- cfgs.select!{|cfg| cfg.first[/#{key}/] } if key
15
-
16
- print_table(cfgs)
17
- end
18
-
19
- desc "set KEY VALUE", 'Sets given key (as path) to given value'
20
- def set(key, value)
21
- _value = case value
22
- when 'true' then true
23
- when 'yes' then true
24
- when 'false' then false
25
- when 'no' then false
26
- when /^[0-9]+$/ then value.to_i
27
- when /^:[a-zA-Z]+$/ then value[1..-1].to_sym
28
- else value
29
- end
30
-
31
- keypath = key.split('/')
32
- cfg = Hash[keypath.pop, _value]
33
- while k = keypath.pop
34
- cfg = Hash[k, cfg]
35
- end
36
- @config.deep_merge!(cfg)
37
-
38
- @config.save
39
- say_status "config", "#{key} set to #{_value}", :green
40
- end
41
-
42
- private
43
- def _build_config_array(cfg, prefix = '')
44
- cfgs = []
45
-
46
- cfg.each do |key, value|
47
- if value.kind_of?(Hash)
48
- cfgs += _build_config_array(value, "#{prefix}/#{key}")
49
- else
50
- cfgs << ["#{prefix}/#{key}", value]
51
- end
52
- end
53
- cfgs
54
- end
55
- end
56
- end
57
- end
@@ -1,79 +0,0 @@
1
- require 'seagull/version'
2
-
3
- module Seagull
4
- module Tasks
5
- class Version < Thor
6
- VERSION = Seagull::Version.instance
7
- CONFIG = Seagull::Config.instance
8
-
9
- desc "print", "Prints current version (#{VERSION.to_s})"
10
- def print
11
- say_status "current", "Version %s (%s)" % [VERSION.marketing, VERSION.bundle], :blue
12
- end
13
-
14
- desc "list", "List all versions and majors"
15
- def list
16
- if CONFIG.version.format != :apple
17
- say_status "UNKNOWN", "Used version format not using version <-> major coding"
18
- exit
19
- end
20
-
21
- if !CONFIG.versions?
22
- say_status "UNKNOWN", "Versions and majors have not been defined"
23
- exit
24
- end
25
-
26
- table = [['Version', 'Major Version']]
27
- table += CONFIG.versions.collect{|k,v| ["%6s.%-3s" % v.split('.'), k.to_i]}.sort
28
-
29
- print_table table
30
- end
31
-
32
- desc "bumplist", "List all possible bump versions"
33
- def bumplist
34
- peeks = [:release, :patch, :update, :build]
35
- versions = [['Type', 'Version']]
36
- versions += peeks.collect{|t| [t.to_s, VERSION.peek(t)]}
37
-
38
- print_table versions
39
- end
40
-
41
- desc "release [MAJOR] [VERSION]", "Releases new version (#{VERSION.peek(:release)})"
42
- def release(major = nil, version = nil)
43
- VERSION.release(major, version)
44
-
45
- say_status "RELEASE", "Version #{VERSION.to_s} has been released", :green
46
- rescue => e
47
- say_status "FAILED", e.message, :red
48
- end
49
-
50
- desc "name [VERSION_NAME]", "Name current major release (#{VERSION.major})"
51
- def name(ver_name)
52
- CONFIG.versions![VERSION.major] = ver_name; CONFIG.save
53
- say_status "version", "Version #{VERSION.major} named as #{ver_name}"
54
- end
55
-
56
- desc "patch", "Release new patch version (#{VERSION.peek(:patch)})"
57
- def patch
58
- VERSION.patch
59
- say_status "PATCH", "Version increased #{VERSION.to_s}"
60
- end
61
-
62
- desc "update", "Release new update (#{VERSION.peek(:update)})"
63
- def update
64
- VERSION.update
65
- say_status "update", "Version update to #{VERSION.to_s}"
66
- end
67
-
68
- desc "build [BUILDNUMBER]", "Increases build number (#{VERSION.peek(:build)}), optionally set to given number"
69
- def build(buildnumber = nil)
70
- if buildnumber
71
- VERSION.set(build: buildnumber)
72
- else
73
- VERSION.build
74
- end
75
- say_status "version", "Increased build number to #{VERSION.to_s}"
76
- end
77
- end
78
- end
79
- end
@@ -1,91 +0,0 @@
1
- require 'versionomy'
2
-
3
- module Versionomy
4
- module Format
5
- def self.apple
6
- get('apple')
7
- end
8
-
9
- module Apple
10
- module ExtraMethods
11
-
12
- end
13
-
14
- def self.create
15
- schema_ = Schema.create do
16
- field(:major, :type => :integer, :default_value => 1) do
17
- field(:minor, :type => :string, :default_value => 'A') do
18
- field(:build, :type => :integer, :default_value => 1) do
19
- field(:update, :type => :string)
20
- end
21
- end
22
- end
23
-
24
- add_module(Format::Apple::ExtraMethods)
25
- end
26
-
27
- Format::Delimiter.new(schema_) do
28
- field(:major) do
29
- recognize_number(:delimiter_regexp => '', :default_delimiter => '')
30
- end
31
-
32
- field(:minor) do
33
- recognize_regexp('[A-Z]',:delimiter_regexp => '', :default_delimiter => '')
34
- end
35
-
36
- field(:build) do
37
- recognize_number(:delimiter_regexp => '', :default_delimiter => '')
38
- end
39
-
40
- field(:update) do
41
- recognize_regexp('[a-z]', :delimiter_regexp => '', :default_delimiter => '', :default_value_optional => true)
42
- end
43
- end
44
- end
45
- end
46
-
47
- register('apple', Format::Apple.create, true)
48
- end
49
-
50
- module Conversion
51
- module Apple
52
- def self.create_standard_to_apple
53
- Conversion::Parsing.new do
54
- to_modify_original_value do |original_, convert_params_|
55
- apple_version = {
56
- major: original_.major,
57
- minor: ('A'..'Z').to_a[original_.minor],
58
- build: original_.tiny2,
59
- update: (original_.tiny > 0 ? ('a'..'z').to_a[original_.tiny - 1] : nil),
60
- }
61
- Versionomy.create(apple_version, :apple)
62
- end
63
- end
64
- end
65
-
66
- def self.create_apple_to_standard
67
- Conversion::Parsing.new do
68
- to_modify_original_value do |original_, convert_params_|
69
- if convert_params_[:versions]
70
- major, minor = convert_params_[:versions][original_.major].split(".").map(&:to_i)
71
- tiny = ('A'..'Z').to_a.index(original_.minor)
72
- tiny2 = original_.build
73
- patchlevel = !original_.update.empty? ? (('a'..'z').to_a.index(original_.update) + 1) : nil
74
- else
75
- major = original_.major
76
- minor = ('A'..'Z').to_a.index(original_.minor)
77
- tiny = !original_.update.empty? ? (('a'..'z').to_a.index(original_.update) + 1) : nil
78
- tiny2 = original_.build
79
- patchlevel = nil
80
- end
81
-
82
- Versionomy.create({major: major, minor: minor, tiny: tiny, tiny2: tiny2, patchlevel: patchlevel})
83
- end
84
- end
85
- end
86
- end
87
-
88
- register(:standard, :apple, Conversion::Apple.create_standard_to_apple, true)
89
- register(:apple, :standard, Conversion::Apple.create_apple_to_standard, true)
90
- end
91
- end