Compare commits
41 Commits
v1.15.0.pr
...
olleolleol
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c96db9490 | ||
|
|
1c8a2d29ea | ||
|
|
fe0fd94ea3 | ||
|
|
3fc0012de2 | ||
|
|
de525fb1e8 | ||
|
|
cacd6dc3c8 | ||
|
|
db1ffdd59b | ||
|
|
0189c2d736 | ||
|
|
559defcb55 | ||
|
|
0fc6da1a75 | ||
|
|
4b50b5b257 | ||
|
|
f98cc8f292 | ||
|
|
8056600180 | ||
|
|
6d45d90a5f | ||
|
|
3df84403c4 | ||
|
|
1763f9c8ea | ||
|
|
180b4cb6c9 | ||
|
|
b82aa64eee | ||
|
|
cb6286fb83 | ||
|
|
7dcf617d61 | ||
|
|
e89b03fe48 | ||
|
|
9ff27b690f | ||
|
|
bcf57dbe0e | ||
|
|
4cfb1e4a5f | ||
|
|
b81f8a4169 | ||
|
|
3179f29a7c | ||
|
|
aee2f43235 | ||
|
|
63b3de1281 | ||
|
|
0517674f04 | ||
|
|
53b0684e67 | ||
|
|
ca5d6d9675 | ||
|
|
3cb3584bb9 | ||
|
|
4fb674b68e | ||
|
|
e494fc004e | ||
|
|
4ecb21c0b0 | ||
|
|
3cf2802d9a | ||
|
|
507b89c665 | ||
|
|
cd14a86f84 | ||
|
|
5d7098282d | ||
|
|
0751082526 | ||
|
|
baa4e3e659 |
@@ -1,12 +0,0 @@
|
||||
engines:
|
||||
duplication:
|
||||
enabled: true
|
||||
config:
|
||||
languages:
|
||||
- ruby
|
||||
rubocop:
|
||||
enabled: true
|
||||
ratings:
|
||||
paths:
|
||||
- "**.rb"
|
||||
exclude_paths:
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,4 +9,3 @@ doc
|
||||
.yardoc
|
||||
Gemfile.lock
|
||||
gemfiles/Gemfile.2_4_0.lock
|
||||
gemfiles/Gemfile.jruby-9.1.5.0.lock
|
||||
|
||||
17
.rubocop.yml
17
.rubocop.yml
@@ -1,7 +1,6 @@
|
||||
inherit_from: .rubocop_todo.yml
|
||||
|
||||
AllCops:
|
||||
TargetRubyVersion: 2.2
|
||||
DisplayCopNames: true
|
||||
DisplayStyleGuide: true
|
||||
Exclude:
|
||||
@@ -11,9 +10,6 @@ AllCops:
|
||||
Metrics/LineLength:
|
||||
Enabled: false
|
||||
|
||||
Performance/RegexpMatch:
|
||||
Enabled: false
|
||||
|
||||
#http://viget.com/extend/just-use-double-quoted-ruby-strings
|
||||
Style/StringLiterals:
|
||||
EnforcedStyle: double_quotes
|
||||
@@ -26,7 +22,7 @@ Metrics/ClassLength:
|
||||
Metrics/MethodLength:
|
||||
Enabled: false
|
||||
|
||||
Naming/FileName:
|
||||
Style/FileName:
|
||||
Exclude:
|
||||
- 'bin/git-generate-changelog'
|
||||
|
||||
@@ -36,7 +32,7 @@ Metrics/AbcSize:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 1
|
||||
Naming/AccessorMethodName:
|
||||
Style/AccessorMethodName:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 10
|
||||
@@ -71,12 +67,3 @@ Style/NumericPredicate:
|
||||
|
||||
Style/SafeNavigation:
|
||||
Enabled: false
|
||||
|
||||
Metrics/BlockLength:
|
||||
Exclude:
|
||||
- 'spec/**/*'
|
||||
|
||||
# Re-enable when merged; https://github.com/bbatsov/rubocop/pull/4756
|
||||
Lint/InterpolationCheck:
|
||||
Enabled: false
|
||||
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config`
|
||||
# on 2016-09-30 23:56:15 +0200 using RuboCop version 0.43.0.
|
||||
# on 2016-02-23 17:18:27 +0200 using RuboCop version 0.37.2.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of RuboCop, may require this file to be generated again.
|
||||
|
||||
# Offense count: 1
|
||||
Lint/ImplicitStringConcatenation:
|
||||
Exclude:
|
||||
- 'lib/github_changelog_generator/parser.rb'
|
||||
|
||||
# Offense count: 14
|
||||
Metrics/AbcSize:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 1
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 7
|
||||
@@ -13,3 +22,30 @@ Metrics/CyclomaticComplexity:
|
||||
# Offense count: 2
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 8
|
||||
|
||||
# Offense count: 1
|
||||
Style/AccessorMethodName:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 10
|
||||
Style/Documentation:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: MinBodyLength.
|
||||
Style/GuardClause:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles.
|
||||
# SupportedStyles: skip_modifier_ifs, always
|
||||
Style/Next:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes.
|
||||
# SupportedStyles: slashes, percent_r, mixed
|
||||
Style/RegexpLiteral:
|
||||
Enabled: false
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.4.0
|
||||
2.3.1
|
||||
35
.travis.yml
35
.travis.yml
@@ -1,35 +1,32 @@
|
||||
language: ruby
|
||||
cache:
|
||||
bundler: true
|
||||
- bundler
|
||||
before_install:
|
||||
- gem update --system
|
||||
- gem install bundler
|
||||
matrix:
|
||||
include:
|
||||
- rvm: 2.2.8
|
||||
- rvm: 2.2.2
|
||||
install: true # This skips 'bundle install'
|
||||
script: gem build github_changelog_generator && gem install *.gem
|
||||
- rvm: 2.2.8
|
||||
- rvm: 2.2.2
|
||||
install: true # This skips 'bundle install'
|
||||
script: gem build github_changelog_generator && bundle install
|
||||
gemfile: spec/install-gem-in-bundler.gemfile
|
||||
- rvm: 2.3.5
|
||||
- rvm: 2.4.2
|
||||
- rvm: jruby-9.1.13.0
|
||||
jdk: oraclejdk8
|
||||
env:
|
||||
- JRUBY_OPTS=--debug
|
||||
- rvm: jruby-head
|
||||
jdk: oraclejdk8
|
||||
env:
|
||||
- JRUBY_OPTS=--debug
|
||||
- DEBUG=1
|
||||
allow_failures:
|
||||
- rvm: jruby-head
|
||||
fast_finish: true
|
||||
- rvm: 2.1
|
||||
gemfile: gemfiles/Gemfile.2_1
|
||||
- rvm: 2.3.1
|
||||
gemfile: gemfiles/Gemfile.2_3_1
|
||||
- rvm: 2.4.0-preview2
|
||||
gemfile: gemfiles/Gemfile.2_4_0
|
||||
|
||||
notifications:
|
||||
email:
|
||||
recipients:
|
||||
- sky4winder+githubchangeloggenerator@gmail.com
|
||||
on_success: never
|
||||
on_failure: change
|
||||
addons:
|
||||
code_climate:
|
||||
repo_token:
|
||||
secure: iMpV5IAvH+/EVGZrpWnt2BnmNFzSbsRcIumsr4ZyLC8N5nrCSXyjCSy0g48btL3Sj0bSgK9hcrJsmrFd2bkqFleyAcPAzNyUQzBuIRZx47O8yFmbZ+Pj+l3+KOlmcbzJNHfDfxkxuWTmTAcSDfsiyApin721T/ey3SUuwKpZNUc=
|
||||
after_success:
|
||||
- bundle exec codeclimate-test-reporter
|
||||
|
||||
109
CHANGELOG.md
109
CHANGELOG.md
@@ -1,113 +1,5 @@
|
||||
# Change Log
|
||||
|
||||
## [v1.14.3](https://github.com/skywinder/github-changelog-generator/tree/v1.14.3) (2016-12-31)
|
||||
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/v1.14.2...v1.14.3)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Use Octokit::Client for both .com and Enterprise [\#455](https://github.com/skywinder/github-changelog-generator/pull/455) ([eliperkins](https://github.com/eliperkins))
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Last tag contains too many PRs [\#291](https://github.com/skywinder/github-changelog-generator/issues/291)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- CodeClimate configuration file [\#465](https://github.com/skywinder/github-changelog-generator/pull/465) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Travis: Build against 2.4.0 [\#464](https://github.com/skywinder/github-changelog-generator/pull/464) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Travis: add jruby-head, 2.4.0-rc1 [\#463](https://github.com/skywinder/github-changelog-generator/pull/463) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Gemfiles for building versions separately dropped [\#461](https://github.com/skywinder/github-changelog-generator/pull/461) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Order Gemfile gems A-Z; add ruby version marker [\#460](https://github.com/skywinder/github-changelog-generator/pull/460) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- README: Documentation update about RakeTask params and how to translate labels [\#454](https://github.com/skywinder/github-changelog-generator/pull/454) ([edusantana](https://github.com/edusantana))
|
||||
- Travis: Use ruby 2.3.3 and 2.2.6 [\#452](https://github.com/skywinder/github-changelog-generator/pull/452) ([olleolleolle](https://github.com/olleolleolle))
|
||||
|
||||
## [v1.14.2](https://github.com/skywinder/github-changelog-generator/tree/v1.14.2) (2016-11-12)
|
||||
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/v1.14.1...v1.14.2)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- OctoFetcher: Moved repositories fail explicitly [\#449](https://github.com/skywinder/github-changelog-generator/pull/449) ([olleolleolle](https://github.com/olleolleolle))
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Error: can't convert Sawyer::Resource to Array when iterating over a 301 Moved Permanently [\#448](https://github.com/skywinder/github-changelog-generator/issues/448)
|
||||
|
||||
## [v1.14.1](https://github.com/skywinder/github-changelog-generator/tree/v1.14.1) (2016-11-06)
|
||||
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/v1.14.0...v1.14.1)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- multi\_json is required but is listed as a test dependency [\#444](https://github.com/skywinder/github-changelog-generator/issues/444)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Add multi\_json as a runtime dependency [\#445](https://github.com/skywinder/github-changelog-generator/pull/445) ([rnelson0](https://github.com/rnelson0))
|
||||
|
||||
## [v1.14.0](https://github.com/skywinder/github-changelog-generator/tree/v1.14.0) (2016-11-05)
|
||||
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/v1.13.2...v1.14.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- On OctoKit::Forbidden error: retry with exponential backoff [\#434](https://github.com/skywinder/github-changelog-generator/pull/434) ([awaage](https://github.com/awaage))
|
||||
- Use octokit, carrying awaage commits [\#422](https://github.com/skywinder/github-changelog-generator/pull/422) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Add option to show selected labels in the issue line [\#418](https://github.com/skywinder/github-changelog-generator/pull/418) ([aih](https://github.com/aih))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- unreleased and unreleased-label [\#374](https://github.com/skywinder/github-changelog-generator/issues/374)
|
||||
- Problems installing 1.11.7 on Windows when git absent [\#349](https://github.com/skywinder/github-changelog-generator/issues/349)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- broken issue-line-labels in log [\#442](https://github.com/skywinder/github-changelog-generator/issues/442)
|
||||
- Broken multi hyphen options in param file [\#440](https://github.com/skywinder/github-changelog-generator/issues/440)
|
||||
- Install error on Mac: "rack requires Ruby version \>= 2.2.2" [\#425](https://github.com/skywinder/github-changelog-generator/issues/425)
|
||||
- Changelog includes issues going back months too far [\#394](https://github.com/skywinder/github-changelog-generator/issues/394)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fixed issue \#442 - broken issue-line-labels in log. [\#443](https://github.com/skywinder/github-changelog-generator/pull/443) ([thorsteneckel](https://github.com/thorsteneckel))
|
||||
- Fixed issue \#440 - broken multi hyphen options in param file. [\#441](https://github.com/skywinder/github-changelog-generator/pull/441) ([thorsteneckel](https://github.com/thorsteneckel))
|
||||
- Option --unreleased-label explained [\#439](https://github.com/skywinder/github-changelog-generator/pull/439) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Fixed issue \#304 - entries of previous tags are included. [\#438](https://github.com/skywinder/github-changelog-generator/pull/438) ([thorsteneckel](https://github.com/thorsteneckel))
|
||||
- man page: Add undescribed options [\#437](https://github.com/skywinder/github-changelog-generator/pull/437) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- On GitHub MAX\_THREAD\_NUMBER is 25 [\#433](https://github.com/skywinder/github-changelog-generator/pull/433) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- OctoFetcher, Options: Refactoring [\#432](https://github.com/skywinder/github-changelog-generator/pull/432) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Fix typo in Readme [\#431](https://github.com/skywinder/github-changelog-generator/pull/431) ([rmtheis](https://github.com/rmtheis))
|
||||
- Fix: Turn Sawyer method into String-keyed hash access [\#429](https://github.com/skywinder/github-changelog-generator/pull/429) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Spec: Test a url helper function [\#428](https://github.com/skywinder/github-changelog-generator/pull/428) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Rubocop TODO file regenerated [\#427](https://github.com/skywinder/github-changelog-generator/pull/427) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Drop a stray Markdown file [\#426](https://github.com/skywinder/github-changelog-generator/pull/426) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Travis: Add JRuby 9.1.5.0 to matrix [\#424](https://github.com/skywinder/github-changelog-generator/pull/424) ([olleolleolle](https://github.com/olleolleolle))
|
||||
|
||||
## [v1.13.2](https://github.com/skywinder/github-changelog-generator/tree/v1.13.2) (2016-09-29)
|
||||
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.13.2...v1.13.2)
|
||||
|
||||
## [1.13.2](https://github.com/skywinder/github-changelog-generator/tree/1.13.2) (2016-09-29)
|
||||
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.13.1...1.13.2)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Replace GPL'd colorize gem with MIT-licensed rainbow [\#408](https://github.com/skywinder/github-changelog-generator/pull/408) ([jamesc](https://github.com/jamesc))
|
||||
- Limit number of simultaneous requests to 25 [\#407](https://github.com/skywinder/github-changelog-generator/pull/407) ([jkeiser](https://github.com/jkeiser))
|
||||
- Report actual github error when rate limit exceeded [\#405](https://github.com/skywinder/github-changelog-generator/pull/405) ([jkeiser](https://github.com/jkeiser))
|
||||
- Make error messages print on error [\#404](https://github.com/skywinder/github-changelog-generator/pull/404) ([jkeiser](https://github.com/jkeiser))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Fetching events for issues and PRs triggers abuse rate limits [\#406](https://github.com/skywinder/github-changelog-generator/issues/406)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Add bump gem to development deps [\#423](https://github.com/skywinder/github-changelog-generator/pull/423) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Skip logger helper in coverage [\#421](https://github.com/skywinder/github-changelog-generator/pull/421) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Travis: Test on 2.4.0-preview2 [\#420](https://github.com/skywinder/github-changelog-generator/pull/420) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Travis: Collecting the config, gemspec: extract development deps to Gemfile [\#417](https://github.com/skywinder/github-changelog-generator/pull/417) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Update README.md [\#415](https://github.com/skywinder/github-changelog-generator/pull/415) ([dijonkitchen](https://github.com/dijonkitchen))
|
||||
- README: Add Gitter badge [\#413](https://github.com/skywinder/github-changelog-generator/pull/413) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- CircleCI hook for Gitter notification [\#411](https://github.com/skywinder/github-changelog-generator/pull/411) ([olleolleolle](https://github.com/olleolleolle))
|
||||
- Spec: avoid Ruby warning about already-defined constant [\#409](https://github.com/skywinder/github-changelog-generator/pull/409) ([olleolleolle](https://github.com/olleolleolle))
|
||||
|
||||
## [1.13.1](https://github.com/skywinder/github-changelog-generator/tree/1.13.1) (2016-07-22)
|
||||
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.13.0...1.13.1)
|
||||
|
||||
@@ -294,7 +186,6 @@
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- We should add a git-generate-changelog command. [\#255](https://github.com/skywinder/github-changelog-generator/issues/255)
|
||||
- YAML front matter [\#322](https://github.com/skywinder/github-changelog-generator/pull/322) ([retorquere](https://github.com/retorquere))
|
||||
- Git Subcommand [\#288](https://github.com/skywinder/github-changelog-generator/pull/288) ([dlanileonardo](https://github.com/dlanileonardo))
|
||||
|
||||
|
||||
27
Gemfile
27
Gemfile
@@ -1,29 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
ruby RUBY_VERSION
|
||||
|
||||
gemspec
|
||||
|
||||
group :development, :test do
|
||||
gem "rake"
|
||||
gem "bundler"
|
||||
gem "overcommit", ">= 0.31"
|
||||
gem "rake"
|
||||
gem "rubocop", ">= 0.50"
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem "bump"
|
||||
gem "rubocop", ">= 0.43"
|
||||
end
|
||||
|
||||
group :test do
|
||||
gem "codeclimate-test-reporter", "~> 1.0"
|
||||
gem "coveralls", "~>0.8", require: false
|
||||
gem "json"
|
||||
gem "multi_json"
|
||||
gem "rspec", "< 4"
|
||||
gem "simplecov", "~>0.10", require: false
|
||||
gem "vcr"
|
||||
gem "multi_json"
|
||||
gem "webmock"
|
||||
gem "coveralls", "~>0.8", require: false
|
||||
gem "simplecov", "~>0.10", require: false
|
||||
gem "codeclimate-test-reporter", "~>0.4"
|
||||
if RUBY_VERSION > "2"
|
||||
gem "json", "~> 2.0", ">= 2.0.2"
|
||||
else
|
||||
gem "json"
|
||||
end
|
||||
gem "rspec", "< 4"
|
||||
end
|
||||
|
||||
51
README.md
51
README.md
@@ -1,7 +1,6 @@
|
||||
[](http://badge.fury.io/rb/github_changelog_generator)
|
||||
[](https://gemnasium.com/skywinder/github-changelog-generator)
|
||||
[](https://travis-ci.org/skywinder/github-changelog-generator)
|
||||
[](https://ci.appveyor.com/project/olleolleolle/github-changelog-generator)
|
||||
[](http://inch-ci.org/github/skywinder/github-changelog-generator)
|
||||
[](https://codeclimate.com/github/skywinder/github-changelog-generator)
|
||||
[](https://codeclimate.com/github/skywinder/github-changelog-generator)
|
||||
@@ -25,20 +24,20 @@ GitHub Changelog Generator 
|
||||
|
||||
### Changelog generation has never been so easy
|
||||
|
||||
**Fully automated changelog generation** - This gem generates a change log file based on **tags**, **issues** and merged **pull requests** (and splits them into separate lists according to labels) from :octocat: GitHub Issue Tracker.
|
||||
**Fully automate changelog generation** - This gem generates change log file based on **tags**, **issues** and merged **pull requests** (and splits them into separate lists according to labels) from :octocat: GitHub Issue Tracker.
|
||||
|
||||
Since you don't have to fill your `CHANGELOG.md` manually now: just run the script, relax and take a cup of :coffee: before your next release! :tada:
|
||||
Since now you don't have to fill your `CHANGELOG.md` manually: just run the script, relax and take a cup of :coffee: before your next release! :tada:
|
||||
|
||||
### *What’s the point of a change log?*
|
||||
>### *What’s the point of a change log?*
|
||||
To make it easier for users and contributors to see precisely what notable changes have been made between each release (or version) of the project.
|
||||
### *Why should I care?*
|
||||
Because software tools are for people. If you don’t care, why are you contributing to open source? Surely, there must be a kernel (ha!) of care somewhere in that lovely little brain of yours.
|
||||
|
||||
:arrow_right: *[http://keepachangelog.com](http://keepachangelog.com)*
|
||||
> :arrow_right: *[http://keepachangelog.com](http://keepachangelog.com)*
|
||||
|
||||
## Installation
|
||||
|
||||
gem install github_changelog_generator
|
||||
gem install github_changelog_generator
|
||||
|
||||
See also Troubleshooting.
|
||||
|
||||
@@ -47,7 +46,7 @@ See also Troubleshooting.
|
||||
- Look at **[CHANGELOG.md](https://github.com/skywinder/Github-Changelog-Generator/blob/master/CHANGELOG.md)** for this project
|
||||
- [ActionSheetPicker-3.0/CHANGELOG.md](https://github.com/skywinder/ActionSheetPicker-3.0/blob/master/CHANGELOG.md) was generated by command:
|
||||
|
||||
github_changelog_generator -u skywinder -p ActionSheetPicker-3.0
|
||||
github_changelog_generator -u skywinder -p ActionSheetPicker-3.0
|
||||
|
||||
- In general, it looks like this:
|
||||
|
||||
@@ -75,16 +74,16 @@ See also Troubleshooting.
|
||||
|
||||
- If your **`git remote`** `origin` refers to your GitHub repo, just go to your project folder and run:
|
||||
|
||||
github_changelog_generator
|
||||
github_changelog_generator
|
||||
|
||||
- Or, run this from anywhere:
|
||||
`github_changelog_generator -u github_username -p github_project`
|
||||
`github_changelog_generator github_username/github_project`
|
||||
- `github_changelog_generator -u github_username -p github_project`
|
||||
- `github_changelog_generator github_username/github_project`
|
||||
|
||||
- If you are running it against a repository on a Github Enterprise install, you must specify *both* `--github-site` and `--github-api` command line options:
|
||||
|
||||
github_changelog_generator --github-site="https://github.yoursite.com" \
|
||||
--github-api="https://github.yoursite.com/api/v3/"
|
||||
github_changelog_generator --github-site="https://github.yoursite.com" \
|
||||
--github-api="https://github.yoursite.com/api/v3/"
|
||||
|
||||
This generates a changelog to the `CHANGELOG.md` file, with pretty markdown formatting.
|
||||
|
||||
@@ -105,7 +104,7 @@ since-tag=1.0.0
|
||||
|
||||
### GitHub token
|
||||
|
||||
GitHub only allows 50 unauthenticated requests per hour.
|
||||
GitHub only allows only 50 unauthenticated requests per hour.
|
||||
Therefore, it's recommended to run this script with authentication by using a **token**.
|
||||
|
||||
Here's how:
|
||||
@@ -117,14 +116,10 @@ Here's how:
|
||||
|
||||
You can set an environment variable by running the following command at the prompt, or by adding it to your shell profile (e.g., `~/.bash_profile` or `~/.zshrc`):
|
||||
|
||||
export CHANGELOG_GITHUB_TOKEN="«your-40-digit-github-token»"
|
||||
export CHANGELOG_GITHUB_TOKEN="«your-40-digit-github-token»"
|
||||
|
||||
So, if you get a message like this:
|
||||
|
||||
``` markdown
|
||||
API rate limit exceeded for github_username.
|
||||
See: https://developer.github.com/v3/#rate-limiting
|
||||
```
|
||||
So, if you got an error like this:
|
||||
>! /Library/Ruby/Gems/2.0.0/gems/github_api-0.12.2/lib/github_api/response/raise_error.rb:14:in `on_complete'
|
||||
|
||||
It's time to create this token! (Or, wait an hour for GitHub to reset your unauthenticated request limit.)
|
||||
|
||||
@@ -156,8 +151,6 @@ end
|
||||
|
||||
All command line options can be passed to the `rake` task as `config` parameters. And since you're naming the `rake` task yourself, you can create as many as you want.
|
||||
|
||||
You can look for params names from the [parser source code (#setup_parser)](https://github.com/skywinder/github-changelog-generator/blob/master/lib/github_changelog_generator/parser.rb). For example, to translate the bugs label to Portuguese, instead of setting `config.bugs_label`, you have to set `config.bug_prefix`, and so on.
|
||||
|
||||
## Features and advantages of this project
|
||||
- Generate canonical, neat change log file, followed by [basic change log guidelines](http://keepachangelog.com) :gem:
|
||||
- Optionally generate **Unreleased** changes (closed issues that have not released yet) :dizzy:
|
||||
@@ -178,7 +171,7 @@ You can look for params names from the [parser source code (#setup_parser)](http
|
||||
(*See `github_changelog_generator --help` for details)*
|
||||
|
||||
|
||||
### Alternatives
|
||||
###Alternatives
|
||||
Here is a [wikipage list of alternatives](https://github.com/skywinder/Github-Changelog-Generator/wiki/Alternatives) that I found. But none satisfied my requirements.
|
||||
|
||||
*If you know other projects, feel free to edit this Wiki page!*
|
||||
@@ -213,14 +206,14 @@ An auto-generated changelog really helps, even if you manually fill in the relea
|
||||
|
||||
For example:
|
||||
|
||||
When you find a closed bug, it is very useful to know which release fixed it.
|
||||
So that you can easily find the issue by \# in `CHANGELOG.md`.
|
||||
When I found a closed bug, it's very useful know which release fixed it.
|
||||
In this case, you can easily find the issue by \# in `CHANGELOG.md`.
|
||||
|
||||
- it's not quite as easy to find this in handwritten releases notes
|
||||
- a generated file saves you the trouble of remembering everything;
|
||||
sometimes people forget to add things to a handwritten file
|
||||
|
||||
Ultimately, I think GitHub Releases are ideal for end-users.
|
||||
Ultimately, I think GitHub Releases is ideal for end-users.
|
||||
Meanwhile, `CHANGELOG.md` lives right in the repository, with its detailed list of changes, which is handy for developers.
|
||||
Finally, there's nothing wrong with using GitHub Releases alongside `CHANGELOG.md` in this combination.
|
||||
|
||||
@@ -235,7 +228,7 @@ If you're seeing this warning, please do the following:
|
||||
|
||||
- ***My Ruby version is very old, can I use this?***
|
||||
|
||||
When your Ruby is old, and you don't want to upgrade, and you want to
|
||||
When your Ruby is old, and you don't want to upgrade, and your want to
|
||||
control which libraries you use, you can use Bundler.
|
||||
|
||||
In a Gemfile, perhaps in a non-deployed `:development` group, add this
|
||||
@@ -261,14 +254,14 @@ can't get the latest version of Ruby installed.
|
||||
## Contributing
|
||||
|
||||
1. Create an issue and describe your idea
|
||||
2. [Fork it](https://github.com/skywinder/github-changelog-generator/fork)
|
||||
2. [Fork it] (https://github.com/skywinder/Github-Changelog-Generator/fork)
|
||||
3. Create your feature branch (`git checkout -b my-new-feature`)
|
||||
4. Commit your changes (`git commit -am 'Add some feature'`)
|
||||
5. Publish the branch (`git push origin my-new-feature`)
|
||||
6. Create a new Pull Request
|
||||
7. Profit! :white_check_mark:
|
||||
|
||||
You can test your workflow with changelog generator with [the skywinder/changelog_test repo](https://github.com/skywinder/changelog_test/).
|
||||
*To test your workflow with changelog generator, you can use [test repo](https://github.com/skywinder/changelog_test/)*
|
||||
|
||||
## License
|
||||
|
||||
|
||||
32
Rakefile
32
Rakefile
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "bundler"
|
||||
require "bundler/gem_tasks"
|
||||
require "rubocop/rake_task"
|
||||
@@ -11,10 +10,31 @@ require "overcommit"
|
||||
RuboCop::RakeTask.new
|
||||
RSpec::Core::RakeTask.new(:rspec)
|
||||
|
||||
desc "When releasing the gem, re-fetch latest cacert.pem from curl.haxx.se. Developer task."
|
||||
task :update_ssl_ca_file do
|
||||
`pushd lib/github_changelog_generator/ssl_certs && curl --remote-name --time-cond cacert.pem https://curl.haxx.se/ca/cacert.pem && popd`
|
||||
task :copy_man_page_to_manpath do |_t|
|
||||
known_manpath_paths = %w(/etc/manpath.config /etc/manpaths)
|
||||
manpath = known_manpath_paths.find do |f|
|
||||
path = Pathname(f)
|
||||
path.file? && path.readable?
|
||||
end
|
||||
|
||||
next unless manpath
|
||||
|
||||
writable_man_path = Pathname(manpath).each_line.find do |line|
|
||||
path = Pathname(line.chomp)
|
||||
path.directory? && path.writable?
|
||||
end
|
||||
|
||||
next unless writable_man_path
|
||||
|
||||
man_prefix = Pathname("#{writable_man_path.chomp}/man1")
|
||||
man_pages = "man/git-*.1"
|
||||
|
||||
Pathname.glob(man_pages) do |path|
|
||||
if path.exist? && man_prefix.exist? && man_prefix.writable?
|
||||
FileUtils.cp(path, man_prefix + path.basename)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
task checks: %i[rubocop rspec]
|
||||
task default: %i[rubocop rspec]
|
||||
task checks: [:rubocop, :rspec]
|
||||
task default: [:rubocop, :rspec]
|
||||
|
||||
@@ -17,9 +17,6 @@ environment:
|
||||
- ruby_version: "21" # Older version, but matches Travis-CI
|
||||
- ruby_version: "21-x64"
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf true
|
||||
|
||||
install:
|
||||
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
||||
|
||||
@@ -51,8 +48,3 @@ notifications:
|
||||
- sky4winder+githubchangeloggenerator@gmail.com
|
||||
on_build_success: false
|
||||
on_build_status_changed: true
|
||||
- provider: GitHubPullRequest
|
||||
on_build_success: true
|
||||
on_build_failure: true
|
||||
on_build_status_changed: true
|
||||
|
||||
|
||||
8
circle.yml
Normal file
8
circle.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
notify:
|
||||
webhooks:
|
||||
# A list of hook hashes, containing the url field
|
||||
# gitter hook
|
||||
- url: https://webhooks.gitter.im/e/2d81eb1ae7695fdc82c4
|
||||
- url: https://webhooks.gitter.im/e/3ec6a35fad7e9991058e
|
||||
|
||||
|
||||
3
gemfiles/Gemfile.2_1
Normal file
3
gemfiles/Gemfile.2_1
Normal file
@@ -0,0 +1,3 @@
|
||||
eval_gemfile File.expand_path('../../Gemfile', __FILE__)
|
||||
gem 'rack', '~> 1.6'
|
||||
gem 'activesupport', '~> 4'
|
||||
3
gemfiles/Gemfile.2_3_1
Normal file
3
gemfiles/Gemfile.2_3_1
Normal file
@@ -0,0 +1,3 @@
|
||||
eval_gemfile File.expand_path('../../Gemfile', __FILE__)
|
||||
gem 'rack', '>= 2'
|
||||
gem 'activesupport', '>= 4'
|
||||
3
gemfiles/Gemfile.2_4_0
Normal file
3
gemfiles/Gemfile.2_4_0
Normal file
@@ -0,0 +1,3 @@
|
||||
eval_gemfile File.expand_path('../../Gemfile', __FILE__)
|
||||
gem 'rack', '>= 2'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# coding: utf-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
lib = File.expand_path("../lib", __FILE__)
|
||||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||
require "github_changelog_generator/version"
|
||||
@@ -18,17 +18,15 @@ Gem::Specification.new do |spec|
|
||||
spec.homepage = "https://github.com/skywinder/Github-Changelog-Generator"
|
||||
spec.license = "MIT"
|
||||
|
||||
spec.files = Dir["{bin,lib,man,spec}/**/*"] + %w[LICENSE Rakefile README.md]
|
||||
spec.files = Dir["{bin,lib,man,spec}/**/*"] + %w(LICENSE Rakefile README.md)
|
||||
|
||||
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
||||
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
||||
spec.require_paths = ["lib"]
|
||||
|
||||
spec.add_runtime_dependency "rake", ">= 10.0"
|
||||
spec.add_runtime_dependency "rainbow", ">= 2.2.1"
|
||||
spec.add_runtime_dependency("octokit", ["~> 4.6"])
|
||||
spec.add_runtime_dependency "rainbow", ">= 2.1"
|
||||
spec.add_runtime_dependency("octokit", ["~> 4.0"])
|
||||
spec.add_runtime_dependency("faraday-http-cache")
|
||||
spec.add_runtime_dependency("activesupport")
|
||||
spec.add_runtime_dependency("retriable", ["~> 3.0"])
|
||||
spec.add_runtime_dependency("multi_json")
|
||||
end
|
||||
|
||||
58
lib/CHANGELOG.md
Normal file
58
lib/CHANGELOG.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Change Log
|
||||
|
||||
## [Unreleased](https://github.com/skywinder/changelog_test/tree/HEAD)
|
||||
|
||||
[Full Changelog](https://github.com/skywinder/changelog_test/compare/0.0.4...HEAD)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Enchancment [\#9](https://github.com/skywinder/changelog_test/issues/9)
|
||||
- PR with enhancement label [\#16](https://github.com/skywinder/changelog_test/pull/16) ([skywinder](https://github.com/skywinder))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- BugFix [\#11](https://github.com/skywinder/changelog_test/issues/11)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Issue closed from commit from PR [\#14](https://github.com/skywinder/changelog_test/issues/14)
|
||||
- Issue, closed by PR [\#12](https://github.com/skywinder/changelog_test/issues/12)
|
||||
- Issue [\#10](https://github.com/skywinder/changelog_test/issues/10)
|
||||
- Issue with some other label - Should be in closed issues [\#8](https://github.com/skywinder/changelog_test/issues/8)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Merged br \(should appear in change log also\) [\#21](https://github.com/skywinder/changelog_test/pull/21) ([skywinder](https://github.com/skywinder))
|
||||
- This a PR with a lot of comments and events [\#17](https://github.com/skywinder/changelog_test/pull/17) ([skywinder](https://github.com/skywinder))
|
||||
- This PR closes 14 from commit [\#15](https://github.com/skywinder/changelog_test/pull/15) ([skywinder](https://github.com/skywinder))
|
||||
- This PR to close \#12 from body [\#13](https://github.com/skywinder/changelog_test/pull/13) ([skywinder](https://github.com/skywinder))
|
||||
|
||||
## [0.0.4](https://github.com/skywinder/changelog_test/tree/0.0.4) (2015-05-22)
|
||||
[Full Changelog](https://github.com/skywinder/changelog_test/compare/v0.0.3...0.0.4)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Test issue, that should appear in 0.0.4 [\#3](https://github.com/skywinder/changelog_test/issues/3)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Add automatically generated change log file. [\#5](https://github.com/skywinder/changelog_test/pull/5) ([skywinder](https://github.com/skywinder))
|
||||
|
||||
## [v0.0.3](https://github.com/skywinder/changelog_test/tree/v0.0.3) (2015-03-04)
|
||||
[Full Changelog](https://github.com/skywinder/changelog_test/compare/v0.0.2...v0.0.3)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- fix \#3. hotfix. Should appear in v0.0.3 [\#4](https://github.com/skywinder/changelog_test/pull/4) ([skywinder](https://github.com/skywinder))
|
||||
|
||||
## [v0.0.2](https://github.com/skywinder/changelog_test/tree/v0.0.2) (2015-03-04)
|
||||
[Full Changelog](https://github.com/skywinder/changelog_test/compare/v0.0.1...v0.0.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Here is a test hotfix should appear in v.0.0.2 [\#2](https://github.com/skywinder/changelog_test/pull/2) ([skywinder](https://github.com/skywinder))
|
||||
|
||||
## [v0.0.1](https://github.com/skywinder/changelog_test/tree/v0.0.1) (2015-03-02)
|
||||
|
||||
|
||||
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
||||
@@ -5,18 +5,18 @@ require "octokit"
|
||||
require "faraday-http-cache"
|
||||
require "logger"
|
||||
require "active_support"
|
||||
require "active_support/core_ext/object/blank"
|
||||
require "json"
|
||||
require "multi_json"
|
||||
require "benchmark"
|
||||
|
||||
require "github_changelog_generator/helper"
|
||||
require "github_changelog_generator/options"
|
||||
require "github_changelog_generator/parser"
|
||||
require "github_changelog_generator/parser_file"
|
||||
require "github_changelog_generator/generator/generator"
|
||||
require "github_changelog_generator/version"
|
||||
require "github_changelog_generator/reader"
|
||||
require_relative "github_changelog_generator/helper"
|
||||
require_relative "github_changelog_generator/parser"
|
||||
require_relative "github_changelog_generator/parser_file"
|
||||
require_relative "github_changelog_generator/generator/generator"
|
||||
require_relative "github_changelog_generator/version"
|
||||
require_relative "github_changelog_generator/reader"
|
||||
require_relative "github_changelog_generator/hash"
|
||||
require_relative "github_changelog_generator/array"
|
||||
|
||||
# The main module, where placed all classes (now, at least)
|
||||
module GitHubChangelogGenerator
|
||||
@@ -34,10 +34,14 @@ module GitHubChangelogGenerator
|
||||
def run
|
||||
log = @generator.compound_changelog
|
||||
|
||||
output_filename = @options[:output].to_s
|
||||
File.open(output_filename, "wb") { |file| file.write(log) }
|
||||
output_filename = (@options[:output]).to_s
|
||||
File.open(output_filename, "w") { |file| file.write(log) }
|
||||
puts "Done!"
|
||||
puts "Generated log placed in #{Dir.pwd}/#{output_filename}"
|
||||
end
|
||||
end
|
||||
|
||||
if __FILE__ == $PROGRAM_NAME
|
||||
GitHubChangelogGenerator::ChangelogGenerator.new.run
|
||||
end
|
||||
end
|
||||
|
||||
14
lib/github_changelog_generator/array.rb
Normal file
14
lib/github_changelog_generator/array.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
class Array
|
||||
def stringify_keys_deep!
|
||||
new_ar = []
|
||||
each do |value|
|
||||
new_value = value
|
||||
if value.is_a?(Hash) || value.is_a?(Array)
|
||||
new_value = value.stringify_keys_deep!
|
||||
end
|
||||
new_ar << new_value
|
||||
end
|
||||
new_ar
|
||||
end
|
||||
end
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../octo_fetcher"
|
||||
require_relative "generator_generation"
|
||||
require_relative "generator_fetcher"
|
||||
@@ -12,7 +11,7 @@ module GitHubChangelogGenerator
|
||||
end
|
||||
|
||||
class Generator
|
||||
attr_accessor :options, :filtered_tags, :github, :tag_section_mapping, :sorted_tags
|
||||
attr_accessor :options, :filtered_tags, :github, :tag_section_mapping
|
||||
|
||||
# A Generator responsible for all logic, related with change log generation from ready-to-parse issues
|
||||
#
|
||||
@@ -36,17 +35,16 @@ module GitHubChangelogGenerator
|
||||
detect_actual_closed_dates(@issues + @pull_requests)
|
||||
end
|
||||
|
||||
ENCAPSULATED_CHARACTERS = %w(< > * _ \( \) [ ] #)
|
||||
|
||||
# Encapsulate characters to make Markdown look as expected.
|
||||
# Encapsulate characters to make markdown look as expected.
|
||||
#
|
||||
# @param [String] string
|
||||
# @return [String] encapsulated input string
|
||||
def encapsulate_string(string)
|
||||
string = string.gsub('\\', '\\\\')
|
||||
string.gsub! '\\', '\\\\'
|
||||
|
||||
ENCAPSULATED_CHARACTERS.each do |char|
|
||||
string = string.gsub(char, "\\#{char}")
|
||||
encpas_chars = %w(< > * _ \( \) [ ] #)
|
||||
encpas_chars.each do |char|
|
||||
string.gsub! char, "\\#{char}"
|
||||
end
|
||||
|
||||
string
|
||||
@@ -57,23 +55,14 @@ module GitHubChangelogGenerator
|
||||
# @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 of the newer tag. Could be nil for `Unreleased` section
|
||||
# @param [Hash, nil] older_tag Older tag, used for the links. Could be nil for last tag.
|
||||
# @param [String] older_tag_name Older tag, used for the links. Could be nil for last tag.
|
||||
# @return [String] Ready and parsed section
|
||||
def create_log_for_tag(pull_requests, issues, newer_tag, older_tag = nil)
|
||||
def create_log_for_tag(pull_requests, issues, newer_tag, older_tag_name = nil)
|
||||
newer_tag_link, newer_tag_name, newer_tag_time = detect_link_tag_time(newer_tag)
|
||||
|
||||
github_site = options[:github_site] || "https://github.com"
|
||||
project_url = "#{github_site}/#{options[:user]}/#{options[:project]}"
|
||||
|
||||
# If the older tag is nil, go back in time from the latest tag and find
|
||||
# the SHA for the first commit.
|
||||
older_tag_name =
|
||||
if older_tag.nil?
|
||||
@fetcher.commits_before(newer_tag_time).last["sha"]
|
||||
else
|
||||
older_tag["name"]
|
||||
end
|
||||
|
||||
log = generate_header(newer_tag_name, newer_tag_link, newer_tag_time, older_tag_name, project_url)
|
||||
|
||||
if options[:issues]
|
||||
@@ -81,7 +70,7 @@ module GitHubChangelogGenerator
|
||||
log += issues_to_log(issues, pull_requests)
|
||||
end
|
||||
|
||||
if options[:pulls] && options[:add_pr_wo_labels]
|
||||
if options[:pulls]
|
||||
# Generate pull requests:
|
||||
log += generate_sub_section(pull_requests, options[:merge_prefix])
|
||||
end
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module GitHubChangelogGenerator
|
||||
class Generator
|
||||
MAX_THREAD_NUMBER = 25
|
||||
MAX_THREAD_NUMBER = 1
|
||||
|
||||
# Fetch event for issues and pull requests
|
||||
# @return [Array] array of fetched issues
|
||||
@@ -78,7 +77,7 @@ module GitHubChangelogGenerator
|
||||
issue["actual_date"] = commit["commit"]["author"]["date"]
|
||||
|
||||
# issue['actual_date'] = commit['author']['date']
|
||||
rescue StandardError
|
||||
rescue
|
||||
puts "Warning: Can't fetch commit #{event['commit_id']}. It is probably referenced from another repo."
|
||||
issue["actual_date"] = issue["closed_at"]
|
||||
end
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module GitHubChangelogGenerator
|
||||
class Generator
|
||||
# Main function to start change log generation
|
||||
@@ -21,15 +20,12 @@ module GitHubChangelogGenerator
|
||||
|
||||
log += File.read(options[:base]) if File.file?(options[:base])
|
||||
|
||||
credit_line = "\n\n\\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*"
|
||||
log.gsub!(credit_line, "") # Remove old credit lines
|
||||
log += credit_line
|
||||
|
||||
log += "\n\n\\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*"
|
||||
@log = log
|
||||
end
|
||||
|
||||
# @param [Array] issues List of issues on sub-section
|
||||
# @param [String] prefix Name of sub-section
|
||||
# @param [String] prefix Nae of sub-section
|
||||
# @return [String] Generate ready-to-go sub-section
|
||||
def generate_sub_section(issues, prefix)
|
||||
log = ""
|
||||
@@ -68,7 +64,7 @@ module GitHubChangelogGenerator
|
||||
log += 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"
|
||||
"## [#{newer_tag_name}](#{release_url}) (#{time_string})\n"
|
||||
end
|
||||
|
||||
if options[:compare_link] && older_tag_link
|
||||
@@ -85,21 +81,22 @@ module GitHubChangelogGenerator
|
||||
def generate_log_between_tags(older_tag, newer_tag)
|
||||
filtered_issues, filtered_pull_requests = filter_issues_for_tags(newer_tag, older_tag)
|
||||
|
||||
older_tag_name = older_tag.nil? ? detect_since_tag : older_tag["name"]
|
||||
|
||||
if newer_tag.nil? && filtered_issues.empty? && filtered_pull_requests.empty?
|
||||
# do not generate empty unreleased section
|
||||
return ""
|
||||
end
|
||||
|
||||
create_log_for_tag(filtered_pull_requests, filtered_issues, newer_tag, older_tag)
|
||||
create_log_for_tag(filtered_pull_requests, filtered_issues, newer_tag, older_tag_name)
|
||||
end
|
||||
|
||||
# Filters issues and pull requests based on, respectively, `closed_at` and `merged_at`
|
||||
# timestamp fields.
|
||||
# Apply all filters to issues and pull requests
|
||||
#
|
||||
# @return [Array] filtered issues and pull requests
|
||||
def filter_issues_for_tags(newer_tag, older_tag)
|
||||
filtered_pull_requests = delete_by_time(@pull_requests, "merged_at", older_tag, newer_tag)
|
||||
filtered_issues = delete_by_time(@issues, "closed_at", older_tag, newer_tag)
|
||||
filtered_pull_requests = delete_by_time(@pull_requests, "actual_date", older_tag, newer_tag)
|
||||
filtered_issues = delete_by_time(@issues, "actual_date", older_tag, newer_tag)
|
||||
|
||||
newer_tag_name = newer_tag.nil? ? nil : newer_tag["name"]
|
||||
|
||||
@@ -129,9 +126,8 @@ module GitHubChangelogGenerator
|
||||
def generate_unreleased_section
|
||||
log = ""
|
||||
if options[:unreleased]
|
||||
start_tag = filtered_tags[0] || sorted_tags.last
|
||||
unreleased_log = generate_log_between_tags(start_tag, nil)
|
||||
log += unreleased_log if unreleased_log
|
||||
unreleased_log = generate_log_between_tags(filtered_tags[0], nil)
|
||||
log += unreleased_log if unreleased_log
|
||||
end
|
||||
log
|
||||
end
|
||||
@@ -147,25 +143,13 @@ module GitHubChangelogGenerator
|
||||
encapsulated_title = encapsulate_string issue["title"]
|
||||
|
||||
title_with_number = "#{encapsulated_title} [\\##{issue['number']}](#{issue['html_url']})"
|
||||
if options[:issue_line_labels].present?
|
||||
title_with_number = "#{title_with_number}#{line_labels_for(issue)}"
|
||||
end
|
||||
issue_line_with_user(title_with_number, issue)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
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
|
||||
|
||||
def issue_line_with_user(line, issue)
|
||||
return line if !options[:author] || issue["pull_request"].nil?
|
||||
return line if !options[:author] || issue.pull_request.nil?
|
||||
|
||||
user = issue["user"]
|
||||
return "#{line} ({Null user})" unless user
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module GitHubChangelogGenerator
|
||||
class Generator
|
||||
# delete all labels with labels from options[:exclude_labels] array
|
||||
@@ -73,8 +72,6 @@ module GitHubChangelogGenerator
|
||||
# in case if not tags specified - return unchanged array
|
||||
return issues if older_tag.nil? && newer_tag.nil?
|
||||
|
||||
older_tag = ensure_older_tag(older_tag, newer_tag)
|
||||
|
||||
newer_tag_time = newer_tag && get_time_of_tag(newer_tag)
|
||||
older_tag_time = older_tag && get_time_of_tag(older_tag)
|
||||
|
||||
@@ -95,14 +92,6 @@ module GitHubChangelogGenerator
|
||||
end
|
||||
end
|
||||
|
||||
def ensure_older_tag(older_tag, newer_tag)
|
||||
return older_tag if older_tag
|
||||
idx = sorted_tags.index { |t| t["name"] == newer_tag["name"] }
|
||||
# skip if we are already at the oldest element
|
||||
return if idx == sorted_tags.size - 1
|
||||
sorted_tags[idx - 1]
|
||||
end
|
||||
|
||||
def tag_older_new_tag?(newer_tag_time, time)
|
||||
tag_in_range_new = if newer_tag_time.nil?
|
||||
true
|
||||
@@ -126,17 +115,19 @@ module GitHubChangelogGenerator
|
||||
# @return [Array] filtered array of issues
|
||||
def include_issues_by_labels(issues)
|
||||
filtered_issues = filter_by_include_labels(issues)
|
||||
filtered_issues = filter_wo_labels(filtered_issues)
|
||||
filtered_issues |= filter_wo_labels(issues)
|
||||
filtered_issues
|
||||
end
|
||||
|
||||
# @return [Array] issues without labels or empty array if add_issues_wo_labels is false
|
||||
def filter_wo_labels(issues)
|
||||
if options[:add_issues_wo_labels]
|
||||
issues
|
||||
else
|
||||
issues.select { |issue| issue["labels"].map { |l| l["name"] }.any? }
|
||||
issues_wo_labels = issues.select do |issue|
|
||||
!issue["labels"].map { |l| l["name"] }.any?
|
||||
end
|
||||
return issues_wo_labels
|
||||
end
|
||||
[]
|
||||
end
|
||||
|
||||
def filter_by_include_labels(issues)
|
||||
@@ -196,8 +187,8 @@ module GitHubChangelogGenerator
|
||||
end
|
||||
end
|
||||
|
||||
pull_requests.reject! do |pr|
|
||||
pr["merged_at"].nil?
|
||||
pull_requests.select! do |pr|
|
||||
!pr["merged_at"].nil?
|
||||
end
|
||||
|
||||
pull_requests
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module GitHubChangelogGenerator
|
||||
class Generator
|
||||
# fetch, filter tags, fetch dates and sort them in time order
|
||||
@@ -7,48 +6,31 @@ module GitHubChangelogGenerator
|
||||
detect_since_tag
|
||||
detect_due_tag
|
||||
|
||||
all_tags = @fetcher.get_all_tags
|
||||
all_tags = @fetcher.get_all_tags
|
||||
included_tags = filter_excluded_tags(all_tags)
|
||||
|
||||
fetch_tags_dates(all_tags) # Creates a Hash @tag_times_hash
|
||||
all_sorted_tags = sort_tags_by_date(all_tags)
|
||||
sorted_tags = sort_tags_by_date(included_tags)
|
||||
@filtered_tags = get_filtered_tags(included_tags)
|
||||
|
||||
@sorted_tags = filter_excluded_tags(all_sorted_tags)
|
||||
@filtered_tags = get_filtered_tags(@sorted_tags)
|
||||
|
||||
# Because we need to properly create compare links, we need a sorted list
|
||||
# of all filtered tags (including the excluded ones). We'll exclude those
|
||||
# tags from section headers inside the mapping function.
|
||||
section_tags = get_filtered_tags(all_sorted_tags)
|
||||
|
||||
@tag_section_mapping = build_tag_section_mapping(section_tags, @filtered_tags)
|
||||
@tag_section_mapping = build_tag_section_mapping(@filtered_tags, sorted_tags)
|
||||
|
||||
@filtered_tags
|
||||
end
|
||||
|
||||
# @param [Array] section_tags are the tags that need a subsection output
|
||||
# @param [Array] filtered_tags is the list of filtered tags ordered from newest -> oldest
|
||||
# @param [Array] filtered_tags are the tags that need a subsection output
|
||||
# @param [Array] all_tags is the list of all tags ordered from newest -> oldest
|
||||
# @return [Hash] key is the tag to output, value is an array of [Left Tag, Right Tag]
|
||||
# PRs to include in this section will be >= [Left Tag Date] and <= [Right Tag Date]
|
||||
# rubocop:disable Style/For - for allows us to be more concise
|
||||
def build_tag_section_mapping(section_tags, filtered_tags)
|
||||
def build_tag_section_mapping(filtered_tags, all_tags)
|
||||
tag_mapping = {}
|
||||
for i in 0..(section_tags.length - 1)
|
||||
tag = section_tags[i]
|
||||
|
||||
# Don't create section header for the "since" tag
|
||||
next if @since_tag && tag["name"] == @since_tag
|
||||
|
||||
# Don't create a section header for the first tag in between_tags
|
||||
next if options[:between_tags] && tag == section_tags.last
|
||||
|
||||
# Don't create a section header for excluded tags
|
||||
next unless filtered_tags.include?(tag)
|
||||
|
||||
older_tag = section_tags[i + 1]
|
||||
filtered_tags.each do |tag|
|
||||
older_tag_idx = all_tags.index(tag) + 1
|
||||
older_tag = all_tags[older_tag_idx]
|
||||
tag_mapping[tag] = [older_tag, tag]
|
||||
end
|
||||
tag_mapping
|
||||
end
|
||||
# rubocop:enable Style/For
|
||||
|
||||
# Sort all tags by date, newest to oldest
|
||||
def sort_tags_by_date(tags)
|
||||
@@ -113,12 +95,13 @@ module GitHubChangelogGenerator
|
||||
sections.first["version"] if sections && sections.any?
|
||||
end
|
||||
|
||||
# Return tags after filtering tags in lists provided by option: --exclude-tags
|
||||
# Return tags after filtering tags in lists provided by option: --between-tags & --exclude-tags
|
||||
#
|
||||
# @return [Array]
|
||||
def get_filtered_tags(all_tags)
|
||||
filtered_tags = filter_since_tag(all_tags)
|
||||
filter_due_tag(filtered_tags)
|
||||
filtered_tags = filter_due_tag(filtered_tags)
|
||||
filter_between_tags(filtered_tags)
|
||||
end
|
||||
|
||||
# @param [Array] all_tags all tags
|
||||
@@ -130,7 +113,7 @@ module GitHubChangelogGenerator
|
||||
if all_tags.map { |t| t["name"] }.include? tag
|
||||
idx = all_tags.index { |t| t["name"] == tag }
|
||||
filtered_tags = if idx > 0
|
||||
all_tags[0..idx]
|
||||
all_tags[0..idx - 1]
|
||||
else
|
||||
[]
|
||||
end
|
||||
@@ -161,6 +144,23 @@ module GitHubChangelogGenerator
|
||||
filtered_tags
|
||||
end
|
||||
|
||||
# @param [Array] all_tags all tags
|
||||
# @return [Array] filtered tags according :between_tags option
|
||||
def filter_between_tags(all_tags)
|
||||
filtered_tags = all_tags
|
||||
tag_names = filtered_tags.map { |ft| ft["name"] }
|
||||
|
||||
if options[:between_tags]
|
||||
options[:between_tags].each do |tag|
|
||||
unless tag_names.include?(tag)
|
||||
Helper.log.warn "Warning: can't find tag #{tag}, specified with --between-tags option."
|
||||
end
|
||||
end
|
||||
filtered_tags = all_tags.select { |tag| options[:between_tags].include?(tag["name"]) }
|
||||
end
|
||||
filtered_tags
|
||||
end
|
||||
|
||||
# @param [Array] all_tags all tags
|
||||
# @return [Array] filtered tags according :exclude_tags or :exclude_tags_regex option
|
||||
def filter_excluded_tags(all_tags)
|
||||
@@ -177,19 +177,18 @@ module GitHubChangelogGenerator
|
||||
|
||||
def apply_exclude_tags(all_tags)
|
||||
if options[:exclude_tags].is_a?(Regexp)
|
||||
filter_tags_with_regex(all_tags, options[:exclude_tags], "--exclude-tags")
|
||||
filter_tags_with_regex(all_tags, options[:exclude_tags])
|
||||
else
|
||||
filter_exact_tags(all_tags)
|
||||
end
|
||||
end
|
||||
|
||||
def apply_exclude_tags_regex(all_tags)
|
||||
regex = Regexp.new(options[:exclude_tags_regex])
|
||||
filter_tags_with_regex(all_tags, regex, "--exclude-tags-regex")
|
||||
filter_tags_with_regex(all_tags, Regexp.new(options[:exclude_tags_regex]))
|
||||
end
|
||||
|
||||
def filter_tags_with_regex(all_tags, regex, regex_option_name)
|
||||
warn_if_nonmatching_regex(all_tags, regex, regex_option_name)
|
||||
def filter_tags_with_regex(all_tags, regex)
|
||||
warn_if_nonmatching_regex(all_tags)
|
||||
all_tags.reject { |tag| regex =~ tag["name"] }
|
||||
end
|
||||
|
||||
@@ -200,10 +199,11 @@ module GitHubChangelogGenerator
|
||||
all_tags.reject { |tag| options[:exclude_tags].include?(tag["name"]) }
|
||||
end
|
||||
|
||||
def warn_if_nonmatching_regex(all_tags, regex, regex_option_name)
|
||||
unless all_tags.map { |t| t["name"] }.any? { |t| regex =~ t }
|
||||
def warn_if_nonmatching_regex(all_tags)
|
||||
unless all_tags.map { |t| t["name"] }.any? { |t| options[:exclude_tags] =~ t }
|
||||
Helper.log.warn "Warning: unable to reject any tag, using regex "\
|
||||
"#{regex.inspect} in #{regex_option_name} option."
|
||||
"#{options[:exclude_tags].inspect} in --exclude-tags "\
|
||||
"option."
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
16
lib/github_changelog_generator/hash.rb
Normal file
16
lib/github_changelog_generator/hash.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
# frozen_string_literal: true
|
||||
class Hash
|
||||
def stringify_keys_deep!
|
||||
new_hash = {}
|
||||
keys.each do |k|
|
||||
ks = k.respond_to?(:to_s) ? k.to_s : k
|
||||
new_hash[ks] = if values_at(k).first.is_a?(Hash) || values_at(k).first.is_a?(Array)
|
||||
values_at(k).first.send(:stringify_keys_deep!)
|
||||
else
|
||||
values_at(k).first
|
||||
end
|
||||
end
|
||||
|
||||
new_hash
|
||||
end
|
||||
end
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "logger"
|
||||
require "rainbow"
|
||||
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "tmpdir"
|
||||
require "retriable"
|
||||
module GitHubChangelogGenerator
|
||||
# A Fetcher responsible for all requests to GitHub and all basic manipulation with related data
|
||||
# (such as filtering, validating, e.t.c)
|
||||
@@ -10,8 +7,7 @@ module GitHubChangelogGenerator
|
||||
# fetcher = GitHubChangelogGenerator::OctoFetcher.new(options)
|
||||
class OctoFetcher
|
||||
PER_PAGE_NUMBER = 100
|
||||
MAX_THREAD_NUMBER = 25
|
||||
MAX_FORBIDDEN_RETRIES = 100
|
||||
MAX_THREAD_NUMBER = 1
|
||||
CHANGELOG_GITHUB_TOKEN = "CHANGELOG_GITHUB_TOKEN"
|
||||
GH_RATE_LIMIT_EXCEEDED_MSG = "Warning: Can't finish operation: GitHub API rate limit exceeded, change log may be " \
|
||||
"missing some issues. You can limit the number of issues fetched using the `--max-issues NUM` argument."
|
||||
@@ -25,17 +21,16 @@ module GitHubChangelogGenerator
|
||||
# @option options [Boolean] :http_cache Use ActiveSupport::Cache::FileStore to cache http requests
|
||||
# @option options [Boolean] :cache_file If using http_cache, this is the cache file path
|
||||
# @option options [Boolean] :cache_log If using http_cache, this is the cache log file path
|
||||
def initialize(options = {})
|
||||
def initialize(options = {}) # rubocop:disable Metrics/CyclomaticComplexity
|
||||
@options = options || {}
|
||||
@user = @options[:user]
|
||||
@project = @options[:project]
|
||||
@since = @options[:since]
|
||||
@http_cache = @options[:http_cache]
|
||||
if @http_cache
|
||||
@cache_file = @options.fetch(:cache_file) { File.join(Dir.tmpdir, "github-changelog-http-cache") }
|
||||
@cache_log = @options.fetch(:cache_log) { File.join(Dir.tmpdir, "github-changelog-logger.log") }
|
||||
init_cache
|
||||
end
|
||||
@cache_file = @options.fetch(:cache_file, "/tmp/github-changelog-http-cache") if @http_cache
|
||||
@cache_log = @options.fetch(:cache_log, "/tmp/github-changelog-logger.log") if @http_cache
|
||||
init_cache if @http_cache
|
||||
|
||||
@github_token = fetch_github_token
|
||||
|
||||
@request_options = { per_page: PER_PAGE_NUMBER }
|
||||
@@ -43,14 +38,8 @@ module GitHubChangelogGenerator
|
||||
@github_options[:access_token] = @github_token unless @github_token.nil?
|
||||
@github_options[:api_endpoint] = @options[:github_endpoint] unless @options[:github_endpoint].nil?
|
||||
|
||||
configure_octokit_ssl
|
||||
|
||||
@client = Octokit::Client.new(@github_options)
|
||||
end
|
||||
|
||||
def configure_octokit_ssl
|
||||
ca_file = @options[:ssl_ca_file] || ENV["SSL_CA_FILE"] || File.expand_path("../ssl_certs/cacert.pem", __FILE__)
|
||||
Octokit.connection_options = { ssl: { ca_file: ca_file } }
|
||||
client_type = @options[:github_endpoint].nil? ? Octokit::Client : Octokit::EnterpriseAdminClient
|
||||
@client = client_type.new(@github_options)
|
||||
end
|
||||
|
||||
def init_cache
|
||||
@@ -90,7 +79,7 @@ module GitHubChangelogGenerator
|
||||
last_response = client.last_response
|
||||
|
||||
if (last_pg = last_response.rels[:last])
|
||||
querystring_as_hash(last_pg.href)["page"].to_i
|
||||
parse_url_for_vars(last_pg.href)["page"].to_i
|
||||
else
|
||||
1
|
||||
end
|
||||
@@ -112,13 +101,13 @@ module GitHubChangelogGenerator
|
||||
print_empty_line
|
||||
|
||||
if tags.count == 0
|
||||
Helper.log.warn "Warning: Can't find any tags in repo. \
|
||||
Helper.log.warn "Warning: Can't find any tags in repo.\
|
||||
Make sure, that you push tags to remote repo via 'git push --tags'"
|
||||
else
|
||||
Helper.log.info "Found #{tags.count} tags"
|
||||
end
|
||||
# tags are a Sawyer::Resource. Convert to hash
|
||||
tags = tags.map { |h| stringify_keys_deep(h.to_hash) }
|
||||
tags = tags.map { |h| h.to_hash.stringify_keys_deep! }
|
||||
tags
|
||||
end
|
||||
|
||||
@@ -148,7 +137,7 @@ Make sure, that you push tags to remote repo via 'git push --tags'"
|
||||
print_empty_line
|
||||
Helper.log.info "Received issues: #{issues.count}"
|
||||
|
||||
issues = issues.map { |h| stringify_keys_deep(h.to_hash) }
|
||||
issues = issues.map { |h| h.to_hash.stringify_keys_deep! }
|
||||
|
||||
# separate arrays of issues and pull requests:
|
||||
issues.partition do |x|
|
||||
@@ -179,7 +168,7 @@ Make sure, that you push tags to remote repo via 'git push --tags'"
|
||||
print_empty_line
|
||||
|
||||
Helper.log.info "Pull Request count: #{pull_requests.count}"
|
||||
pull_requests = pull_requests.map { |h| stringify_keys_deep(h.to_hash) }
|
||||
pull_requests = pull_requests.map { |h| h.to_hash.stringify_keys_deep! }
|
||||
pull_requests
|
||||
end
|
||||
|
||||
@@ -198,7 +187,7 @@ Make sure, that you push tags to remote repo via 'git push --tags'"
|
||||
iterate_pages(@client, "issue_events", issue["number"], {}) do |new_event|
|
||||
issue["events"].concat(new_event)
|
||||
end
|
||||
issue["events"] = issue["events"].map { |h| stringify_keys_deep(h.to_hash) }
|
||||
issue["events"] = issue["events"].map { |h| h.to_hash.stringify_keys_deep! }
|
||||
print_in_same_line("Fetching events for issues and PR: #{i + 1}/#{issues.count}")
|
||||
i += 1
|
||||
end
|
||||
@@ -220,7 +209,7 @@ Make sure, that you push tags to remote repo via 'git push --tags'"
|
||||
# @return [Time] time of specified tag
|
||||
def fetch_date_of_tag(tag)
|
||||
commit_data = check_github_response { @client.commit(user_project, tag["commit"]["sha"]) }
|
||||
commit_data = stringify_keys_deep(commit_data.to_hash)
|
||||
commit_data = commit_data.to_hash.stringify_keys_deep!
|
||||
|
||||
commit_data["commit"]["committer"]["date"]
|
||||
end
|
||||
@@ -231,129 +220,62 @@ Make sure, that you push tags to remote repo via 'git push --tags'"
|
||||
def fetch_commit(event)
|
||||
check_github_response do
|
||||
commit = @client.commit(user_project, event["commit_id"])
|
||||
commit = stringify_keys_deep(commit.to_hash)
|
||||
commit = commit.to_hash.stringify_keys_deep!
|
||||
commit
|
||||
end
|
||||
end
|
||||
|
||||
# Fetch all commits before certain point
|
||||
#
|
||||
# @return [String]
|
||||
def commits_before(start_time)
|
||||
commits = []
|
||||
iterate_pages(@client, "commits_before", start_time.to_datetime.to_s) do |new_commits|
|
||||
commits.concat(new_commits)
|
||||
end
|
||||
commits
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def stringify_keys_deep(indata)
|
||||
case indata
|
||||
when Array
|
||||
indata.map do |value|
|
||||
stringify_keys_deep(value)
|
||||
end
|
||||
when Hash
|
||||
indata.each_with_object({}) do |(k, v), output|
|
||||
output[k.to_s] = stringify_keys_deep(v)
|
||||
end
|
||||
else
|
||||
indata
|
||||
end
|
||||
end
|
||||
|
||||
MovedPermanentlyError = Class.new(RuntimeError)
|
||||
|
||||
# Iterates through all pages until there are no more :next pages to follow
|
||||
# yields the result per page
|
||||
#
|
||||
# @param [Octokit::Client] client
|
||||
# @param [String] method (eg. 'tags')
|
||||
#
|
||||
# @yield [Sawyer::Resource] An OctoKit-provided response (which can be empty)
|
||||
#
|
||||
# @return [Integer] total number of pages
|
||||
def iterate_pages(client, method, *args)
|
||||
request_opts = extract_request_args(args)
|
||||
args.push(@request_options.merge(request_opts))
|
||||
|
||||
number_of_pages = 1
|
||||
|
||||
check_github_response { client.send(method, user_project, *args) }
|
||||
last_response = client.last_response
|
||||
if last_response.status == 301
|
||||
raise MovedPermanentlyError, last_response.data[:url]
|
||||
if args.size == 1 && args.first.is_a?(Hash)
|
||||
request_options = args.delete_at(0)
|
||||
elsif args.size > 1 && args.last.is_a?(Hash)
|
||||
request_options = args.delete_at(args.length - 1)
|
||||
end
|
||||
|
||||
yield(last_response.data)
|
||||
args.push(@request_options.merge(request_options))
|
||||
|
||||
pages = 1
|
||||
|
||||
check_github_response do
|
||||
client.send(method, user_project, *args)
|
||||
end
|
||||
last_response = client.last_response
|
||||
|
||||
yield last_response.data
|
||||
|
||||
until (next_one = last_response.rels[:next]).nil?
|
||||
number_of_pages += 1
|
||||
pages += 1
|
||||
|
||||
last_response = check_github_response { next_one.get }
|
||||
yield(last_response.data)
|
||||
yield last_response.data
|
||||
end
|
||||
|
||||
number_of_pages
|
||||
end
|
||||
|
||||
def extract_request_args(args)
|
||||
if args.size == 1 && args.first.is_a?(Hash)
|
||||
args.delete_at(0)
|
||||
elsif args.size > 1 && args.last.is_a?(Hash)
|
||||
args.delete_at(args.length - 1)
|
||||
else
|
||||
{}
|
||||
end
|
||||
pages
|
||||
end
|
||||
|
||||
# This is wrapper with rescue block
|
||||
#
|
||||
# @return [Object] returns exactly the same, what you put in the block, but wrap it with begin-rescue block
|
||||
def check_github_response
|
||||
Retriable.retriable(retry_options) do
|
||||
yield
|
||||
end
|
||||
rescue MovedPermanentlyError => e
|
||||
Helper.log.error("#{e.class}: #{e.message}")
|
||||
sys_abort("The repository has moved, please update your configuration")
|
||||
rescue Octokit::Forbidden => e
|
||||
Helper.log.error("#{e.class}: #{e.message}")
|
||||
sys_abort("Exceeded retry limit")
|
||||
rescue Octokit::Unauthorized => e
|
||||
Helper.log.error("#{e.class}: #{e.message}")
|
||||
sys_abort("Error: wrong GitHub token")
|
||||
end
|
||||
|
||||
# Exponential backoff
|
||||
def retry_options
|
||||
{
|
||||
on: [Octokit::Forbidden],
|
||||
tries: MAX_FORBIDDEN_RETRIES,
|
||||
base_interval: sleep_base_interval,
|
||||
multiplier: 1.0,
|
||||
rand_factor: 0.0,
|
||||
on_retry: retry_callback
|
||||
}
|
||||
end
|
||||
|
||||
def sleep_base_interval
|
||||
1.0
|
||||
end
|
||||
|
||||
def retry_callback
|
||||
proc do |exception, try, elapsed_time, next_interval|
|
||||
Helper.log.warn("RETRY - #{exception.class}: '#{exception.message}'")
|
||||
Helper.log.warn("#{try} tries in #{elapsed_time} seconds and #{next_interval} seconds until the next try")
|
||||
begin
|
||||
value = yield
|
||||
rescue Octokit::Unauthorized => e
|
||||
Helper.log.error e.message
|
||||
abort "Error: wrong GitHub token"
|
||||
rescue Octokit::Forbidden => e
|
||||
Helper.log.warn e.message
|
||||
Helper.log.warn GH_RATE_LIMIT_EXCEEDED_MSG
|
||||
Helper.log.warn @client.rate_limit
|
||||
end
|
||||
end
|
||||
|
||||
def sys_abort(msg)
|
||||
abort(msg)
|
||||
value
|
||||
end
|
||||
|
||||
# Print specified line on the same string
|
||||
@@ -385,12 +307,16 @@ Make sure, that you push tags to remote repo via 'git push --tags'"
|
||||
"#{@options[:user]}/#{@options[:project]}"
|
||||
end
|
||||
|
||||
# Returns Hash of all querystring variables in given URI.
|
||||
# Parses a URI and returns a hash of all GET variables
|
||||
#
|
||||
# @param [String] uri eg. https://api.github.com/repositories/43914960/tags?page=37&foo=1
|
||||
# @return [Hash] of all GET variables. eg. { 'page' => 37, 'foo' => 1 }
|
||||
def querystring_as_hash(uri)
|
||||
Hash[URI.decode_www_form(URI(uri).query || "")]
|
||||
def parse_url_for_vars(uri)
|
||||
URI(uri).query.split("&").each_with_object({}) do |get_var, params|
|
||||
k, v = get_var.split("=")
|
||||
params[k] = v
|
||||
params
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "delegate"
|
||||
module GitHubChangelogGenerator
|
||||
class Options < SimpleDelegator
|
||||
UnsupportedOptionError = Class.new(ArgumentError)
|
||||
|
||||
KNOWN_OPTIONS = %i[
|
||||
add_issues_wo_labels
|
||||
add_pr_wo_labels
|
||||
author
|
||||
base
|
||||
between_tags
|
||||
bug_labels
|
||||
bug_prefix
|
||||
cache_file
|
||||
cache_log
|
||||
compare_link
|
||||
date_format
|
||||
due_tag
|
||||
enhancement_labels
|
||||
enhancement_prefix
|
||||
exclude_labels
|
||||
exclude_tags
|
||||
exclude_tags_regex
|
||||
filter_issues_by_milestone
|
||||
frontmatter
|
||||
future_release
|
||||
git_remote
|
||||
github_endpoint
|
||||
github_site
|
||||
header
|
||||
http_cache
|
||||
include_labels
|
||||
issue_prefix
|
||||
issue_line_labels
|
||||
issues
|
||||
max_issues
|
||||
merge_prefix
|
||||
output
|
||||
project
|
||||
pulls
|
||||
release_branch
|
||||
release_url
|
||||
simple_list
|
||||
since_tag
|
||||
ssl_ca_file
|
||||
token
|
||||
unreleased
|
||||
unreleased_label
|
||||
unreleased_only
|
||||
user
|
||||
usernames_as_github_logins
|
||||
verbose
|
||||
]
|
||||
|
||||
def initialize(values)
|
||||
super(values)
|
||||
unsupported_options.any? && raise(UnsupportedOptionError, unsupported_options.inspect)
|
||||
end
|
||||
|
||||
def []=(key, val)
|
||||
supported_option?(key) || raise(UnsupportedOptionError, key.inspect)
|
||||
values[key] = val
|
||||
end
|
||||
|
||||
def to_hash
|
||||
values
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def values
|
||||
__getobj__
|
||||
end
|
||||
|
||||
def unsupported_options
|
||||
values.keys - KNOWN_OPTIONS
|
||||
end
|
||||
|
||||
def supported_option?(key)
|
||||
KNOWN_OPTIONS.include?(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,6 +1,5 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "optparse"
|
||||
require "pp"
|
||||
require_relative "version"
|
||||
@@ -14,10 +13,7 @@ module GitHubChangelogGenerator
|
||||
ParserFile.new(options).parse!
|
||||
|
||||
parser = setup_parser(options)
|
||||
begin parser.parse!
|
||||
rescue OptionParser::InvalidOption => e
|
||||
abort [e, parser].join("\n")
|
||||
end
|
||||
parser.parse!
|
||||
|
||||
fetch_user_and_project(options)
|
||||
|
||||
@@ -46,7 +42,7 @@ module GitHubChangelogGenerator
|
||||
|
||||
# setup parsing options
|
||||
def self.setup_parser(options)
|
||||
parser = OptionParser.new do |opts| # rubocop:disable Metrics/BlockLength
|
||||
parser = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: github_changelog_generator [options]"
|
||||
opts.on("-u", "--user [USER]", "Username of the owner of target GitHub repo") do |last|
|
||||
options[:user] = last
|
||||
@@ -111,7 +107,7 @@ module GitHubChangelogGenerator
|
||||
opts.on("--[no-]unreleased", "Add to log unreleased closed issues. Default is true") do |v|
|
||||
options[:unreleased] = v
|
||||
end
|
||||
opts.on("--unreleased-label [label]", "Setup custom label for unreleased closed issues section. Default is \"**Unreleased:**\"") do |v|
|
||||
opts.on("--unreleased-label [label]", "Add to log unreleased closed issues. Default is true") do |v|
|
||||
options[:unreleased_label] = v
|
||||
end
|
||||
opts.on("--[no-]compare-link", "Include compare link (Full Changelog) between older version and newer version. Default is true") do |v|
|
||||
@@ -129,8 +125,8 @@ module GitHubChangelogGenerator
|
||||
opts.on("--enhancement-labels x,y,z", Array, 'Issues with the specified labels will be always added to "Implemented enhancements" section. Default is \'enhancement,Enhancement\'') do |list|
|
||||
options[:enhancement_labels] = list
|
||||
end
|
||||
opts.on("--issue-line-labels x,y,z", Array, 'The specified labels will be shown in brackets next to each matching issue. Use "ALL" to show all labels. Default is [].') do |list|
|
||||
options[:issue_line_labels] = list
|
||||
opts.on("--between-tags x,y,z", Array, "Change log will be filled only between specified tags") do |list|
|
||||
options[:between_tags] = list
|
||||
end
|
||||
opts.on("--exclude-tags x,y,z", Array, "Change log will exclude specified tags") do |list|
|
||||
options[:exclude_tags] = list
|
||||
@@ -168,15 +164,12 @@ module GitHubChangelogGenerator
|
||||
opts.on("--[no-]http-cache", "Use HTTP Cache to cache Github API requests (useful for large repos) Default is true.") do |http_cache|
|
||||
options[:http_cache] = http_cache
|
||||
end
|
||||
opts.on("--cache-file [CACHE-FILE]", "Filename to use for cache. Default is github-changelog-http-cache in a temporary directory.") do |cache_file|
|
||||
opts.on("--cache-file [CACHE-FILE]", "Filename to use for cache. Default is /tmp/github-changelog-http-cache") do |cache_file|
|
||||
options[:cache_file] = cache_file
|
||||
end
|
||||
opts.on("--cache-log [CACHE-LOG]", "Filename to use for cache log. Default is github-changelog-logger.log in a temporary directory.") do |cache_log|
|
||||
opts.on("--cache-log [CACHE-LOG]", "Filename to use for cache log. Default is /tmp/github-changelog-logger.log") do |cache_log|
|
||||
options[:cache_log] = cache_log
|
||||
end
|
||||
opts.on("--ssl-ca-file [PATH]", "Path to cacert.pem file. Default is a bundled lib/github_changelog_generator/ssl_certs/cacert.pem. Respects SSL_CA_PATH.") do |ssl_ca_file|
|
||||
options[:ssl_ca_file] = ssl_ca_file
|
||||
end
|
||||
opts.on("--[no-]verbose", "Run verbosely. Default is true") do |v|
|
||||
options[:verbose] = v
|
||||
end
|
||||
@@ -194,7 +187,9 @@ module GitHubChangelogGenerator
|
||||
|
||||
# @return [Hash] Default options
|
||||
def self.default_options
|
||||
Options.new(
|
||||
{
|
||||
tag1: nil,
|
||||
tag2: nil,
|
||||
date_format: "%Y-%m-%d",
|
||||
output: "CHANGELOG.md",
|
||||
base: "HISTORY.md",
|
||||
@@ -207,13 +202,11 @@ module GitHubChangelogGenerator
|
||||
unreleased: true,
|
||||
unreleased_label: "Unreleased",
|
||||
compare_link: true,
|
||||
enhancement_labels: ["enhancement", "Enhancement", "Type: Enhancement"],
|
||||
bug_labels: ["bug", "Bug", "Type: Bug"],
|
||||
exclude_labels: ["duplicate", "question", "invalid", "wontfix", "Duplicate", "Question", "Invalid", "Wontfix", "Meta: Exclude From Changelog"],
|
||||
issue_line_labels: [],
|
||||
enhancement_labels: %w(enhancement Enhancement),
|
||||
bug_labels: %w(bug Bug),
|
||||
exclude_labels: %w(duplicate question invalid wontfix Duplicate Question Invalid Wontfix),
|
||||
max_issues: nil,
|
||||
simple_list: false,
|
||||
ssl_ca_file: nil,
|
||||
verbose: true,
|
||||
header: "# Change Log",
|
||||
merge_prefix: "**Merged pull requests:**",
|
||||
@@ -221,8 +214,10 @@ module GitHubChangelogGenerator
|
||||
bug_prefix: "**Fixed bugs:**",
|
||||
enhancement_prefix: "**Implemented enhancements:**",
|
||||
git_remote: "origin",
|
||||
http_cache: true
|
||||
)
|
||||
http_cache: true,
|
||||
cache_file: "/tmp/github-changelog-http-cache",
|
||||
cache_log: "/tmp/github-changelog-logger.log"
|
||||
}
|
||||
end
|
||||
|
||||
# If `:user` or `:project` not set in options, try setting them
|
||||
@@ -277,7 +272,7 @@ module GitHubChangelogGenerator
|
||||
|
||||
begin
|
||||
param = match[2].nil?
|
||||
rescue StandardError
|
||||
rescue
|
||||
puts "Can't detect user and name from first parameter: '#{arg0}' -> exit'"
|
||||
return
|
||||
end
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "pathname"
|
||||
|
||||
module GitHubChangelogGenerator
|
||||
@@ -48,7 +47,7 @@ module GitHubChangelogGenerator
|
||||
return if non_configuration_line?(line)
|
||||
option_name, value = extract_pair(line)
|
||||
@options[option_key_for(option_name)] = convert_value(value, option_name)
|
||||
rescue StandardError
|
||||
rescue
|
||||
raise ParserError, "Failed on line ##{line_number}: \"#{line.gsub(/[\n\r]+/, '')}\""
|
||||
end
|
||||
|
||||
@@ -63,11 +62,11 @@ module GitHubChangelogGenerator
|
||||
# @return [Array<Symbol, String>]
|
||||
def extract_pair(line)
|
||||
key, value = line.split("=", 2)
|
||||
[key.tr("-", "_").to_sym, value.gsub(/[\n\r]+/, "")]
|
||||
[key.sub("-", "_").to_sym, value.gsub(/[\n\r]+/, "")]
|
||||
end
|
||||
|
||||
KNOWN_ARRAY_KEYS = %i[exclude_labels include_labels bug_labels
|
||||
enhancement_labels issue_line_labels between_tags exclude_tags]
|
||||
KNOWN_ARRAY_KEYS = [:exclude_labels, :include_labels, :bug_labels,
|
||||
:enhancement_labels, :between_tags, :exclude_tags]
|
||||
KNOWN_INTEGER_KEYS = [:max_issues]
|
||||
|
||||
def convert_value(value, option_name)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Author:: Enrico Stahn <mail@enricostahn.com>
|
||||
#
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rake"
|
||||
require "rake/tasklib"
|
||||
require "github_changelog_generator"
|
||||
@@ -8,7 +7,7 @@ module GitHubChangelogGenerator
|
||||
class RakeTask < ::Rake::TaskLib
|
||||
include ::Rake::DSL if defined?(::Rake::DSL)
|
||||
|
||||
OPTIONS = %w[ user project token date_format output
|
||||
OPTIONS = %w( user project token date_format output
|
||||
bug_prefix enhancement_prefix issue_prefix
|
||||
header merge_prefix issues
|
||||
add_issues_wo_labels add_pr_wo_labels
|
||||
@@ -19,7 +18,7 @@ module GitHubChangelogGenerator
|
||||
between_tags exclude_tags exclude_tags_regex since_tag max_issues
|
||||
github_site github_endpoint simple_list
|
||||
future_release release_branch verbose release_url
|
||||
base ]
|
||||
base )
|
||||
|
||||
OPTIONS.each do |o|
|
||||
attr_accessor o.to_sym
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module GitHubChangelogGenerator
|
||||
VERSION = "1.15.0-alpha"
|
||||
VERSION = "1.13.1"
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.\" generated with Ronn/v0.7.3
|
||||
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||
.
|
||||
.TH "GIT\-GENERATE\-CHANGELOG" "1" "December 2016" "" ""
|
||||
.TH "GIT\-GENERATE\-CHANGELOG" "1" "October 2015" "" ""
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBgit\-generate\-changelog\fR \- Generate changelog from github
|
||||
@@ -73,12 +73,6 @@ Setup custom label for closed\-issues section\. Default is "\fBClosed issues:\fR
|
||||
Setup custom header label\. Default is "# Change Log"
|
||||
.
|
||||
.P
|
||||
\-\-front\-matter [JSON]
|
||||
.
|
||||
.P
|
||||
Add YAML front matter\. Formatted as JSON because it\'s easier to add on the command line
|
||||
.
|
||||
.P
|
||||
\-\-pr\-label [LABEL]
|
||||
.
|
||||
.P
|
||||
@@ -121,12 +115,6 @@ Use milestone to detect when issue was resolved\. Default is true
|
||||
Add author of pull\-request in the end\. Default is true
|
||||
.
|
||||
.P
|
||||
\-\-usernames\-as\-github\-logins
|
||||
.
|
||||
.P
|
||||
Use GitHub tags instead of Markdown links for the author of an issue or pull\-request\.
|
||||
.
|
||||
.P
|
||||
\-\-unreleased\-only
|
||||
.
|
||||
.P
|
||||
@@ -142,7 +130,7 @@ Add to log unreleased closed issues\. Default is true
|
||||
\-\-unreleased\-label [label]
|
||||
.
|
||||
.P
|
||||
Setup custom label for unreleased closed issues section\. Default is "\fBUnreleased:\fR"
|
||||
Add to log unreleased closed issues\. Default is true
|
||||
.
|
||||
.P
|
||||
\-\-[no\-]compare\-link
|
||||
@@ -187,12 +175,6 @@ Change log will be filled only between specified tags
|
||||
Change log will exclude specified tags
|
||||
.
|
||||
.P
|
||||
\-\-exclude\-tags\-regex [REGEX]
|
||||
.
|
||||
.P
|
||||
Apply a regular expression on tag names so that they can be excluded, for example: \-\-exclude\-tags\-regex "\.*+\ed{1,}"
|
||||
.
|
||||
.P
|
||||
\-\-since\-tag x
|
||||
.
|
||||
.P
|
||||
@@ -241,30 +223,6 @@ Create simple list from issues and pull requests\. Default is false\.
|
||||
Put the unreleased changes in the specified release number\.
|
||||
.
|
||||
.P
|
||||
\-\-release\-branch [RELEASE\-BRANCH]
|
||||
.
|
||||
.P
|
||||
Limit pull requests to the release branch, such as master or release
|
||||
.
|
||||
.P
|
||||
\-\-http\-cache
|
||||
.
|
||||
.P
|
||||
Use HTTP Cache to cache Github API requests (useful for large repos) Default is true\.
|
||||
.
|
||||
.P
|
||||
\-\-[no\-]cache\-file [CACHE\-FILE]
|
||||
.
|
||||
.P
|
||||
Filename to use for cache\. Default is github\-changelog\-http\-cache in a temporary directory\.
|
||||
.
|
||||
.P
|
||||
\-\-cache\-log [CACHE\-LOG]
|
||||
.
|
||||
.P
|
||||
Filename to use for cache log\. Default is github\-changelog\-logger\.log in a temporary directory\.
|
||||
.
|
||||
.P
|
||||
\-\-[no\-]verbose
|
||||
.
|
||||
.P
|
||||
|
||||
@@ -1,286 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv='content-type' value='text/html;charset=utf8'>
|
||||
<meta name='generator' value='Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)'>
|
||||
<title>git-generate-changelog(1) - Generate changelog from github</title>
|
||||
<style type='text/css' media='all'>
|
||||
/* style: man */
|
||||
body#manpage {margin:0}
|
||||
.mp {max-width:100ex;padding:0 9ex 1ex 4ex}
|
||||
.mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
|
||||
.mp h2 {margin:10px 0 0 0}
|
||||
.mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
|
||||
.mp h3 {margin:0 0 0 4ex}
|
||||
.mp dt {margin:0;clear:left}
|
||||
.mp dt.flush {float:left;width:8ex}
|
||||
.mp dd {margin:0 0 0 9ex}
|
||||
.mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
|
||||
.mp pre {margin-bottom:20px}
|
||||
.mp pre+h2,.mp pre+h3 {margin-top:22px}
|
||||
.mp h2+pre,.mp h3+pre {margin-top:5px}
|
||||
.mp img {display:block;margin:auto}
|
||||
.mp h1.man-title {display:none}
|
||||
.mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
|
||||
.mp h2 {font-size:16px;line-height:1.25}
|
||||
.mp h1 {font-size:20px;line-height:2}
|
||||
.mp {text-align:justify;background:#fff}
|
||||
.mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
|
||||
.mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
|
||||
.mp u {text-decoration:underline}
|
||||
.mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
|
||||
.mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
|
||||
.mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
|
||||
.mp b.man-ref {font-weight:normal;color:#434241}
|
||||
.mp pre {padding:0 4ex}
|
||||
.mp pre code {font-weight:normal;color:#434241}
|
||||
.mp h2+pre,h3+pre {padding-left:0}
|
||||
ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
|
||||
ol.man-decor {width:100%}
|
||||
ol.man-decor li.tl {text-align:left}
|
||||
ol.man-decor li.tc {text-align:center;letter-spacing:4px}
|
||||
ol.man-decor li.tr {text-align:right;float:right}
|
||||
</style>
|
||||
</head>
|
||||
<!--
|
||||
The following styles are deprecated and will be removed at some point:
|
||||
div#man, div#man ol.man, div#man ol.head, div#man ol.man.
|
||||
|
||||
The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
|
||||
.man-navigation should be used instead.
|
||||
-->
|
||||
<body id='manpage'>
|
||||
<div class='mp' id='man'>
|
||||
|
||||
<div class='man-navigation' style='display:none'>
|
||||
<a href="#NAME">NAME</a>
|
||||
<a href="#SYNOPSIS">SYNOPSIS</a>
|
||||
<a href="#DESCRIPTION">DESCRIPTION</a>
|
||||
<a href="#OPTIONS">OPTIONS</a>
|
||||
<a href="#EXAMPLES">EXAMPLES</a>
|
||||
<a href="#AUTHOR">AUTHOR</a>
|
||||
<a href="#REPORTING-BUGS">REPORTING BUGS</a>
|
||||
<a href="#SEE-ALSO">SEE ALSO</a>
|
||||
</div>
|
||||
|
||||
<ol class='man-decor man-head man head'>
|
||||
<li class='tl'>git-generate-changelog(1)</li>
|
||||
<li class='tc'></li>
|
||||
<li class='tr'>git-generate-changelog(1)</li>
|
||||
</ol>
|
||||
|
||||
<h2 id="NAME">NAME</h2>
|
||||
<p class="man-name">
|
||||
<code>git-generate-changelog</code> - <span class="man-whatis">Generate changelog from github</span>
|
||||
</p>
|
||||
|
||||
<h2 id="SYNOPSIS">SYNOPSIS</h2>
|
||||
|
||||
<p><code>git generate-changelog</code> [-h|--help] [-u|--user] [-p|--project]</p>
|
||||
|
||||
<h2 id="DESCRIPTION">DESCRIPTION</h2>
|
||||
|
||||
<p>Automatically generate change log from your tags, issues, labels and pull requests on GitHub.</p>
|
||||
|
||||
<h2 id="OPTIONS">OPTIONS</h2>
|
||||
|
||||
<p> -u, --user [USER]</p>
|
||||
|
||||
<p> Username of the owner of target GitHub repo</p>
|
||||
|
||||
<p> -p, --project [PROJECT]</p>
|
||||
|
||||
<p> Name of project on GitHub</p>
|
||||
|
||||
<p> -t, --token [TOKEN]</p>
|
||||
|
||||
<p> To make more than 50 requests per hour your GitHub token is required. You can generate it at: https://github.com/settings/tokens/new</p>
|
||||
|
||||
<p> -f, --date-format [FORMAT]</p>
|
||||
|
||||
<p> Date format. Default is %Y-%m-%d</p>
|
||||
|
||||
<p> -o, --output [NAME]</p>
|
||||
|
||||
<p> Output file. Default is CHANGELOG.md</p>
|
||||
|
||||
<p> -b, --base [NAME]</p>
|
||||
|
||||
<p> Optional base file to append generated changes to.</p>
|
||||
|
||||
<p> --bugs-label [LABEL]</p>
|
||||
|
||||
<p> Setup custom label for bug-fixes section. Default is "<strong>Fixed bugs:</strong></p>
|
||||
|
||||
<p> --enhancement-label [LABEL]</p>
|
||||
|
||||
<p> Setup custom label for enhancements section. Default is "<strong>Implemented enhancements:</strong>"</p>
|
||||
|
||||
<p> --issues-label [LABEL]</p>
|
||||
|
||||
<p> Setup custom label for closed-issues section. Default is "<strong>Closed issues:</strong>"</p>
|
||||
|
||||
<p> --header-label [LABEL]</p>
|
||||
|
||||
<p> Setup custom header label. Default is "# Change Log"</p>
|
||||
|
||||
<p> --front-matter [JSON]</p>
|
||||
|
||||
<p> Add YAML front matter. Formatted as JSON because it's easier to add on the command line</p>
|
||||
|
||||
<p> --pr-label [LABEL]</p>
|
||||
|
||||
<p> Setup custom label for pull requests section. Default is "<strong>Merged pull requests:</strong>"</p>
|
||||
|
||||
<p> --[no-]issues</p>
|
||||
|
||||
<p> Include closed issues in changelog. Default is true</p>
|
||||
|
||||
<p> --[no-]issues-wo-labels</p>
|
||||
|
||||
<p> Include closed issues without labels in changelog. Default is true</p>
|
||||
|
||||
<p> --[no-]pr-wo-labels</p>
|
||||
|
||||
<p> Include pull requests without labels in changelog. Default is true</p>
|
||||
|
||||
<p> --[no-]pull-requests</p>
|
||||
|
||||
<p> Include pull-requests in changelog. Default is true</p>
|
||||
|
||||
<p> --[no-]filter-by-milestone</p>
|
||||
|
||||
<p> Use milestone to detect when issue was resolved. Default is true</p>
|
||||
|
||||
<p> --[no-]author</p>
|
||||
|
||||
<p> Add author of pull-request in the end. Default is true</p>
|
||||
|
||||
<p> --usernames-as-github-logins</p>
|
||||
|
||||
<p> Use GitHub tags instead of Markdown links for the author of an issue or pull-request.</p>
|
||||
|
||||
<p> --unreleased-only</p>
|
||||
|
||||
<p> Generate log from unreleased closed issues only.</p>
|
||||
|
||||
<p> --[no-]unreleased</p>
|
||||
|
||||
<p> Add to log unreleased closed issues. Default is true</p>
|
||||
|
||||
<p> --unreleased-label [label]</p>
|
||||
|
||||
<p> Setup custom label for unreleased closed issues section. Default is "<strong>Unreleased:</strong>"</p>
|
||||
|
||||
<p> --[no-]compare-link</p>
|
||||
|
||||
<p> Include compare link (Full Changelog) between older version and newer version. Default is true</p>
|
||||
|
||||
<p> --include-labels x,y,z</p>
|
||||
|
||||
<p> Only issues with the specified labels will be included in the changelog.</p>
|
||||
|
||||
<p> --exclude-labels x,y,z</p>
|
||||
|
||||
<p> Issues with the specified labels will be always excluded from changelog. Default is 'duplicate,question,invalid,wontfix'</p>
|
||||
|
||||
<p> --bug-labels x,y,z</p>
|
||||
|
||||
<p> Issues with the specified labels will be always added to "Fixed bugs" section. Default is 'bug,Bug'</p>
|
||||
|
||||
<p> --enhancement-labels x,y,z</p>
|
||||
|
||||
<p> Issues with the specified labels will be always added to "Implemented enhancements" section. Default is 'enhancement,Enhancement'</p>
|
||||
|
||||
<p> --exclude-tags x,y,z</p>
|
||||
|
||||
<p> Change log will exclude specified tags</p>
|
||||
|
||||
<p> --exclude-tags-regex [REGEX]</p>
|
||||
|
||||
<p> Apply a regular expression on tag names so that they can be excluded, for example: --exclude-tags-regex ".*+\d{1,}"</p>
|
||||
|
||||
<p> --since-tag x</p>
|
||||
|
||||
<p> Change log will start after specified tag</p>
|
||||
|
||||
<p> --due-tag x</p>
|
||||
|
||||
<p> Change log will end before specified tag</p>
|
||||
|
||||
<p> --max-issues [NUMBER]</p>
|
||||
|
||||
<p> Max number of issues to fetch from GitHub. Default is unlimited</p>
|
||||
|
||||
<p> --release-url [URL]</p>
|
||||
|
||||
<p> The URL to point to for release links, in printf format (with the tag as variable).</p>
|
||||
|
||||
<p> --github-site [URL]</p>
|
||||
|
||||
<p> The Enterprise Github site on which your project is hosted.</p>
|
||||
|
||||
<p> --github-api [URL]</p>
|
||||
|
||||
<p> The enterprise endpoint to use for your Github API.</p>
|
||||
|
||||
<p> --simple-list</p>
|
||||
|
||||
<p> Create simple list from issues and pull requests. Default is false.</p>
|
||||
|
||||
<p> --future-release [RELEASE-VERSION]</p>
|
||||
|
||||
<p> Put the unreleased changes in the specified release number.</p>
|
||||
|
||||
<p> --release-branch [RELEASE-BRANCH]</p>
|
||||
|
||||
<p> Limit pull requests to the release branch, such as master or release</p>
|
||||
|
||||
<p> --http-cache</p>
|
||||
|
||||
<p> Use HTTP Cache to cache Github API requests (useful for large repos) Default is true.</p>
|
||||
|
||||
<p> --[no-]cache-file [CACHE-FILE]</p>
|
||||
|
||||
<p> Filename to use for cache. Default is github-changelog-http-cache in a temporary directory.</p>
|
||||
|
||||
<p> --cache-log [CACHE-LOG]</p>
|
||||
|
||||
<p> Filename to use for cache log. Default is github-changelog-logger.log in a temporary directory.</p>
|
||||
|
||||
<p> --[no-]verbose</p>
|
||||
|
||||
<p> Run verbosely. Default is true</p>
|
||||
|
||||
<p> -v, --version</p>
|
||||
|
||||
<p> Print version number</p>
|
||||
|
||||
<p> -h, --help</p>
|
||||
|
||||
<p> Displays Help</p>
|
||||
|
||||
<h2 id="EXAMPLES">EXAMPLES</h2>
|
||||
|
||||
<h2 id="AUTHOR">AUTHOR</h2>
|
||||
|
||||
<p>Written by Petr Korolev sky4winder@gmail.com</p>
|
||||
|
||||
<h2 id="REPORTING-BUGS">REPORTING BUGS</h2>
|
||||
|
||||
<p><<a href="https://github.com/skywinder/github-changelog-generator/issues" data-bare-link="true">https://github.com/skywinder/github-changelog-generator/issues</a>></p>
|
||||
|
||||
<h2 id="SEE-ALSO">SEE ALSO</h2>
|
||||
|
||||
<p><<a href="https://github.com/skywinder/github-changelog-generator/" data-bare-link="true">https://github.com/skywinder/github-changelog-generator/</a>></p>
|
||||
|
||||
|
||||
<ol class='man-decor man-foot man foot'>
|
||||
<li class='tl'></li>
|
||||
<li class='tc'>December 2016</li>
|
||||
<li class='tr'>git-generate-changelog(1)</li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -184,6 +184,10 @@
|
||||
|
||||
<p> Issues with the specified labels will be always added to "Implemented enhancements" section. Default is 'enhancement,Enhancement'</p>
|
||||
|
||||
<p> --between-tags x,y,z</p>
|
||||
|
||||
<p> Change log will be filled only between specified tags</p>
|
||||
|
||||
<p> --exclude-tags x,y,z</p>
|
||||
|
||||
<p> Change log will exclude specified tags</p>
|
||||
|
||||
@@ -51,10 +51,6 @@ Automatically generate change log from your tags, issues, labels and pull reques
|
||||
|
||||
Setup custom header label. Default is "# Change Log"
|
||||
|
||||
--front-matter [JSON]
|
||||
|
||||
Add YAML front matter. Formatted as JSON because it's easier to add on the command line
|
||||
|
||||
--pr-label [LABEL]
|
||||
|
||||
Setup custom label for pull requests section. Default is "**Merged pull requests:**"
|
||||
@@ -83,10 +79,6 @@ Automatically generate change log from your tags, issues, labels and pull reques
|
||||
|
||||
Add author of pull-request in the end. Default is true
|
||||
|
||||
--usernames-as-github-logins
|
||||
|
||||
Use GitHub tags instead of Markdown links for the author of an issue or pull-request.
|
||||
|
||||
--unreleased-only
|
||||
|
||||
Generate log from unreleased closed issues only.
|
||||
@@ -97,7 +89,7 @@ Automatically generate change log from your tags, issues, labels and pull reques
|
||||
|
||||
--unreleased-label [label]
|
||||
|
||||
Setup custom label for unreleased closed issues section. Default is "**Unreleased:**"
|
||||
Add to log unreleased closed issues. Default is true
|
||||
|
||||
--[no-]compare-link
|
||||
|
||||
@@ -119,14 +111,14 @@ Automatically generate change log from your tags, issues, labels and pull reques
|
||||
|
||||
Issues with the specified labels will be always added to "Implemented enhancements" section. Default is 'enhancement,Enhancement'
|
||||
|
||||
--between-tags x,y,z
|
||||
|
||||
Change log will be filled only between specified tags
|
||||
|
||||
--exclude-tags x,y,z
|
||||
|
||||
Change log will exclude specified tags
|
||||
|
||||
--exclude-tags-regex [REGEX]
|
||||
|
||||
Apply a regular expression on tag names so that they can be excluded, for example: --exclude-tags-regex ".*\+\d{1,}"
|
||||
|
||||
--since-tag x
|
||||
|
||||
Change log will start after specified tag
|
||||
@@ -159,26 +151,6 @@ Automatically generate change log from your tags, issues, labels and pull reques
|
||||
|
||||
Put the unreleased changes in the specified release number.
|
||||
|
||||
--release-branch [RELEASE-BRANCH]
|
||||
|
||||
Limit pull requests to the release branch, such as master or release
|
||||
|
||||
--http-cache
|
||||
|
||||
Use HTTP Cache to cache Github API requests (useful for large repos) Default is true.
|
||||
|
||||
--[no-]cache-file [CACHE-FILE]
|
||||
|
||||
Filename to use for cache. Default is github-changelog-http-cache in a temporary directory.
|
||||
|
||||
--cache-log [CACHE-LOG]
|
||||
|
||||
Filename to use for cache log. Default is github-changelog-logger.log in a temporary directory.
|
||||
|
||||
--ssl-ca-file [PATH]
|
||||
|
||||
Path to cacert.pem file. Default is a bundled lib/github_changelog_generator/ssl_certs/cacert.pem. Respects SSL_CA_PATH.
|
||||
|
||||
--[no-]verbose
|
||||
|
||||
Run verbosely. Default is true
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Author:: Enrico Stahn <mail@enricostahn.com>
|
||||
#
|
||||
@@ -17,6 +16,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
require "codeclimate-test-reporter"
|
||||
require "simplecov"
|
||||
require "coveralls"
|
||||
require "vcr"
|
||||
@@ -28,7 +28,8 @@ end
|
||||
|
||||
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
|
||||
Coveralls::SimpleCov::Formatter,
|
||||
SimpleCov::Formatter::HTMLFormatter
|
||||
SimpleCov::Formatter::HTMLFormatter,
|
||||
CodeClimate::TestReporter::Formatter
|
||||
])
|
||||
SimpleCov.start do
|
||||
add_filter "gemfiles/"
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module GitHubChangelogGenerator
|
||||
describe Generator do
|
||||
describe "#get_string_for_issue" do
|
||||
let(:issue) do
|
||||
{ "title" => "Bug in code" }
|
||||
end
|
||||
|
||||
it "formats an issue according to options" do
|
||||
expect do
|
||||
described_class.new.get_string_for_issue(issue)
|
||||
end.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,32 +1,19 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module GitHubChangelogGenerator
|
||||
describe Generator do
|
||||
let(:default_options) { GitHubChangelogGenerator::Parser.default_options }
|
||||
let(:options) { {} }
|
||||
let(:generator) { described_class.new(default_options.merge(options)) }
|
||||
context "#exclude_issues_by_labels" do
|
||||
let(:label) { { "name" => "BAD" } }
|
||||
let(:issue) { { "labels" => [label] } }
|
||||
let(:good_label) { { "name" => "GOOD" } }
|
||||
let(:good_issue) { { "labels" => [good_label] } }
|
||||
let(:issues) { [issue, good_issue] }
|
||||
subject(:generator) { described_class.new(exclude_labels: %w(BAD BOO)) }
|
||||
|
||||
let(:bad_label) { { "name" => "BAD" } }
|
||||
let(:bad_issue) { { "labels" => [bad_label] } }
|
||||
let(:good_label) { { "name" => "GOOD" } }
|
||||
let(:good_issue) { { "labels" => [good_label] } }
|
||||
let(:unlabeled_issue) { { "labels" => [] } }
|
||||
let(:issues) { [bad_issue, good_issue, unlabeled_issue] }
|
||||
it "removes issues with labels in the exclude_label list" do
|
||||
result = generator.exclude_issues_by_labels(issues)
|
||||
|
||||
describe "#exclude_issues_by_labels" do
|
||||
subject do
|
||||
generator.exclude_issues_by_labels(issues)
|
||||
end
|
||||
|
||||
let(:expected_issues) { issues }
|
||||
|
||||
it { is_expected.to eq(expected_issues) }
|
||||
|
||||
context "when 'exclude_lables' is provided" do
|
||||
let(:options) { { exclude_labels: %w[BAD BOO] } }
|
||||
let(:expected_issues) { [good_issue, unlabeled_issue] }
|
||||
|
||||
it { is_expected.to eq(expected_issues) }
|
||||
expect(result).to include(good_issue)
|
||||
expect(result).not_to include(issue)
|
||||
end
|
||||
|
||||
context "with no option given" do
|
||||
@@ -38,43 +25,5 @@ module GitHubChangelogGenerator
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#get_filtered_issues" do
|
||||
subject do
|
||||
generator.get_filtered_issues(issues)
|
||||
end
|
||||
|
||||
let(:expected_issues) { issues }
|
||||
|
||||
it { is_expected.to eq(expected_issues) }
|
||||
|
||||
context "when 'exclude_labels' is provided" do
|
||||
let(:options) { { exclude_labels: %w[BAD BOO] } }
|
||||
let(:expected_issues) { [good_issue, unlabeled_issue] }
|
||||
|
||||
it { is_expected.to eq(expected_issues) }
|
||||
end
|
||||
|
||||
context "when 'add_issues_wo_labels' is false" do
|
||||
let(:options) { { add_issues_wo_labels: false } }
|
||||
let(:expected_issues) { [bad_issue, good_issue] }
|
||||
|
||||
it { is_expected.to eq(expected_issues) }
|
||||
|
||||
context "with 'exclude_labels'" do
|
||||
let(:options) { { add_issues_wo_labels: false, exclude_labels: %w[GOOD] } }
|
||||
let(:expected_issues) { [bad_issue] }
|
||||
|
||||
it { is_expected.to eq(expected_issues) }
|
||||
end
|
||||
end
|
||||
|
||||
context "when 'include_labels' is specified" do
|
||||
let(:options) { { include_labels: %w[GOOD] } }
|
||||
let(:expected_issues) { [good_issue] }
|
||||
|
||||
it { is_expected.to eq(expected_issues) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe GitHubChangelogGenerator::Generator do
|
||||
def tag_with_name(tag)
|
||||
{
|
||||
@@ -13,231 +12,174 @@ describe GitHubChangelogGenerator::Generator do
|
||||
end
|
||||
end
|
||||
|
||||
describe "#tag_section_mapping" do
|
||||
let(:all_tags) { tags_from_strings(%w[8 7 6 5 4 3 2 1]) }
|
||||
let(:sorted_tags) { all_tags }
|
||||
describe "#filter_between_tags" do
|
||||
context "when between_tags nil" do
|
||||
before do
|
||||
@generator = GitHubChangelogGenerator::Generator.new(between_tags: nil)
|
||||
end
|
||||
|
||||
let(:default_options) { GitHubChangelogGenerator::Parser.default_options }
|
||||
let(:options) { {} }
|
||||
let(:generator) { described_class.new(default_options.merge(options)) }
|
||||
|
||||
before do
|
||||
allow_any_instance_of(GitHubChangelogGenerator::OctoFetcher).to receive(:get_all_tags).and_return(all_tags)
|
||||
allow(generator).to receive(:fetch_tags_dates).with(all_tags)
|
||||
allow(generator).to receive(:sort_tags_by_date).with(all_tags).and_return(sorted_tags)
|
||||
generator.fetch_and_filter_tags
|
||||
subject do
|
||||
@generator.get_filtered_tags(tags_from_strings(%w(1 2 3)))
|
||||
end
|
||||
it { is_expected.to be_a(Array) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) }
|
||||
end
|
||||
context "when between_tags same as input array" do
|
||||
before do
|
||||
@generator = GitHubChangelogGenerator::Generator.new(between_tags: %w(1 2 3))
|
||||
end
|
||||
subject do
|
||||
@generator.get_filtered_tags(tags_from_strings(%w(1 2 3)))
|
||||
end
|
||||
it { is_expected.to be_a(Array) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) }
|
||||
end
|
||||
|
||||
context "when between_tags filled with correct values" do
|
||||
before do
|
||||
@generator = GitHubChangelogGenerator::Generator.new(between_tags: %w(1 2))
|
||||
end
|
||||
subject do
|
||||
@generator.get_filtered_tags(tags_from_strings(%w(1 2 3)))
|
||||
end
|
||||
it { is_expected.to be_a(Array) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1 2))) }
|
||||
end
|
||||
|
||||
context "when between_tags filled with invalid values" do
|
||||
before do
|
||||
@generator = GitHubChangelogGenerator::Generator.new(between_tags: %w(1 q w))
|
||||
end
|
||||
|
||||
subject do
|
||||
@generator.get_filtered_tags(tags_from_strings(%w(1 2 3)))
|
||||
end
|
||||
it { is_expected.to be_a(Array) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1))) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#get_filtered_tags" do
|
||||
subject do
|
||||
generator.tag_section_mapping
|
||||
generator.get_filtered_tags(tags_from_strings(%w(1 2 3 4 5)))
|
||||
end
|
||||
|
||||
shared_examples_for "a section mapping" do
|
||||
it { is_expected.to be_a(Hash) }
|
||||
it { is_expected.to eq(expected_mapping) }
|
||||
end
|
||||
context "respects between tags" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(between_tags: %w(1 2 3)) }
|
||||
|
||||
shared_examples_for "a full changelog" do
|
||||
let(:expected_mapping) do
|
||||
{
|
||||
tag_with_name("8") => [tag_with_name("7"), tag_with_name("8")],
|
||||
tag_with_name("7") => [tag_with_name("6"), tag_with_name("7")],
|
||||
tag_with_name("6") => [tag_with_name("5"), tag_with_name("6")],
|
||||
tag_with_name("5") => [tag_with_name("4"), tag_with_name("5")],
|
||||
tag_with_name("4") => [tag_with_name("3"), tag_with_name("4")],
|
||||
tag_with_name("3") => [tag_with_name("2"), tag_with_name("3")],
|
||||
tag_with_name("2") => [tag_with_name("1"), tag_with_name("2")],
|
||||
tag_with_name("1") => [nil, tag_with_name("1")]
|
||||
}
|
||||
end
|
||||
|
||||
it_behaves_like "a section mapping"
|
||||
end
|
||||
|
||||
shared_examples_for "a changelog with some exclusions" do
|
||||
let(:expected_mapping) do
|
||||
{
|
||||
tag_with_name("8") => [tag_with_name("7"), tag_with_name("8")],
|
||||
tag_with_name("6") => [tag_with_name("5"), tag_with_name("6")],
|
||||
tag_with_name("4") => [tag_with_name("3"), tag_with_name("4")],
|
||||
tag_with_name("3") => [tag_with_name("2"), tag_with_name("3")],
|
||||
tag_with_name("1") => [nil, tag_with_name("1")]
|
||||
}
|
||||
end
|
||||
|
||||
it_behaves_like "a section mapping"
|
||||
end
|
||||
|
||||
context "with no constraints" do
|
||||
it_behaves_like "a full changelog"
|
||||
end
|
||||
|
||||
context "with since only" do
|
||||
let(:options) { { since_tag: "6" } }
|
||||
let(:expected_mapping) do
|
||||
{
|
||||
tag_with_name("8") => [tag_with_name("7"), tag_with_name("8")],
|
||||
tag_with_name("7") => [tag_with_name("6"), tag_with_name("7")]
|
||||
}
|
||||
end
|
||||
|
||||
it_behaves_like "a section mapping"
|
||||
end
|
||||
|
||||
context "with due only" do
|
||||
let(:options) { { due_tag: "4" } }
|
||||
let(:expected_mapping) do
|
||||
{
|
||||
tag_with_name("3") => [tag_with_name("2"), tag_with_name("3")],
|
||||
tag_with_name("2") => [tag_with_name("1"), tag_with_name("2")],
|
||||
tag_with_name("1") => [nil, tag_with_name("1")]
|
||||
}
|
||||
end
|
||||
|
||||
it_behaves_like "a section mapping"
|
||||
end
|
||||
|
||||
context "with since and due" do
|
||||
let(:options) { { since_tag: "2", due_tag: "5" } }
|
||||
let(:expected_mapping) do
|
||||
{
|
||||
tag_with_name("4") => [tag_with_name("3"), tag_with_name("4")],
|
||||
tag_with_name("3") => [tag_with_name("2"), tag_with_name("3")]
|
||||
}
|
||||
end
|
||||
|
||||
it_behaves_like "a section mapping"
|
||||
end
|
||||
|
||||
context "with excluded tags" do
|
||||
context "as a list of strings" do
|
||||
let(:options) { { exclude_tags: %w[2 5 7] } }
|
||||
|
||||
it_behaves_like "a changelog with some exclusions"
|
||||
end
|
||||
|
||||
context "as a regex" do
|
||||
let(:options) { { exclude_tags: /[257]/ } }
|
||||
|
||||
it_behaves_like "a changelog with some exclusions"
|
||||
end
|
||||
|
||||
context "as a regex string" do
|
||||
let(:options) { { exclude_tags_regex: "[257]" } }
|
||||
|
||||
it_behaves_like "a changelog with some exclusions"
|
||||
end
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#filter_excluded_tags" do
|
||||
subject { generator.filter_excluded_tags(tags_from_strings(%w[1 2 3])) }
|
||||
subject { generator.filter_excluded_tags(tags_from_strings(%w(1 2 3))) }
|
||||
|
||||
context "with matching string" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags: %w[3]) }
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags: %w(3)) }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[1 2])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1 2))) }
|
||||
end
|
||||
|
||||
context "with non-matching string" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags: %w[invalid tags]) }
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags: %w(invalid tags)) }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[1 2 3])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) }
|
||||
end
|
||||
|
||||
context "with matching regex" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags: /[23]/) }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[1])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1))) }
|
||||
end
|
||||
|
||||
context "with non-matching regex" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags: /[abc]/) }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[1 2 3])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#filter_excluded_tags_regex" do
|
||||
subject { generator.filter_excluded_tags(tags_from_strings(%w[1 2 3])) }
|
||||
subject { generator.filter_excluded_tags(tags_from_strings(%w(1 2 3))) }
|
||||
|
||||
context "with matching regex" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags_regex: "[23]") }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[1])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1))) }
|
||||
end
|
||||
|
||||
context "with non-matching regex" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags_regex: "[45]") }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[1 2 3])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#filter_since_tag" do
|
||||
context "with filled array" do
|
||||
subject { generator.filter_since_tag(tags_from_strings(%w[1 2 3])) }
|
||||
subject { generator.filter_since_tag(tags_from_strings(%w(1 2 3))) }
|
||||
|
||||
context "with valid since tag" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(since_tag: "2") }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[1 2])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1))) }
|
||||
end
|
||||
|
||||
context "with invalid since tag" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(since_tag: "Invalid tag") }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[1 2 3])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) }
|
||||
end
|
||||
end
|
||||
|
||||
context "with empty array" do
|
||||
subject { generator.filter_since_tag(tags_from_strings(%w[])) }
|
||||
subject { generator.filter_since_tag(tags_from_strings(%w())) }
|
||||
|
||||
context "with valid since tag" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(since_tag: "2") }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w())) }
|
||||
end
|
||||
|
||||
context "with invalid since tag" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(since_tag: "Invalid tag") }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w())) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#filter_due_tag" do
|
||||
context "with filled array" do
|
||||
subject { generator.filter_due_tag(tags_from_strings(%w[1 2 3])) }
|
||||
subject { generator.filter_due_tag(tags_from_strings(%w(1 2 3))) }
|
||||
|
||||
context "with valid due tag" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(due_tag: "2") }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[3])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(3))) }
|
||||
end
|
||||
|
||||
context "with invalid due tag" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(due_tag: "Invalid tag") }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[1 2 3])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) }
|
||||
end
|
||||
end
|
||||
|
||||
context "with empty array" do
|
||||
subject { generator.filter_due_tag(tags_from_strings(%w[])) }
|
||||
subject { generator.filter_due_tag(tags_from_strings(%w())) }
|
||||
|
||||
context "with valid due tag" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(due_tag: "2") }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w())) }
|
||||
end
|
||||
|
||||
context "with invalid due tag" do
|
||||
let(:generator) { GitHubChangelogGenerator::Generator.new(due_tag: "Invalid tag") }
|
||||
it { is_expected.to be_a Array }
|
||||
it { is_expected.to match_array(tags_from_strings(%w[])) }
|
||||
it { is_expected.to match_array(tags_from_strings(%w())) }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -290,13 +232,13 @@ describe GitHubChangelogGenerator::Generator do
|
||||
@generator.sort_tags_by_date(tags)
|
||||
end
|
||||
context "sort unsorted tags" do
|
||||
let(:tags) { tags_from_strings %w[valid_tag1 valid_tag2 valid_tag3] }
|
||||
let(:tags) { tags_from_strings %w(valid_tag1 valid_tag2 valid_tag3) }
|
||||
|
||||
it { is_expected.to be_a_kind_of(Array) }
|
||||
it { is_expected.to match_array(tags.reverse!) }
|
||||
end
|
||||
context "sort sorted tags" do
|
||||
let(:tags) { tags_from_strings %w[valid_tag3 valid_tag2 valid_tag1] }
|
||||
let(:tags) { tags_from_strings %w(valid_tag3 valid_tag2 valid_tag1) }
|
||||
|
||||
it { is_expected.to be_a_kind_of(Array) }
|
||||
it { is_expected.to match_array(tags) }
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
VALID_TOKEN = "0123456789abcdef"
|
||||
INVALID_TOKEN = "0000000000000000"
|
||||
|
||||
@@ -13,31 +12,6 @@ describe GitHubChangelogGenerator::OctoFetcher do
|
||||
|
||||
let(:fetcher) { GitHubChangelogGenerator::OctoFetcher.new(options) }
|
||||
|
||||
describe "#check_github_response" do
|
||||
context "when returns successfully" do
|
||||
it "returns block value" do
|
||||
expect(fetcher.send(:check_github_response) { 1 + 1 }).to eq(2)
|
||||
end
|
||||
end
|
||||
|
||||
context "when raises Octokit::Unauthorized" do
|
||||
it "aborts" do
|
||||
expect(fetcher).to receive(:sys_abort).with("Error: wrong GitHub token")
|
||||
fetcher.send(:check_github_response) { raise(Octokit::Unauthorized) }
|
||||
end
|
||||
end
|
||||
|
||||
context "when raises Octokit::Forbidden" do
|
||||
it "sleeps and retries and then aborts" do
|
||||
retry_limit = GitHubChangelogGenerator::OctoFetcher::MAX_FORBIDDEN_RETRIES - 1
|
||||
allow(fetcher).to receive(:sleep_base_interval).exactly(retry_limit).times.and_return(0)
|
||||
|
||||
expect(fetcher).to receive(:sys_abort).with("Exceeded retry limit")
|
||||
fetcher.send(:check_github_response) { raise(Octokit::Forbidden) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#fetch_github_token" do
|
||||
token = GitHubChangelogGenerator::OctoFetcher::CHANGELOG_GITHUB_TOKEN
|
||||
context "when token in ENV exist" do
|
||||
@@ -300,7 +274,7 @@ describe GitHubChangelogGenerator::OctoFetcher do
|
||||
pull_requests = fetcher.fetch_closed_pull_requests
|
||||
|
||||
pr = pull_requests.first
|
||||
expect(pr.keys).to eq(%w[url id html_url diff_url patch_url issue_url number state locked title user body created_at updated_at closed_at merged_at merge_commit_sha assignee assignees milestone commits_url review_comments_url review_comment_url comments_url statuses_url head base _links])
|
||||
expect(pr.keys).to eq(%w(url id html_url diff_url patch_url issue_url number state locked title user body created_at updated_at closed_at merged_at merge_commit_sha assignee assignees milestone commits_url review_comments_url review_comment_url comments_url statuses_url head base _links))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -452,20 +426,6 @@ describe GitHubChangelogGenerator::OctoFetcher do
|
||||
end
|
||||
end
|
||||
|
||||
describe "#querystring_as_hash" do
|
||||
it "works on the blank URL" do
|
||||
expect { fetcher.send(:querystring_as_hash, "") }.not_to raise_error
|
||||
end
|
||||
|
||||
it "where there are no querystring params" do
|
||||
expect { fetcher.send(:querystring_as_hash, "http://example.com") }.not_to raise_error
|
||||
end
|
||||
|
||||
it "returns a String-keyed Hash of querystring params" do
|
||||
expect(fetcher.send(:querystring_as_hash, "http://example.com/o.html?str=18&wis=12")).to include("wis" => "12", "str" => "18")
|
||||
end
|
||||
end
|
||||
|
||||
describe "#fetch_commit" do
|
||||
context "when API call is valid", :vcr do
|
||||
it "returns commit" do
|
||||
@@ -501,7 +461,7 @@ describe GitHubChangelogGenerator::OctoFetcher do
|
||||
commit = fetcher.fetch_commit(event)
|
||||
|
||||
expectations = [
|
||||
%w[sha decfe840d1a1b86e0c28700de5362d3365a29555],
|
||||
%w(sha decfe840d1a1b86e0c28700de5362d3365a29555),
|
||||
["url",
|
||||
"https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555"],
|
||||
# OLD API: "https://api.github.com/repos/skywinder/changelog_test/git/commits/decfe840d1a1b86e0c28700de5362d3365a29555"],
|
||||
@@ -526,18 +486,4 @@ describe GitHubChangelogGenerator::OctoFetcher do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#commits_before" do
|
||||
context "when API is valid", :vcr do
|
||||
let(:start_time) { Time.parse("Wed Mar 4 18:47:17 2015 +0200") }
|
||||
|
||||
subject do
|
||||
fetcher.commits_before(start_time)
|
||||
end
|
||||
|
||||
it "returns commits" do
|
||||
expect(subject.last["sha"]).to eq("4c2d6d1ed58bdb24b870dcb5d9f2ceed0283d69d")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe GitHubChangelogGenerator::Options do
|
||||
describe "#initialize" do
|
||||
context "with known options" do
|
||||
it "instantiates successfully" do
|
||||
expect(described_class.new(user: "olle")[:user]).to eq("olle")
|
||||
end
|
||||
end
|
||||
|
||||
context "with unknown options" do
|
||||
it "raises an error" do
|
||||
expect do
|
||||
described_class.new(
|
||||
git_remote: "origin",
|
||||
strength: "super-strength",
|
||||
wisdom: "deep"
|
||||
)
|
||||
end.to raise_error("[:strength, :wisdom]")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#[]=(key, value)" do
|
||||
let(:options) { described_class.new(git_remote: "origin") }
|
||||
|
||||
context "with known options" do
|
||||
it "sets the option value" do
|
||||
expect do
|
||||
options[:git_remote] = "in the cloud"
|
||||
end.to change { options[:git_remote] }.to "in the cloud"
|
||||
end
|
||||
end
|
||||
|
||||
context "with unknown options" do
|
||||
it "raises an error" do
|
||||
expect do
|
||||
options[:charisma] = 8
|
||||
end.to raise_error(":charisma")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe GitHubChangelogGenerator::ParserFile do
|
||||
describe ".github_changelog_generator" do
|
||||
let(:options) { {} }
|
||||
@@ -14,7 +13,7 @@ describe GitHubChangelogGenerator::ParserFile do
|
||||
let(:parser) { GitHubChangelogGenerator::ParserFile.new(options, StringIO.new("")) }
|
||||
|
||||
it "does not change the options" do
|
||||
expect { parser.parse! }.to_not(change { options })
|
||||
expect { parser.parse! }.to_not change { options }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -52,11 +51,12 @@ describe GitHubChangelogGenerator::ParserFile do
|
||||
|
||||
context "turns exclude-labels into an Array", bug: "#327" do
|
||||
let(:file) do
|
||||
line1 = "exclude-labels=73a91042-da6f-11e5-9335-1040f38d7f90,7adf83b4-da6f-11e5-ae18-1040f38d7f90\n"
|
||||
line2 = "header_label=# My changelog\n"
|
||||
StringIO.new(line1 + line2)
|
||||
StringIO.new(<<EOF
|
||||
exclude-labels=73a91042-da6f-11e5-9335-1040f38d7f90,7adf83b4-da6f-11e5-ae18-1040f38d7f90
|
||||
header_label=# My changelog
|
||||
EOF
|
||||
)
|
||||
end
|
||||
|
||||
it "reads exclude_labels into an Array" do
|
||||
expect { parser.parse! }.to change { options[:exclude_labels] }
|
||||
.from(default_options[:exclude_labels])
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe GitHubChangelogGenerator::Parser do
|
||||
describe ".user_project_from_remote" do
|
||||
context "when remote is type 1" do
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Author:: Enrico Stahn <mail@enricostahn.com>
|
||||
#
|
||||
@@ -86,6 +85,10 @@ describe GitHubChangelogGenerator::Reader do
|
||||
context "angular.js.md" do
|
||||
it { is_expected.to be_an(Array) }
|
||||
it { is_expected.not_to be_empty }
|
||||
it do
|
||||
pending("Implement heading_level for parser.")
|
||||
expect(subject.count).to eq(134)
|
||||
end
|
||||
# it do
|
||||
# pending('Implement heading_level for parser.')
|
||||
# expect(subject.first).to include('version' => '1.4.0-beta.6 cookie-liberation')
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user