renogen 1.0.1 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +162 -23
- data/lib/renogen/change_log.rb +1 -0
- data/lib/renogen/change_log/item.rb +6 -4
- data/lib/renogen/change_log/model.rb +11 -8
- data/lib/renogen/change_log/validator.rb +61 -0
- data/lib/renogen/change_log/writer.rb +22 -2
- data/lib/renogen/cli.rb +28 -7
- data/lib/renogen/cli/param_parser.rb +19 -3
- data/lib/renogen/config.rb +15 -14
- data/lib/renogen/exceptions.rb +5 -0
- data/lib/renogen/exceptions/invalid_item_found.rb +32 -0
- data/lib/renogen/exceptions/yaml_file_blank.rb +21 -0
- data/lib/renogen/exceptions/yaml_file_invalid.rb +20 -0
- data/lib/renogen/extraction_stratagies.rb +0 -2
- data/lib/renogen/extraction_stratagies/yaml_file.rb +0 -1
- data/lib/renogen/extraction_stratagies/yaml_file/parser.rb +5 -4
- data/lib/renogen/extraction_stratagies/yaml_file/reader.rb +20 -11
- data/lib/renogen/formatters.rb +2 -0
- data/lib/renogen/formatters/base.rb +32 -7
- data/lib/renogen/formatters/csv.rb +42 -0
- data/lib/renogen/formatters/html.rb +1 -1
- data/lib/renogen/formatters/markdown.rb +2 -2
- data/lib/renogen/formatters/markdown_table.rb +58 -0
- data/lib/renogen/generator.rb +9 -1
- data/lib/renogen/version.rb +1 -1
- data/lib/renogen/writers/csv.rb +23 -0
- data/spec/lib/renogen/change_log/item_spec.rb +1 -1
- data/spec/lib/renogen/change_log/model_spec.rb +22 -8
- data/spec/lib/renogen/change_log/validator_spec.rb +38 -0
- data/spec/lib/renogen/change_log/writer_spec.rb +141 -2
- data/spec/lib/renogen/config_spec.rb +7 -2
- data/spec/lib/renogen/exceptions/invalid_item_found_spec.rb +35 -0
- data/spec/lib/renogen/exceptions/stratagy_not_found_spec.rb +2 -1
- data/spec/lib/renogen/{extraction_stratagies/yaml_file/exceptions → exceptions}/yaml_file_blank_spec.rb +1 -1
- data/spec/lib/renogen/exceptions/yaml_file_invalid_spec.rb +12 -0
- data/spec/lib/renogen/extraction_stratagies/yaml_file/parser_spec.rb +3 -3
- data/spec/lib/renogen/extraction_stratagies/yaml_file/reader_spec.rb +11 -5
- data/spec/lib/renogen/formatters/base_spec.rb +14 -4
- data/spec/lib/renogen/formatters/csv_spec.rb +49 -0
- data/spec/lib/renogen/formatters/html_spec.rb +1 -1
- data/spec/lib/renogen/formatters/markdown_spec.rb +2 -2
- data/spec/spec_helper.rb +5 -0
- data/spec/support/renogen_helper.rb +9 -0
- metadata +21 -12
- data/lib/renogen/extraction_stratagies/yaml_file/exceptions.rb +0 -12
- 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
|
data/lib/renogen/generator.rb
CHANGED
@@ -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
|
data/lib/renogen/version.rb
CHANGED
@@ -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
|
@@ -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
|