seagull 0.0.1 → 0.1.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.
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