yes_ship_it 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 444ecc2191ed065ffeb7d23921a8518897ef5f59
4
+ data.tar.gz: 41ccaa7257b29964108a58bd27ddd5a9519984b8
5
+ SHA512:
6
+ metadata.gz: e5ab4853e2fd9337988199767d0264046b49f3122c773bda25d15d0f182f9f75caa73fa30764cb6dfa4c53fc72b1dafb52ccdba7ed625a9fafbf2d2599042afb
7
+ data.tar.gz: 9396162f0020b8ce79e9fc15475010f41b0da38a55c3f677172436a12e1c2d61b3a8d5152a07721688f1f5ab7037b6d9fc78d1a6323d3eb12da132c9a7fb84c4
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # Yes, ship it!
2
+
3
+ *The ultimate release script*
4
+
5
+ Whenever the answer is "Yes, ship it!" you will need `yes_ship_it`, this tool.
6
+ It is the ultimate helper in releasing software.
7
+
8
+ Shipping software is not an action. It's a state of mind. `yes_ship_it` helps
9
+ you to make sure that reality matches this state of mind. It won't fix the bugs
10
+ in your software, it doesn't create the tests which would need to be there, it
11
+ doesn't write your release notes. It does make sure that your good engineering
12
+ is delivered to your users with zero cost.
13
+
14
+ The approach of `yes_ship_it` is different from the typical release script. It
15
+ doesn't define a series of steps which are executed to make a release. It
16
+ defines a sequence of assertions about the release, which then are checked and
17
+ enforced.
18
+
19
+ This works in a way you could describe as idempotent, which means you
20
+ can execute it as many times as you want, the result will always be the same,
21
+ regardless of the initial state. That means the whole process is robust against
22
+ errors which happen during releasing, it transparently copes with manual tweaks
23
+ and changes, and it works on old releases just as well as on new releases.
24
+
25
+ After successfully running `yes_ship_it` your release will have shipped, and the
26
+ state of the world will reflect the state of your mind.
27
+
28
+ ## Assumptions
29
+
30
+ `yes_ship_it` assumes that you develop your software in a version control
31
+ system and keep at least some minimal state of releases there. This could just
32
+ be a tag. It also assumes that you are able to run `yes_ship_it` from the
33
+ command line and have some access to the systems which are needed to complete
34
+ the things part of a release.
35
+
36
+ ## How to run it
37
+
38
+ Go to the checkout of the sources of your software. Check that there is a file
39
+ called `yes_ship_it.conf` there. Run `yes_ship_it`. Done.
40
+
41
+ ## Configuration
42
+
43
+ The central configuration of what happens when you run `yes_ship_it` is the
44
+ `yes_ship_it.conf` file in the root directory of the sources of your software.
45
+ There you define the sequence of assertions which are run through for making
46
+ sure that the release is happening in the way you intend. `yes_ship_it` comes
47
+ with some predefined sequences of assertions you can simply reuse.
48
+
49
+ The format of `yes_ship_it.conf` uses YAML. A minimal `yes_ship_it.conf` file
50
+ could look like this:
51
+
52
+ ```yaml
53
+ include:
54
+ standard_rubygem
55
+ ```
56
+
57
+ A more detailed configuration could look like this:
58
+
59
+ ```yaml
60
+ assertions:
61
+ ci_green
62
+ release_notes
63
+ version_number
64
+ gem_built
65
+ release_tagged
66
+ gem_pushed
67
+ ```
68
+
69
+ There can be more configuration on a general level or the level of the
70
+ assertions to adjust to specific needs of each software project. There also can
71
+ be other or additional assertions.
72
+
73
+ ## Extending `yes_ship_it`
74
+
75
+ Many software projects will have specific needs for their releases. These can
76
+ be broken down and reflected in additional assertions. Adding assertions is
77
+ easy. There is a well-defined API for it.
78
+
79
+ There is no supported plugin concept. The idea is that all assertions ship with
80
+ `yes_ship_it`. This will maximize the value for the community of people who ship
81
+ software. The project is very open to include new assertions. Just submit a pull
82
+ request. `yes_ship_it` will ship it with the next release.
83
+
84
+ ## Testing
85
+
86
+ Testing a tool such as `yes_ship_it` is not easy because its prime functionality
87
+ is to interact with other systems and publish data. There are unit tests for the
88
+ code. There also are integration tests which work in a virtual environment which
89
+ fakes the services `yes_ship_it` interacts with. It uses the `pennyworth` tool
90
+ to manage the virtual environment and make them accessible in a convenient way
91
+ from the RSpec tests.
92
+
93
+ ## Further documentation
94
+
95
+ You get basic documentation from the tool itself by executing
96
+ `yes_ship_it help`. There also is a simple man page with some pointers.
97
+
98
+ The main documentation with details about different scenarios how `yes_ship_it`
99
+ can be used is maintained in the Wiki. You are welcome to contribute there.
100
+
101
+ ## License
102
+
103
+ `yes_ship_it` is licensed under the MIT license.
104
+
105
+ ## Contact
106
+
107
+ If you have any questions or comments, please don't hesitate to get in touch
108
+ with me: Cornelius Schumacher <schumacher@kde.org>.
@@ -0,0 +1,43 @@
1
+ module YSI
2
+ class BuiltGem < Assertion
3
+ attr_accessor :error
4
+
5
+ def initialize(engine)
6
+ @engine = engine
7
+ end
8
+
9
+ def display_name
10
+ "built gem"
11
+ end
12
+
13
+ def gem_file
14
+ "#{@engine.project_name}-#{@engine.version}.gem"
15
+ end
16
+
17
+ def gemspec_file
18
+ "#{@engine.project_name}.gemspec"
19
+ end
20
+
21
+ def check
22
+ if !File.exist?(gemspec_file)
23
+ @error = "I need a gemspec: #{gemspec_file}"
24
+ return nil
25
+ end
26
+
27
+ if !File.exist?(gem_file)
28
+ return nil
29
+ end
30
+
31
+ gem_file
32
+ end
33
+
34
+ def assert(dry_run: false)
35
+ if !dry_run
36
+ if !system("gem build #{gemspec_file}")
37
+ return nil
38
+ end
39
+ end
40
+ gem_file
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ module YSI
2
+ class ChangeLog < Assertion
3
+ attr_reader :error
4
+
5
+ def initialize(engine)
6
+ @engine = engine
7
+ end
8
+
9
+ def display_name
10
+ "change log"
11
+ end
12
+
13
+ def check
14
+ if !File.exist?("CHANGELOG.md")
15
+ @error = "Expected change log in CHANGELOG.md"
16
+ return nil
17
+ end
18
+
19
+ "CHANGELOG.md"
20
+ end
21
+
22
+ def assert(dry_run: false)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,39 @@
1
+ module YSI
2
+ class PublishedGem < Assertion
3
+ attr_accessor :error
4
+
5
+ def initialize(engine)
6
+ @engine = engine
7
+ end
8
+
9
+ def display_name
10
+ "published gem"
11
+ end
12
+
13
+ def gem_file
14
+ "#{@engine.project_name}-#{@engine.version}.gem"
15
+ end
16
+
17
+ def check
18
+ begin
19
+ json = RestClient.get("http://rubygems.org/api/v1/versions/#{engine.project_name}.json")
20
+ rescue RestClient::ResourceNotFound
21
+ return nil
22
+ end
23
+ versions = JSON.parse(json)
24
+ versions.each do |version|
25
+ if version["number"] == @engine.version
26
+ return @engine.version
27
+ end
28
+ end
29
+ nil
30
+ end
31
+
32
+ def assert(dry_run: false)
33
+ if !dry_run
34
+ `gem push #{gem_file}`
35
+ end
36
+ gem_file
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ module YSI
2
+ class PushedTag < Assertion
3
+ def display_name
4
+ "pushed tag"
5
+ end
6
+
7
+ def tag
8
+ "v#{@engine.version}"
9
+ end
10
+
11
+ def check
12
+ response = `git ls-remote --tags origin #{tag}`
13
+ if response.include?(tag)
14
+ return response
15
+ end
16
+
17
+ nil
18
+ end
19
+
20
+ def assert(dry_run: false)
21
+ if !dry_run
22
+ `git push --tags`
23
+ end
24
+ tag
25
+ end
26
+ end
27
+ end
data/assertions/tag.rb ADDED
@@ -0,0 +1,32 @@
1
+ module YSI
2
+ class Tag < Assertion
3
+ def display_name
4
+ "tag"
5
+ end
6
+
7
+ def tag
8
+ "v#{@engine.version}"
9
+ end
10
+
11
+ def check
12
+ `git tag`.each_line do |line|
13
+ if line.chomp == tag
14
+ `git show #{tag}`.each_line do |show_line|
15
+ if show_line =~ /Date:\s+(.*)/
16
+ @engine.tag_date = $1
17
+ end
18
+ end
19
+ return tag
20
+ end
21
+ end
22
+ return nil
23
+ end
24
+
25
+ def assert(dry_run: false)
26
+ if !dry_run
27
+ `git tag -a #{tag} -m "Version #{@engine.version}"`
28
+ end
29
+ tag
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ module YSI
2
+ class Version < Assertion
3
+ attr_accessor :error
4
+
5
+ def initialize(engine)
6
+ @engine = engine
7
+ end
8
+
9
+ def display_name
10
+ "version number"
11
+ end
12
+
13
+ def check
14
+ version_file = "lib/version.rb"
15
+ if !File.exist?(version_file)
16
+ @error = "Expected version in #{version_file}"
17
+ return nil
18
+ end
19
+
20
+ File.read(version_file).each_line do |line|
21
+ if line =~ /VERSION = "(.*)"/
22
+ @engine.version = $1
23
+ return @engine.version
24
+ end
25
+ end
26
+ @error = "Couldn't find version in #{version_file}"
27
+ nil
28
+ end
29
+
30
+ def assert(dry_run: false)
31
+ end
32
+ end
33
+ end
data/bin/yes_ship_it ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require_relative("../lib/yes_ship_it.rb")
4
+
5
+ puts "Shipping..."
6
+ puts
7
+
8
+ config_file = "yes_ship_it.conf"
9
+
10
+ if !File.exist?(config_file)
11
+ STDERR.puts("Unable to find file `yes_ship_it.conf`. I need it.")
12
+ exit 1
13
+ end
14
+
15
+ engine = YSI::Engine.new
16
+ engine.dry_run = ARGV == ["--dry-run"]
17
+
18
+ begin
19
+ engine.read(config_file)
20
+
21
+ exit engine.run
22
+ rescue YSI::Error => e
23
+ STDERR.puts e
24
+ exit 1
25
+ end
@@ -0,0 +1,10 @@
1
+ module YSI
2
+ class Assertion
3
+ attr_reader :error
4
+ attr_accessor :engine
5
+
6
+ def initialize(engine)
7
+ @engine = engine
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,104 @@
1
+ module YSI
2
+ class Engine
3
+ attr_reader :assertions
4
+ attr_accessor :version, :tag_date
5
+ attr_accessor :out
6
+ attr_accessor :dry_run
7
+
8
+ def self.class_for_assertion_name(name)
9
+ class_name = name.split("_").map { |n| n.capitalize }.join
10
+ begin
11
+ Object.const_get("YSI::" + class_name)
12
+ rescue NameError
13
+ raise YSI::Error.new("Error: Unknown assertion '#{name}'")
14
+ end
15
+ end
16
+
17
+ def initialize
18
+ @assertions = []
19
+ @out = STDOUT
20
+ end
21
+
22
+ def read(filename)
23
+ config = YAML.load_file(filename)
24
+
25
+ assertions = config["assertions"]
26
+ if assertions
27
+ assertions.each do |assertion|
28
+ if assertion == "version_number"
29
+ out.puts "Warning: use `version` instead of `version_number`."
30
+ out.puts
31
+ assertion = "version"
32
+ end
33
+
34
+ @assertions << YSI::Engine.class_for_assertion_name(assertion).new(self)
35
+ end
36
+ end
37
+ end
38
+
39
+ def project_name
40
+ File.basename(Dir.pwd)
41
+ end
42
+
43
+ def run
44
+ failed_assertions = []
45
+ errored_assertions = []
46
+
47
+ @assertions.each do |assertion|
48
+ out.print "Checking #{assertion.display_name}: "
49
+ success = assertion.check
50
+ if success
51
+ out.puts success
52
+ else
53
+ if assertion.error
54
+ out.puts "error"
55
+ out.puts " " + assertion.error
56
+ errored_assertions.push(assertion)
57
+ else
58
+ out.puts "fail"
59
+ failed_assertions.push(assertion)
60
+ end
61
+ end
62
+ end
63
+
64
+ out.puts
65
+
66
+ if !errored_assertions.empty?
67
+ out.puts "Couldn't ship #{project_name}. Help me."
68
+ return 1
69
+ else
70
+ if failed_assertions.empty?
71
+ if tag_date
72
+ out.puts "#{project_name} #{version} already shipped on #{tag_date}"
73
+ else
74
+ out.puts "#{project_name} #{version} already shipped"
75
+ end
76
+ return 0
77
+ else
78
+ failed_assertions.each do |assertion|
79
+ if dry_run
80
+ out.print "Dry run: "
81
+ end
82
+ out.print "Asserting #{assertion.display_name}: "
83
+ success = assertion.assert(dry_run: dry_run)
84
+ if !success
85
+ out.puts
86
+ out.puts "Ran into an error. Stopping shipping."
87
+ return 1
88
+ end
89
+ out.puts success
90
+ end
91
+
92
+ out.puts
93
+ if dry_run
94
+ out.puts "Did a dry run of shipping #{project_name} #{version}." +
95
+ " Nothing was changed."
96
+ else
97
+ out.puts "Shipped #{project_name} #{version}. Hooray!"
98
+ end
99
+ return 0
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,4 @@
1
+ module YSI
2
+ class Error < StandardError
3
+ end
4
+ end
@@ -0,0 +1,9 @@
1
+ require "yaml"
2
+ require "rest-client"
3
+
4
+ require_relative "yes_ship_it/assertion.rb"
5
+ require_relative "yes_ship_it/engine.rb"
6
+ require_relative "yes_ship_it/exceptions.rb"
7
+
8
+ assertions_dir = File.expand_path("../../assertions", __FILE__)
9
+ Dir[File.join(assertions_dir, "*.rb")].each { |f| require(f) }
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,3 @@
1
+ assertions:
2
+ - version
3
+ - change_log
@@ -0,0 +1,4 @@
1
+ assertions:
2
+ - version
3
+ - change_log
4
+ - xyz
@@ -0,0 +1,123 @@
1
+ require_relative "spec_helper"
2
+
3
+ include CliTester
4
+ include GivenFilesystemSpecHelpers
5
+
6
+ describe "command line interface" do
7
+ use_given_filesystem(keep_files: true)
8
+
9
+ it "does not find yes_ship_it.conf" do
10
+ dir = given_directory
11
+ expect(run_command(working_directory: dir)).to exit_with_error(1, /yes_ship_it.conf/)
12
+ end
13
+
14
+ describe "runs" do
15
+ it "fails when version is not there" do
16
+ dir = given_directory
17
+
18
+ setup_test_git_repo("000", dir)
19
+
20
+ expected_output = <<EOT
21
+ Shipping...
22
+
23
+ Warning: use `version` instead of `version_number`.
24
+
25
+ Checking version number: error
26
+ Expected version in lib/version.rb
27
+ Checking change log: error
28
+ Expected change log in CHANGELOG.md
29
+
30
+ Couldn't ship red_herring. Help me.
31
+ EOT
32
+
33
+ expect(run_command(working_directory: File.join(dir, "red_herring"))).
34
+ to exit_with_error(1, "", expected_output)
35
+ end
36
+
37
+ it "succeeds when all checks are met" do
38
+ dir = given_directory
39
+
40
+ setup_test_git_repo("001", dir)
41
+
42
+ expected_output = <<EOT
43
+ Shipping...
44
+
45
+ Warning: use `version` instead of `version_number`.
46
+
47
+ Checking version number: 0.0.1
48
+ Checking change log: CHANGELOG.md
49
+
50
+ red_herring 0.0.1 already shipped
51
+ EOT
52
+
53
+ expect(run_command(working_directory: File.join(dir, "red_herring"))).
54
+ to exit_with_success(expected_output)
55
+ end
56
+
57
+ it "succeeds when tag is there" do
58
+ dir = given_directory
59
+
60
+ setup_test_git_repo("002", dir)
61
+
62
+ expected_output = <<EOT
63
+ Shipping...
64
+
65
+ Warning: use `version` instead of `version_number`.
66
+
67
+ Checking version number: 0.0.1
68
+ Checking change log: CHANGELOG.md
69
+ Checking tag: v0.0.1
70
+
71
+ red_herring 0.0.1 already shipped on Wed Jul 1 00:46:19 2015 +0200
72
+ EOT
73
+
74
+ expect(run_command(working_directory: File.join(dir, "red_herring"))).
75
+ to exit_with_success(expected_output)
76
+ end
77
+
78
+ it "fails when gem is not built" do
79
+ dir = given_directory
80
+
81
+ setup_test_git_repo("003", dir)
82
+
83
+ expected_output = <<EOT
84
+ Shipping...
85
+
86
+ Checking version number: 0.0.1
87
+ Checking change log: CHANGELOG.md
88
+ Checking built gem: fail
89
+ Checking tag: v0.0.1
90
+
91
+ Asserting built gem: red_herring-0.0.1.gem
92
+
93
+ Shipped red_herring 0.0.1. Hooray!
94
+ EOT
95
+
96
+ expect(run_command(working_directory: File.join(dir, "red_herring"))).
97
+ to exit_with_success(expected_output)
98
+ end
99
+
100
+ it "processes the --dry-run option" do
101
+ dir = given_directory
102
+
103
+ setup_test_git_repo("003", dir)
104
+
105
+ expected_output = <<EOT
106
+ Shipping...
107
+
108
+ Checking version number: 0.0.1
109
+ Checking change log: CHANGELOG.md
110
+ Checking built gem: fail
111
+ Checking tag: v0.0.1
112
+
113
+ Dry run: Asserting built gem: red_herring-0.0.1.gem
114
+
115
+ Did a dry run of shipping red_herring 0.0.1. Nothing was changed.
116
+ EOT
117
+
118
+ expect(run_command(args: ["--dry-run"],
119
+ working_directory: File.join(dir, "red_herring"))).
120
+ to exit_with_success(expected_output)
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,10 @@
1
+ require "cli_tester"
2
+ require "given_filesystem/spec_helpers"
3
+
4
+ def setup_test_git_repo(version, dir)
5
+ tarball = "spec/data/red_herring-#{version}.tar.gz"
6
+ tarball_path = File.expand_path(tarball)
7
+ if !system("cd #{dir}; tar xzf #{tarball_path}")
8
+ raise "Unable to extract tarball #{tarball}"
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ require_relative "spec_helper"
2
+
3
+ describe "all assertions" do
4
+ all_classes = ObjectSpace.each_object(Class).select { |klass| klass < YSI::Assertion }
5
+
6
+ all_classes.each do |assertion_class|
7
+ describe assertion_class do
8
+ it_behaves_like "an assertion" do
9
+ let(:assertion) {assertion_class.new(YSI::Engine.new) }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,68 @@
1
+ require_relative "spec_helper.rb"
2
+
3
+ include GivenFilesystemSpecHelpers
4
+
5
+ describe YSI::Engine do
6
+ use_given_filesystem
7
+
8
+ describe "#class_for_assertion_name" do
9
+ it "creates VersionNumber class" do
10
+ expect(YSI::Engine.class_for_assertion_name("version")).
11
+ to be(YSI::Version)
12
+ end
13
+
14
+ it "creates ChangeLog class" do
15
+ expect(YSI::Engine.class_for_assertion_name("change_log")).
16
+ to be(YSI::ChangeLog)
17
+ end
18
+ end
19
+
20
+ describe "#read" do
21
+ it "reads valid configuration" do
22
+ path = nil
23
+ given_directory do
24
+ path = given_file("yes_ship_it.conf")
25
+ end
26
+
27
+ ysi = YSI::Engine.new
28
+
29
+ ysi.read(path)
30
+
31
+ expect(ysi.assertions.count).to eq(2)
32
+ expect(ysi.assertions[0].class).to eq(YSI::Version)
33
+ expect(ysi.assertions[1].class).to eq(YSI::ChangeLog)
34
+ end
35
+
36
+ it "fails on configuration with unknown assertions" do
37
+ path = nil
38
+ given_directory do
39
+ path = given_file("yes_ship_it.conf", from: "yes_ship_it.unknown.conf")
40
+ end
41
+
42
+ ysi = YSI::Engine.new
43
+
44
+ expect {
45
+ ysi.read(path)
46
+ }.to raise_error YSI::Error
47
+ end
48
+ end
49
+
50
+ it "runs assertions" do
51
+ path = nil
52
+ given_directory do
53
+ path = given_file("yes_ship_it.conf")
54
+ end
55
+
56
+ ysi = YSI::Engine.new
57
+
58
+ ysi.read(path)
59
+
60
+ ysi.assertions.each do |a|
61
+ expect(a).to receive(:check)
62
+ end
63
+
64
+ ysi.out = StringIO.new
65
+
66
+ ysi.run
67
+ end
68
+ end
@@ -0,0 +1,5 @@
1
+ require_relative "../../lib/yes_ship_it.rb"
2
+
3
+ support = File.expand_path("../support", __FILE__) + "/*.rb"
4
+
5
+ Dir[support].each { |f| require f }
@@ -0,0 +1,21 @@
1
+ shared_examples "an assertion" do
2
+ it "initializes with an engine" do
3
+ expect(assertion.engine).to be_a(YSI::Engine)
4
+ end
5
+
6
+ it "has a display name" do
7
+ expect(assertion.display_name).to be_a(String)
8
+ end
9
+
10
+ it "checks" do
11
+ expect(assertion).to respond_to(:check)
12
+ end
13
+
14
+ it "asserts" do
15
+ expect(assertion).to respond_to(:assert)
16
+ end
17
+
18
+ it "reports errors" do
19
+ expect(assertion).to respond_to(:error)
20
+ end
21
+ end
data/yes_ship_it.conf ADDED
@@ -0,0 +1,9 @@
1
+ # Experimental release automation. See https://github.com/cornelius/yes_ship_it.
2
+
3
+ assertions:
4
+ - version
5
+ - change_log
6
+ - built_gem
7
+ - published_gem
8
+ - tag
9
+ - pushed_tag
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yes_ship_it
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Cornelius Schumacher
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: given_filesystem
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: cli_tester
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Whenever the answer is 'Yes, ship it!' you will need yes_ship_it. It
56
+ is the ultimate helper in releasing software..
57
+ email:
58
+ - schumacher@kde.org
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - .rspec
64
+ - README.md
65
+ - assertions/built_gem.rb
66
+ - assertions/change_log.rb
67
+ - assertions/published_gem.rb
68
+ - assertions/pushed_tag.rb
69
+ - assertions/tag.rb
70
+ - assertions/version.rb
71
+ - bin/yes_ship_it
72
+ - lib/yes_ship_it.rb
73
+ - lib/yes_ship_it/assertion.rb
74
+ - lib/yes_ship_it/engine.rb
75
+ - lib/yes_ship_it/exceptions.rb
76
+ - spec/data/red_herring-000.tar.gz
77
+ - spec/data/red_herring-001.tar.gz
78
+ - spec/data/red_herring-002.tar.gz
79
+ - spec/data/red_herring-003.tar.gz
80
+ - spec/data/yes_ship_it.conf
81
+ - spec/data/yes_ship_it.unknown.conf
82
+ - spec/integration/cli_spec.rb
83
+ - spec/integration/spec_helper.rb
84
+ - spec/unit/assertions_spec.rb
85
+ - spec/unit/engine_spec.rb
86
+ - spec/unit/spec_helper.rb
87
+ - spec/unit/support/assertion_examples.rb
88
+ - yes_ship_it.conf
89
+ homepage: http://github.com/cornelius/yes_ship_it
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - '>='
105
+ - !ruby/object:Gem::Version
106
+ version: 1.3.6
107
+ requirements: []
108
+ rubyforge_project: yes_ship_it
109
+ rubygems_version: 2.0.3
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: The ultimate release script
113
+ test_files: []
114
+ has_rdoc: