109 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Ruby
		
	
	
	
# frozen_string_literal: true
 | 
						|
 | 
						|
module Gitlab
 | 
						|
  module Changelog
 | 
						|
    # A release to add to a changelog.
 | 
						|
    class Release
 | 
						|
      attr_reader :version
 | 
						|
 | 
						|
      def initialize(version:, date:, config:)
 | 
						|
        @version = version
 | 
						|
        @date = date
 | 
						|
        @config = config
 | 
						|
        @entries = Hash.new { |h, k| h[k] = [] }
 | 
						|
 | 
						|
        # This ensures that entries are presented in the same order as the
 | 
						|
        # categories Hash in the user's configuration.
 | 
						|
        @config.categories.values.each do |category|
 | 
						|
          @entries[category] = []
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      def add_entry(
 | 
						|
        title:,
 | 
						|
        commit:,
 | 
						|
        category:,
 | 
						|
        author: nil,
 | 
						|
        merge_request: nil
 | 
						|
      )
 | 
						|
        # When changing these fields, keep in mind that this needs to be
 | 
						|
        # backwards compatible. For example, you can't just remove a field as
 | 
						|
        # this will break the changelog generation process for existing users.
 | 
						|
        entry = {
 | 
						|
          'title' => title,
 | 
						|
          'commit' => {
 | 
						|
            'reference' => commit.to_reference(full: true),
 | 
						|
            'trailers' => commit.trailers
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        if author
 | 
						|
          entry['author'] = {
 | 
						|
            'reference' => author.to_reference(full: true),
 | 
						|
            'contributor' => @config.contributor?(author)
 | 
						|
          }
 | 
						|
          entry['author']['credit'] = entry['author']['contributor'] || @config.always_credit_author?(author)
 | 
						|
        end
 | 
						|
 | 
						|
        if merge_request
 | 
						|
          entry['merge_request'] = {
 | 
						|
            'reference' => merge_request.to_reference(full: true)
 | 
						|
          }
 | 
						|
        end
 | 
						|
 | 
						|
        @entries[@config.category(category)] << entry
 | 
						|
      end
 | 
						|
 | 
						|
      def to_markdown
 | 
						|
        state = TemplateParser::EvalState.new
 | 
						|
        data = { 'categories' => entries_for_template }
 | 
						|
 | 
						|
        # While not critical, we would like release sections to be separated by
 | 
						|
        # an empty line in the changelog; ensuring it's readable even in its
 | 
						|
        # raw form.
 | 
						|
        #
 | 
						|
        # Since it can be a bit tricky to get this right in a template, we
 | 
						|
        # enforce an empty line separator ourselves.
 | 
						|
        markdown =
 | 
						|
          begin
 | 
						|
            @config.template.evaluate(state, data).strip
 | 
						|
          rescue TemplateParser::Error => e
 | 
						|
            raise Error, e.message
 | 
						|
          end
 | 
						|
 | 
						|
        # The release header can't be changed using the Liquid template, as we
 | 
						|
        # need this to be in a known format. Without this restriction, we won't
 | 
						|
        # know where to insert a new release section in an existing changelog.
 | 
						|
        "## #{@version} (#{release_date})\n\n#{markdown}\n\n"
 | 
						|
      end
 | 
						|
 | 
						|
      def header_start_pattern
 | 
						|
        /^##\s*#{Regexp.escape(@version)}/
 | 
						|
      end
 | 
						|
 | 
						|
      private
 | 
						|
 | 
						|
      def release_date
 | 
						|
        @config.format_date(@date)
 | 
						|
      end
 | 
						|
 | 
						|
      def entries_for_template
 | 
						|
        rows = []
 | 
						|
 | 
						|
        @entries.each do |category, entries|
 | 
						|
          next if entries.empty?
 | 
						|
 | 
						|
          rows << {
 | 
						|
            'title' => category,
 | 
						|
            'count' => entries.length,
 | 
						|
            'single_change' => entries.length == 1,
 | 
						|
            'entries' => entries
 | 
						|
          }
 | 
						|
        end
 | 
						|
 | 
						|
        rows
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |