renogen 1.0.1 → 1.3.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.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +162 -23
  3. data/lib/renogen/change_log.rb +1 -0
  4. data/lib/renogen/change_log/item.rb +6 -4
  5. data/lib/renogen/change_log/model.rb +11 -8
  6. data/lib/renogen/change_log/validator.rb +61 -0
  7. data/lib/renogen/change_log/writer.rb +22 -2
  8. data/lib/renogen/cli.rb +28 -7
  9. data/lib/renogen/cli/param_parser.rb +19 -3
  10. data/lib/renogen/config.rb +15 -14
  11. data/lib/renogen/exceptions.rb +5 -0
  12. data/lib/renogen/exceptions/invalid_item_found.rb +32 -0
  13. data/lib/renogen/exceptions/yaml_file_blank.rb +21 -0
  14. data/lib/renogen/exceptions/yaml_file_invalid.rb +20 -0
  15. data/lib/renogen/extraction_stratagies.rb +0 -2
  16. data/lib/renogen/extraction_stratagies/yaml_file.rb +0 -1
  17. data/lib/renogen/extraction_stratagies/yaml_file/parser.rb +5 -4
  18. data/lib/renogen/extraction_stratagies/yaml_file/reader.rb +20 -11
  19. data/lib/renogen/formatters.rb +2 -0
  20. data/lib/renogen/formatters/base.rb +32 -7
  21. data/lib/renogen/formatters/csv.rb +42 -0
  22. data/lib/renogen/formatters/html.rb +1 -1
  23. data/lib/renogen/formatters/markdown.rb +2 -2
  24. data/lib/renogen/formatters/markdown_table.rb +58 -0
  25. data/lib/renogen/generator.rb +9 -1
  26. data/lib/renogen/version.rb +1 -1
  27. data/lib/renogen/writers/csv.rb +23 -0
  28. data/spec/lib/renogen/change_log/item_spec.rb +1 -1
  29. data/spec/lib/renogen/change_log/model_spec.rb +22 -8
  30. data/spec/lib/renogen/change_log/validator_spec.rb +38 -0
  31. data/spec/lib/renogen/change_log/writer_spec.rb +141 -2
  32. data/spec/lib/renogen/config_spec.rb +7 -2
  33. data/spec/lib/renogen/exceptions/invalid_item_found_spec.rb +35 -0
  34. data/spec/lib/renogen/exceptions/stratagy_not_found_spec.rb +2 -1
  35. data/spec/lib/renogen/{extraction_stratagies/yaml_file/exceptions → exceptions}/yaml_file_blank_spec.rb +1 -1
  36. data/spec/lib/renogen/exceptions/yaml_file_invalid_spec.rb +12 -0
  37. data/spec/lib/renogen/extraction_stratagies/yaml_file/parser_spec.rb +3 -3
  38. data/spec/lib/renogen/extraction_stratagies/yaml_file/reader_spec.rb +11 -5
  39. data/spec/lib/renogen/formatters/base_spec.rb +14 -4
  40. data/spec/lib/renogen/formatters/csv_spec.rb +49 -0
  41. data/spec/lib/renogen/formatters/html_spec.rb +1 -1
  42. data/spec/lib/renogen/formatters/markdown_spec.rb +2 -2
  43. data/spec/spec_helper.rb +5 -0
  44. data/spec/support/renogen_helper.rb +9 -0
  45. metadata +21 -12
  46. data/lib/renogen/extraction_stratagies/yaml_file/exceptions.rb +0 -12
  47. data/lib/renogen/extraction_stratagies/yaml_file/exceptions/yaml_file_blank.rb +0 -25
@@ -0,0 +1,58 @@
1
+ module Renogen
2
+ module Formatters
3
+ # For formatting a change into markdown format
4
+ class MarkdownTable < Markdown
5
+ register :markdown_table
6
+ register :md_table
7
+
8
+ attr_reader :headings
9
+
10
+ def table_formatter?
11
+ true
12
+ end
13
+
14
+ # Generate header
15
+ #
16
+ # @param changelog [Renogen::ChangeLog::Model]
17
+ #
18
+ # return [String]
19
+ def header(changelog)
20
+ @headings = changelog.groups.keys
21
+ [
22
+ "# #{changelog.version} (#{changelog.date})",
23
+ "",
24
+ "| #{headings.join(' | ')} |",
25
+ "| #{headings.map{|_| '-' }.join(' | ')} |"
26
+ ].join("\n")
27
+ end
28
+
29
+ # Outputs a line or block of text appearing at the top of the change log.
30
+ #
31
+ # @param header [String]
32
+ # @return [String]
33
+ def write_header(header)
34
+ "#{header}\n"
35
+ end
36
+
37
+ # Outputs a line or block as a header for a group.
38
+ #
39
+ # @param group [String]
40
+ # @return [String]
41
+ def write_group(group)
42
+ "## #{group}\n\n"
43
+ end
44
+
45
+ # Outputs a line or block as the body for a change in a group.
46
+ #
47
+ # @param ticket [Hash<group: string>]
48
+ # @return [String]
49
+ def write_change(ticket)
50
+ "| "+ @headings.map do |heading|
51
+ value = ticket.fetch(heading, '-')
52
+ value = value.join("\n") if value.is_a?(Array)
53
+ value.gsub("\n", "<br>")
54
+ end.join(' | ') + " |"
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Renogen
2
4
  # This is the conductor of the application
3
5
  class Generator
4
6
  attr_accessor :source, :version, :output_format, :options
5
7
 
6
- def initialize(version, source, output_format, options={})
8
+ def initialize(version, source, output_format, options = {})
7
9
  @version = version
8
10
  @source = source
9
11
  @output_format = output_format
@@ -14,7 +16,9 @@ module Renogen
14
16
  def generate!
15
17
  changelog = extraction_stratagy.extract
16
18
  changelog.version = version
19
+ changelog.date = options['release_date']
17
20
 
21
+ validator.validate!(changelog) if options['allowed_values']&.any?
18
22
  writer.write!(changelog)
19
23
  end
20
24
 
@@ -31,5 +35,9 @@ module Renogen
31
35
  def formatter
32
36
  Renogen::Formatters.obtain(output_format, options)
33
37
  end
38
+
39
+ def validator
40
+ Renogen::ChangeLog::Validator.new(formatter)
41
+ end
34
42
  end
35
43
  end
@@ -1,3 +1,3 @@
1
1
  module Renogen
2
- VERSION='1.0.1'.freeze # :nodoc:
2
+ VERSION = '1.3.1'.freeze # :nodoc:
3
3
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Renogen
4
+ module Writers
5
+ # Writes out the change log in CSV format
6
+ class Csv < Base
7
+ register :csv
8
+
9
+ def write!(changelog)
10
+ puts formatter.write_headings(changelog)
11
+ output_files(changelog)
12
+ end
13
+
14
+ private
15
+
16
+ def output_files(changelog)
17
+ changelog.files.each do |file|
18
+ puts formatter.write_file(file, changelog)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Renogen::ChangeLog::Item do
4
4
  let(:change) { Array.new }
5
- subject { described_class.new('foo', change) }
5
+ subject { described_class.new(1, 'foo', change) }
6
6
 
7
7
  describe '#to_s' do
8
8
  context "when change type is nil" do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Renogen::ChangeLog::Model do
4
- let(:change_item) { Renogen::ChangeLog::Item.new('foo', 'bar') }
4
+ let(:change_item) { Renogen::ChangeLog::Item.new(1, 'foo', 'bar') }
5
5
 
6
6
  describe '#groups' do
7
7
  it 'returns an empty hash when no changes' do
@@ -14,13 +14,6 @@ describe Renogen::ChangeLog::Model do
14
14
  end
15
15
  end
16
16
 
17
- describe '#header' do
18
- it 'returns version and date' do
19
- subject.version = '123'
20
- expect(subject.header).to eql "123 (#{Date.today})"
21
- end
22
- end
23
-
24
17
  describe '#add_change' do
25
18
  it 'adds change to changes store' do
26
19
  subject.add_change(change_item)
@@ -33,4 +26,25 @@ describe Renogen::ChangeLog::Model do
33
26
  end
34
27
  end
35
28
 
29
+ describe '#date' do
30
+ it 'defaults to Date.today' do
31
+ expect(subject.date).to eql Date.today
32
+ end
33
+
34
+ it 'can be set using an option' do
35
+ date = Date.parse('2015-12-25')
36
+ model_instance = described_class.new(date: date)
37
+
38
+ expect(model_instance.date).to eql date
39
+ end
40
+
41
+ it 'has a setter' do
42
+ date = Date.parse('1981-03-20')
43
+
44
+ subject.date = date
45
+
46
+ expect(subject.date).to eql date
47
+ end
48
+ end
49
+
36
50
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Renogen::ChangeLog::Validator do
6
+ let(:change_log) { Renogen::ChangeLog::Model.new }
7
+ let(:validations) { { 'foo' => %w(bar baz) } }
8
+
9
+ subject { described_class.new(double('Formatter', options: { 'allowed_values' => validations })) }
10
+
11
+ before(:each) { change_log.add_change(Renogen::ChangeLog::Item.new(1, 'foo', 'bar')) }
12
+
13
+ describe '#validate!' do
14
+ context 'when no validations are available' do
15
+ let(:validations) { nil }
16
+
17
+ it 'successfully passes the validation process' do
18
+ expect { subject.validate!(change_log) }.to_not raise_error
19
+ subject.validate!(change_log)
20
+ end
21
+ end
22
+
23
+ context 'when validation is successful' do
24
+ it 'successfully passes the validation process' do
25
+ expect { subject.validate!(change_log) }.to_not raise_error
26
+ subject.validate!(change_log)
27
+ end
28
+ end
29
+
30
+ context 'when validation has failed' do
31
+ let(:validations) { { 'foo' => ['baz'] } }
32
+
33
+ it 'fails validation' do
34
+ expect { subject.validate!(change_log) }.to raise_error(Renogen::Exceptions::InvalidItemFound)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,8 +1,147 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Renogen::ChangeLog::Writer do
4
-
5
6
  describe '#write!' do
7
+ shared_examples 'a valid output format' do
8
+ let(:changelog) do
9
+ Renogen::ChangeLog::Model.new(
10
+ version: 'test',
11
+ date: Date.new(2020, 7, 8)
12
+ )
13
+ end
14
+
15
+ let(:changes) do
16
+ [
17
+ renogen_change(1, 'Group 1', 'This is a Group 1 change'),
18
+ renogen_change(1, 'Group 2', 'This is a Group 2 change')
19
+ ]
20
+ end
21
+
22
+ subject { Renogen::ChangeLog::Writer.new(formatter) }
23
+
24
+ before do
25
+ changes.each { |c| changelog.add_change(c) }
26
+ $stdout = StringIO.new
27
+ end
28
+
29
+ after do
30
+ $stdout = STDOUT
31
+ end
32
+
33
+ it 'writes all lines' do
34
+ subject.write!(changelog)
35
+ $stdout.rewind
36
+ expected_output.split("\n").each do |line|
37
+ expect($stdout.gets.strip).to eq(line)
38
+ end
39
+ end
40
+ end
41
+
42
+ context 'when formatter is CSV' do
43
+ let(:formatter) { Renogen::Formatters::Csv.new }
44
+ let(:expected_output) do
45
+ <<~EOS
46
+ Group 1,Group 2
47
+ This is a Group 1 change,This is a Group 2 change
48
+ EOS
49
+ end
50
+
51
+ it_behaves_like 'a valid output format'
52
+
53
+ context 'when changes contain commas' do
54
+ it_behaves_like 'a valid output format' do
55
+ let(:changes) do
56
+ [
57
+ renogen_change(1, 'Group 1', 'This,is,a,Group 1,change'),
58
+ renogen_change(1, 'Group 2', 'This is a Group 2 change')
59
+ ]
60
+ end
61
+
62
+ let(:expected_output) do
63
+ <<~EOS
64
+ Group 1,Group 2
65
+ "This,is,a,Group 1,change",This is a Group 2 change
66
+ EOS
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ context 'when formatter is HTML' do
73
+ let(:formatter) { Renogen::Formatters::Html.new }
74
+ let(:expected_output) do
75
+ <<~EOS
76
+ <html>
77
+ <h1>test (2020-07-08)</h1>
78
+ <h2>Group 1</h2>
79
+ <ul>
80
+ <li>This is a Group 1 change
81
+ </li>
82
+ </ul>
83
+ <h2>Group 2</h2>
84
+ <ul>
85
+ <li>This is a Group 2 change
86
+ </li>
87
+ </ul>
88
+ </html>
89
+ EOS
90
+ end
91
+
92
+ it_behaves_like 'a valid output format'
93
+ end
94
+
95
+ context 'when formatter is Markdown' do
96
+ let(:formatter) { Renogen::Formatters::Markdown.new }
97
+ let(:expected_output) do
98
+ <<~EOS
99
+ # test (2020-07-08)
100
+
101
+ ## Group 1
102
+
103
+ * This is a Group 1 change
104
+
105
+ ## Group 2
106
+
107
+ * This is a Group 2 change
108
+ EOS
109
+ end
110
+
111
+ it_behaves_like 'a valid output format'
112
+ end
113
+
114
+ context 'when formatter is MarkdownTable' do
115
+ let(:formatter) { Renogen::Formatters::MarkdownTable.new }
116
+
117
+ let(:expected_output) do
118
+ <<~EOS
119
+ # test (2020-07-08)
120
+
121
+ | Group 1 | Group 2 |
122
+ | - | - |
123
+ | This is a Group 1 change<br> | This is a Group 2 change<br> |
124
+ EOS
125
+ end
126
+
127
+ it_behaves_like 'a valid output format'
128
+ end
129
+
130
+ context 'when formatter is PlainText' do
131
+ let(:formatter) { Renogen::Formatters::PlainText.new }
132
+ let(:expected_output) do
133
+ <<~EOS
134
+ test (2020-07-08)
135
+
136
+ Group 1
137
+ - This is a Group 1 change
138
+
139
+ Group 2
140
+ - This is a Group 2 change
141
+ EOS
142
+ end
143
+
144
+ it_behaves_like 'a valid output format'
145
+ end
6
146
  end
7
147
  end
8
-
@@ -1,19 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Renogen::Config do
4
-
5
6
  subject { described_class.instance }
6
7
 
7
8
  describe '#configure' do
8
9
  before :each do
9
10
  described_class.configure do |config|
10
11
  config.single_line_format = 'bar'
12
+ config.validations = ['test']
11
13
  end
12
14
  end
13
15
 
14
16
  it 'can set value' do
15
17
  expect(subject.single_line_format).to eql 'bar'
16
18
  end
17
- end
18
19
 
20
+ it 'sets the validations value' do
21
+ expect(subject.validations).to eql ['test']
22
+ end
23
+ end
19
24
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Renogen::Exceptions::InvalidItemFound do
6
+ subject { described_class.new(invalid_items) }
7
+
8
+ describe '#message' do
9
+ context 'valid_values is an array' do
10
+ let(:invalid_items) do
11
+ [
12
+ { group_name: 'Product', invalid_value: 'Foo', valid_values: %w(Bar Baz) },
13
+ { group_name: 'Country', invalid_value: 'LL', valid_values: %w(UK IE) }
14
+ ]
15
+ end
16
+ let(:expected_error) do
17
+ "Invalid items:\nGroup: Product, Content: Foo, Valid Values: [\"Bar\", \"Baz\"]" \
18
+ "\nGroup: Country, Content: LL, Valid Values: [\"UK\", \"IE\"]"
19
+ end
20
+
21
+ it 'returns a user friendly error message' do
22
+ expect(subject.message).to eql expected_error
23
+ end
24
+ end
25
+
26
+ context 'valid_values is a RegExp' do
27
+ let(:invalid_items) { [{ group_name: 'Product', invalid_value: 'Foo', valid_values: /\b(Bar|Baz)\b/ }] }
28
+ let(:expected_error) { "Invalid items:\nGroup: Product, Content: Foo, Pattern: #{/\b(Bar|Baz)\b/.inspect}" }
29
+
30
+ it 'returns a user friendly error message' do
31
+ expect(subject.message).to eql expected_error
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Renogen::Exceptions::StratagyNotFound do
@@ -8,6 +10,5 @@ describe Renogen::Exceptions::StratagyNotFound do
8
10
  it 'returns friendly error message' do
9
11
  expect(subject.message).to eql "Error: Stratagy type '#{name}' not found"
10
12
  end
11
-
12
13
  end
13
14
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Renogen::ExtractionStratagies::YamlFile::Exceptions::YamlFileBlank do
3
+ describe Renogen::Exceptions::YamlFileBlank do
4
4
  let(:name) { 'foobar' }
5
5
  subject { described_class.new(name) }
6
6