yes_ship_it 0.0.2 → 0.0.3

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +1 -0
  4. data/CHANGELOG.md +14 -0
  5. data/README.md +9 -1
  6. data/USERS.md +13 -0
  7. data/assertions/built_gem.rb +0 -6
  8. data/assertions/change_log.rb +0 -6
  9. data/assertions/published_gem.rb +1 -7
  10. data/assertions/release_archive.rb +43 -0
  11. data/assertions/release_branch.rb +37 -0
  12. data/assertions/submitted_rpm.rb +134 -0
  13. data/assertions/version.rb +22 -11
  14. data/assertions/working_directory.rb +42 -0
  15. data/bin/yes_ship_it +22 -5
  16. data/configs/ruby_gem.conf +2 -0
  17. data/lib/version.rb +1 -1
  18. data/lib/yes_ship_it.rb +3 -0
  19. data/lib/yes_ship_it/assertion.rb +26 -0
  20. data/lib/yes_ship_it/engine.rb +25 -5
  21. data/spec/data/obs/mycroft.spec.erb +11 -0
  22. data/spec/data/obs/oscrc +8 -0
  23. data/spec/data/red_herring-006.tar.gz +0 -0
  24. data/spec/data/version/version.go +5 -0
  25. data/spec/data/version/version.rb +3 -0
  26. data/spec/integration/cli_spec.rb +74 -0
  27. data/spec/system/data/red_herring-checkout-build.tar.gz +0 -0
  28. data/spec/system/data/red_herring-checkout-not-push.tar.gz +0 -0
  29. data/spec/system/data/red_herring-checkout-push.tar.gz +0 -0
  30. data/spec/system/data/red_herring-remote.tar.gz +0 -0
  31. data/spec/system/ruby_gem_spec.rb +119 -0
  32. data/spec/system/spec_helper.rb +1 -0
  33. data/spec/unit/assertion_spec.rb +46 -0
  34. data/spec/unit/assertions/release_archive_spec.rb +13 -0
  35. data/spec/unit/assertions/release_branch_spec.rb +29 -0
  36. data/spec/unit/assertions/submitted_rpm_spec.rb +48 -0
  37. data/spec/unit/assertions/version_spec.rb +44 -0
  38. data/spec/unit/assertions/working_directory_spec.rb +79 -0
  39. data/spec/unit/engine_spec.rb +14 -0
  40. data/yes_ship_it.gemspec +7 -1
  41. metadata +78 -15
@@ -1,4 +1,6 @@
1
1
  assertions:
2
+ - release_branch
3
+ - working_directory
2
4
  - version
3
5
  - change_log
4
6
  - tag
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module YSI
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/yes_ship_it.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  require "yaml"
2
2
  require "rest-client"
3
3
  require "optparse"
4
+ require "inifile"
5
+ require "rexml/document"
6
+ require "erb"
4
7
 
5
8
  require_relative "yes_ship_it/assertion.rb"
6
9
  require_relative "yes_ship_it/engine.rb"
@@ -23,8 +23,34 @@ module YSI
23
23
  @dependency_names || []
24
24
  end
25
25
 
26
+ def self.parameter(name, default_value = nil)
27
+ define_method("#{name}=") do |value|
28
+ @parameters[name] = value
29
+ end
30
+
31
+ if default_value
32
+ define_method("#{name}_default") do
33
+ return default_value
34
+ end
35
+ end
36
+
37
+ define_method("#{name}") do
38
+ if @parameters.has_key?(name)
39
+ return @parameters[name]
40
+ else
41
+ if respond_to?("#{name}_default")
42
+ return send("#{name}_default")
43
+ else
44
+ return nil
45
+ end
46
+ end
47
+ end
48
+ end
49
+
26
50
  def initialize(engine)
27
51
  @engine = engine
52
+ @parameters = {}
53
+ @parameter_defaults = {}
28
54
  end
29
55
 
30
56
  def needs
@@ -1,18 +1,28 @@
1
1
  module YSI
2
2
  class Engine
3
3
  attr_reader :assertions
4
- attr_accessor :version, :tag_date
4
+ attr_accessor :version, :tag_date, :release_archive
5
5
  attr_accessor :out
6
6
  attr_accessor :dry_run
7
+ attr_accessor :data_dir
7
8
 
8
9
  def initialize
9
10
  @assertions = []
10
11
  @out = STDOUT
12
+ @data_dir = File.expand_path("~/.ysi")
13
+ end
14
+
15
+ def read_config(yaml)
16
+ config = YAML.load(yaml)
17
+ parse(config)
11
18
  end
12
19
 
13
20
  def read(filename)
14
21
  config = YAML.load_file(filename)
22
+ parse(config)
23
+ end
15
24
 
25
+ def parse(config)
16
26
  config.each do |key,value|
17
27
  if key == "include"
18
28
  included_file = value
@@ -21,14 +31,20 @@ module YSI
21
31
  elsif key == "assertions"
22
32
  assertions = value
23
33
  if assertions
24
- assertions.each do |assertion|
25
- if assertion == "version_number"
34
+ assertions.each do |assertion_name, parameters|
35
+ if assertion_name == "version_number"
26
36
  out.puts "Warning: use `version` instead of `version_number`."
27
37
  out.puts
28
- assertion = "version"
38
+ assertion_name = "version"
29
39
  end
30
40
 
31
- @assertions << YSI::Assertion.class_for_name(assertion).new(self)
41
+ assertion = YSI::Assertion.class_for_name(assertion_name).new(self)
42
+ if parameters
43
+ parameters.each do |parameter_name, parameter_value|
44
+ assertion.send(parameter_name + "=", parameter_value)
45
+ end
46
+ end
47
+ @assertions << assertion
32
48
  end
33
49
  end
34
50
  end
@@ -47,6 +63,10 @@ module YSI
47
63
  "v#{version}"
48
64
  end
49
65
 
66
+ def release_archive_file_name
67
+ File.basename(release_archive)
68
+ end
69
+
50
70
  def dependency_errored?(assertion, errored_assertions)
51
71
  assertion.needs.each do |need|
52
72
  errored_assertions.each do |errored_assertion|
@@ -0,0 +1,11 @@
1
+ # Header of artificial RPM spec file snippet
2
+
3
+ Name: go-mycroft
4
+ Version: <%= version %>
5
+ Release: 0
6
+ Source: <%= release_archive %>
7
+
8
+ %prep
9
+ %setup -q -n <%= release_directory %>
10
+
11
+ %changelog
@@ -0,0 +1,8 @@
1
+ [general]
2
+ # URL to access API server, e.g. https://api.opensuse.org
3
+ # you also need a section [https://api.opensuse.org] with the credentials
4
+ apiurl = https://api.opensuse.org
5
+
6
+ [https://api.opensuse.org]
7
+ user = myuser
8
+ pass = mypassword
Binary file
@@ -0,0 +1,5 @@
1
+ package main
2
+
3
+ const (
4
+ Version = "0.0.1"
5
+ )
@@ -0,0 +1,3 @@
1
+ module YSI
2
+ VERSION = "0.0.2"
3
+ end
@@ -146,11 +146,16 @@ EOT
146
146
  dir = given_directory "test_project" do
147
147
  given_file("yes_ship_it.conf", from: "yes_ship_it.include.conf")
148
148
  end
149
+ system("cd #{dir}; git init >/dev/null")
149
150
  end
150
151
 
151
152
  expected_output = <<EOT
152
153
  Shipping...
153
154
 
155
+ Checking release branch: error
156
+ Not on release branch 'master'
157
+ Checking working directory: error
158
+ untracked files
154
159
  Checking version number: error
155
160
  Expected version in lib/version.rb
156
161
  Checking change log: skip (because dependency errored)
@@ -166,6 +171,54 @@ EOT
166
171
  expect(run_command(working_directory: dir)).
167
172
  to exit_with_error(1, "", expected_output)
168
173
  end
174
+
175
+ it "creates release archive" do
176
+ git_dir = given_directory
177
+ setup_test_git_repo("006", git_dir)
178
+
179
+ data_dir = given_directory
180
+
181
+ expected_output = <<EOT
182
+ Shipping...
183
+
184
+ Checking version number: 0.0.2
185
+ Checking tag: fail
186
+ Checking release archive: fail
187
+
188
+ Asserting tag: v0.0.2
189
+ Asserting release archive: red_herring-0.0.2.tar.gz
190
+
191
+ Shipped red_herring 0.0.2. Hooray!
192
+ EOT
193
+
194
+ expect(run_command(args: ["--data-dir=#{data_dir}"],
195
+ working_directory: File.join(git_dir, "red_herring"))).
196
+ to exit_with_success(expected_output)
197
+
198
+ release_archive = File.join(data_dir, "release_archives", "red_herring",
199
+ "4ba08cb0f26d813cd754bc9ccb9f89274f24f2b6",
200
+ "red_herring-0.0.2.tar.gz")
201
+
202
+ expect(File.exist?(File.join(git_dir, "red_herring", "red_herring-0.0.2"))).to be(false)
203
+
204
+ expect(File.exist?(release_archive)).to be(true)
205
+
206
+ expected_file_list = <<EOT
207
+ red_herring-0.0.2/
208
+ red_herring-0.0.2/bin/
209
+ red_herring-0.0.2/bin/tickle
210
+ red_herring-0.0.2/CHANGELOG.md
211
+ red_herring-0.0.2/Gemfile
212
+ red_herring-0.0.2/red_herring.gemspec
213
+ red_herring-0.0.2/MIT-LICENSE
214
+ red_herring-0.0.2/README.md
215
+ red_herring-0.0.2/lib/
216
+ red_herring-0.0.2/lib/red_herring.rb
217
+ red_herring-0.0.2/lib/version.rb
218
+ EOT
219
+ file_list = `tar tzf #{release_archive}`.split("\n").sort
220
+ expect(file_list).to eq(expected_file_list.split("\n").sort)
221
+ end
169
222
  end
170
223
 
171
224
  describe "changelog helper" do
@@ -193,4 +246,25 @@ EOT
193
246
  to exit_with_success(expected_output)
194
247
  end
195
248
  end
249
+
250
+ describe "init" do
251
+ it "initializes directory with generic template" do
252
+ dir = given_directory
253
+
254
+ expected_output = <<EOT
255
+ Initialized directory for shipping.
256
+
257
+ Check the file `yes_ship_it.conf` and adapt it to your needs.
258
+
259
+ Happy shipping!
260
+ EOT
261
+
262
+ expect(run_command(args: ["init"], working_directory: dir)).
263
+ to exit_with_success(expected_output)
264
+
265
+ expect(File.read(File.join(dir, "yes_ship_it.conf"))).to eq(
266
+ "# Experimental release automation. See https://github.com/cornelius/yes_ship_it.\ninclude:\n ruby_gem\n"
267
+ )
268
+ end
269
+ end
196
270
  end
@@ -0,0 +1,119 @@
1
+ require_relative "spec_helper"
2
+
3
+ describe "ship ruby gem" do
4
+ it "builds gem" do
5
+ out = double
6
+ allow(out).to receive(:puts)
7
+
8
+ test = Httpotemkin::Test.new(out: out)
9
+ test.add_server("rubygems")
10
+ test.add_server("api.rubygems")
11
+ test.add_server("obs")
12
+
13
+ test.run do |client|
14
+ client.install_gem_from_spec("yes_ship_it.gemspec")
15
+
16
+ remote_tar = File.expand_path("../data/red_herring-remote.tar.gz", __FILE__)
17
+ checkout_tar = File.expand_path("../data/red_herring-checkout-build.tar.gz", __FILE__)
18
+ client.inject_tarball(remote_tar)
19
+ client.inject_tarball(checkout_tar)
20
+
21
+ client.execute(["yes_ship_it.ruby2.1"], working_directory: "red_herring")
22
+
23
+ expect(client.exit_code).to eq(0)
24
+
25
+ expected_output = <<EOT
26
+ Shipping...
27
+
28
+ Checking version number: 0.0.2
29
+ Checking tag: fail
30
+ Checking release archive: fail
31
+
32
+ Asserting tag: v0.0.2
33
+ Asserting release archive: red_herring-0.0.2.tar.gz
34
+
35
+ Shipped red_herring 0.0.2. Hooray!
36
+ EOT
37
+ expect(client.out).to eq(expected_output)
38
+
39
+ expect(client.err.empty?).to be(true)
40
+ end
41
+ end
42
+
43
+ it "pushes gem if it isn't pushed yet" do
44
+ out = double
45
+ allow(out).to receive(:puts)
46
+
47
+ test = Httpotemkin::Test.new(out: out)
48
+ test.add_server("rubygems")
49
+ test.add_server("api.rubygems")
50
+ test.add_server("obs")
51
+
52
+ test.run do |client|
53
+ client.install_gem_from_spec("yes_ship_it.gemspec")
54
+
55
+ remote_tar = File.expand_path("../data/red_herring-remote.tar.gz", __FILE__)
56
+ checkout_tar = File.expand_path("../data/red_herring-checkout-push.tar.gz", __FILE__)
57
+ client.inject_tarball(remote_tar)
58
+ client.inject_tarball(checkout_tar)
59
+
60
+ client.execute(["yes_ship_it.ruby2.1"], working_directory: "red_herring")
61
+
62
+ expect(client.exit_code).to eq(0)
63
+
64
+ expected_output = <<EOT
65
+ Shipping...
66
+
67
+ Checking version number: 0.0.2
68
+ Checking tag: fail
69
+ Checking built gem: fail
70
+ Checking published gem: fail
71
+
72
+ Asserting tag: v0.0.2
73
+ Asserting built gem: red_herring-0.0.2.gem
74
+ Asserting published gem: red_herring-0.0.2.gem
75
+
76
+ Shipped red_herring 0.0.2. Hooray!
77
+ EOT
78
+ expect(client.out).to eq(expected_output)
79
+
80
+ expect(client.err.empty?).to be(true)
81
+ end
82
+ end
83
+
84
+ it "doesn't push gem if it already is pushed" do
85
+ out = double
86
+ allow(out).to receive(:puts)
87
+
88
+ test = Httpotemkin::Test.new(out: out)
89
+ test.add_server("rubygems")
90
+ test.add_server("api.rubygems")
91
+ test.add_server("obs")
92
+
93
+ test.run do |client|
94
+ client.install_gem_from_spec("yes_ship_it.gemspec")
95
+
96
+ remote_tar = File.expand_path("../data/red_herring-remote.tar.gz", __FILE__)
97
+ checkout_tar = File.expand_path("../data/red_herring-checkout-not-push.tar.gz", __FILE__)
98
+ client.inject_tarball(remote_tar)
99
+ client.inject_tarball(checkout_tar)
100
+
101
+ client.execute(["yes_ship_it.ruby2.1"], working_directory: "red_herring")
102
+
103
+ expect(client.exit_code).to eq(0)
104
+
105
+ expected_output = <<EOT
106
+ Shipping...
107
+
108
+ Checking version number: 0.0.1
109
+ Checking built gem: red_herring-0.0.1.gem
110
+ Checking published gem: 0.0.1
111
+
112
+ red_herring 0.0.1 already shipped
113
+ EOT
114
+ expect(client.out).to eq(expected_output)
115
+
116
+ expect(client.err.empty?).to be(true)
117
+ end
118
+ end
119
+ end
@@ -0,0 +1 @@
1
+ require "httpotemkin"
@@ -12,4 +12,50 @@ describe YSI::Assertion do
12
12
  to be(YSI::ChangeLog)
13
13
  end
14
14
  end
15
+
16
+ describe "parameters" do
17
+ class MyAssertion < YSI::Assertion
18
+ parameter :some_thing
19
+ parameter :some_other_thing, "default_hello"
20
+
21
+ def display_name
22
+ "My Assertion"
23
+ end
24
+
25
+ def check
26
+ end
27
+
28
+ def assert
29
+ end
30
+ end
31
+
32
+ it "has methods for parameter" do
33
+ my = MyAssertion.new(YSI::Engine.new)
34
+ my.some_thing = "hello"
35
+ expect(my.some_thing).to eq("hello")
36
+ end
37
+
38
+ it "has default value for parameter" do
39
+ my = MyAssertion.new(YSI::Engine.new)
40
+ expect(my.some_other_thing).to eq("default_hello")
41
+ end
42
+
43
+ it "returns nil when parameter is not set" do
44
+ my = MyAssertion.new(YSI::Engine.new)
45
+ expect(my.some_thing).to be(nil)
46
+ end
47
+
48
+ it "reads parameter from config" do
49
+ config = <<EOT
50
+ assertions:
51
+ my_assertion:
52
+ some_thing: world
53
+ EOT
54
+ engine = YSI::Engine.new
55
+ engine.read_config(config)
56
+ my = engine.assertions.first
57
+
58
+ expect(my.some_thing).to eq("world")
59
+ end
60
+ end
15
61
  end
@@ -0,0 +1,13 @@
1
+ require_relative "../spec_helper.rb"
2
+
3
+ describe YSI::ReleaseArchive do
4
+ describe "#check" do
5
+ it "sets engine.release_archive" do
6
+ engine = YSI::Engine.new
7
+ a = YSI::ReleaseArchive.new(engine)
8
+ a.check
9
+
10
+ expect(engine.release_archive).to_not be(nil)
11
+ end
12
+ end
13
+ end