renogen 1.0.0 → 1.3.0

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 +10 -7
  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 +23 -3
  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 +41 -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 +8 -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/config_spec.rb +7 -2
  32. data/spec/lib/renogen/exceptions/invalid_item_found_spec.rb +35 -0
  33. data/spec/lib/renogen/exceptions/stratagy_not_found_spec.rb +2 -1
  34. data/spec/lib/renogen/{extraction_stratagies/yaml_file/exceptions → exceptions}/yaml_file_blank_spec.rb +1 -1
  35. data/spec/lib/renogen/exceptions/yaml_file_invalid_spec.rb +12 -0
  36. data/spec/lib/renogen/extraction_stratagies/yaml_file/parser_spec.rb +3 -3
  37. data/spec/lib/renogen/extraction_stratagies/yaml_file/reader_spec.rb +11 -5
  38. data/spec/lib/renogen/formatters/base_spec.rb +14 -4
  39. data/spec/lib/renogen/formatters/csv_spec.rb +49 -0
  40. data/spec/lib/renogen/formatters/html_spec.rb +1 -1
  41. data/spec/lib/renogen/formatters/markdown_spec.rb +2 -2
  42. data/spec/spec_helper.rb +5 -0
  43. data/spec/support/renogen_helper.rb +9 -0
  44. metadata +17 -8
  45. data/lib/renogen/extraction_stratagies/yaml_file/exceptions.rb +0 -12
  46. data/lib/renogen/extraction_stratagies/yaml_file/exceptions/yaml_file_blank.rb +0 -25
  47. data/spec/lib/renogen/change_log/writer_spec.rb +0 -8
@@ -17,10 +17,14 @@ module Renogen
17
17
  args = Hash.new
18
18
 
19
19
  opt_parser = OptionParser.new do |opts|
20
- opts.banner = "Usage: renogen [options] VERSION"
20
+ opts.banner = "Usage:"
21
+ opts.separator " renogen [options] VERSION"
22
+ opts.separator " renogen new TICKET_NAME"
23
+ opts.separator " renogen init"
21
24
  opts.separator ""
22
25
  opts.separator "Required:"
23
- opts.separator " VERSION this is the version that is currently being required:"
26
+ opts.separator " VERSION this is the version that is currently being required:"
27
+ opts.separator " TICKET_NAME this is the name of the new ticket to be created:"
24
28
  opts.separator ""
25
29
  opts.separator "Options:"
26
30
 
@@ -40,6 +44,18 @@ module Renogen
40
44
  args['legacy_version'] = n
41
45
  end
42
46
 
47
+ opts.on("-rDATE", "--release-date=DATE", "Release date") do |n|
48
+ args['release_date'] = n
49
+ end
50
+
51
+ opts.on("-IPATH", "--include=PATH", "Add a path to the load path") do |n|
52
+ $LOAD_PATH << n
53
+ end
54
+
55
+ opts.on("-RFILE", "--require=FILE", "Require a file from the load path") do |n|
56
+ require n
57
+ end
58
+
43
59
  opts.on_tail("-h", "--help", "Show this message") do
44
60
  puts opts
45
61
  exit
@@ -55,7 +71,7 @@ module Renogen
55
71
 
56
72
  new_version = options.shift
57
73
  if new_version.nil?
58
- puts "Error: Missing argument 'VERSION'"
74
+ puts "Error: Missing argument"
59
75
  puts
60
76
  puts opt_parser
61
77
  exit 1
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'singleton'
2
4
  require 'yaml'
3
5
 
@@ -5,18 +7,20 @@ module Renogen
5
7
  # Stores configuratin values to be used by the libary
6
8
  class Config
7
9
  include Singleton
8
- attr_accessor :single_line_format, :input_source, :output_format, :supported_keys, :changelog_path
10
+ attr_accessor :single_line_format, :input_source, :output_format, :supported_keys, :changelog_path,
11
+ :default_headings, :validations
9
12
 
10
13
  def initialize
11
14
  config_file = load_yaml_config
12
- self.single_line_format = config_file['single_line_format'] || 'summary (see link)'.freeze
13
- self.supported_keys = config_file['supported_keys'] || ['identifier', 'link', 'summary'].freeze
14
- self.input_source = config_file['input_source'] || 'yaml'.freeze
15
- self.output_format = config_file['output_format'] || 'markdown'.freeze
16
- self.changelog_path = config_file['changelog_path']
15
+ self.single_line_format = config_file['single_line_format'] || 'summary (see link)'
16
+ self.supported_keys = config_file['supported_keys'] || %w(identifier link summary)
17
+ self.input_source = config_file['input_source'] || 'yaml'
18
+ self.output_format = config_file['output_format'] || 'markdown'
19
+ self.changelog_path = config_file['changelog_path'] || './change_log'
20
+ self.default_headings = config_file['default_headings'] || %w(Summary Detailed Tasks)
21
+ self.validations = config_file['allowed_values']
17
22
  end
18
23
 
19
-
20
24
  # Renogen configuration extension
21
25
  # a block can be provided to programatily setup configuration values
22
26
  def self.configure
@@ -25,13 +29,10 @@ module Renogen
25
29
 
26
30
  private
27
31
 
28
- def load_yaml_config(config_file_path='.renogen')
29
- begin
30
- YAML.load_file(config_file_path)
31
- rescue
32
- {}
33
- end
32
+ def load_yaml_config(config_file_path = '.renogen')
33
+ YAML.load_file(config_file_path)
34
+ rescue StandardError
35
+ {}
34
36
  end
35
37
  end
36
38
  end
37
-
@@ -1,7 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Renogen
2
4
  # Custom exceptions throw by the libary
3
5
  module Exceptions
4
6
  require_relative 'exceptions/base'
5
7
  require_relative 'exceptions/stratagy_not_found'
8
+ require_relative 'exceptions/invalid_item_found'
9
+ require_relative 'exceptions/yaml_file_blank'
10
+ require_relative 'exceptions/yaml_file_invalid'
6
11
  end
7
12
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Renogen
4
+ module Exceptions
5
+ # Raised when change log contains invalid items.
6
+ class InvalidItemFound < Base
7
+ attr_reader :invalid_items
8
+
9
+ def initialize(invalid_items)
10
+ @invalid_items = invalid_items
11
+ super
12
+ end
13
+
14
+ # Friendly error message
15
+ #
16
+ # @return [String]
17
+ def message
18
+ messages = ['Invalid items:']
19
+ invalid_items.each do |item|
20
+ invalid_value = item[:invalid_value]
21
+
22
+ messages << if item[:valid_values].is_a?(Regexp)
23
+ "Group: #{item[:group_name]}, Content: #{invalid_value}, Pattern: #{item[:valid_values].inspect}"
24
+ else
25
+ "Group: #{item[:group_name]}, Content: #{invalid_value}, Valid Values: #{item[:valid_values]}"
26
+ end
27
+ end
28
+ messages.join("\n")
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,21 @@
1
+ module Renogen
2
+ module Exceptions
3
+ # This is raised when a yaml file change is found but has not contents
4
+ class YamlFileBlank < Renogen::Exceptions::Base
5
+ attr_reader :file_path
6
+
7
+ def initialize(file_path)
8
+ @file_path = file_path
9
+ super
10
+ end
11
+
12
+ # Friendly error message
13
+ #
14
+ # @return [String]
15
+ def message
16
+ "Error: File contents blank '#{file_path}'"
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,20 @@
1
+ module Renogen
2
+ module Exceptions
3
+ # This is raised when a yaml file change is found but has invalid contents
4
+ class YamlFileInvalid < Renogen::Exceptions::Base
5
+ attr_reader :file_path
6
+
7
+ def initialize(file_path)
8
+ @file_path = file_path
9
+ super
10
+ end
11
+
12
+ # Friendly error message
13
+ #
14
+ # @return [String]
15
+ def message
16
+ "Error: File contents invalid '#{file_path}'"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -36,7 +36,5 @@ module Renogen
36
36
 
37
37
  require_relative 'extraction_stratagies/base'
38
38
  require_relative 'extraction_stratagies/yaml_file'
39
- # require_relative 'extraction_stratagies/github'
40
- # require_relative 'extraction_stratagies/gitlog'
41
39
  end
42
40
  end
@@ -5,7 +5,6 @@ module Renogen
5
5
  require_relative 'yaml_file/reader'
6
6
  require_relative 'yaml_file/parser'
7
7
  require_relative 'yaml_file/provider'
8
- require_relative 'yaml_file/exceptions'
9
8
  end
10
9
  end
11
10
  end
@@ -13,8 +13,8 @@ module Renogen
13
13
 
14
14
  # @return [ChangeLog::Model]
15
15
  def parse!
16
- yaml_file_reader.each_yaml_file do |file|
17
- parse_file(file)
16
+ yaml_file_reader.each_yaml_file do |file, index|
17
+ parse_file(index, file)
18
18
  end
19
19
  changelog
20
20
  end
@@ -23,9 +23,10 @@ module Renogen
23
23
 
24
24
  attr_reader :yaml_file_reader
25
25
 
26
- def parse_file(file)
26
+ # @param [Hash] data
27
+ def parse_file(id, file)
27
28
  file.each do |group_name, content|
28
- changelog.add_change(ChangeLog::Item.new(group_name, content))
29
+ changelog.add_change(ChangeLog::Item.new(id, group_name, content))
29
30
  end
30
31
  end
31
32
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
 
3
5
  module Renogen
@@ -7,23 +9,28 @@ module Renogen
7
9
  class Reader
8
10
  attr_accessor :directory_path, :legacy_version
9
11
 
10
- def initialize(directory_path, options={})
12
+ def initialize(directory_path, options = {})
11
13
  @legacy_version = options['legacy_version']
12
14
  @directory_path = directory_path
13
15
  @directory_path ||= './change_log/'
14
16
  end
15
17
 
16
18
  # Iterates thorugh each change file and yields the contents.
17
- #
18
- # an exception is thrown if the contents are blank
19
+ #
20
+ # an exception is thrown if the contents are blank or invalid
19
21
  #
20
22
  # @yield [Hash] yaml_file
21
23
  def each_yaml_file
22
- change_directories.each do |file_path|
24
+ path = ''
25
+ change_directories.each_with_index do |file_path, i|
26
+ path = file_path
23
27
  content = ::YAML.load_file(file_path)
24
- raise Exceptions::YamlFileBlank.new(file_path) unless content
25
- yield content
28
+ raise Exceptions::YamlFileBlank, file_path unless content
29
+
30
+ yield content, i
26
31
  end
32
+ rescue Psych::SyntaxError
33
+ raise Exceptions::YamlFileInvalid, path
27
34
  end
28
35
 
29
36
  private
@@ -31,20 +38,22 @@ module Renogen
31
38
  # @return [Array]
32
39
  def change_directories
33
40
  upgrade_versions = legacy_versions.map do |path|
34
- File.join(path, "*.yml")
41
+ File.join(path, '*.yml')
35
42
  end
36
- upgrade_versions << File.join(directory_path, 'next', "*.yml")
43
+ upgrade_versions << File.join(directory_path, 'next', '*.yml')
37
44
 
38
45
  Dir.glob(upgrade_versions)
39
46
  end
40
47
 
41
- # @return [Array]
48
+ # @return [Array]
42
49
  def legacy_versions
43
50
  return [] unless legacy_version
44
- legacy_version.gsub!('v','')
51
+
52
+ legacy_version.gsub!('v', '')
45
53
  Dir.glob(File.join(directory_path, '*')).select do |dir|
46
- dir = dir.split('/').last.gsub('v','').gsub('_','.')
54
+ dir = dir.split('/').last.gsub('v', '').gsub('_', '.')
47
55
  next if dir == 'next'
56
+
48
57
  Gem::Version.new(dir) > Gem::Version.new(legacy_version)
49
58
  end
50
59
  end
@@ -37,7 +37,9 @@ module Renogen
37
37
  end
38
38
 
39
39
  require_relative 'formatters/base'
40
+ require_relative 'formatters/csv'
40
41
  require_relative 'formatters/plain_text'
41
42
  require_relative 'formatters/markdown'
43
+ require_relative 'formatters/markdown_table'
42
44
  require_relative 'formatters/html'
43
45
  end
@@ -1,9 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Renogen
2
4
  module Formatters
3
- # Implements a template pattern that forces the implemention of required
5
+ # Implements a template pattern that forces the implemention of required
4
6
  # methods in sub classes
5
7
  class Base
6
- def initialize(options={})
8
+ attr_reader :options
9
+
10
+ def initialize(options = {})
11
+ @options = options
12
+ end
13
+
14
+ # Switch to determine if the formatter is in table format(instead of group format)
15
+ #
16
+ # return [Boolean] (default: false)
17
+ def table_formatter?
18
+ false # for backward compatibility
7
19
  end
8
20
 
9
21
  # Adds class with identifier to formatters
@@ -13,20 +25,31 @@ module Renogen
13
25
  Renogen::Formatters.add(identifier.to_sym, self)
14
26
  end
15
27
 
28
+ # Generate a header for a given changelog
29
+ #
30
+ # @param changelog [Renogen::ChangeLog::Model]
31
+ #
32
+ # return [String]
33
+ def header(changelog)
34
+ "#{changelog.version} (#{changelog.date})"
35
+ end
36
+
16
37
  # Outputs a line or block of text appearing at the top of the change log.
17
38
  #
39
+ # @abstract
40
+ #
18
41
  # @param header [String]
19
- # @return [NotImplementedError]
42
+ # @raise NotImplementedError
20
43
  def write_header(header)
21
- raise NotImplementedError
22
44
  end
23
45
 
24
46
  # Outputs a line or block as a header for a group.
25
47
  #
48
+ # @abstract
49
+ #
26
50
  # @param group [String]
27
- # @return [NotImplementedError]
51
+ # @raise NotImplementedError
28
52
  def write_group(group)
29
- raise NotImplementedError
30
53
  end
31
54
 
32
55
  # Outputs a line or block of text appearing after a group.
@@ -37,8 +60,10 @@ module Renogen
37
60
 
38
61
  # Outputs a line or block as the body for a change.
39
62
  #
63
+ # @abstract
64
+ #
40
65
  # @param change [String]
41
- # @return [NotImplementedError]
66
+ # @raise NotImplementedError
42
67
  def write_change(change)
43
68
  raise NotImplementedError
44
69
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Renogen
4
+ module Formatters
5
+ # For formatting a change into CSV output
6
+ class Csv < Base
7
+ register :csv
8
+
9
+ attr_reader :headings
10
+
11
+ def table_formatter?
12
+ true
13
+ end
14
+
15
+ def write_header(header)
16
+ "#{header}\n"
17
+ end
18
+
19
+ def write_change(ticket)
20
+ headings.map do |header|
21
+ raw_line = ticket[header]
22
+ next if raw_line.nil?
23
+
24
+ parsed_line = raw_line.is_a?(Array) ? raw_line.join(',') : raw_line
25
+ parsed_line.gsub!("\n", '\n') if parsed_line.include?("\n")
26
+
27
+ if parsed_line.include?(',')
28
+ "\"#{parsed_line}\""
29
+ else
30
+ parsed_line
31
+ end
32
+ end.join(',')
33
+ end
34
+
35
+ def header(changelog)
36
+ @headings = changelog.groups.keys
37
+ @headings.join(',')
38
+ end
39
+ end
40
+ end
41
+ end
@@ -9,7 +9,7 @@ module Renogen
9
9
  # @param header [String]
10
10
  # @return [String]
11
11
  def write_header(header)
12
- "<html>\n<h1>#{header}</h1>"
12
+ "<html>\n<h1>#{header}</h1>\n"
13
13
  end
14
14
 
15
15
  # Outputs a line or block as a header for a group.
@@ -10,7 +10,7 @@ module Renogen
10
10
  # @param header [String]
11
11
  # @return [String]
12
12
  def write_header(header)
13
- "# #{header}"
13
+ "# #{header}\n\n"
14
14
  end
15
15
 
16
16
  # Outputs a line or block as a header for a group.
@@ -18,7 +18,7 @@ module Renogen
18
18
  # @param group [String]
19
19
  # @return [String]
20
20
  def write_group(group)
21
- "### #{group}"
21
+ "## #{group}\n\n"
22
22
  end
23
23
 
24
24
  # Outputs a line or block as the body for a change.