dean 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +45 -0
- data/Rakefile +1 -0
- data/bin/dean +7 -0
- data/dean.gemspec +33 -0
- data/lib/dean/cli.rb +69 -0
- data/lib/dean/commands/build.rb +83 -0
- data/lib/dean/commands/upload.rb +38 -0
- data/lib/dean/commands/version_bumper.rb +57 -0
- data/lib/dean/configuration_helper.rb +28 -0
- data/lib/dean/git_helper.rb +32 -0
- data/lib/dean/project_version_helper.rb +50 -0
- data/lib/dean/semver_helper.rb +61 -0
- data/lib/dean/version.rb +3 -0
- data/lib/dean.rb +10 -0
- data/spec/build_spec.rb +51 -0
- data/spec/project_version_helper_spec.rb +64 -0
- data/spec/semver_helper_spec.rb +47 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/version_bumper_spec.rb +114 -0
- metadata +202 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 39811a0eb56c2613b18a882892cba34fabdb520c
|
4
|
+
data.tar.gz: 5ef2b22df5d268019258badb828b7d962bd975d3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5427b65efdcafa8d1dbd0336a62f7ea7e2c34387f42ec5ff82bfff610e3d3a941a75928d4c4d767b27d6e4b9ea93be156e294493be5b68efcaf81ae64dcb6e15
|
7
|
+
data.tar.gz: 8013cb47d62ebac211db76ba71522d9f096ae2654ec1238ac633bb3a3c57ac80741e8304deab25952d74bc2efe8cd98203be0c0d735d06fc4f8daeac7d330258
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Gio
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# Dean
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/Bizzby/dean.svg)](https://travis-ci.org/Bizzby/dean)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/Bizzby/dean.png)](https://codeclimate.com/github/Bizzby/dean)
|
5
|
+
[![Stories in Ready](https://badge.waffle.io/bizzby/dean.png?label=ready&title=Ready)](https://waffle.io/bizzby/dean)
|
6
|
+
|
7
|
+
Dean is a **very opinionated** gem that the [BIZZBY](http://bizzby.com/) iOS team uses to automate the mundane tasks of bumping build numbers and distributing beta versions of the apps. Deep down is nothing more than a wrapper around other tools, mainly the excellent [shenzhen](https://github.com/nomad/shenzhen/) by [Mattt Thompson](http://github.com/mattt).
|
8
|
+
|
9
|
+
The project is super alpha, use it at your own risk.
|
10
|
+
|
11
|
+
A better documentation will be provided once the Dean is more stable. If you're interested in using it or contributing just tweet at [@mokagio](https://twitter.com/mokagio).
|
12
|
+
|
13
|
+
### A note on the code
|
14
|
+
|
15
|
+
Dean is been made by an iOS developer surrounded by Node developers, so the quality of the Ruby code might not be awesome. Every comment on the code is very welcome!
|
16
|
+
|
17
|
+
---
|
18
|
+
|
19
|
+
_This is the default gem file README, gonna use it when the project is more mature_
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
Add this line to your application's Gemfile:
|
24
|
+
|
25
|
+
gem 'dean'
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
|
29
|
+
$ bundle
|
30
|
+
|
31
|
+
Or install it yourself as:
|
32
|
+
|
33
|
+
$ gem install dean
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
TODO: Write usage instructions here
|
38
|
+
|
39
|
+
## Contributing
|
40
|
+
|
41
|
+
1. Fork it
|
42
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
43
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
44
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
45
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/dean
ADDED
data/dean.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dean/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "dean"
|
8
|
+
spec.version = Dean::VERSION
|
9
|
+
spec.authors = ["Giovanni Lodi"]
|
10
|
+
spec.email = ["giovanni.lodi42@gmail.com"]
|
11
|
+
spec.description = %q{An (opinionated) CLI tool to ease mundane tasks of the iOS beta distribution}
|
12
|
+
spec.summary = %q{An (opinionated) CLI tool to ease mundane tasks of the iOS beta distribution, such as version bumps, archiving, and deploying, all configured in a simple unique file.}
|
13
|
+
spec.homepage = "https://github.com/bizzby/dean"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'thor', '~> 0.17.0'
|
22
|
+
spec.add_dependency 'shenzhen', '~> 0.6'
|
23
|
+
spec.add_dependency 'plist', '~> 3.1.0'
|
24
|
+
# shenzhen already adds dependency to aws-sdk
|
25
|
+
# spec.add_dependency 'aws-sdk', '~> 1.31.3'
|
26
|
+
spec.add_dependency 'colorize', '~> 0.7.0'
|
27
|
+
spec.add_dependency 'semantic', '~> 1.3.0'
|
28
|
+
spec.add_dependency 'xcodeproj', '~> 0.16.1'
|
29
|
+
|
30
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
31
|
+
spec.add_development_dependency "rake"
|
32
|
+
spec.add_development_dependency "rspec", "~> 2.14.1"
|
33
|
+
end
|
data/lib/dean/cli.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module Dean
|
4
|
+
module Cli
|
5
|
+
class Application < Thor
|
6
|
+
|
7
|
+
desc 'bump_version VALUE', 'Bump the given version VALUE of the project'
|
8
|
+
def bump(value)
|
9
|
+
plists = []
|
10
|
+
Dean::ConfigurationHelper.new.all_environments.each do |environment|
|
11
|
+
plists.push environment[:plist]
|
12
|
+
end
|
13
|
+
old_version = Dean::ProjectVersionHelper.new.version_from_plist plists[0]
|
14
|
+
|
15
|
+
Dean::VersionBumper.new.bump_all_environments value.to_sym
|
16
|
+
|
17
|
+
# commit and tag, here only for the moment!
|
18
|
+
new_version = Dean::ProjectVersionHelper.new.version_from_plist plists[0]
|
19
|
+
message = "Do you want to commit the changes to the version (#{old_version} -> #{new_version})?"
|
20
|
+
Dean::GitHelper.new.commit_asking_user(message, new_version, plists)
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'build', 'Builds the ipa'
|
24
|
+
def build()
|
25
|
+
begin
|
26
|
+
Dean::Build.new.build_all_environments
|
27
|
+
rescue Exception => e
|
28
|
+
log_exception e
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'distribute', 'Distribute the app. (Now only uploads the ipa to the S3 server)'
|
34
|
+
def distribute()
|
35
|
+
Dean::Upload.new.upload_all_environments
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'deploy ENV', 'Deploy the app. Builds AND distributes the app. An optional environment name can be passed to deploy only one environment'
|
39
|
+
def deploy(environment_name=nil)
|
40
|
+
Dean::ConfigurationHelper.new.all_environments.each do |environment|
|
41
|
+
if environment_name != nil
|
42
|
+
if environment_name == environment[:name]
|
43
|
+
begin
|
44
|
+
Dean::Build.new.build_environment environment
|
45
|
+
Dean::Upload.new.upload_environment environment
|
46
|
+
rescue Exception => e
|
47
|
+
log_exception e
|
48
|
+
end
|
49
|
+
end
|
50
|
+
else
|
51
|
+
begin
|
52
|
+
Dean::Build.new.build_environment environment
|
53
|
+
Dean::Upload.new.upload_environment environment
|
54
|
+
rescue Exception => e
|
55
|
+
log_exception e
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def log_exception(exception)
|
64
|
+
puts "Something went wrong!".red
|
65
|
+
puts "#{exception.message}".red
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'shenzhen'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'plist'
|
5
|
+
|
6
|
+
module Dean
|
7
|
+
class Build
|
8
|
+
|
9
|
+
def build_all_environments
|
10
|
+
configurations_helper = ConfigurationHelper.new
|
11
|
+
configurations_helper.all_environments.each do |environment|
|
12
|
+
build_environment environment
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def build_environment(environment)
|
17
|
+
build_settings = ConfigurationHelper.new().build_settings_for_environment environment
|
18
|
+
|
19
|
+
if not build_configuration_exists? build_settings[:build_configuration]
|
20
|
+
fail IOError, "Build configuration #{build_settings[:build_configuration]} does not exist!"
|
21
|
+
end
|
22
|
+
|
23
|
+
if not provisioning_profile_exists? build_settings[:provisioning_profile]
|
24
|
+
fail IOError, "Provisioning profile #{build_settings[:provisioning_profile]} not found on disk!"
|
25
|
+
end
|
26
|
+
|
27
|
+
version = ProjectVersionHelper.new().version_from_plist environment[:plist]
|
28
|
+
|
29
|
+
ipa_path = "#{Dir.pwd}/#{build_settings[:location]}/#{version}"
|
30
|
+
|
31
|
+
if ipa_lookup ipa_path
|
32
|
+
build_options = "--workspace #{build_settings[:workspace]}"
|
33
|
+
build_options += " --project #{build_settings[:project]}"
|
34
|
+
build_options += " -c #{build_settings[:build_configuration]}"
|
35
|
+
build_options += " -s #{build_settings[:scheme]}"
|
36
|
+
build_options += " -m #{build_settings[:provisioning_profile]}"
|
37
|
+
build_options += " --clean"
|
38
|
+
build_options += " --archive"
|
39
|
+
|
40
|
+
system "ipa build #{build_options}"
|
41
|
+
|
42
|
+
# Once build succeeded move .ipa and .dSYM in the proper folder
|
43
|
+
FileUtils.mkdir_p ipa_path
|
44
|
+
ipa_name = ipa_name_from_project build_settings[:project]
|
45
|
+
dSYM_name = dSYM_name_from_project build_settings[:project]
|
46
|
+
FileUtils.mv "#{Dir.pwd}/#{ipa_name}", "#{ipa_path}/#{ipa_name}"
|
47
|
+
FileUtils.mv "#{Dir.pwd}/#{dSYM_name}", "#{ipa_path}/#{dSYM_name}"
|
48
|
+
else
|
49
|
+
puts "Skipping".yellow
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def ipa_lookup(path)
|
56
|
+
if Dir.exists? path
|
57
|
+
puts "A build was found already. Do you wish to continue and override it? (y/n)"
|
58
|
+
answer = $stdin.gets.chomp!
|
59
|
+
return answer == 'y'
|
60
|
+
else
|
61
|
+
return true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def build_configuration_exists?(build_configuration)
|
66
|
+
# This is **very** dirty
|
67
|
+
matches = `xcodeproj show Bizzby.xcodeproj --format hash | grep -w #{build_configuration} | wc -l`
|
68
|
+
matches.to_i > 0
|
69
|
+
end
|
70
|
+
|
71
|
+
def provisioning_profile_exists?(profile)
|
72
|
+
File.exists? "#{Dir.pwd}/#{profile}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def ipa_name_from_project(project)
|
76
|
+
File.basename(project, ".xcodeproj") + ".ipa"
|
77
|
+
end
|
78
|
+
|
79
|
+
def dSYM_name_from_project(project)
|
80
|
+
File.basename(project, ".xcodeproj") + ".app.dSYM.zip"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
|
3
|
+
module Dean
|
4
|
+
class Upload
|
5
|
+
|
6
|
+
def upload_all_environments
|
7
|
+
ConfigurationHelper.new().all_environments.each do |environment|
|
8
|
+
upload_environment environment
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def upload_environment(environment)
|
13
|
+
configurations = ConfigurationHelper.new().s3_settings_for_environment environment
|
14
|
+
|
15
|
+
s3 = AWS::S3.new
|
16
|
+
bucket = s3.buckets[configurations[:bucket_name]]
|
17
|
+
|
18
|
+
version = ProjectVersionHelper.new.version_from_plist environment[:plist]
|
19
|
+
|
20
|
+
s3_location = "#{configurations[:bucket_location]}/v#{version}/app.ipa"
|
21
|
+
|
22
|
+
ipa_on_s3 = bucket.objects[s3_location]
|
23
|
+
if ipa_on_s3.exists?
|
24
|
+
puts "The file already exists on the bucket!"
|
25
|
+
else
|
26
|
+
#
|
27
|
+
# TODO this shouldn't be static, but I need more time to think about how to structure it
|
28
|
+
#
|
29
|
+
build_settings = ConfigurationHelper.new().build_settings_for_environment environment
|
30
|
+
disk_location = "#{Dir.pwd}/#{build_settings[:location]}/#{version}/Bizzby.ipa"
|
31
|
+
|
32
|
+
puts "Uploading .ipa to #{s3_location}"
|
33
|
+
ipa_on_s3.write( :file => disk_location)
|
34
|
+
puts "Uploaded :)"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Dean
|
2
|
+
class VersionBumper
|
3
|
+
|
4
|
+
def bump_all_environments(value)
|
5
|
+
configurations_helper = ConfigurationHelper.new
|
6
|
+
# TODO: this is a dirty hack! please remove it soon!
|
7
|
+
environments = configurations_helper.all_environments.uniq { |e| e[:plist] }
|
8
|
+
environments.each do |environment|
|
9
|
+
bump_environment value, environment
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def bump_environment(value, environment)
|
14
|
+
bump environment[:plist], value
|
15
|
+
bump_short environment[:plist], value
|
16
|
+
end
|
17
|
+
|
18
|
+
def bump(plist, value)
|
19
|
+
version = Dean::ProjectVersionHelper.new.version_from_plist plist
|
20
|
+
semver_helper = Dean::SemverHelper.new
|
21
|
+
|
22
|
+
new_version = version
|
23
|
+
|
24
|
+
if value == :major
|
25
|
+
new_version = semver_helper.bump_major version
|
26
|
+
elsif value == :minor
|
27
|
+
new_version = semver_helper.bump_minor version
|
28
|
+
elsif value == :patch
|
29
|
+
new_version = semver_helper.bump_patch version
|
30
|
+
elsif value == :pre
|
31
|
+
new_version = semver_helper.bump_pre version
|
32
|
+
end
|
33
|
+
|
34
|
+
Dean::ProjectVersionHelper.new.set_version_in_plist new_version, plist
|
35
|
+
end
|
36
|
+
|
37
|
+
def bump_short(plist, value)
|
38
|
+
version = Dean::ProjectVersionHelper.new.short_version_from_plist plist
|
39
|
+
semver_helper = Dean::SemverHelper.new
|
40
|
+
|
41
|
+
new_version = version
|
42
|
+
|
43
|
+
if value == :major
|
44
|
+
new_version = semver_helper.bump_major version
|
45
|
+
elsif value == :minor
|
46
|
+
new_version = semver_helper.bump_minor version
|
47
|
+
elsif value == :patch
|
48
|
+
new_version = semver_helper.bump_patch version
|
49
|
+
elsif value == :pre
|
50
|
+
new_version = semver_helper.bump_pre version
|
51
|
+
end
|
52
|
+
|
53
|
+
Dean::ProjectVersionHelper.new.set_short_version_in_plist new_version, plist
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
module Dean
|
3
|
+
class ConfigurationHelper
|
4
|
+
|
5
|
+
def all_environments
|
6
|
+
raw_environments = symbolize_keys YAML.load_file Dir.pwd + '/.dean.yml'
|
7
|
+
environments = []
|
8
|
+
raw_environments[:environments].each do |environment|
|
9
|
+
environments.push symbolize_keys environment
|
10
|
+
end
|
11
|
+
return environments
|
12
|
+
end
|
13
|
+
|
14
|
+
def build_settings_for_environment(environment)
|
15
|
+
symbolize_keys environment[:build_settings]
|
16
|
+
end
|
17
|
+
|
18
|
+
def s3_settings_for_environment(environment)
|
19
|
+
symbolize_keys environment[:s3_settings]
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def symbolize_keys(hash)
|
25
|
+
Hash[hash.map { |key, value| [key.to_sym, value] }]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Dean
|
2
|
+
class GitHelper
|
3
|
+
|
4
|
+
def commit_asking_user(prompt, new_version, envs_paths)
|
5
|
+
def ask_user(message)
|
6
|
+
puts message.chomp + " (y/n)"
|
7
|
+
user_input = $stdin.gets.chomp!
|
8
|
+
user_input == 'y'
|
9
|
+
end
|
10
|
+
|
11
|
+
if ask_user prompt
|
12
|
+
# unstage everything for safety
|
13
|
+
system "git reset HEAD . 1> /dev/null"
|
14
|
+
# stage the info plists
|
15
|
+
envs_paths.each do |path|
|
16
|
+
system "git add #{path}"
|
17
|
+
end
|
18
|
+
# commit
|
19
|
+
message = "Bumped version to #{new_version}"
|
20
|
+
system "git commit -m 'Bumped version to #{new_version}' 1> /dev/null"
|
21
|
+
|
22
|
+
if ask_user "Do you want to tag this commit with version #{new_version}? (Editor will open to insert message)"
|
23
|
+
system "git tag -a #{new_version}"
|
24
|
+
end
|
25
|
+
|
26
|
+
puts "Done"
|
27
|
+
else
|
28
|
+
puts "Changes not committed"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Dean
|
2
|
+
class ProjectVersionHelper
|
3
|
+
|
4
|
+
def version_from_plist(plist)
|
5
|
+
value_from_plist('CFBundleVersion', plist)
|
6
|
+
end
|
7
|
+
|
8
|
+
def set_version_in_plist(version, plist_path)
|
9
|
+
set_value_in_plist("CFBundleVersion", version, plist_path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def short_version_from_plist(plist)
|
13
|
+
value_from_plist('CFBundleShortVersionString', plist)
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_short_version_in_plist(version, plist_path)
|
17
|
+
set_value_in_plist("CFBundleShortVersionString", version, plist_path)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def value_from_plist(key, plist)
|
23
|
+
plist_path = ''
|
24
|
+
if plist[0] == '/'
|
25
|
+
plist_path = plist
|
26
|
+
else
|
27
|
+
plist_path = "#{Dir.pwd}/#{plist}"
|
28
|
+
end
|
29
|
+
|
30
|
+
if not File.exists? plist_path
|
31
|
+
# Maybe raise exception instead?
|
32
|
+
return -1
|
33
|
+
end
|
34
|
+
|
35
|
+
plist = Plist::parse_xml plist_path
|
36
|
+
return plist[key]
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_value_in_plist(key, value, plist_path)
|
40
|
+
if not File.exists? plist_path
|
41
|
+
puts "Cannot open #{plist_path}. File not found"
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
plist = Plist::parse_xml plist_path
|
46
|
+
plist[key] = value
|
47
|
+
plist.save_plist plist_path
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "semantic"
|
2
|
+
|
3
|
+
module Dean
|
4
|
+
class SemverHelper
|
5
|
+
|
6
|
+
def bump_major version
|
7
|
+
semver = no_pre_semver version
|
8
|
+
semver.major += 1
|
9
|
+
semver.minor = 0
|
10
|
+
semver.patch = 0
|
11
|
+
semver.pre = nil
|
12
|
+
semver.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
def bump_minor version
|
16
|
+
semver = no_pre_semver version
|
17
|
+
semver.minor += 1
|
18
|
+
semver.patch = 0
|
19
|
+
semver.pre = nil
|
20
|
+
semver.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def bump_patch version
|
24
|
+
semver = no_pre_semver version
|
25
|
+
semver.patch += 1
|
26
|
+
semver.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def bump_pre version
|
30
|
+
semver = semver version
|
31
|
+
pre = semver.pre
|
32
|
+
|
33
|
+
return if not pre
|
34
|
+
|
35
|
+
split = pre.split('.')
|
36
|
+
if split.length == 1
|
37
|
+
semver.pre += '.1'
|
38
|
+
else
|
39
|
+
value = split[-1]
|
40
|
+
split[-1] = (value.to_i + 1).to_s
|
41
|
+
semver.pre = split.join '.'
|
42
|
+
end
|
43
|
+
|
44
|
+
semver.to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def semver(string)
|
50
|
+
Semantic::Version.new string
|
51
|
+
end
|
52
|
+
|
53
|
+
def no_pre_semver(string)
|
54
|
+
v = semver string
|
55
|
+
if v.pre
|
56
|
+
v.pre = nil
|
57
|
+
end
|
58
|
+
return v
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/dean/version.rb
ADDED
data/lib/dean.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require "dean/version"
|
2
|
+
require "dean/configuration_helper"
|
3
|
+
require "dean/project_version_helper"
|
4
|
+
require "dean/semver_helper"
|
5
|
+
require "dean/git_helper"
|
6
|
+
require "dean/cli"
|
7
|
+
require "dean/commands/build"
|
8
|
+
require "dean/commands/upload"
|
9
|
+
require "dean/commands/version_bumper"
|
10
|
+
require "colorize"
|
data/spec/build_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Dean::Build do
|
4
|
+
let (:builder) { described_class.new }
|
5
|
+
|
6
|
+
context "when building an environment with a missing plist file" do
|
7
|
+
it "should raise an IOError" do
|
8
|
+
invalid_plist_path = 'invalid.plist'
|
9
|
+
environment = {
|
10
|
+
:name => 'environment',
|
11
|
+
:plist => invalid_plist_path,
|
12
|
+
:build_settings => {
|
13
|
+
:workspace => 'MyProject.xcworkspace',
|
14
|
+
:project => 'MyProject.xcodeproj',
|
15
|
+
:build_configuration => 'Beta',
|
16
|
+
:scheme => 'MyProject-Beta',
|
17
|
+
:provisioning_profile => 'MyProject_Stage_Enterprise_Provisioning_Profile.mobileprovision',
|
18
|
+
:location => 'Builds/Beta',
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
File.stub(:exists?) { true } # default stub value
|
23
|
+
File.stub(:exists?).with(/#{invalid_plist_path}/) { false }
|
24
|
+
|
25
|
+
expect{ builder.build_environment environment }.to raise_error(IOError)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when building an environment with a missing provisioning profile file" do
|
30
|
+
it "should raise an IOError" do
|
31
|
+
invalid_provisioning_profile_path = 'invalid.mobileprovision'
|
32
|
+
environment = {
|
33
|
+
:name => 'environment',
|
34
|
+
:plist => 'MyProject-Info.plist',
|
35
|
+
:build_settings => {
|
36
|
+
:workspace => 'MyProject.xcworkspace',
|
37
|
+
:project => 'MyProject.xcodeproj',
|
38
|
+
:build_configuration => 'Beta',
|
39
|
+
:scheme => 'MyProject-Beta',
|
40
|
+
:provisioning_profile => invalid_provisioning_profile_path,
|
41
|
+
:location => 'Builds/Beta',
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
File.stub(:exists?) { true } # default stub value
|
46
|
+
File.stub(:exists?).with(/#{invalid_provisioning_profile_path}/) { false }
|
47
|
+
|
48
|
+
expect{ builder.build_environment environment }.to raise_error(IOError)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "tempfile"
|
3
|
+
|
4
|
+
describe Dean::ProjectVersionHelper do
|
5
|
+
let (:helper) { described_class.new }
|
6
|
+
|
7
|
+
context "when the plist exists on disk" do
|
8
|
+
before do
|
9
|
+
@expected_version = '4.2.0'
|
10
|
+
@expected_short_version = '42'
|
11
|
+
@temp_plist = Tempfile.new 'plist'
|
12
|
+
@plist = {
|
13
|
+
'CFBundleVersion' => @expected_version,
|
14
|
+
'CFBundleShortVersionString' => @expected_short_version
|
15
|
+
}
|
16
|
+
# I don't like using plist gem in here, need more context independency
|
17
|
+
Plist::Emit::save_plist @plist, @temp_plist.path
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return the CFBundleVersion value" do
|
21
|
+
expect(helper.version_from_plist @temp_plist.path).to eq @expected_version
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should set the CFBundleVersion value to the given one" do
|
25
|
+
expected_version = '1.2.3'
|
26
|
+
helper.set_version_in_plist expected_version, @temp_plist.path
|
27
|
+
|
28
|
+
version = Plist::parse_xml(@temp_plist.path)['CFBundleVersion']
|
29
|
+
|
30
|
+
expect(version).to eq expected_version
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return the CFBundleShortVersionString value" do
|
34
|
+
expect(helper.short_version_from_plist @temp_plist.path).to eq @expected_short_version
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should set the CFBundleShortVersionString value to the given one" do
|
38
|
+
expected_version = '23'
|
39
|
+
helper.set_short_version_in_plist expected_version, @temp_plist.path
|
40
|
+
|
41
|
+
version = Plist::parse_xml(@temp_plist.path)['CFBundleShortVersionString']
|
42
|
+
|
43
|
+
expect(version).to eq expected_version
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "when the plist does not exists on disk" do
|
48
|
+
before do
|
49
|
+
File.stub(:exists?).and_return false
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return a -1 version value" do
|
53
|
+
expect(helper.version_from_plist 'plist').to eq -1
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should return a -1 short version value" do
|
57
|
+
expect(helper.version_from_plist 'plist').to eq -1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def local_file(name)
|
62
|
+
"#{Dir.pwd}/#{name}"
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Dean::SemverHelper do
|
4
|
+
let (:helper) { described_class.new }
|
5
|
+
|
6
|
+
it "shuold bump the major value of the given version" do
|
7
|
+
expect(helper.bump_major '1.0.0').to eq '2.0.0'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "shuold bump the major value of the given version, zeroing the lesser values" do
|
11
|
+
expect(helper.bump_major '1.2.3-pre.4').to eq '2.0.0'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "shuold bump the minor value of the given version" do
|
15
|
+
expect(helper.bump_minor '1.0.0').to eq '1.1.0'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "shuold bump the minor value of the given version, zeroing the lesser values" do
|
19
|
+
expect(helper.bump_minor '1.2.3-pre.4').to eq '1.3.0'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "shuold bump the patch value of the given version" do
|
23
|
+
expect(helper.bump_patch '1.0.0').to eq '1.0.1'
|
24
|
+
end
|
25
|
+
|
26
|
+
it "shuold bump the pre value of the given version" do
|
27
|
+
expect(helper.bump_pre '1.0.0-pre.0').to eq '1.0.0-pre.1'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "shuold bump the pre value of the given version to 1 if no number is present" do
|
31
|
+
expect(helper.bump_pre '1.0.0-pre').to eq '1.0.0-pre.1'
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when bumping a version with a pre value" do
|
35
|
+
it "shold remove the pre value if bumping the major value" do
|
36
|
+
expect(helper.bump_major '1.0.0-pre.0').to eq '2.0.0'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "shold remove the pre value if bumping the minor value" do
|
40
|
+
expect(helper.bump_minor '1.0.0-pre.0').to eq '1.1.0'
|
41
|
+
end
|
42
|
+
|
43
|
+
it "shold remove the pre value if bumping the patch value" do
|
44
|
+
expect(helper.bump_patch '1.0.0-pre').to eq '1.0.1'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "tempfile"
|
3
|
+
|
4
|
+
describe Dean::VersionBumper do
|
5
|
+
let (:bumper) { described_class.new }
|
6
|
+
|
7
|
+
context "bumping an environment" do
|
8
|
+
before(:each) do
|
9
|
+
Dean::ProjectVersionHelper.stub(:version_from_plist) { "1.0.0" }
|
10
|
+
Dean::ProjectVersionHelper.any_instance.stub(:set_version_in_plist)
|
11
|
+
Dean::ProjectVersionHelper.stub(:short_version_from_plist) { "1.0.0" }
|
12
|
+
Dean::ProjectVersionHelper.any_instance.stub(:set_short_version_in_plist)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should bump the version" do
|
16
|
+
bumper.should_receive :bump
|
17
|
+
bumper.bump_environment "major", { :plist => "path" }
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should bump the short version" do
|
21
|
+
bumper.should_receive :bump_short
|
22
|
+
bumper.bump_environment "major", { :plist => "path" }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "bumping all environments" do
|
27
|
+
it "should not bump the same plist twice" do
|
28
|
+
@temp_plist = setup_plist
|
29
|
+
stage_env = { :name => "stage", :plist => @temp_plist.path }
|
30
|
+
production_env = { :name => "prod", :plist => @temp_plist.path }
|
31
|
+
Dean::ConfigurationHelper.any_instance.stub(:all_environments) { [stage_env, production_env] }
|
32
|
+
|
33
|
+
bumper.bump_all_environments(:major)
|
34
|
+
expect(Plist::parse_xml(@temp_plist.path)['CFBundleVersion']).to eq '1.0.0'
|
35
|
+
expect(Plist::parse_xml(@temp_plist.path)['CFBundleShortVersionString']).to eq '1.0.0'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "bumping the version value of a plist file" do
|
40
|
+
before(:each) do
|
41
|
+
@temp_plist = setup_plist
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should have two mandatory parameter" do
|
45
|
+
expect{ bumper.bump }.to raise_error(ArgumentError)
|
46
|
+
expect{ bumper.bump "something" }.to raise_error(ArgumentError)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should bump the major value of the given version when passed the :major parameter" do
|
50
|
+
bumper.bump @temp_plist.path, :major
|
51
|
+
expect(Plist::parse_xml(@temp_plist.path)['CFBundleVersion']).to eq '1.0.0'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should bump the minor value of the given version when passed the :minor parameter" do
|
55
|
+
bumper.bump @temp_plist.path, :minor
|
56
|
+
expect(Plist::parse_xml(@temp_plist.path)['CFBundleVersion']).to eq '0.1.0'
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should bump the patch value of the given version when passed the :patch parameter" do
|
60
|
+
bumper.bump @temp_plist.path, :patch
|
61
|
+
expect(Plist::parse_xml(@temp_plist.path)['CFBundleVersion']).to eq '0.0.1'
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should bump the pre value of the given version when passed the :pre parameter" do
|
65
|
+
tempfile = setup_plist '0.0.0-pre.0'
|
66
|
+
bumper.bump tempfile.path, :pre
|
67
|
+
expect(Plist::parse_xml(tempfile.path)['CFBundleVersion']).to eq '0.0.0-pre.1'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "bumping the short version value of a plist file" do
|
72
|
+
before(:each) do
|
73
|
+
@temp_plist = setup_plist
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should have two mandatory parameter" do
|
77
|
+
expect{ bumper.bump_short }.to raise_error(ArgumentError)
|
78
|
+
expect{ bumper.bump_short "something" }.to raise_error(ArgumentError)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should bump the major value of the given version when passed the :major parameter" do
|
82
|
+
bumper.bump_short @temp_plist.path, :major
|
83
|
+
expect(Plist::parse_xml(@temp_plist.path)['CFBundleShortVersionString']).to eq '1.0.0'
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should bump the minor value of the given version when passed the :minor parameter" do
|
87
|
+
bumper.bump_short @temp_plist.path, :minor
|
88
|
+
expect(Plist::parse_xml(@temp_plist.path)['CFBundleShortVersionString']).to eq '0.1.0'
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should bump the patch value of the given version when passed the :patch parameter" do
|
92
|
+
bumper.bump_short @temp_plist.path, :patch
|
93
|
+
expect(Plist::parse_xml(@temp_plist.path)['CFBundleShortVersionString']).to eq '0.0.1'
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should bump the pre value of the given version when passed the :pre parameter" do
|
97
|
+
tempfile = setup_plist '0.0.0', '0.0.0-pre.0'
|
98
|
+
bumper.bump_short tempfile.path, :pre
|
99
|
+
expect(Plist::parse_xml(tempfile.path)['CFBundleShortVersionString']).to eq '0.0.0-pre.1'
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def setup_plist(version='0.0.0', version_short='0.0.0')
|
105
|
+
tempfile = Tempfile.new 'plist'
|
106
|
+
plist = {
|
107
|
+
'CFBundleVersion' => version,
|
108
|
+
'CFBundleShortVersionString' => version_short
|
109
|
+
}
|
110
|
+
# I don't like using plist gem in here, need more context independency
|
111
|
+
Plist::Emit::save_plist plist, tempfile.path
|
112
|
+
return tempfile
|
113
|
+
end
|
114
|
+
end
|
metadata
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dean
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Giovanni Lodi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.17.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.17.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: shenzhen
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: plist
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.1.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.1.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: colorize
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.7.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.7.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: semantic
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.3.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.3.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: xcodeproj
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.16.1
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.16.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: bundler
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.3'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.3'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ~>
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 2.14.1
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ~>
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 2.14.1
|
139
|
+
description: An (opinionated) CLI tool to ease mundane tasks of the iOS beta distribution
|
140
|
+
email:
|
141
|
+
- giovanni.lodi42@gmail.com
|
142
|
+
executables:
|
143
|
+
- dean
|
144
|
+
extensions: []
|
145
|
+
extra_rdoc_files: []
|
146
|
+
files:
|
147
|
+
- .gitignore
|
148
|
+
- .travis.yml
|
149
|
+
- Gemfile
|
150
|
+
- LICENSE.txt
|
151
|
+
- README.md
|
152
|
+
- Rakefile
|
153
|
+
- bin/dean
|
154
|
+
- dean.gemspec
|
155
|
+
- lib/dean.rb
|
156
|
+
- lib/dean/cli.rb
|
157
|
+
- lib/dean/commands/build.rb
|
158
|
+
- lib/dean/commands/upload.rb
|
159
|
+
- lib/dean/commands/version_bumper.rb
|
160
|
+
- lib/dean/configuration_helper.rb
|
161
|
+
- lib/dean/git_helper.rb
|
162
|
+
- lib/dean/project_version_helper.rb
|
163
|
+
- lib/dean/semver_helper.rb
|
164
|
+
- lib/dean/version.rb
|
165
|
+
- spec/build_spec.rb
|
166
|
+
- spec/project_version_helper_spec.rb
|
167
|
+
- spec/semver_helper_spec.rb
|
168
|
+
- spec/spec_helper.rb
|
169
|
+
- spec/version_bumper_spec.rb
|
170
|
+
homepage: https://github.com/bizzby/dean
|
171
|
+
licenses:
|
172
|
+
- MIT
|
173
|
+
metadata: {}
|
174
|
+
post_install_message:
|
175
|
+
rdoc_options: []
|
176
|
+
require_paths:
|
177
|
+
- lib
|
178
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
179
|
+
requirements:
|
180
|
+
- - '>='
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: '0'
|
183
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - '>='
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
requirements: []
|
189
|
+
rubyforge_project:
|
190
|
+
rubygems_version: 2.2.1
|
191
|
+
signing_key:
|
192
|
+
specification_version: 4
|
193
|
+
summary: An (opinionated) CLI tool to ease mundane tasks of the iOS beta distribution,
|
194
|
+
such as version bumps, archiving, and deploying, all configured in a simple unique
|
195
|
+
file.
|
196
|
+
test_files:
|
197
|
+
- spec/build_spec.rb
|
198
|
+
- spec/project_version_helper_spec.rb
|
199
|
+
- spec/semver_helper_spec.rb
|
200
|
+
- spec/spec_helper.rb
|
201
|
+
- spec/version_bumper_spec.rb
|
202
|
+
has_rdoc:
|