class GitHubChangelogGenerator::Entry

This class generates the content for a single changelog entry. An entry is generally either for a specific tagged release or the collection of unreleased changes.

An entry is comprised of header text followed by a series of sections relating to the entry.

@see GitHubChangelogGenerator::Generator @see GitHubChangelogGenerator::Section

Attributes

content[R]

Public Class Methods

new(options = Options.new({})) click to toggle source
# File lib/github_changelog_generator/generator/entry.rb, line 18
def initialize(options = Options.new({}))
  @content = ""
  @options = Options.new(options)
end

Public Instance Methods

generate_entry_for_tag(pull_requests, issues, newer_tag_name, newer_tag_link, newer_tag_time, older_tag_name) click to toggle source

Generates log entry with header and body

@param [Array] pull_requests List or PR's in new section @param [Array] issues List of issues in new section @param [String] newer_tag_name Name of the newer tag. Could be nil for `Unreleased` section. @param [String] newer_tag_link Name of the newer tag. Could be “HEAD” for `Unreleased` section. @param [Time] newer_tag_time Time of the newer tag @param [Hash, nil] older_tag_name Older tag, used for the links. Could be nil for last tag. @return [String] Ready and parsed section content.

# File lib/github_changelog_generator/generator/entry.rb, line 32
def generate_entry_for_tag(pull_requests, issues, newer_tag_name, newer_tag_link, newer_tag_time, older_tag_name) # rubocop:disable Metrics/ParameterLists
  github_site = @options[:github_site] || "https://github.com"
  project_url = "#{github_site}/#{@options[:user]}/#{@options[:project]}"

  create_sections

  @content = generate_header(newer_tag_name, newer_tag_link, newer_tag_time, older_tag_name, project_url)
  @content += generate_body(pull_requests, issues)
  @content
end
line_labels_for(issue) click to toggle source
# File lib/github_changelog_generator/generator/entry.rb, line 43
def line_labels_for(issue)
  labels = if @options[:issue_line_labels] == ["ALL"]
             issue["labels"]
           else
             issue["labels"].select { |label| @options[:issue_line_labels].include?(label["name"]) }
           end
  labels.map { |label| " \[[#{label['name']}](#{label['url'].sub('api.github.com/repos', 'github.com')})\]" }.join("")
end

Private Instance Methods

add_unmapped_section(issues) click to toggle source

Creates a section for issues/PRs with no labels or no mapped labels.

@param [Array] issues @return [Nil]

# File lib/github_changelog_generator/generator/entry.rb, line 194
def add_unmapped_section(issues)
  unless issues.empty?
    # Distinguish between issues and pull requests
    if issues.first.key?("pull_request")
      name = "merged"
      prefix = @options[:merge_prefix]
      add_wo_labels = @options[:add_pr_wo_labels]
    else
      name = "issues"
      prefix = @options[:issue_prefix]
      add_wo_labels = @options[:add_issues_wo_labels]
    end
    add_issues = if add_wo_labels
                   issues
                 else
                   # Only add unmapped issues
                   issues.select { |issue| issue["labels"].any? }
                 end
    merged = Section.new(name: name, prefix: prefix, labels: [], issues: add_issues, options: @options) unless add_issues.empty?
    @sections << merged
  end
  nil
end
create_sections() click to toggle source

Creates section objects for this entry. @return [Nil]

# File lib/github_changelog_generator/generator/entry.rb, line 56
def create_sections
  @sections = if @options.configure_sections?
                parse_sections(@options[:configure_sections])
              elsif @options.add_sections?
                default_sections.concat parse_sections(@options[:add_sections])
              else
                default_sections
              end
  nil
end
default_sections() click to toggle source

Default sections to used when –configure-sections is not set.

@return [Array] Section objects.

# File lib/github_changelog_generator/generator/entry.rb, line 135
def default_sections
  [
    Section.new(name: "summary", prefix: @options[:summary_prefix], labels: @options[:summary_labels], options: @options, body_only: true),
    Section.new(name: "breaking", prefix: @options[:breaking_prefix], labels: @options[:breaking_labels], options: @options),
    Section.new(name: "enhancements", prefix: @options[:enhancement_prefix], labels: @options[:enhancement_labels], options: @options),
    Section.new(name: "bugs", prefix: @options[:bug_prefix], labels: @options[:bug_labels], options: @options),
    Section.new(name: "deprecated", prefix: @options[:deprecated_prefix], labels: @options[:deprecated_labels], options: @options),
    Section.new(name: "removed", prefix: @options[:removed_prefix], labels: @options[:removed_labels], options: @options),
    Section.new(name: "security", prefix: @options[:security_prefix], labels: @options[:security_labels], options: @options)
  ]
end
generate_body(pull_requests, issues) click to toggle source

Generates complete body text for a tag (without a header)

@param [Array] pull_requests @param [Array] issues @return [String] Content generated from sections of sorted issues & PRs.

# File lib/github_changelog_generator/generator/entry.rb, line 127
def generate_body(pull_requests, issues)
  sort_into_sections(pull_requests, issues)
  @sections.map(&:generate_content).join
end
generate_header(newer_tag_name, newer_tag_link, newer_tag_time, older_tag_name, project_url) click to toggle source

Generates header text for an entry.

@param [String] newer_tag_name The name of a newer tag @param [String] newer_tag_link Used for URL generation. Could be same as newer_tag_name or some specific value, like HEAD @param [Time] newer_tag_time Time when the newer tag was created @param [String] older_tag_name The name of an older tag; used for URLs. @param [String] project_url URL for the current project. @return [String] Header text content.

# File lib/github_changelog_generator/generator/entry.rb, line 96
def generate_header(newer_tag_name, newer_tag_link, newer_tag_time, older_tag_name, project_url)
  header = ""

  # Generate date string:
  time_string = newer_tag_time.strftime(@options[:date_format])

  # Generate tag name and link
  release_url = if @options[:release_url]
                  format(@options[:release_url], newer_tag_link)
                else
                  "#{project_url}/tree/#{newer_tag_link}"
                end
  header += if newer_tag_name.equal?(@options[:unreleased_label])
              "## [#{newer_tag_name}](#{release_url})\n\n"
            else
              "## [#{newer_tag_name}](#{release_url}) (#{time_string})\n\n"
            end

  if @options[:compare_link] && older_tag_name
    # Generate compare link
    header += "[Full Changelog](#{project_url}/compare/#{older_tag_name}...#{newer_tag_link})\n\n"
  end

  header
end
parse_sections(sections_desc) click to toggle source

Turns the argument from the commandline of –configure-sections or –add-sections into an array of Section objects.

@param [String, Hash] sections_desc Either string or hash describing sections @return [Array] Parsed section objects.

# File lib/github_changelog_generator/generator/entry.rb, line 72
def parse_sections(sections_desc)
  require "json"

  sections_desc = sections_desc.to_json if sections_desc.class == Hash

  begin
    sections_json = JSON.parse(sections_desc)
  rescue JSON::ParserError => e
    raise "There was a problem parsing your JSON string for sections: #{e}"
  end

  sections_json.collect do |name, v|
    Section.new(name: name.to_s, prefix: v["prefix"], labels: v["labels"], body_only: v["body_only"], options: @options)
  end
end
sort_into_sections(pull_requests, issues) click to toggle source

Sorts issues and PRs into entry sections by labels and lack of labels.

@param [Array] pull_requests @param [Array] issues @return [Nil]

# File lib/github_changelog_generator/generator/entry.rb, line 152
def sort_into_sections(pull_requests, issues)
  if @options[:issues]
    unmapped_issues = sort_labeled_issues(issues)
    add_unmapped_section(unmapped_issues)
  end
  if @options[:pulls]
    unmapped_pull_requests = sort_labeled_issues(pull_requests)
    add_unmapped_section(unmapped_pull_requests)
  end
  nil
end
sort_labeled_issues(issues) click to toggle source

Iterates through sections and sorts labeled issues into them based on the label mapping. Returns any unmapped or unlabeled issues.

@param [Array] issues Issues or pull requests. @return [Array] Issues that were not mapped into any sections.

# File lib/github_changelog_generator/generator/entry.rb, line 169
def sort_labeled_issues(issues)
  sorted_issues = []
  issues.each do |issue|
    label_names = issue["labels"].collect { |l| l["name"] }

    # Add PRs in the order of the @sections array. This will either be the
    # default sections followed by any --add-sections sections in
    # user-defined order, or --configure-sections in user-defined order.
    # Ignore the order of the issue labels from github which cannot be
    # controled by the user.
    @sections.each do |section|
      unless (section.labels & label_names).empty?
        section.issues << issue
        sorted_issues << issue
        break
      end
    end
  end
  issues - sorted_issues
end