yes_ship_it 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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