px_github_changelog_generator 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +9 -0
- data/README.md +357 -0
- data/Rakefile +19 -0
- data/bin/git-generate-changelog +5 -0
- data/bin/github_changelog_generator +5 -0
- data/lib/github_changelog_generator/argv_parser.rb +225 -0
- data/lib/github_changelog_generator/file_parser_chooser.rb +27 -0
- data/lib/github_changelog_generator/generator/entry.rb +218 -0
- data/lib/github_changelog_generator/generator/generator.rb +177 -0
- data/lib/github_changelog_generator/generator/generator_fetcher.rb +202 -0
- data/lib/github_changelog_generator/generator/generator_processor.rb +237 -0
- data/lib/github_changelog_generator/generator/generator_tags.rb +210 -0
- data/lib/github_changelog_generator/generator/section.rb +129 -0
- data/lib/github_changelog_generator/helper.rb +37 -0
- data/lib/github_changelog_generator/octo_fetcher.rb +535 -0
- data/lib/github_changelog_generator/options.rb +159 -0
- data/lib/github_changelog_generator/parser.rb +89 -0
- data/lib/github_changelog_generator/parser_file.rb +101 -0
- data/lib/github_changelog_generator/reader.rb +88 -0
- data/lib/github_changelog_generator/ssl_certs/cacert.pem +3138 -0
- data/lib/github_changelog_generator/task.rb +68 -0
- data/lib/github_changelog_generator/version.rb +5 -0
- data/lib/github_changelog_generator.rb +49 -0
- data/man/git-generate-changelog.1 +393 -0
- data/man/git-generate-changelog.1.html +359 -0
- data/man/git-generate-changelog.html +270 -0
- data/man/git-generate-changelog.md +274 -0
- data/spec/files/angular.js.md +9395 -0
- data/spec/files/bundler.md +1911 -0
- data/spec/files/config_example +5 -0
- data/spec/files/github-changelog-generator.md +305 -0
- data/spec/github_changelog_generator_spec.rb +32 -0
- data/spec/install_gem_in_bundler.gemfile +5 -0
- data/spec/spec_helper.rb +74 -0
- data/spec/unit/generator/entry_spec.rb +766 -0
- data/spec/unit/generator/generator_processor_spec.rb +203 -0
- data/spec/unit/generator/generator_spec.rb +47 -0
- data/spec/unit/generator/generator_tags_spec.rb +337 -0
- data/spec/unit/generator/section_spec.rb +43 -0
- data/spec/unit/octo_fetcher_spec.rb +590 -0
- data/spec/unit/options_spec.rb +67 -0
- data/spec/unit/parser_file_spec.rb +94 -0
- data/spec/unit/parser_spec.rb +54 -0
- data/spec/unit/reader_spec.rb +120 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits/when_API_is_valid/returns_commits.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits_before/when_API_is_valid/returns_commits.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issue_with_proper_key/values.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues_with_labels.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_request_with_proper_key/values.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_requests_with_labels.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_correct_pull_request_keys.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_pull_requests.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid/returns_commit.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid/returns_date.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid/populates_issues.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags_count.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided/should_raise_Unauthorized_error.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided.json +1 -0
- metadata +250 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "github_changelog_generator/helper"
|
4
|
+
require "github_changelog_generator/argv_parser"
|
5
|
+
require "github_changelog_generator/parser_file"
|
6
|
+
require "github_changelog_generator/file_parser_chooser"
|
7
|
+
|
8
|
+
module GitHubChangelogGenerator
|
9
|
+
class Parser
|
10
|
+
class << self
|
11
|
+
PARSERS = [
|
12
|
+
ArgvParser, # Parse arguments first to get initial options populated
|
13
|
+
FileParserChooser, # Then parse possible configuration files
|
14
|
+
ArgvParser # Lastly parse arguments again to keep the given arguments the strongest
|
15
|
+
].freeze
|
16
|
+
|
17
|
+
def parse_options(argv = ARGV)
|
18
|
+
options = default_options
|
19
|
+
|
20
|
+
PARSERS.each do |parser|
|
21
|
+
parser.new(options).parse!(argv)
|
22
|
+
end
|
23
|
+
|
24
|
+
abort_if_user_and_project_not_given!(options)
|
25
|
+
|
26
|
+
options.print_options
|
27
|
+
|
28
|
+
options
|
29
|
+
end
|
30
|
+
|
31
|
+
def abort_if_user_and_project_not_given!(options)
|
32
|
+
return if options[:user] && options[:project]
|
33
|
+
|
34
|
+
warn "Configure which user and project to work on."
|
35
|
+
warn "Options --user and --project, or settings to that effect. See --help for more."
|
36
|
+
warn ArgvParser.banner
|
37
|
+
|
38
|
+
Kernel.abort
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Options] Default options
|
42
|
+
def default_options
|
43
|
+
Options.new(
|
44
|
+
date_format: "%Y-%m-%d",
|
45
|
+
output: "CHANGELOG.md",
|
46
|
+
base: "HISTORY.md",
|
47
|
+
issues: true,
|
48
|
+
add_issues_wo_labels: true,
|
49
|
+
add_pr_wo_labels: true,
|
50
|
+
pulls: true,
|
51
|
+
filter_issues_by_milestone: true,
|
52
|
+
issues_of_open_milestones: true,
|
53
|
+
author: true,
|
54
|
+
unreleased: true,
|
55
|
+
unreleased_label: "Unreleased",
|
56
|
+
compare_link: true,
|
57
|
+
exclude_labels: ["duplicate", "question", "invalid", "wontfix", "Duplicate", "Question", "Invalid", "Wontfix", "Meta: Exclude From Changelog"],
|
58
|
+
summary_labels: ["Release summary", "release-summary", "Summary", "summary"],
|
59
|
+
breaking_labels: ["backwards-incompatible", "Backwards incompatible", "breaking"],
|
60
|
+
enhancement_labels: ["enhancement", "Enhancement", "Type: Enhancement"],
|
61
|
+
bug_labels: ["bug", "Bug", "Type: Bug"],
|
62
|
+
deprecated_labels: ["deprecated", "Deprecated", "Type: Deprecated"],
|
63
|
+
removed_labels: ["removed", "Removed", "Type: Removed"],
|
64
|
+
security_labels: ["security", "Security", "Type: Security"],
|
65
|
+
configure_sections: {},
|
66
|
+
add_sections: {},
|
67
|
+
issue_line_labels: [],
|
68
|
+
max_issues: nil,
|
69
|
+
simple_list: false,
|
70
|
+
ssl_ca_file: nil,
|
71
|
+
verbose: true,
|
72
|
+
header: "# Changelog",
|
73
|
+
merge_prefix: "**Merged pull requests:**",
|
74
|
+
issue_prefix: "**Closed issues:**",
|
75
|
+
summary_prefix: "",
|
76
|
+
breaking_prefix: "**Breaking changes:**",
|
77
|
+
enhancement_prefix: "**Implemented enhancements:**",
|
78
|
+
bug_prefix: "**Fixed bugs:**",
|
79
|
+
deprecated_prefix: "**Deprecated:**",
|
80
|
+
removed_prefix: "**Removed:**",
|
81
|
+
security_prefix: "**Security fixes:**",
|
82
|
+
http_cache: true,
|
83
|
+
require: [],
|
84
|
+
config_file: ".github_changelog_generator"
|
85
|
+
)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GitHubChangelogGenerator
|
4
|
+
ParserError = Class.new(StandardError)
|
5
|
+
|
6
|
+
# ParserFile is a configuration file reader which sets options in the
|
7
|
+
# given Hash.
|
8
|
+
#
|
9
|
+
# In your project's root, you can put a file named
|
10
|
+
# <tt>.github_changelog_generator</tt> to override defaults.
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# header_label=# My Super Changelog
|
14
|
+
# ; Comments are allowed
|
15
|
+
# future-release=5.0.0
|
16
|
+
# # Ruby-style comments, too
|
17
|
+
# since-tag=1.0.0
|
18
|
+
#
|
19
|
+
# The configuration format is <tt>some-key=value</tt> or <tt>some_key=value</tt>.
|
20
|
+
#
|
21
|
+
class ParserFile
|
22
|
+
# @param options [Hash] options to be configured from file contents
|
23
|
+
# @param io [nil, IO] configuration file handle
|
24
|
+
def initialize(options, io = nil)
|
25
|
+
@options = options
|
26
|
+
@io = io
|
27
|
+
end
|
28
|
+
|
29
|
+
# Sets options using configuration file content
|
30
|
+
def parse!
|
31
|
+
return unless @io
|
32
|
+
|
33
|
+
@io.each_with_index { |line, i| parse_line!(line, i + 1) }
|
34
|
+
@io.close
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def parse_line!(line, line_number)
|
40
|
+
return if non_configuration_line?(line)
|
41
|
+
|
42
|
+
option_name, value = extract_pair(line)
|
43
|
+
@options[option_key_for(option_name)] = convert_value(value, option_name)
|
44
|
+
rescue StandardError
|
45
|
+
raise ParserError, "Failed on line ##{line_number}: \"#{line.gsub(/[\n\r]+/, '')}\""
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns true if the line starts with a pound sign or a semi-colon.
|
49
|
+
def non_configuration_line?(line)
|
50
|
+
line =~ /^[\#;]/ || line =~ /^\s+$/
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns a the option name as a symbol and its string value sans newlines.
|
54
|
+
#
|
55
|
+
# @param line [String] unparsed line from config file
|
56
|
+
# @return [Array<Symbol, String>]
|
57
|
+
def extract_pair(line)
|
58
|
+
key, value = line.split("=", 2)
|
59
|
+
[key.tr("-", "_").to_sym, value.gsub(/[\n\r]+/, "")]
|
60
|
+
end
|
61
|
+
|
62
|
+
KNOWN_ARRAY_KEYS = %i[exclude_labels include_labels
|
63
|
+
summary_labels breaking_labels enhancement_labels bug_labels
|
64
|
+
deprecated_labels removed_labels security_labels
|
65
|
+
issue_line_labels between_tags exclude_tags]
|
66
|
+
KNOWN_INTEGER_KEYS = [:max_issues]
|
67
|
+
|
68
|
+
def convert_value(value, option_name)
|
69
|
+
if KNOWN_ARRAY_KEYS.include?(option_name)
|
70
|
+
value.split(",")
|
71
|
+
elsif KNOWN_INTEGER_KEYS.include?(option_name)
|
72
|
+
value.to_i
|
73
|
+
elsif value =~ /^(true|t|yes|y|1)$/i
|
74
|
+
true
|
75
|
+
elsif value =~ /^(false|f|no|n|0)$/i
|
76
|
+
false
|
77
|
+
else
|
78
|
+
value
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
IRREGULAR_OPTIONS = {
|
83
|
+
bugs_label: :bug_prefix,
|
84
|
+
enhancement_label: :enhancement_prefix,
|
85
|
+
issues_label: :issue_prefix,
|
86
|
+
header_label: :header,
|
87
|
+
front_matter: :frontmatter,
|
88
|
+
pr_label: :merge_prefix,
|
89
|
+
breaking_label: :breaking_prefix,
|
90
|
+
issues_wo_labels: :add_issues_wo_labels,
|
91
|
+
pr_wo_labels: :add_pr_wo_labels,
|
92
|
+
pull_requests: :pulls,
|
93
|
+
filter_by_milestone: :filter_issues_by_milestone,
|
94
|
+
github_api: :github_endpoint
|
95
|
+
}
|
96
|
+
|
97
|
+
def option_key_for(option_name)
|
98
|
+
IRREGULAR_OPTIONS.fetch(option_name) { option_name }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Author:: Enrico Stahn <mail@enricostahn.com>
|
5
|
+
#
|
6
|
+
# Copyright 2014, Zanui, <engineering@zanui.com.au>
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
module GitHubChangelogGenerator
|
22
|
+
# A Reader to read an existing ChangeLog file and return a structured object
|
23
|
+
#
|
24
|
+
# Example:
|
25
|
+
# reader = GitHubChangelogGenerator::Reader.new
|
26
|
+
# content = reader.read('./CHANGELOG.md')
|
27
|
+
class Reader
|
28
|
+
def initialize(options = {})
|
29
|
+
defaults = {
|
30
|
+
heading_level: "##",
|
31
|
+
heading_structures: [
|
32
|
+
/^## \[(?<version>.+?)\](\((?<url>.+?)\))?( \((?<date>.+?)\))?$/, # rubocop:disable Lint/MixedRegexpCaptureTypes
|
33
|
+
/^## (?<version>.+?)( \((?<date>.+?)\))?$/ # rubocop:disable Lint/MixedRegexpCaptureTypes
|
34
|
+
]
|
35
|
+
}
|
36
|
+
|
37
|
+
@options = options.merge(defaults)
|
38
|
+
|
39
|
+
@heading_level = @options[:heading_level]
|
40
|
+
@heading_structures = @options[:heading_structures]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Parse a single heading and return a Hash
|
44
|
+
#
|
45
|
+
# The following heading structures are currently valid:
|
46
|
+
# - ## [v1.0.2](https://github.com/zanui/chef-thumbor/tree/v1.0.1) (2015-03-24)
|
47
|
+
# - ## [v1.0.2](https://github.com/zanui/chef-thumbor/tree/v1.0.1)
|
48
|
+
# - ## [v1.0.2] (2015-03-24)
|
49
|
+
# - ## [v1.0.2]
|
50
|
+
# - ## v1.0.2 (2015-03-24)
|
51
|
+
# - ## v1.0.2
|
52
|
+
#
|
53
|
+
# @param [String] heading Heading from the ChangeLog File
|
54
|
+
# @return [Hash] Returns a structured Hash with version, url and date
|
55
|
+
def parse_heading(heading)
|
56
|
+
captures = { "version" => nil, "url" => nil, "date" => nil }
|
57
|
+
|
58
|
+
@heading_structures.each do |regexp|
|
59
|
+
matches = Regexp.new(regexp).match(heading)
|
60
|
+
if matches
|
61
|
+
captures.merge!(Hash[matches.names.zip(matches.captures)])
|
62
|
+
break
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
captures
|
67
|
+
end
|
68
|
+
|
69
|
+
# Parse the given ChangeLog data into a list of Hashes
|
70
|
+
#
|
71
|
+
# @param [String] data File data from the ChangeLog.md
|
72
|
+
# @return [Array<Hash>] Parsed data, e.g. [{ 'version' => ..., 'url' => ..., 'date' => ..., 'content' => ...}, ...]
|
73
|
+
def parse(data)
|
74
|
+
sections = data.split(/^## .+?$/)
|
75
|
+
headings = data.scan(/^## .+?$/)
|
76
|
+
|
77
|
+
headings.each_with_index.map do |heading, index|
|
78
|
+
section = parse_heading(heading)
|
79
|
+
section["content"] = sections.at(index + 1)
|
80
|
+
section
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def read(file_path)
|
85
|
+
parse File.read(file_path)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|