Compare commits

...

57 Commits

Author SHA1 Message Date
Petr Korolev
e864abd623 Merge branch 'release/1.4.0' 2015-05-07 17:14:30 +03:00
Petr Korolev
6710078766 Update gemspec to version 1.4.0 2015-05-07 17:14:25 +03:00
Petr Korolev
f0736e67a5 update readme 2015-05-07 17:14:15 +03:00
Petr Korolev
784bd50a8f Fix #232 2015-05-07 17:14:14 +03:00
Petr Korolev
a9eabfc38b update readme 2015-05-07 11:57:14 +03:00
Petr Korolev
8123b3e2fa Fix #232 2015-05-06 20:07:10 +03:00
Petr Korolev
2b148f2e69 Merge branch 'develop' 2015-04-22 12:28:43 +03:00
Petr Korolev
6a7dbeb450 Merge branch 'feature/fetcher' into develop 2015-04-22 12:28:10 +03:00
Petr Korolev
8aa5d524b7 Merge branch 'master' into develop 2015-04-22 12:27:47 +03:00
Petr Korolev
0a35113a88 rubocop fixes 2015-04-22 00:33:50 +03:00
Petr Korolev
79a84a14f4 add logger 2015-04-22 00:26:28 +03:00
Petr Korolev
6d8dbd16ad fix long lines (>80) 2015-04-22 00:00:57 +03:00
Petr Korolev
cf8df992c5 Merge branch 'develop' into feature/fetcher 2015-04-21 23:53:56 +03:00
Petr Korolev
b620ad0d1b add hound yml 2015-04-21 23:53:40 +03:00
Petr Korolev
b7980c8900 rubocop autofixes 2015-04-21 23:37:03 +03:00
Petr Korolev
e27fe24a76 refactoring 2015-04-21 23:32:52 +03:00
Petr Korolev
088c98d0bf move methods 2015-04-21 20:42:33 +03:00
Petr Korolev
9ab84ac181 Merge branch 'master' into feature/fetcher 2015-04-04 03:41:09 +03:00
Petr Korolev
f04d581dbc Merge branch 'develop' 2015-04-04 03:40:58 +03:00
Petr Korolev
911b91c0ab add docs. add fail statment 2015-04-04 03:40:48 +03:00
Petr Korolev
26e202d7f0 add documentation 2015-04-04 03:37:31 +03:00
Petr Korolev
c2e5118cc9 Merge branch 'develop' 2015-04-04 03:31:04 +03:00
Petr Korolev
b598bd5ba1 add docs. add fail statment 2015-04-04 03:30:35 +03:00
Petr Korolev
1673677df0 add docs. add fail statment 2015-04-04 03:27:05 +03:00
Petr Korolev
c44be45ce4 add doc fix bug with filtering in case of nil issues 2015-04-04 03:18:12 +03:00
Petr Korolev
177b7aa18f code cleanup. remove code duplication 2015-04-04 03:10:16 +03:00
Petr Korolev
e495b58682 Merge branch 'develop' into feature/fetcher
Conflicts:
	.rubocop_todo.yml
	lib/github_changelog_generator.rb
2015-04-04 02:31:44 +03:00
Petr Korolev
e82a75611c refactoring 2015-04-04 02:30:02 +03:00
Petr Korolev
38576e23e3 update changelog
set default debug repo
add documentation
2015-04-04 02:23:30 +03:00
Petr Korolev
79d228c7a0 cleanup 2015-04-04 00:25:14 +03:00
Petr Korolev
e1161f9d90 code cleanup. remove duplicate code 2015-04-04 00:22:40 +03:00
Petr Korolev
31c5ac4c55 Merge branch 'feature/custom-error' into develop 2015-04-04 00:11:38 +03:00
Petr Korolev
dae68ee3b5 rubocop fixes 2015-04-04 00:08:00 +03:00
Petr Korolev
2b656c83b6 add doc + fix raise 2015-04-03 19:13:50 +03:00
Petr Korolev
4e9ed5df28 add error class and documentation 2015-04-03 18:59:37 +03:00
Petr Korolev
47bba9d384 update rubocop 2015-04-03 18:41:39 +03:00
Petr Korolev
ce7f35777b Merge branch 'develop' into feature/fetcher
Conflicts:
	lib/github_changelog_generator.rb
2015-04-03 18:40:11 +03:00
Petr Korolev
115762af82 Merge branch 'master' into develop 2015-04-03 18:37:15 +03:00
Petr Korolev
a50ad5b5c9 Merge branch 'develop' 2015-04-02 12:07:35 +03:00
Petr Korolev
da60c73502 Go with souble quotes. (See https://github.com/skywinder/github-changelog-generator/pull/220#discussion_r27262657 ) 2015-04-02 12:05:26 +03:00
Petr Korolev
b5d073c0af Merge branch 'develop' into feature/fetcher 2015-04-01 14:17:14 +03:00
Petr Korolev
6fcd0c95ed update readme 2015-03-29 23:03:32 +03:00
Petr Korolev
5c66591d71 Merge branch 'develop' 2015-03-29 22:44:58 +03:00
Petr Korolev
77941049e6 Merge branch 'feature/codeclimate-test-reporter-intergration' into develop 2015-03-29 22:44:48 +03:00
Petr Korolev
ca334b430c Merge branch 'master' into develop 2015-03-29 22:42:52 +03:00
Petr Korolev
1498790a78 fix codeclimate token 2015-03-29 22:38:18 +03:00
Petr Korolev
55001f48c2 rubocop fix 2015-03-29 22:32:03 +03:00
Petr Korolev
643b266679 add codeclimate encrypted token 2015-03-29 22:31:24 +03:00
Petr Korolev
2590883c3a Add codeclimate-test-reporter integration 2015-03-29 21:47:39 +03:00
Petr Korolev
51755cbe34 update 2015-03-27 17:17:23 +02:00
Petr Korolev
d361baaec5 add documentation 2015-03-27 17:15:08 +02:00
Petr Korolev
ae0d1d16de Fix missed sub-section headers and add documentation 2015-03-27 17:06:09 +02:00
Petr Korolev
c8584a1749 add documentation 2015-03-27 16:48:13 +02:00
Petr Korolev
7c29f3ddd2 move @github to fetcher
Conflicts:
	lib/github_changelog_generator.rb
2015-03-27 16:29:47 +02:00
Petr Korolev
a2cf6810ad add fetcher class 2015-03-27 16:25:57 +02:00
Petr Korolev
629a08b890 Merge branch 'develop' 2015-03-27 16:11:02 +02:00
Petr Korolev
4f9bb03265 add gem version to readme 2015-03-27 15:59:03 +02:00
21 changed files with 839 additions and 679 deletions

2
.hound.yml Normal file
View File

@@ -0,0 +1,2 @@
ruby:
config_file: .rubocop.yml

View File

@@ -4,5 +4,5 @@ Metrics/LineLength:
Enabled: false Enabled: false
#http://viget.com/extend/just-use-double-quoted-ruby-strings #http://viget.com/extend/just-use-double-quoted-ruby-strings
#Style/StringLiterals: Style/StringLiterals:
# EnforcedStyle: double_quotes EnforcedStyle: double_quotes

View File

@@ -1,35 +1,35 @@
# This configuration was generated by `rubocop --auto-gen-config` # This configuration was generated by `rubocop --auto-gen-config`
# on 2015-03-27 03:03:45 +0200 using RuboCop version 0.29.1. # on 2015-04-04 02:29:34 +0300 using RuboCop version 0.29.1.
# The point is for the user to remove these configuration records # The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base. # one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new # Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again. # versions of RuboCop, may require this file to be generated again.
# Offense count: 20 # Offense count: 21
Metrics/AbcSize: Metrics/AbcSize:
Max: 114 Max: 71
# Offense count: 1 # Offense count: 2
Metrics/BlockNesting: Metrics/BlockNesting:
Max: 4 Max: 4
# Offense count: 2 # Offense count: 2
# Configuration parameters: CountComments. # Configuration parameters: CountComments.
Metrics/ClassLength: Metrics/ClassLength:
Max: 471 Max: 457
# Offense count: 6 # Offense count: 6
Metrics/CyclomaticComplexity: Metrics/CyclomaticComplexity:
Max: 18 Max: 15
# Offense count: 27 # Offense count: 28
# Configuration parameters: CountComments. # Configuration parameters: CountComments.
Metrics/MethodLength: Metrics/MethodLength:
Max: 147 Max: 118
# Offense count: 6 # Offense count: 5
Metrics/PerceivedComplexity: Metrics/PerceivedComplexity:
Max: 20 Max: 18
# Offense count: 3 # Offense count: 3
Style/AccessorMethodName: Style/AccessorMethodName:
@@ -41,7 +41,7 @@ Style/AccessorMethodName:
Style/AndOr: Style/AndOr:
Enabled: false Enabled: false
# Offense count: 29 # Offense count: 27
# Cop supports --auto-correct. # Cop supports --auto-correct.
Style/Blocks: Style/Blocks:
Enabled: false Enabled: false
@@ -51,7 +51,7 @@ Style/Blocks:
Style/CaseIndentation: Style/CaseIndentation:
Enabled: false Enabled: false
# Offense count: 5 # Offense count: 4
Style/Documentation: Style/Documentation:
Enabled: false Enabled: false

View File

@@ -1,17 +1,17 @@
---
sudo: false sudo: false
cache: bundler cache: bundler
language: ruby language: ruby
rvm: rvm:
- 2.1.0 - 2.1.0
script: script:
- bundle exec rake - bundle exec rake
notifications: notifications:
email: email:
recipients: recipients:
- sky4winder+githubchangeloggenerator@gmail.com - sky4winder+githubchangeloggenerator@gmail.com
on_success: never # [always|never|change] on_success: never
on_failure: change # [always|never|change] on_failure: change
addons:
code_climate:
repo_token:
secure: iMpV5IAvH+/EVGZrpWnt2BnmNFzSbsRcIumsr4ZyLC8N5nrCSXyjCSy0g48btL3Sj0bSgK9hcrJsmrFd2bkqFleyAcPAzNyUQzBuIRZx47O8yFmbZ+Pj+l3+KOlmcbzJNHfDfxkxuWTmTAcSDfsiyApin721T/ey3SUuwKpZNUc=

View File

@@ -1,304 +1,336 @@
# Change Log # Change Log
## [1.3.10](https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.10) (2015-03-18) ## [Unreleased](https://github.com/skywinder/github-changelog-generator/tree/HEAD)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.3.9...1.3.10) [Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.3.11...HEAD)
**Fixed bugs:**
- Exclude closed PR's from changelog. [\#69](https://github.com/skywinder/Github-Changelog-Generator/issues/69)
**Merged pull requests:**
- Fix termination in case of empty unreleased section with `--unreleased-only` option. [\#70](https://github.com/skywinder/Github-Changelog-Generator/pull/70) ([skywinder](https://github.com/skywinder))
## [1.3.9](https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.9) (2015-03-06)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.3.8...1.3.9)
**Implemented enhancements:** **Implemented enhancements:**
- Improve method of detecting owner and repository [\#63](https://github.com/skywinder/Github-Changelog-Generator/issues/63) - Parsing of existing Change Log file [\#212](https://github.com/skywinder/github-changelog-generator/issues/212)
**Merged pull requests:** - Warn users about 0 tags in repo. [\#208](https://github.com/skywinder/github-changelog-generator/issues/208)
- Resolved concurrency problem in case of issues \> 2048 [\#65](https://github.com/skywinder/Github-Changelog-Generator/pull/65) ([skywinder](https://github.com/skywinder))
## [1.3.8](https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.8) (2015-03-05)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.3.6...1.3.8)
**Merged pull requests:**
- Fix `git remote` parsing in case, when script running without parameters inside destination directory [\#61](https://github.com/skywinder/Github-Changelog-Generator/pull/61) ([skywinder](https://github.com/skywinder))
## [1.3.6](https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.6) (2015-03-05)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.3.5...1.3.6)
## [1.3.5](https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.5) (2015-03-04)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.3.4...1.3.5)
**Fixed bugs:**
- Pull Requests in Wrong Tag [\#60](https://github.com/skywinder/Github-Changelog-Generator/issues/60)
## [1.3.4](https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.4) (2015-03-03)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.3.3...1.3.4)
**Fixed bugs:**
- --no-issues appears to break PRs [\#59](https://github.com/skywinder/Github-Changelog-Generator/issues/59)
## [1.3.3](https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.3) (2015-03-03)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.3.2...1.3.3)
**Closed issues:** **Closed issues:**
- Add \# character to encapsulate list. [\#58](https://github.com/skywinder/Github-Changelog-Generator/issues/58) - Add CodeClimate and Inch CI [\#219](https://github.com/skywinder/github-changelog-generator/issues/219)
## [1.3.2](https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.2) (2015-03-03)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.3.1...1.3.2)
**Fixed bugs:**
- generation failed if github commit api return `404 Not Found` [\#57](https://github.com/skywinder/Github-Changelog-Generator/issues/57)
## [1.3.1](https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.1) (2015-02-27)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.3.0...1.3.1)
## [1.3.0](https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.0) (2015-02-26)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.2.8...1.3.0)
**Implemented enhancements:**
- Do not show `Unreleased` section, when it's empty. [\#55](https://github.com/skywinder/Github-Changelog-Generator/issues/55)
- Separate list exclude and include labels [\#52](https://github.com/skywinder/Github-Changelog-Generator/issues/52)
- Unreleased issues in separate section [\#47](https://github.com/skywinder/Github-Changelog-Generator/issues/47)
- Separate by lists: Enhancements, Bugs, Pull requests. [\#31](https://github.com/skywinder/Github-Changelog-Generator/issues/31)
**Fixed bugs:**
- Test pull request with invalid label \(\#26\) in changelog appeared. [\#44](https://github.com/skywinder/Github-Changelog-Generator/issues/44)
**Merged pull requests:** **Merged pull requests:**
- Implement filtering of Pull Requests by milestones [\#50](https://github.com/skywinder/Github-Changelog-Generator/pull/50) ([skywinder](https://github.com/skywinder)) - Cleanup [\#220](https://github.com/skywinder/github-changelog-generator/pull/220) ([tuexss](https://github.com/tuexss))
## [1.2.8](https://github.com/skywinder/Github-Changelog-Generator/tree/1.2.8) (2015-02-17) - Add coveralls integration [\#223](https://github.com/skywinder/github-changelog-generator/pull/223) ([skywinder](https://github.com/skywinder))
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.2.7...1.2.8) - Rspec & rubocop integration [\#217](https://github.com/skywinder/github-changelog-generator/pull/217) ([skywinder](https://github.com/skywinder))
- Implement Reader class to parse ChangeLog.md [\#216](https://github.com/skywinder/github-changelog-generator/pull/216) ([estahn](https://github.com/estahn))
- Relatively require github\_changelog\_generator library [\#207](https://github.com/skywinder/github-changelog-generator/pull/207) ([sneal](https://github.com/sneal))
- Add --max-issues argument to limit requests [\#76](https://github.com/skywinder/github-changelog-generator/pull/76) ([sneal](https://github.com/sneal))
## [1.3.11](https://github.com/skywinder/github-changelog-generator/tree/1.3.11) (2015-03-21)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.3.10...1.3.11)
**Merged pull requests:**
- Add fallback with warning message to prevent crash in case of exceed API Rate Limit \(temporary workaround for \#71\) [\#75](https://github.com/skywinder/github-changelog-generator/pull/75) ([skywinder](https://github.com/skywinder))
## [1.3.10](https://github.com/skywinder/github-changelog-generator/tree/1.3.10) (2015-03-18)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.3.9...1.3.10)
**Merged pull requests:**
- Fix termination in case of empty unreleased section with `--unreleased-only` option. [\#70](https://github.com/skywinder/github-changelog-generator/pull/70) ([skywinder](https://github.com/skywinder))
## [1.3.9](https://github.com/skywinder/github-changelog-generator/tree/1.3.9) (2015-03-06)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.3.8...1.3.9)
**Implemented enhancements:**
- Improve method of detecting owner and repository [\#63](https://github.com/skywinder/github-changelog-generator/issues/63)
**Merged pull requests:**
- Resolved concurrency problem in case of issues \> 2048 [\#65](https://github.com/skywinder/github-changelog-generator/pull/65) ([skywinder](https://github.com/skywinder))
## [1.3.8](https://github.com/skywinder/github-changelog-generator/tree/1.3.8) (2015-03-05)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.3.6...1.3.8)
**Merged pull requests:**
- Fix `git remote` parsing in case, when script running without parameters inside destination directory [\#61](https://github.com/skywinder/github-changelog-generator/pull/61) ([skywinder](https://github.com/skywinder))
## [1.3.6](https://github.com/skywinder/github-changelog-generator/tree/1.3.6) (2015-03-05)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.3.5...1.3.6)
## [1.3.5](https://github.com/skywinder/github-changelog-generator/tree/1.3.5) (2015-03-04)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.3.4...1.3.5)
**Fixed bugs:**
- Pull Requests in Wrong Tag [\#60](https://github.com/skywinder/github-changelog-generator/issues/60)
## [1.3.4](https://github.com/skywinder/github-changelog-generator/tree/1.3.4) (2015-03-03)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.3.3...1.3.4)
**Fixed bugs:**
- --no-issues appears to break PRs [\#59](https://github.com/skywinder/github-changelog-generator/issues/59)
## [1.3.3](https://github.com/skywinder/github-changelog-generator/tree/1.3.3) (2015-03-03)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.3.2...1.3.3)
**Closed issues:** **Closed issues:**
- Bugs, that closed simultaneously with push not appeared in correct version. [\#37](https://github.com/skywinder/Github-Changelog-Generator/issues/37) - Add \# character to encapsulate list. [\#58](https://github.com/skywinder/github-changelog-generator/issues/58)
**Merged pull requests:** ## [1.3.2](https://github.com/skywinder/github-changelog-generator/tree/1.3.2) (2015-03-03)
- Feature/fix 37 [\#49](https://github.com/skywinder/Github-Changelog-Generator/pull/49) ([skywinder](https://github.com/skywinder)) [Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.3.1...1.3.2)
- Prettify output [\#48](https://github.com/skywinder/Github-Changelog-Generator/pull/48) ([skywinder](https://github.com/skywinder)) **Fixed bugs:**
## [1.2.7](https://github.com/skywinder/Github-Changelog-Generator/tree/1.2.7) (2015-01-26) - generation failed if github commit api return `404 Not Found` [\#57](https://github.com/skywinder/github-changelog-generator/issues/57)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.2.6...1.2.7) ## [1.3.1](https://github.com/skywinder/github-changelog-generator/tree/1.3.1) (2015-02-27)
**Merged pull requests:** [Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.3.0...1.3.1)
- Add compare link between older version and newer version [\#46](https://github.com/skywinder/Github-Changelog-Generator/pull/46) ([sue445](https://github.com/sue445)) ## [1.3.0](https://github.com/skywinder/github-changelog-generator/tree/1.3.0) (2015-02-26)
## [1.2.6](https://github.com/skywinder/Github-Changelog-Generator/tree/1.2.6) (2015-01-21) [Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.2.8...1.3.0)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.2.5...1.2.6)
**Merged pull requests:**
- fix link tag format [\#45](https://github.com/skywinder/Github-Changelog-Generator/pull/45) ([sugamasao](https://github.com/sugamasao))
## [1.2.5](https://github.com/skywinder/Github-Changelog-Generator/tree/1.2.5) (2015-01-15)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.2.4...1.2.5)
**Implemented enhancements:** **Implemented enhancements:**
- Use milestone to specify in which version bug was fixed [\#22](https://github.com/skywinder/Github-Changelog-Generator/issues/22) - Do not show `Unreleased` section, when it's empty. [\#55](https://github.com/skywinder/github-changelog-generator/issues/55)
- Separate list exclude and include labels [\#52](https://github.com/skywinder/github-changelog-generator/issues/52)
- Unreleased issues in separate section [\#47](https://github.com/skywinder/github-changelog-generator/issues/47)
- Separate by lists: Enhancements, Bugs, Pull requests. [\#31](https://github.com/skywinder/github-changelog-generator/issues/31)
**Fixed bugs:** **Fixed bugs:**
- Error when trying to generate log for repo without tags [\#32](https://github.com/skywinder/Github-Changelog-Generator/issues/32) - Pull request with invalid label \(\#26\) in changelog appeared. [\#44](https://github.com/skywinder/github-changelog-generator/issues/44)
**Merged pull requests:** **Merged pull requests:**
- PrettyPrint class is included using lowercase 'pp' [\#43](https://github.com/skywinder/Github-Changelog-Generator/pull/43) ([schwing](https://github.com/schwing)) - Implement filtering of Pull Requests by milestones [\#50](https://github.com/skywinder/github-changelog-generator/pull/50) ([skywinder](https://github.com/skywinder))
- support enterprise github via command line options [\#42](https://github.com/skywinder/Github-Changelog-Generator/pull/42) ([glenlovett](https://github.com/glenlovett)) ## [1.2.8](https://github.com/skywinder/github-changelog-generator/tree/1.2.8) (2015-02-17)
## [1.2.4](https://github.com/skywinder/Github-Changelog-Generator/tree/1.2.4) (2014-12-16) [Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.2.7...1.2.8)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.2.3...1.2.4) **Closed issues:**
**Fixed bugs:** - Bugs, that closed simultaneously with push not appeared in correct version. [\#37](https://github.com/skywinder/github-changelog-generator/issues/37)
- Sometimes user is NULL during merges [\#41](https://github.com/skywinder/Github-Changelog-Generator/issues/41) **Merged pull requests:**
- Crash when try generate log for rails [\#35](https://github.com/skywinder/Github-Changelog-Generator/issues/35) - Feature/fix 37 [\#49](https://github.com/skywinder/github-changelog-generator/pull/49) ([skywinder](https://github.com/skywinder))
## [1.2.3](https://github.com/skywinder/Github-Changelog-Generator/tree/1.2.3) (2014-12-16) - Prettify output [\#48](https://github.com/skywinder/github-changelog-generator/pull/48) ([skywinder](https://github.com/skywinder))
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.2.2...1.2.3) ## [1.2.7](https://github.com/skywinder/github-changelog-generator/tree/1.2.7) (2015-01-26)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.2.6...1.2.7)
**Merged pull requests:**
- Add compare link between older version and newer version [\#46](https://github.com/skywinder/github-changelog-generator/pull/46) ([sue445](https://github.com/sue445))
## [1.2.6](https://github.com/skywinder/github-changelog-generator/tree/1.2.6) (2015-01-21)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.2.5...1.2.6)
**Merged pull requests:**
- fix link tag format [\#45](https://github.com/skywinder/github-changelog-generator/pull/45) ([sugamasao](https://github.com/sugamasao))
## [1.2.5](https://github.com/skywinder/github-changelog-generator/tree/1.2.5) (2015-01-15)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.2.4...1.2.5)
**Implemented enhancements:** **Implemented enhancements:**
- Add ability to run with one parameter instead -u -p [\#38](https://github.com/skywinder/Github-Changelog-Generator/issues/38) - Use milestone to specify in which version bug was fixed [\#22](https://github.com/skywinder/github-changelog-generator/issues/22)
- Detailed output [\#33](https://github.com/skywinder/Github-Changelog-Generator/issues/33)
**Fixed bugs:** **Fixed bugs:**
- Docs lacking or basic behavior not as advertised [\#30](https://github.com/skywinder/Github-Changelog-Generator/issues/30) - Error when trying to generate log for repo without tags [\#32](https://github.com/skywinder/github-changelog-generator/issues/32)
**Merged pull requests:** **Merged pull requests:**
- Implement async fetching [\#39](https://github.com/skywinder/Github-Changelog-Generator/pull/39) ([skywinder](https://github.com/skywinder)) - PrettyPrint class is included using lowercase 'pp' [\#43](https://github.com/skywinder/github-changelog-generator/pull/43) ([schwing](https://github.com/schwing))
- Fix crash when user is NULL [\#40](https://github.com/skywinder/Github-Changelog-Generator/pull/40) ([skywinder](https://github.com/skywinder)) - support enterprise github via command line options [\#42](https://github.com/skywinder/github-changelog-generator/pull/42) ([glenlovett](https://github.com/glenlovett))
## [1.2.2](https://github.com/skywinder/Github-Changelog-Generator/tree/1.2.2) (2014-12-10) ## [1.2.4](https://github.com/skywinder/github-changelog-generator/tree/1.2.4) (2014-12-16)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.2.1...1.2.2) [Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.2.3...1.2.4)
**Fixed bugs:** **Fixed bugs:**
- Encapsulate \[ \> \* \_ \ \] signs in issues names [\#34](https://github.com/skywinder/Github-Changelog-Generator/issues/34) - Sometimes user is NULL during merges [\#41](https://github.com/skywinder/github-changelog-generator/issues/41)
**Merged pull requests:** - Crash when try generate log for rails [\#35](https://github.com/skywinder/github-changelog-generator/issues/35)
- Add a Bitdeli Badge to README [\#36](https://github.com/skywinder/Github-Changelog-Generator/pull/36) ([bitdeli-chef](https://github.com/bitdeli-chef)) ## [1.2.3](https://github.com/skywinder/github-changelog-generator/tree/1.2.3) (2014-12-16)
## [1.2.1](https://github.com/skywinder/Github-Changelog-Generator/tree/1.2.1) (2014-11-22) [Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.2.2...1.2.3)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.2.0...1.2.1)
**Fixed bugs:**
- Script fills changelog only for first 30 tags. [\#20](https://github.com/skywinder/Github-Changelog-Generator/issues/20)
**Merged pull requests:**
- Issues for last tag not in list [\#29](https://github.com/skywinder/Github-Changelog-Generator/pull/29) ([skywinder](https://github.com/skywinder))
- Disable default --filter-pull-requests option. [\#28](https://github.com/skywinder/Github-Changelog-Generator/pull/28) ([skywinder](https://github.com/skywinder))
## [1.2.0](https://github.com/skywinder/Github-Changelog-Generator/tree/1.2.0) (2014-11-19)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.1.4...1.2.0)
**Merged pull requests:**
- Add filter for pull-requests labels. \(option --filter-pull-requests\) [\#27](https://github.com/skywinder/Github-Changelog-Generator/pull/27) ([skywinder](https://github.com/skywinder))
- Add ability to insert authors of pull-requests \(--\[no-\]author option\) [\#25](https://github.com/skywinder/Github-Changelog-Generator/pull/25) ([skywinder](https://github.com/skywinder))
- Don't receive issues in case of --no-isses flag specied [\#24](https://github.com/skywinder/Github-Changelog-Generator/pull/24) ([skywinder](https://github.com/skywinder))
## [1.1.4](https://github.com/skywinder/Github-Changelog-Generator/tree/1.1.4) (2014-11-18)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.1.2...1.1.4)
**Implemented enhancements:** **Implemented enhancements:**
- Implement ability to retrieve GitHub token from ENV variable \(to not put it to script directly\) [\#19](https://github.com/skywinder/Github-Changelog-Generator/issues/19) - Add ability to run with one parameter instead -u -p [\#38](https://github.com/skywinder/github-changelog-generator/issues/38)
**Merged pull requests:** - Detailed output [\#33](https://github.com/skywinder/github-changelog-generator/issues/33)
- Sort tags by date [\#23](https://github.com/skywinder/Github-Changelog-Generator/pull/23) ([skywinder](https://github.com/skywinder))
## [1.1.2](https://github.com/skywinder/Github-Changelog-Generator/tree/1.1.2) (2014-11-12)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.1.1...1.1.2)
**Merged pull requests:**
- Fix bug with dot signs in project name [\#18](https://github.com/skywinder/Github-Changelog-Generator/pull/18) ([skywinder](https://github.com/skywinder))
- Fix bug with dot signs in user name [\#17](https://github.com/skywinder/Github-Changelog-Generator/pull/17) ([skywinder](https://github.com/skywinder))
## [1.1.1](https://github.com/skywinder/Github-Changelog-Generator/tree/1.1.1) (2014-11-10)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.1.0...1.1.1)
**Merged pull requests:**
- Remove duplicates of issues and pull-requests with same number [\#15](https://github.com/skywinder/Github-Changelog-Generator/pull/15) ([skywinder](https://github.com/skywinder))
- Sort issues by tags [\#14](https://github.com/skywinder/Github-Changelog-Generator/pull/14) ([skywinder](https://github.com/skywinder))
- Add ability to add or exclude issues without any labels [\#13](https://github.com/skywinder/Github-Changelog-Generator/pull/13) ([skywinder](https://github.com/skywinder))
## [1.1.0](https://github.com/skywinder/Github-Changelog-Generator/tree/1.1.0) (2014-11-10)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.0.1...1.1.0)
**Implemented enhancements:**
- Detect username and project form origin [\#11](https://github.com/skywinder/Github-Changelog-Generator/issues/11)
**Fixed bugs:** **Fixed bugs:**
- Bug with wrong credentials in 1.0.1 [\#12](https://github.com/skywinder/Github-Changelog-Generator/issues/12) - Docs lacking or basic behavior not as advertised [\#30](https://github.com/skywinder/github-changelog-generator/issues/30)
- Markdown formating in the last line wrong [\#9](https://github.com/skywinder/Github-Changelog-Generator/issues/9) **Merged pull requests:**
## [1.0.1](https://github.com/skywinder/Github-Changelog-Generator/tree/1.0.1) (2014-11-10) - Implement async fetching [\#39](https://github.com/skywinder/github-changelog-generator/pull/39) ([skywinder](https://github.com/skywinder))
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/1.0.0...1.0.1) - Fix crash when user is NULL [\#40](https://github.com/skywinder/github-changelog-generator/pull/40) ([skywinder](https://github.com/skywinder))
## [1.0.0](https://github.com/skywinder/Github-Changelog-Generator/tree/1.0.0) (2014-11-07) ## [1.2.2](https://github.com/skywinder/github-changelog-generator/tree/1.2.2) (2014-12-10)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/0.1.0...1.0.0) [Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.2.1...1.2.2)
**Implemented enhancements:**
- Add support for fixed issues and implemented enchanments. [\#6](https://github.com/skywinder/Github-Changelog-Generator/issues/6)
- Implement option to specify output filename [\#4](https://github.com/skywinder/Github-Changelog-Generator/issues/4)
**Fixed bugs:** **Fixed bugs:**
- Last tag not appeared in changelog [\#5](https://github.com/skywinder/Github-Changelog-Generator/issues/5) - Encapsulate \[ \> \* \_ \ \] signs in issues names [\#34](https://github.com/skywinder/github-changelog-generator/issues/34)
**Merged pull requests:** **Merged pull requests:**
- Implement support of different tags. [\#8](https://github.com/skywinder/Github-Changelog-Generator/pull/8) ([skywinder](https://github.com/skywinder)) - Add a Bitdeli Badge to README [\#36](https://github.com/skywinder/github-changelog-generator/pull/36) ([bitdeli-chef](https://github.com/bitdeli-chef))
- Add support for issues in CHANGELOG [\#7](https://github.com/skywinder/Github-Changelog-Generator/pull/7) ([skywinder](https://github.com/skywinder)) ## [1.2.1](https://github.com/skywinder/github-changelog-generator/tree/1.2.1) (2014-11-22)
## [0.1.0](https://github.com/skywinder/Github-Changelog-Generator/tree/0.1.0) (2014-11-07) [Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.2.0...1.2.1)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/0.0.2...0.1.0) **Fixed bugs:**
- Script fills changelog only for first 30 tags. [\#20](https://github.com/skywinder/github-changelog-generator/issues/20)
**Merged pull requests:** **Merged pull requests:**
- Fix parsing date of pull request [\#3](https://github.com/skywinder/Github-Changelog-Generator/pull/3) ([skywinder](https://github.com/skywinder)) - Issues for last tag not in list [\#29](https://github.com/skywinder/github-changelog-generator/pull/29) ([skywinder](https://github.com/skywinder))
- Add changelog generation for last tag [\#2](https://github.com/skywinder/Github-Changelog-Generator/pull/2) ([skywinder](https://github.com/skywinder)) - Disable default --filter-pull-requests option. [\#28](https://github.com/skywinder/github-changelog-generator/pull/28) ([skywinder](https://github.com/skywinder))
- Add option \(-o --output\) to specify name of the output file. [\#1](https://github.com/skywinder/Github-Changelog-Generator/pull/1) ([skywinder](https://github.com/skywinder)) ## [1.2.0](https://github.com/skywinder/github-changelog-generator/tree/1.2.0) (2014-11-19)
## [0.0.2](https://github.com/skywinder/Github-Changelog-Generator/tree/0.0.2) (2014-11-06) [Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.1.4...1.2.0)
[Full Changelog](https://github.com/skywinder/Github-Changelog-Generator/compare/0.0.1...0.0.2) **Merged pull requests:**
## [0.0.1](https://github.com/skywinder/Github-Changelog-Generator/tree/0.0.1) (2014-11-06) - Add filter for pull-requests labels. \(option --filter-pull-requests\) [\#27](https://github.com/skywinder/github-changelog-generator/pull/27) ([skywinder](https://github.com/skywinder))
- Add ability to insert authors of pull-requests \(--\[no-\]author option\) [\#25](https://github.com/skywinder/github-changelog-generator/pull/25) ([skywinder](https://github.com/skywinder))
- Don't receive issues in case of --no-isses flag specied [\#24](https://github.com/skywinder/github-changelog-generator/pull/24) ([skywinder](https://github.com/skywinder))
## [1.1.4](https://github.com/skywinder/github-changelog-generator/tree/1.1.4) (2014-11-18)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.1.2...1.1.4)
**Implemented enhancements:**
- Implement ability to retrieve GitHub token from ENV variable \(to not put it to script directly\) [\#19](https://github.com/skywinder/github-changelog-generator/issues/19)
**Merged pull requests:**
- Sort tags by date [\#23](https://github.com/skywinder/github-changelog-generator/pull/23) ([skywinder](https://github.com/skywinder))
## [1.1.2](https://github.com/skywinder/github-changelog-generator/tree/1.1.2) (2014-11-12)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.1.1...1.1.2)
**Merged pull requests:**
- Fix bug with dot signs in project name [\#18](https://github.com/skywinder/github-changelog-generator/pull/18) ([skywinder](https://github.com/skywinder))
- Fix bug with dot signs in user name [\#17](https://github.com/skywinder/github-changelog-generator/pull/17) ([skywinder](https://github.com/skywinder))
## [1.1.1](https://github.com/skywinder/github-changelog-generator/tree/1.1.1) (2014-11-10)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.1.0...1.1.1)
**Merged pull requests:**
- Remove duplicates of issues and pull-requests with same number [\#15](https://github.com/skywinder/github-changelog-generator/pull/15) ([skywinder](https://github.com/skywinder))
- Sort issues by tags [\#14](https://github.com/skywinder/github-changelog-generator/pull/14) ([skywinder](https://github.com/skywinder))
- Add ability to add or exclude issues without any labels [\#13](https://github.com/skywinder/github-changelog-generator/pull/13) ([skywinder](https://github.com/skywinder))
## [1.1.0](https://github.com/skywinder/github-changelog-generator/tree/1.1.0) (2014-11-10)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.0.1...1.1.0)
**Implemented enhancements:**
- Detect username and project form origin [\#11](https://github.com/skywinder/github-changelog-generator/issues/11)
**Fixed bugs:**
- Bug with wrong credentials in 1.0.1 [\#12](https://github.com/skywinder/github-changelog-generator/issues/12)
- Markdown formating in the last line wrong [\#9](https://github.com/skywinder/github-changelog-generator/issues/9)
## [1.0.1](https://github.com/skywinder/github-changelog-generator/tree/1.0.1) (2014-11-10)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/1.0.0...1.0.1)
## [1.0.0](https://github.com/skywinder/github-changelog-generator/tree/1.0.0) (2014-11-07)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/0.1.0...1.0.0)
**Implemented enhancements:**
- Add support for fixed issues and implemented enchanments. [\#6](https://github.com/skywinder/github-changelog-generator/issues/6)
- Implement option to specify output filename [\#4](https://github.com/skywinder/github-changelog-generator/issues/4)
**Fixed bugs:**
- Last tag not appeared in changelog [\#5](https://github.com/skywinder/github-changelog-generator/issues/5)
**Merged pull requests:**
- Implement support of different tags. [\#8](https://github.com/skywinder/github-changelog-generator/pull/8) ([skywinder](https://github.com/skywinder))
- Add support for issues in CHANGELOG [\#7](https://github.com/skywinder/github-changelog-generator/pull/7) ([skywinder](https://github.com/skywinder))
## [0.1.0](https://github.com/skywinder/github-changelog-generator/tree/0.1.0) (2014-11-07)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/0.0.2...0.1.0)
**Merged pull requests:**
- Fix parsing date of pull request [\#3](https://github.com/skywinder/github-changelog-generator/pull/3) ([skywinder](https://github.com/skywinder))
- Add changelog generation for last tag [\#2](https://github.com/skywinder/github-changelog-generator/pull/2) ([skywinder](https://github.com/skywinder))
- Add option \(-o --output\) to specify name of the output file. [\#1](https://github.com/skywinder/github-changelog-generator/pull/1) ([skywinder](https://github.com/skywinder))
## [0.0.2](https://github.com/skywinder/github-changelog-generator/tree/0.0.2) (2014-11-06)
[Full Changelog](https://github.com/skywinder/github-changelog-generator/compare/0.0.1...0.0.2)
## [0.0.1](https://github.com/skywinder/github-changelog-generator/tree/0.0.1) (2014-11-06)

17
Gemfile
View File

@@ -1,13 +1,14 @@
source 'https://rubygems.org' source "https://rubygems.org"
gem 'rake' gem "rake"
gem 'github_api' gem "github_api"
gem 'colorize' gem "colorize"
group :test do group :test do
gem 'rspec' gem "rspec"
gem 'rubocop' gem "rubocop"
gem 'coveralls', require: false gem "coveralls", require: false
gem 'simplecov', require: false gem "simplecov", require: false
gem "codeclimate-test-reporter"
end end

View File

@@ -5,6 +5,8 @@ GEM
ast (2.0.0) ast (2.0.0)
astrolabe (1.3.0) astrolabe (1.3.0)
parser (>= 2.2.0.pre.3, < 3.0) parser (>= 2.2.0.pre.3, < 3.0)
codeclimate-test-reporter (0.4.7)
simplecov (>= 0.7.1, < 1.0.0)
colorize (0.7.5) colorize (0.7.5)
coveralls (0.7.12) coveralls (0.7.12)
multi_json (~> 1.10) multi_json (~> 1.10)
@@ -94,6 +96,7 @@ PLATFORMS
ruby ruby
DEPENDENCIES DEPENDENCIES
codeclimate-test-reporter
colorize colorize
coveralls coveralls
github_api github_api

View File

@@ -1,8 +1,9 @@
[![Gem Version](https://badge.fury.io/rb/github_changelog_generator.svg)](http://badge.fury.io/rb/github_changelog_generator)
[![Dependency Status](https://gemnasium.com/skywinder/github-changelog-generator.svg)](https://gemnasium.com/skywinder/github-changelog-generator) [![Dependency Status](https://gemnasium.com/skywinder/github-changelog-generator.svg)](https://gemnasium.com/skywinder/github-changelog-generator)
[![Build Status](https://travis-ci.org/skywinder/github-changelog-generator.svg?branch=master)](https://travis-ci.org/skywinder/github-changelog-generator) [![Build Status](https://travis-ci.org/skywinder/github-changelog-generator.svg?branch=master)](https://travis-ci.org/skywinder/github-changelog-generator)
[![Coverage Status](http://img.shields.io/coveralls/skywinder/github-changelog-generator/master.svg)](https://coveralls.io/r/skywinder/github-changelog-generator)
[![Code Climate](https://codeclimate.com/github/skywinder/github-changelog-generator/badges/gpa.svg)](https://codeclimate.com/github/skywinder/github-changelog-generator)
[![Inline docs](http://inch-ci.org/github/skywinder/github-changelog-generator.svg)](http://inch-ci.org/github/skywinder/github-changelog-generator) [![Inline docs](http://inch-ci.org/github/skywinder/github-changelog-generator.svg)](http://inch-ci.org/github/skywinder/github-changelog-generator)
[![Code Climate](https://codeclimate.com/github/skywinder/github-changelog-generator/badges/gpa.svg)](https://codeclimate.com/github/skywinder/github-changelog-generator)
[![Test Coverage](https://codeclimate.com/github/skywinder/github-changelog-generator/badges/coverage.svg)](https://codeclimate.com/github/skywinder/github-changelog-generator)
GitHub Changelog Generator ![GitHub Logo](../master/images/logo.jpg) GitHub Changelog Generator ![GitHub Logo](../master/images/logo.jpg)
================== ==================
@@ -110,7 +111,7 @@ Type `github_changelog_generator --help` for detailed usage.
Since GitHub allows you to make only 50 requests without authentication it's recommended to run this script with a token (`-t, --token` option) Since GitHub allows you to make only 50 requests without authentication it's recommended to run this script with a token (`-t, --token` option)
**You can easily [generate it here](https://github.com/settings/applications)**. **You can easily [generate it here](https://github.com/settings/tokens)**.
And: And:
@@ -155,6 +156,8 @@ Here is a [wikipage list of alternatives](https://github.com/skywinder/Github-Ch
### Projects using this library ### Projects using this library
[Wikipage with list of projects](https://github.com/skywinder/Github-Changelog-Generator/wiki/Projects-using-Github-Changelog-Generator) [Wikipage with list of projects](https://github.com/skywinder/Github-Changelog-Generator/wiki/Projects-using-Github-Changelog-Generator)
If you've used this project in a live app, please let me know! Nothing makes me happier than seeing someone else take my work and go wild with it.
*If you are using `github_changelog_generator` for generation change log in your project or know another project that uses it, please add it to [this] (https://github.com/skywinder/Github-Changelog-Generator/wiki/Projects-using-Github-Changelog-Generator) list.* *If you are using `github_changelog_generator` for generation change log in your project or know another project that uses it, please add it to [this] (https://github.com/skywinder/Github-Changelog-Generator/wiki/Projects-using-Github-Changelog-Generator) list.*
## Am I missing some essential feature? ## Am I missing some essential feature?

View File

@@ -1,5 +1,5 @@
require 'rubocop/rake_task' require "rubocop/rake_task"
require 'rspec/core/rake_task' require "rspec/core/rake_task"
RuboCop::RakeTask.new RuboCop::RakeTask.new
RSpec::Core::RakeTask.new(:rspec) RSpec::Core::RakeTask.new(:rspec)

View File

@@ -1,4 +1,4 @@
#! /usr/bin/env ruby #! /usr/bin/env ruby
require_relative '../lib/github_changelog_generator' require_relative "../lib/github_changelog_generator"
GitHubChangelogGenerator::ChangelogGenerator.new.compound_changelog GitHubChangelogGenerator::ChangelogGenerator.new.compound_changelog

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
require 'optparse' require "optparse"
SPEC_TYPE = 'gemspec' SPEC_TYPE = "gemspec"
:major :major
:minor :minor
@@ -10,21 +10,21 @@ SPEC_TYPE = 'gemspec'
@options = { dry_run: false, bump_number: :patch } @options = { dry_run: false, bump_number: :patch }
OptionParser.new { |opts| OptionParser.new { |opts|
opts.banner = 'Usage: bump.rb [options]' opts.banner = "Usage: bump.rb [options]"
opts.on('-d', '--dry-run', 'Dry run') do |v| opts.on("-d", "--dry-run", "Dry run") do |v|
@options[:dry_run] = v @options[:dry_run] = v
end end
opts.on('-a', '--major', 'Bump major version') do |_v| opts.on("-a", "--major", "Bump major version") do |_v|
@options[:bump_number] = :major @options[:bump_number] = :major
end end
opts.on('-m', '--minor', 'Bump minor version') do |_v| opts.on("-m", "--minor", "Bump minor version") do |_v|
@options[:bump_number] = :minor @options[:bump_number] = :minor
end end
opts.on('-p', '--patch', 'Bump patch version') do |_v| opts.on("-p", "--patch", "Bump patch version") do |_v|
@options[:bump_number] = :patch @options[:bump_number] = :patch
end end
opts.on('-r', '--revert', 'Revert last bump') do |v| opts.on("-r", "--revert", "Revert last bump") do |v|
@options[:revert] = v @options[:revert] = v
end end
}.parse! }.parse!
@@ -32,15 +32,15 @@ OptionParser.new { |opts|
p @options p @options
def check_repo_is_clean_or_dry_run def check_repo_is_clean_or_dry_run
value = `#{'git status --porcelain'}` value = `#{"git status --porcelain"}`
if value.empty? if value.empty?
puts 'Repo is clean -> continue' puts "Repo is clean -> continue"
else else
if @options[:dry_run] if @options[:dry_run]
puts 'Repo not clean, "Dry run" enabled -> continue' puts 'Repo not clean, "Dry run" enabled -> continue'
else else
puts 'Repository not clean -> exit' puts "Repository not clean -> exit"
exit exit
end end
end end
@@ -50,7 +50,7 @@ def find_spec_file
list_of_specs = execute_line("find . -name '*.#{SPEC_TYPE}'") list_of_specs = execute_line("find . -name '*.#{SPEC_TYPE}'")
arr = list_of_specs.split("\n") arr = list_of_specs.split("\n")
spec_file = '' spec_file = ""
case arr.count case arr.count
when 0 when 0
@@ -59,7 +59,7 @@ def find_spec_file
when 1 when 1
spec_file = arr[0] spec_file = arr[0]
else else
puts 'Which spec should be used?' puts "Which spec should be used?"
arr.each_with_index { |file, index| puts "#{index + 1}. #{file}" } arr.each_with_index { |file, index| puts "#{index + 1}. #{file}" }
input_index = Integer(gets.chomp) input_index = Integer(gets.chomp)
spec_file = arr[input_index - 1] spec_file = arr[input_index - 1]
@@ -70,14 +70,14 @@ def find_spec_file
exit exit
end end
spec_file.sub('./', '') spec_file.sub("./", "")
end end
def find_current_gem_file def find_current_gem_file
list_of_specs = execute_line("find . -name '*.gem'") list_of_specs = execute_line("find . -name '*.gem'")
arr = list_of_specs.split("\n") arr = list_of_specs.split("\n")
spec_file = '' spec_file = ""
case arr.count case arr.count
when 0 when 0
@@ -86,7 +86,7 @@ def find_current_gem_file
when 1 when 1
spec_file = arr[0] spec_file = arr[0]
else else
puts 'Which spec should be used?' puts "Which spec should be used?"
arr.each_with_index { |file, index| puts "#{index + 1}. #{file}" } arr.each_with_index { |file, index| puts "#{index + 1}. #{file}" }
input_index = Integer(gets.chomp) input_index = Integer(gets.chomp)
spec_file = arr[input_index - 1] spec_file = arr[input_index - 1]
@@ -97,7 +97,7 @@ def find_current_gem_file
exit exit
end end
spec_file.sub('./', '') spec_file.sub("./", "")
end end
def find_version_in_podspec(podspec) def find_version_in_podspec(podspec)
@@ -109,7 +109,7 @@ def find_version_in_podspec(podspec)
match_result = re.match(readme) match_result = re.match(readme)
unless match_result unless match_result
puts 'Not found any versions' puts "Not found any versions"
exit exit
end end
@@ -132,10 +132,10 @@ def bump_version(versions_array)
when :patch when :patch
bumped_result[2] += 1 bumped_result[2] += 1
else else
fail('unknown bump_number') fail("unknown bump_number")
end end
bumped_version = bumped_result.join('.') bumped_version = bumped_result.join(".")
puts "Bump version: #{versions_array.join('.')} -> #{bumped_version}" puts "Bump version: #{versions_array.join('.')} -> #{bumped_version}"
bumped_version bumped_version
end end
@@ -174,10 +174,10 @@ def run_bumping_script
bumped_version = bump_version(versions_array) bumped_version = bump_version(versions_array)
unless @options[:dry_run] unless @options[:dry_run]
puts 'Are you sure? Press Y to continue:' puts "Are you sure? Press Y to continue:"
str = gets.chomp str = gets.chomp
if str != 'Y' if str != "Y"
puts '-> exit' puts "-> exit"
exit exit
end end
end end
@@ -186,8 +186,8 @@ def run_bumping_script
execute_line_if_not_dry_run("sed -i \"\" \"s/#{result}/#{bumped_version}/\" #{spec_file}") execute_line_if_not_dry_run("sed -i \"\" \"s/#{result}/#{bumped_version}/\" #{spec_file}")
execute_line_if_not_dry_run("git commit --all -m \"Update #{$SPEC_TYPE} to version #{bumped_version}\"") execute_line_if_not_dry_run("git commit --all -m \"Update #{$SPEC_TYPE} to version #{bumped_version}\"")
execute_line_if_not_dry_run("git tag #{bumped_version}") execute_line_if_not_dry_run("git tag #{bumped_version}")
execute_line_if_not_dry_run('git push') execute_line_if_not_dry_run("git push")
execute_line_if_not_dry_run('git push --tags') execute_line_if_not_dry_run("git push --tags")
execute_line_if_not_dry_run("gem build #{spec_file}") execute_line_if_not_dry_run("gem build #{spec_file}")
gem = find_current_gem_file gem = find_current_gem_file
@@ -201,12 +201,12 @@ def revert_last_bump
puts "DELETE tag #{result} and HARD reset HEAD~1?\nPress Y to continue:" puts "DELETE tag #{result} and HARD reset HEAD~1?\nPress Y to continue:"
str = gets.chomp str = gets.chomp
if str != 'Y' if str != "Y"
puts '-> exit' puts "-> exit"
exit exit
end end
execute_line_if_not_dry_run("git tag -d #{result}") execute_line_if_not_dry_run("git tag -d #{result}")
execute_line_if_not_dry_run('git reset --hard HEAD~1') execute_line_if_not_dry_run("git reset --hard HEAD~1")
execute_line_if_not_dry_run("git push --delete origin #{result}") execute_line_if_not_dry_run("git push --delete origin #{result}")
end end

View File

@@ -1,31 +1,31 @@
# coding: utf-8 # coding: utf-8
lib = File.expand_path('../lib', __FILE__) lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'github_changelog_generator/version' require "github_changelog_generator/version"
Gem::Specification.new do |spec| Gem::Specification.new do |spec|
spec.name = 'github_changelog_generator' spec.name = "github_changelog_generator"
spec.version = GitHubChangelogGenerator::VERSION spec.version = GitHubChangelogGenerator::VERSION
spec.default_executable = 'github_changelog_generator' spec.default_executable = "github_changelog_generator"
spec.required_ruby_version = '>= 1.9.3' spec.required_ruby_version = ">= 1.9.3"
spec.authors = ['Petr Korolev'] spec.authors = ["Petr Korolev"]
spec.email = 'sky4winder+github_changelog_generator@gmail.com' spec.email = "sky4winder+github_changelog_generator@gmail.com"
spec.date = `date +"%Y-%m-%d"`.strip! spec.date = `date +"%Y-%m-%d"`.strip!
spec.summary = 'Script, that automatically generate changelog from your tags, issues, labels and pull requests.' spec.summary = "Script, that automatically generate changelog from your tags, issues, labels and pull requests."
spec.description = 'Changelog generation has never been so easy. Fully automate changelog generation - this gem generate change log file based on tags, issues and merged pull requests from Github issue tracker.' spec.description = "Changelog generation has never been so easy. Fully automate changelog generation - this gem generate change log file based on tags, issues and merged pull requests from Github issue tracker."
spec.homepage = 'https://github.com/skywinder/Github-Changelog-Generator' spec.homepage = "https://github.com/skywinder/Github-Changelog-Generator"
spec.license = 'MIT' spec.license = "MIT"
spec.files = `git ls-files -z`.split("\x0") spec.files = `git ls-files -z`.split("\x0")
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ['lib'] spec.require_paths = ["lib"]
spec.add_development_dependency 'bundler', '~> 1.7' spec.add_development_dependency "bundler", "~> 1.7"
spec.add_development_dependency 'rake', '~> 10.0' spec.add_development_dependency "rake", "~> 10.0"
spec.add_runtime_dependency('github_api', ['~> 0.12']) spec.add_runtime_dependency("github_api", ["~> 0.12"])
spec.add_runtime_dependency('colorize', ['~> 0.7']) spec.add_runtime_dependency("colorize", ["~> 0.7"])
end end

View File

@@ -6,6 +6,8 @@
**Merged pull requests:** **Merged pull requests:**
- This PR SHOULD NOT appear in change log! [\#6](https://github.com/skywinder/changelog_test/pull/6) ([skywinder](https://github.com/skywinder))
- Add automatically generated change log file. [\#5](https://github.com/skywinder/changelog_test/pull/5) ([skywinder](https://github.com/skywinder)) - 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) ## [v0.0.3](https://github.com/skywinder/changelog_test/tree/v0.0.3) (2015-03-04)

View File

@@ -1,59 +1,62 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
require 'github_api' require "github_api"
require 'json' require "json"
require 'colorize' require "colorize"
require 'benchmark' require "benchmark"
require_relative 'github_changelog_generator/parser' require_relative "github_changelog_generator/parser"
require_relative 'github_changelog_generator/generator' require_relative "github_changelog_generator/generator"
require_relative 'github_changelog_generator/version' require_relative "github_changelog_generator/version"
require_relative 'github_changelog_generator/reader' require_relative "github_changelog_generator/reader"
require_relative "github_changelog_generator/fetcher"
module GitHubChangelogGenerator module GitHubChangelogGenerator
# Default error for ChangelogGenerator
class ChangelogGeneratorError < StandardError
end
# Main class and entry point for this script.
class ChangelogGenerator class ChangelogGenerator
attr_accessor :options, :all_tags, :github attr_accessor :options, :all_tags, :github
PER_PAGE_NUMBER = 30 # Class, responsible for whole change log generation cycle
GH_RATE_LIMIT_EXCEEDED_MSG = 'Warning: GitHub API rate limit (5000 per hour) exceeded, change log may be ' \ # @return initialised instance of ChangelogGenerator
'missing some issues. You can limit the number of issues fetched using the `--max-issues NUM` argument.'
def initialize def initialize
@options = Parser.parse_options @options = Parser.parse_options
fetch_github_token @fetcher = GitHubChangelogGenerator::Fetcher.new @options
github_options = { per_page: PER_PAGE_NUMBER } @generator = Generator.new @options
github_options[:oauth_token] = @github_token unless @github_token.nil?
github_options[:endpoint] = options[:github_endpoint] unless options[:github_endpoint].nil?
github_options[:site] = options[:github_endpoint] unless options[:github_site].nil?
begin # @all_tags = get_filtered_tags
@github = Github.new github_options @all_tags = @fetcher.get_all_tags
rescue
puts GH_RATE_LIMIT_EXCEEDED_MSG.yellow
end
@generator = Generator.new(@options) @issues, @pull_requests = @fetcher.fetch_issues_and_pull_requests
@all_tags = get_all_tags @pull_requests = @options[:pulls] ? get_filtered_pull_requests : []
@issues, @pull_requests = fetch_issues_and_pull_requests
if @options[:pulls] @issues = @options[:issues] ? get_filtered_issues : []
@pull_requests = get_filtered_pull_requests
else
@pull_requests = []
end
if @options[:issues]
@issues = get_filtered_issues
else
@issues = []
end
fetch_event_for_issues_and_pr fetch_event_for_issues_and_pr
detect_actual_closed_dates detect_actual_closed_dates
@tag_times_hash = {} end
# Return tags after filtering tags in lists provided by option: --between-tags & --exclude-tags
#
# @return [Array]
def get_filtered_tags
all_tags = @fetcher.get_all_tags
filtered_tags = []
if @options[:between_tags]
@options[:between_tags].each do |tag|
unless all_tags.include? tag
puts "Warning: can't find tag #{tag}, specified with --between-tags option.".yellow
end
end
filtered_tags = all_tags.select { |tag| @options[:between_tags].include? tag }
end
filtered_tags
end end
def detect_actual_closed_dates def detect_actual_closed_dates
@@ -77,22 +80,24 @@ module GitHubChangelogGenerator
threads.each(&:join) threads.each(&:join)
if @options[:verbose] if @options[:verbose]
puts 'Fetching closed dates for issues: Done!' puts "Fetching closed dates for issues: Done!"
end end
end end
# Fill :actual_date parameter of specified issue by closed date of the commit, it it was closed by commit.
# @param [Hash] issue
def find_closed_date_by_commit(issue) def find_closed_date_by_commit(issue)
unless issue['events'].nil? unless issue["events"].nil?
# if it's PR -> then find "merged event", in case of usual issue -> fond closed date # if it's PR -> then find "merged event", in case of usual issue -> fond closed date
compare_string = issue[:merged_at].nil? ? 'closed' : 'merged' compare_string = issue[:merged_at].nil? ? "closed" : "merged"
# reverse! - to find latest closed event. (event goes in date order) # reverse! - to find latest closed event. (event goes in date order)
issue['events'].reverse!.each { |event| issue["events"].reverse!.each { |event|
if event[:event].eql? compare_string if event[:event].eql? compare_string
if event[:commit_id].nil? if event[:commit_id].nil?
issue[:actual_date] = issue[:closed_at] issue[:actual_date] = issue[:closed_at]
else else
begin begin
commit = @github.git_data.commits.get @options[:user], @options[:project], event[:commit_id] commit = @fetcher.fetch_commit(event)
issue[:actual_date] = commit[:author][:date] issue[:actual_date] = commit[:author][:date]
rescue rescue
puts "Warning: Can't fetch commit #{event[:commit_id]}. It is probably referenced from another repo.".yellow puts "Warning: Can't fetch commit #{event[:commit_id]}. It is probably referenced from another repo.".yellow
@@ -110,25 +115,32 @@ module GitHubChangelogGenerator
puts JSON.pretty_generate(json) puts JSON.pretty_generate(json)
end end
# This method fetches missing params for PR and filter them by specified options
# It include add all PR's with labels from @options[:include_labels] array
# And exclude all from :exclude_labels array.
# @return [Array] filtered PR's
def get_filtered_pull_requests
fetch_merged_at_pull_requests
filtered_pull_requests = include_issues_by_labels(@pull_requests)
filtered_pull_requests = exclude_issues_by_labels(filtered_pull_requests)
if @options[:verbose]
puts "Filtered pull requests: #{filtered_pull_requests.count}"
end
filtered_pull_requests
end
# This method fetch missing required attributes for pull requests
# :merged_at - is a date, when issue PR was merged.
# More correct to use this date, not closed date.
def fetch_merged_at_pull_requests def fetch_merged_at_pull_requests
if @options[:verbose] if @options[:verbose]
print "Fetching merged dates...\r" print "Fetching merged dates...\r"
end end
pull_requests = [] pull_requests = @fetcher.fetch_pull_requests
begin
response = @github.pull_requests.list @options[:user], @options[:project], state: 'closed'
page_i = 0
response.each_page do |page|
page_i += PER_PAGE_NUMBER
count_pages = response.count_pages
print "Fetching merged dates... #{page_i}/#{count_pages * PER_PAGE_NUMBER}\r"
pull_requests.concat(page)
end
rescue
puts GH_RATE_LIMIT_EXCEEDED_MSG.yellow
end
print " \r"
@pull_requests.each { |pr| @pull_requests.each { |pr|
fetched_pr = pull_requests.find { |fpr| fetched_pr = pull_requests.find { |fpr|
@@ -139,43 +151,39 @@ module GitHubChangelogGenerator
} }
if @options[:verbose] if @options[:verbose]
puts 'Fetching merged dates: Done!' puts "Fetching merged dates: Done!"
end end
end end
def get_filtered_pull_requests # Include issues with labels, specified in :include_labels
fetch_merged_at_pull_requests # @param [Array] issues to filter
# @return [Array] filtered array of issues
def include_issues_by_labels(issues)
filtered_issues = @options[:include_labels].nil? ? issues : issues.select { |issue| (issue.labels.map(&:name) & @options[:include_labels]).any? }
filtered_pull_requests = @pull_requests.select { |pr| !pr[:merged_at].nil? } if @options[:add_issues_wo_labels]
issues_wo_labels = issues.select { |issue|
unless @options[:include_labels].nil? !issue.labels.map(&:name).any?
filtered_pull_requests = @pull_requests.select { |issue|
# add all labels from @options[:include_labels] array
(issue.labels.map(&:name) & @options[:include_labels]).any?
} }
filtered_issues |= issues_wo_labels
end end
filtered_issues
end
# delete all labels with labels from @options[:exclude_labels] array
# @param [Array] issues
# @return [Array] filtered array
def exclude_issues_by_labels(issues)
unless @options[:exclude_labels].nil? unless @options[:exclude_labels].nil?
filtered_pull_requests = filtered_pull_requests.select { |issue| issues = issues.select { |issue|
# delete all labels from @options[:exclude_labels] array
!(issue.labels.map(&:name) & @options[:exclude_labels]).any? !(issue.labels.map(&:name) & @options[:exclude_labels]).any?
} }
end end
issues
if @options[:add_issues_wo_labels]
issues_wo_labels = @pull_requests.select { |issue|
!issue.labels.map(&:name).any?
}
filtered_pull_requests |= issues_wo_labels
end
if @options[:verbose]
puts "Filtered pull requests: #{filtered_pull_requests.count}"
end
filtered_pull_requests
end end
# The entry point of this script to generate change log
# @raise (ChangelogGeneratorError) Is thrown when one of specified tags was not found in list of tags.
def compound_changelog def compound_changelog
log = "# Change Log\n\n" log = "# Change Log\n\n"
@@ -185,7 +193,7 @@ module GitHubChangelogGenerator
tag1 = @options[:tag1] tag1 = @options[:tag1]
tag2 = @options[:tag2] tag2 = @options[:tag2]
tags_strings = [] tags_strings = []
all_tags.each { |x| tags_strings.push(x['name']) } all_tags.each { |x| tags_strings.push(x["name"]) }
if tags_strings.include?(tag1) if tags_strings.include?(tag1)
if tags_strings.include?(tag2) if tags_strings.include?(tag2)
@@ -195,12 +203,10 @@ module GitHubChangelogGenerator
index2 = hash[tag2] index2 = hash[tag2]
log += generate_log_between_tags(all_tags[index1], all_tags[index2]) log += generate_log_between_tags(all_tags[index1], all_tags[index2])
else else
puts "Can't find tag #{tag2} -> exit" fail ChangelogGeneratorError, "Can't find tag #{tag2} -> exit".red
exit
end end
else else
puts "Can't find tag #{tag1} -> exit" fail ChangelogGeneratorError, "Can't find tag #{tag1} -> exit".red
exit
end end
else else
log += generate_log_for_all_tags log += generate_log_for_all_tags
@@ -209,25 +215,27 @@ module GitHubChangelogGenerator
log += "\n\n\\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*" log += "\n\n\\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*"
output_filename = "#{@options[:output]}" output_filename = "#{@options[:output]}"
File.open(output_filename, 'w') { |file| file.write(log) } File.open(output_filename, "w") { |file| file.write(log) }
puts 'Done!' puts "Done!"
puts "Generated log placed in #{`pwd`.strip!}/#{output_filename}" puts "Generated log placed in #{`pwd`.strip!}/#{output_filename}"
end end
# The full cycle of generation for whole project
# @return [String] The complete change log
def generate_log_for_all_tags def generate_log_for_all_tags
fetch_tags_dates fetch_tags_dates
if @options[:verbose] if @options[:verbose]
puts 'Sorting tags...' puts "Sorting tags..."
end end
@all_tags.sort_by! { |x| get_time_of_tag(x) }.reverse! @all_tags.sort_by! { |x| @fetcher.get_time_of_tag(x) }.reverse!
if @options[:verbose] if @options[:verbose]
puts 'Generating log...' puts "Generating log..."
end end
log = '' log = ""
if @options[:unreleased] && @all_tags.count != 0 if @options[:unreleased] && @all_tags.count != 0
unreleased_log = generate_log_between_tags(all_tags[0], nil) unreleased_log = generate_log_between_tags(all_tags[0], nil)
@@ -246,6 +254,7 @@ module GitHubChangelogGenerator
log log
end end
# Async fetching of all tags dates
def fetch_tags_dates def fetch_tags_dates
if @options[:verbose] if @options[:verbose]
print "Fetching tag dates...\r" print "Fetching tag dates...\r"
@@ -256,9 +265,8 @@ module GitHubChangelogGenerator
i = 0 i = 0
all = @all_tags.count all = @all_tags.count
@all_tags.each { |tag| @all_tags.each { |tag|
# explicit set @tag_times_hash to write data safety.
threads << Thread.new { threads << Thread.new {
get_time_of_tag(tag, @tag_times_hash) @fetcher.get_time_of_tag(tag)
if @options[:verbose] if @options[:verbose]
print "Fetching tags dates: #{i + 1}/#{all}\r" print "Fetching tags dates: #{i + 1}/#{all}\r"
i += 1 i += 1
@@ -275,55 +283,15 @@ module GitHubChangelogGenerator
end end
end end
def get_all_tags # Generate log only between 2 specified tags
if @options[:verbose] # @param [String] older_tag all issues before this tag date will be excluded. May be nil, if it's first tag
print "Fetching tags...\r" # @param [String] newer_tag all issue after this tag will be excluded. May be nil for unreleased section
end
tags = []
begin
response = @github.repos.tags @options[:user], @options[:project]
page_i = 0
count_pages = response.count_pages
response.each_page do |page|
page_i += PER_PAGE_NUMBER
print "Fetching tags... #{page_i}/#{count_pages * PER_PAGE_NUMBER}\r"
tags.concat(page)
end
print " \r"
if tags.count == 0
puts "Warning: Can't find any tags in repo. Make sure, that you push tags to remote repo via 'git push --tags'".yellow
elsif @options[:verbose]
puts "Found #{tags.count} tags"
end
rescue
puts GH_RATE_LIMIT_EXCEEDED_MSG.yellow
end
tags
end
def fetch_github_token
env_var = @options[:token] ? @options[:token] : (ENV.fetch 'CHANGELOG_GITHUB_TOKEN', nil)
unless env_var
puts 'Warning: No token provided (-t option) and variable $CHANGELOG_GITHUB_TOKEN was not found.'.yellow
puts 'This script can make only 50 requests per hour to GitHub API without a token!'.yellow
end
@github_token ||= env_var
end
def generate_log_between_tags(older_tag, newer_tag) def generate_log_between_tags(older_tag, newer_tag)
# older_tag nil - means it's first tag, newer_tag nil - means it unreleased section
filtered_pull_requests = delete_by_time(@pull_requests, :actual_date, 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) filtered_issues = delete_by_time(@issues, :actual_date, older_tag, newer_tag)
newer_tag_name = newer_tag.nil? ? nil : newer_tag['name'] newer_tag_name = newer_tag.nil? ? nil : newer_tag["name"]
older_tag_name = older_tag.nil? ? nil : older_tag['name'] older_tag_name = older_tag.nil? ? nil : older_tag["name"]
if @options[:filter_issues_by_milestone] if @options[:filter_issues_by_milestone]
# delete excess irrelevant issues (according milestones) # delete excess irrelevant issues (according milestones)
@@ -333,7 +301,7 @@ module GitHubChangelogGenerator
if filtered_issues.empty? && filtered_pull_requests.empty? && newer_tag.nil? if filtered_issues.empty? && filtered_pull_requests.empty? && newer_tag.nil?
# do not generate empty unreleased section # do not generate empty unreleased section
return '' return ""
end end
create_log(filtered_pull_requests, filtered_issues, newer_tag, older_tag_name) create_log(filtered_pull_requests, filtered_issues, newer_tag, older_tag_name)
@@ -374,11 +342,17 @@ module GitHubChangelogGenerator
filtered_issues filtered_issues
end end
def delete_by_time(array, hash_key, older_tag = nil, newer_tag = nil) # Method filter issues, that belong only specified tag range
fail 'At least one of the tags should be not nil!' if older_tag.nil? && newer_tag.nil? # @param [Array] array of issues to filter
# @param [Symbol] hash_key key of date value default is :actual_date
# @param [String] older_tag all issues before this tag date will be excluded. May be nil, if it's first tag
# @param [String] newer_tag all issue after this tag will be excluded. May be nil for unreleased section
# @return [Array] filtered issues
def delete_by_time(array, hash_key = :actual_date, older_tag = nil, newer_tag = nil)
fail ChangelogGeneratorError, "At least one of the tags should be not nil!".red if older_tag.nil? && newer_tag.nil?
newer_tag_time = get_time_of_tag(newer_tag) newer_tag_time = newer_tag && @fetcher.get_time_of_tag(newer_tag)
older_tag_time = get_time_of_tag(older_tag) older_tag_time = older_tag && @fetcher.get_time_of_tag(older_tag)
array.select { |req| array.select { |req|
if req[hash_key] if req[hash_key]
@@ -405,16 +379,19 @@ module GitHubChangelogGenerator
} }
end end
# @param [Array] pull_requests # Generates log for section with header and body
# @param [Array] issues #
# @param [String] older_tag_name # @param [Array] pull_requests List or PR's in new section
# @return [String] # @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 [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(pull_requests, issues, newer_tag, older_tag_name = nil) def create_log(pull_requests, issues, newer_tag, older_tag_name = nil)
newer_tag_time = newer_tag.nil? ? Time.new : get_time_of_tag(newer_tag) newer_tag_time = newer_tag.nil? ? Time.new : @fetcher.get_time_of_tag(newer_tag)
newer_tag_name = newer_tag.nil? ? @options[:unreleased_label] : newer_tag['name'] newer_tag_name = newer_tag.nil? ? @options[:unreleased_label] : newer_tag["name"]
newer_tag_link = newer_tag.nil? ? 'HEAD' : newer_tag_name newer_tag_link = newer_tag.nil? ? "HEAD" : newer_tag_name
github_site = options[:github_site] || 'https://github.com' github_site = options[:github_site] || "https://github.com"
project_url = "#{github_site}/#{@options[:user]}/#{@options[:project]}" project_url = "#{github_site}/#{@options[:user]}/#{@options[:project]}"
log = generate_header(newer_tag_name, newer_tag_link, newer_tag_time, older_tag_name, project_url) log = generate_header(newer_tag_name, newer_tag_link, newer_tag_time, older_tag_name, project_url)
@@ -428,12 +405,12 @@ module GitHubChangelogGenerator
issues.each { |dict| issues.each { |dict|
added = false added = false
dict.labels.each { |label| dict.labels.each { |label|
if label.name == 'bug' if label.name == "bug"
bugs_a.push dict bugs_a.push dict
added = true added = true
next next
end end
if label.name == 'enhancement' if label.name == "enhancement"
enhancement_a.push dict enhancement_a.push dict
added = true added = true
next next
@@ -444,22 +421,26 @@ module GitHubChangelogGenerator
end end
} }
log += generate_log_from_array(enhancement_a, @options[:enhancement_prefix]) log += generate_sub_section(enhancement_a, @options[:enhancement_prefix])
log += generate_log_from_array(bugs_a, @options[:bug_prefix]) log += generate_sub_section(bugs_a, @options[:bug_prefix])
log += generate_log_from_array(issues_a, @options[:issue_prefix]) log += generate_sub_section(issues_a, @options[:issue_prefix])
end end
if @options[:pulls] if @options[:pulls]
# Generate pull requests: # Generate pull requests:
log += generate_log_from_array(pull_requests, @options[:merge_prefix]) log += generate_sub_section(pull_requests, @options[:merge_prefix])
end end
log log
end end
def generate_log_from_array(issues, prefix) # @param [Array] issues List of issues on sub-section
log = '' # @param [String] prefix Nae of sub-section
if options[:simple_list].nil? && issues.any? # @return [String] Generate ready-to-go sub-section
def generate_sub_section(issues, prefix)
log = ""
if options[:simple_list] != true && issues.any?
log += "#{prefix}\n\n" log += "#{prefix}\n\n"
end end
@@ -472,70 +453,41 @@ module GitHubChangelogGenerator
log log
end end
def generate_header(newer_tag_name, newer_tag_name2, newer_tag_time, older_tag_name, project_url) # It generate one header for section with specific parameters.
log = '' #
# @param [String] newer_tag_name - name of newer tag
# @param [String] newer_tag_link - used for links. Could be same as #newer_tag_name or some specific value, like HEAD
# @param [Time] newer_tag_time - time, when newer tag created
# @param [String] older_tag_link - tag name, used for links.
# @param [String] project_url - url for current project.
# @return [String] - Generate one ready-to-add section.
def generate_header(newer_tag_name, newer_tag_link, newer_tag_time, older_tag_link, project_url)
log = ""
# Generate date string: # Generate date string:
time_string = newer_tag_time.strftime @options[:dateformat] time_string = newer_tag_time.strftime @options[:dateformat]
# Generate tag name and link # Generate tag name and link
if newer_tag_name.equal? @options[:unreleased_label] if newer_tag_name.equal? @options[:unreleased_label]
log += "## [#{newer_tag_name}](#{project_url}/tree/#{newer_tag_name2})\n\n" log += "## [#{newer_tag_name}](#{project_url}/tree/#{newer_tag_link})\n\n"
else else
log += "## [#{newer_tag_name}](#{project_url}/tree/#{newer_tag_name2}) (#{time_string})\n\n" log += "## [#{newer_tag_name}](#{project_url}/tree/#{newer_tag_link}) (#{time_string})\n\n"
end end
if @options[:compare_link] && older_tag_name if @options[:compare_link] && older_tag_link
# Generate compare link # Generate compare link
log += "[Full Changelog](#{project_url}/compare/#{older_tag_name}...#{newer_tag_name2})\n\n" log += "[Full Changelog](#{project_url}/compare/#{older_tag_link}...#{newer_tag_link})\n\n"
end end
log log
end end
def get_time_of_tag(tag_name, tag_times_hash = @tag_times_hash) # Filter issues according labels
if tag_name.nil? # @return [Array] Filtered issues
return nil
end
if tag_times_hash[tag_name['name']]
return @tag_times_hash[tag_name['name']]
end
begin
github_git_data_commits_get = @github.git_data.commits.get @options[:user], @options[:project], tag_name['commit']['sha']
rescue
puts GH_RATE_LIMIT_EXCEEDED_MSG.yellow
end
time_string = github_git_data_commits_get['committer']['date']
@tag_times_hash[tag_name['name']] = Time.parse(time_string)
end
def get_filtered_issues def get_filtered_issues
issues = @issues filtered_issues = include_issues_by_labels(@issues)
filtered_issues = issues filtered_issues = exclude_issues_by_labels(filtered_issues)
unless @options[:include_labels].nil?
filtered_issues = issues.select { |issue|
# add all labels from @options[:include_labels] array
(issue.labels.map(&:name) & @options[:include_labels]).any?
}
end
unless @options[:exclude_labels].nil?
filtered_issues = filtered_issues.select { |issue|
# delete all labels from @options[:exclude_labels] array
!(issue.labels.map(&:name) & @options[:exclude_labels]).any?
}
end
if @options[:add_issues_wo_labels]
issues_wo_labels = issues.select { |issue|
!issue.labels.map(&:name).any?
}
filtered_issues |= issues_wo_labels
end
if @options[:verbose] if @options[:verbose]
puts "Filtered issues: #{filtered_issues.count}" puts "Filtered issues: #{filtered_issues.count}"
@@ -544,42 +496,8 @@ module GitHubChangelogGenerator
filtered_issues filtered_issues
end end
def fetch_issues_and_pull_requests # Fetch event for issues and pull requests
if @options[:verbose] # @return [Array] array of fetched issues
print "Fetching closed issues...\r"
end
issues = []
begin
response = @github.issues.list user: @options[:user], repo: @options[:project], state: 'closed', filter: 'all', labels: nil
page_i = 0
count_pages = response.count_pages
response.each_page do |page|
page_i += PER_PAGE_NUMBER
print "Fetching issues... #{page_i}/#{count_pages * PER_PAGE_NUMBER}\r"
issues.concat(page)
break if @options[:max_issues] && issues.length >= @options[:max_issues]
end
rescue
puts GH_RATE_LIMIT_EXCEEDED_MSG.yellow
end
print " \r"
if @options[:verbose]
puts "Received issues: #{issues.count}"
end
# remove pull request from issues:
issues_wo_pr = issues.select { |x|
x.pull_request.nil?
}
pull_requests = issues.select { |x|
!x.pull_request.nil?
}
[issues_wo_pr, pull_requests]
end
def fetch_event_for_issues_and_pr def fetch_event_for_issues_and_pr
if @options[:verbose] if @options[:verbose]
print "Fetching events for issues and PR: 0/#{@issues.count + @pull_requests.count}\r" print "Fetching events for issues and PR: 0/#{@issues.count + @pull_requests.count}\r"
@@ -587,36 +505,7 @@ module GitHubChangelogGenerator
# Async fetching events: # Async fetching events:
fetch_events_async(@issues + @pull_requests) @fetcher.fetch_events_async(@issues + @pull_requests)
end
def fetch_events_async(issues)
i = 0
max_thread_number = 50
threads = []
issues.each_slice(max_thread_number) { |issues_slice|
issues_slice.each { |issue|
threads << Thread.new {
begin
obj = @github.issues.events.list user: @options[:user], repo: @options[:project], issue_number: issue['number']
rescue
puts GH_RATE_LIMIT_EXCEEDED_MSG.yellow
end
issue[:events] = obj.body
print "Fetching events for issues and PR: #{i + 1}/#{@issues.count + @pull_requests.count}\r"
i += 1
}
}
threads.each(&:join)
threads = []
}
# to clear line from prev print
print " \r"
if @options[:verbose]
puts "Fetching events for issues and PR: #{i} Done!"
end
end end
end end

View File

@@ -0,0 +1,209 @@
require "logger"
module GitHubChangelogGenerator
# A Fetcher responsible for all requests to GitHub and all basic manipulation with related data
# (such as filtering, validating, e.t.c)
#
# Example:
# fetcher = GitHubChangelogGenerator::Fetcher.new options
class Fetcher
PER_PAGE_NUMBER = 30
GH_RATE_LIMIT_EXCEEDED_MSG = "Warning: GitHub API rate limit (5000 per hour) exceeded, change log may be " \
"missing some issues. You can limit the number of issues fetched using the `--max-issues NUM` argument."
def initialize(options = {})
@options = options
@user = @options[:user]
@project = @options[:project]
@github_token = fetch_github_token
@tag_times_hash = {}
@logger = Logger.new(STDOUT)
@logger.formatter = proc do |_severity, _datetime, _progname, msg|
"#{msg}\n"
end
github_options = { per_page: PER_PAGE_NUMBER }
github_options[:oauth_token] = @github_token unless @github_token.nil?
github_options[:endpoint] = options[:github_endpoint] unless options[:github_endpoint].nil?
github_options[:site] = options[:github_endpoint] unless options[:github_site].nil?
begin
@github = Github.new github_options
rescue
@logger.warn GH_RATE_LIMIT_EXCEEDED_MSG.yellow
end
end
# Returns GitHub token. First try to use variable, provided by --token option,
# otherwise try to fetch it from CHANGELOG_GITHUB_TOKEN env variable.
#
# @return [String]
def fetch_github_token
env_var = @options[:token] ? @options[:token] : (ENV.fetch "CHANGELOG_GITHUB_TOKEN", nil)
unless env_var
@logger.warn "Warning: No token provided (-t option) and variable $CHANGELOG_GITHUB_TOKEN was not found.".yellow
@logger.warn "This script can make only 50 requests to GitHub API per hour without token!".yellow
end
env_var
end
# Fetch all tags from repo
# @return [Array] array of tags
def get_all_tags
if @options[:verbose]
print "Fetching tags...\r"
end
tags = []
begin
response = @github.repos.tags @options[:user], @options[:project]
page_i = 0
count_pages = response.count_pages
response.each_page do |page|
page_i += PER_PAGE_NUMBER
print "Fetching tags... #{page_i}/#{count_pages * PER_PAGE_NUMBER}\r"
tags.concat(page)
end
print " \r"
if tags.count == 0
@logger.warn "Warning: Can't find any tags in repo.\
Make sure, that you push tags to remote repo via 'git push --tags'".yellow
elsif @options[:verbose]
@logger.info "Found #{tags.count} tags"
end
rescue
@logger.warn GH_RATE_LIMIT_EXCEEDED_MSG.yellow
end
tags
end
# This method fetch all closed issues and separate them to pull requests and pure issues
# (pull request is kind of issue in term of GitHub)
# @return [Tuple] with issues and pull requests
def fetch_issues_and_pull_requests
if @options[:verbose]
print "Fetching closed issues...\r"
end
issues = []
begin
response = @github.issues.list user: @options[:user],
repo: @options[:project],
state: "closed",
filter: "all",
labels: nil
page_i = 0
count_pages = response.count_pages
response.each_page do |page|
page_i += PER_PAGE_NUMBER
print "Fetching issues... #{page_i}/#{count_pages * PER_PAGE_NUMBER}\r"
issues.concat(page)
break if @options[:max_issues] && issues.length >= @options[:max_issues]
end
rescue
@logger.warn GH_RATE_LIMIT_EXCEEDED_MSG.yellow
end
print " \r"
if @options[:verbose]
@logger.info "Received issues: #{issues.count}"
end
# remove pull request from issues:
issues.partition { |x|
x[:pull_request].nil?
}
end
# Fetch all pull requests. We need them to detect :merged_at parameter
# @return [Array] all pull requests
def fetch_pull_requests
pull_requests = []
begin
response = @github.pull_requests.list @options[:user], @options[:project], state: "closed"
page_i = 0
response.each_page do |page|
page_i += PER_PAGE_NUMBER
count_pages = response.count_pages
print "Fetching merged dates... #{page_i}/#{count_pages * PER_PAGE_NUMBER}\r"
pull_requests.concat(page)
end
rescue
@logger.warn GH_RATE_LIMIT_EXCEEDED_MSG.yellow
end
print " \r"
pull_requests
end
# Fetch event for all issues and add them to :events
# @param [Array] issues
# @return [Void]
def fetch_events_async(issues)
i = 0
max_thread_number = 50
threads = []
issues.each_slice(max_thread_number) { |issues_slice|
issues_slice.each { |issue|
threads << Thread.new {
begin
obj = @github.issues.events.list user: @options[:user],
repo: @options[:project],
issue_number: issue["number"]
rescue
@logger.warn GH_RATE_LIMIT_EXCEEDED_MSG.yellow
end
issue[:events] = obj.body
print "Fetching events for issues and PR: #{i + 1}/#{issues.count}\r"
i += 1
}
}
threads.each(&:join)
threads = []
}
# to clear line from prev print
print " \r"
if @options[:verbose]
@logger.info "Fetching events for issues and PR: #{i} Done!"
end
end
# Try to find tag date in local hash.
# Otherwise fFetch tag time and put it to local hash file.
# @param [String] tag_name name of the tag
# @return [Time] time of specified tag
def get_time_of_tag(tag_name)
fail ChangelogGeneratorError, "tag_name is nil".red if tag_name.nil?
if @tag_times_hash[tag_name["name"]]
return @tag_times_hash[tag_name["name"]]
end
begin
github_git_data_commits_get = @github.git_data.commits.get @options[:user],
@options[:project],
tag_name["commit"]["sha"]
rescue
@logger.warn GH_RATE_LIMIT_EXCEEDED_MSG.yellow
end
time_string = github_git_data_commits_get["committer"]["date"]
@tag_times_hash[tag_name["name"]] = Time.parse(time_string)
end
# Fetch commit for specifed event
# @return [Hash]
def fetch_commit(event)
@github.git_data.commits.get @options[:user], @options[:project], event[:commit_id]
end
end
end

View File

@@ -4,6 +4,13 @@ module GitHubChangelogGenerator
@options = options @options = options
end end
# Parse issue and generate single line formatted issue line.
#
# Example output:
# - Add coveralls integration [\#223](https://github.com/skywinder/github-changelog-generator/pull/223) ([skywinder](https://github.com/skywinder))
#
# @param [Hash] issue Fetched issue from GitHub
# @return [String] Markdown-formatted single issue
def get_string_for_issue(issue) def get_string_for_issue(issue)
encapsulated_title = encapsulate_string issue[:title] encapsulated_title = encapsulate_string issue[:title]
@@ -12,7 +19,7 @@ module GitHubChangelogGenerator
unless issue.pull_request.nil? unless issue.pull_request.nil?
if @options[:author] if @options[:author]
if issue.user.nil? if issue.user.nil?
title_with_number += ' ({Null user})' title_with_number += " ({Null user})"
else else
title_with_number += " ([#{issue.user.login}](#{issue.user.html_url}))" title_with_number += " ([#{issue.user.login}](#{issue.user.html_url}))"
end end

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
require 'optparse' require "optparse"
require 'pp' require "pp"
require_relative 'version' require_relative "version"
module GitHubChangelogGenerator module GitHubChangelogGenerator
class Parser class Parser
@@ -9,8 +9,8 @@ module GitHubChangelogGenerator
options = { options = {
tag1: nil, tag1: nil,
tag2: nil, tag2: nil,
dateformat: '%Y-%m-%d', dateformat: "%Y-%m-%d",
output: 'CHANGELOG.md', output: "CHANGELOG.md",
issues: true, issues: true,
add_issues_wo_labels: true, add_issues_wo_labels: true,
add_pr_wo_labels: true, add_pr_wo_labels: true,
@@ -18,7 +18,7 @@ module GitHubChangelogGenerator
filter_issues_by_milestone: true, filter_issues_by_milestone: true,
author: true, author: true,
unreleased: true, unreleased: true,
unreleased_label: 'Unreleased', unreleased_label: "Unreleased",
compare_link: true, compare_link: true,
include_labels: %w(bug enhancement), include_labels: %w(bug enhancement),
exclude_labels: %w(duplicate question invalid wontfix), exclude_labels: %w(duplicate question invalid wontfix),
@@ -26,86 +26,86 @@ module GitHubChangelogGenerator
simple_list: false, simple_list: false,
verbose: true, verbose: true,
merge_prefix: '**Merged pull requests:**', merge_prefix: "**Merged pull requests:**",
issue_prefix: '**Closed issues:**', issue_prefix: "**Closed issues:**",
bug_prefix: '**Fixed bugs:**', bug_prefix: "**Fixed bugs:**",
enhancement_prefix: '**Implemented enhancements:**', enhancement_prefix: "**Implemented enhancements:**",
branch: 'origin' branch: "origin"
} }
parser = OptionParser.new do |opts| parser = OptionParser.new do |opts|
opts.banner = 'Usage: github_changelog_generator [options]' opts.banner = "Usage: github_changelog_generator [options]"
opts.on('-u', '--user [USER]', 'Username of the owner of target GitHub repo') do |last| opts.on("-u", "--user [USER]", "Username of the owner of target GitHub repo") do |last|
options[:user] = last options[:user] = last
end end
opts.on('-p', '--project [PROJECT]', 'Name of project on GitHub') do |last| opts.on("-p", "--project [PROJECT]", "Name of project on GitHub") do |last|
options[:project] = last options[:project] = last
end end
opts.on('-t', '--token [TOKEN]', 'To make more than 50 requests per hour your GitHub token is required. You can generate it at: https://github.com/settings/tokens/new') do |last| opts.on("-t", "--token [TOKEN]", "To make more than 50 requests per hour your GitHub token is required. You can generate it at: https://github.com/settings/tokens/new") do |last|
options[:token] = last options[:token] = last
end end
opts.on('-f', '--date-format [FORMAT]', 'Date format. Default is %Y-%m-%d') do |last| opts.on("-f", "--date-format [FORMAT]", "Date format. Default is %Y-%m-%d") do |last|
options[:dateformat] = last options[:dateformat] = last
end end
opts.on('-o', '--output [NAME]', 'Output file. Default is CHANGELOG.md') do |last| opts.on("-o", "--output [NAME]", "Output file. Default is CHANGELOG.md") do |last|
options[:output] = last options[:output] = last
end end
opts.on('--[no-]issues', 'Include closed issues in changelog. Default is true') do |v| opts.on("--[no-]issues", "Include closed issues in changelog. Default is true") do |v|
options[:issues] = v options[:issues] = v
end end
opts.on('--[no-]issues-wo-labels', 'Include closed issues without labels in changelog. Default is true') do |v| opts.on("--[no-]issues-wo-labels", "Include closed issues without labels in changelog. Default is true") do |v|
options[:add_issues_wo_labels] = v options[:add_issues_wo_labels] = v
end end
opts.on('--[no-]pr-wo-labels', 'Include pull requests without labels in changelog. Default is true') do |v| opts.on("--[no-]pr-wo-labels", "Include pull requests without labels in changelog. Default is true") do |v|
options[:add_pr_wo_labels] = v options[:add_pr_wo_labels] = v
end end
opts.on('--[no-]pull-requests', 'Include pull-requests in changelog. Default is true') do |v| opts.on("--[no-]pull-requests", "Include pull-requests in changelog. Default is true") do |v|
options[:pulls] = v options[:pulls] = v
end end
opts.on('--[no-]filter-by-milestone', 'Use milestone to detect when issue was resolved. Default is true') do |last| opts.on("--[no-]filter-by-milestone", "Use milestone to detect when issue was resolved. Default is true") do |last|
options[:filter_issues_by_milestone] = last options[:filter_issues_by_milestone] = last
end end
opts.on('--[no-]author', 'Add author of pull-request in the end. Default is true') do |author| opts.on("--[no-]author", "Add author of pull-request in the end. Default is true") do |author|
options[:author] = author options[:author] = author
end end
opts.on('--unreleased-only', 'Generate log from unreleased closed issues only.') do |v| opts.on("--unreleased-only", "Generate log from unreleased closed issues only.") do |v|
options[:unreleased_only] = v options[:unreleased_only] = v
end end
opts.on('--[no-]unreleased', 'Add to log unreleased closed issues. Default is true') do |v| opts.on("--[no-]unreleased", "Add to log unreleased closed issues. Default is true") do |v|
options[:unreleased] = v options[:unreleased] = v
end end
opts.on('--unreleased-label [label]', 'Add to log unreleased closed issues. Default is true') do |v| opts.on("--unreleased-label [label]", "Add to log unreleased closed issues. Default is true") do |v|
options[:unreleased_label] = v options[:unreleased_label] = v
end end
opts.on('--[no-]compare-link', 'Include compare link (Full Changelog) between older version and newer version. Default is true') do |v| opts.on("--[no-]compare-link", "Include compare link (Full Changelog) between older version and newer version. Default is true") do |v|
options[:compare_link] = v options[:compare_link] = v
end end
opts.on('--include-labels x,y,z', Array, 'Only issues with the specified labels will be included in the changelog. Default is \'bug,enhancement\'') do |list| opts.on("--include-labels x,y,z", Array, 'Only issues with the specified labels will be included in the changelog. Default is \'bug,enhancement\'') do |list|
options[:include_labels] = list options[:include_labels] = list
end end
opts.on('--exclude-labels x,y,z', Array, 'Issues with the specified labels will be always excluded from changelog. Default is \'duplicate,question,invalid,wontfix\'') do |list| opts.on("--exclude-labels x,y,z", Array, 'Issues with the specified labels will be always excluded from changelog. Default is \'duplicate,question,invalid,wontfix\'') do |list|
options[:exclude_labels] = list options[:exclude_labels] = list
end end
opts.on('--max-issues [NUMBER]', Integer, 'Max number of issues to fetch from GitHub. Default is unlimited') do |max| opts.on("--max-issues [NUMBER]", Integer, "Max number of issues to fetch from GitHub. Default is unlimited") do |max|
options[:max_issues] = max options[:max_issues] = max
end end
opts.on('--github-site [URL]', 'The Enterprise Github site on which your project is hosted.') do |last| opts.on("--github-site [URL]", "The Enterprise Github site on which your project is hosted.") do |last|
options[:github_site] = last options[:github_site] = last
end end
opts.on('--github-api [URL]', 'The enterprise endpoint to use for your Github API.') do |last| opts.on("--github-api [URL]", "The enterprise endpoint to use for your Github API.") do |last|
options[:github_endpoint] = last options[:github_endpoint] = last
end end
opts.on('--simple-list', 'Create simple list from issues and pull requests. Default is false.') do |v| opts.on("--simple-list", "Create simple list from issues and pull requests. Default is false.") do |v|
options[:simple_list] = v options[:simple_list] = v
end end
opts.on('--[no-]verbose', 'Run verbosely. Default is true') do |v| opts.on("--[no-]verbose", "Run verbosely. Default is true") do |v|
options[:verbose] = v options[:verbose] = v
end end
opts.on('-v', '--version', 'Print version number') do |_v| opts.on("-v", "--version", "Print version number") do |_v|
puts "Version: #{GitHubChangelogGenerator::VERSION}" puts "Version: #{GitHubChangelogGenerator::VERSION}"
exit exit
end end
opts.on('-h', '--help', 'Displays Help') do opts.on("-h", "--help", "Displays Help") do
puts opts puts opts
exit exit
end end
@@ -113,8 +113,30 @@ module GitHubChangelogGenerator
parser.parse! parser.parse!
detect_user_and_project(options)
if !options[:user] || !options[:project]
puts parser.banner
exit
end
if ARGV[1]
options[:tag1] = ARGV[0]
options[:tag2] = ARGV[1]
end
if options[:verbose]
puts "Performing task with options:"
pp options
puts ""
end
options
end
def self.detect_user_and_project(options)
if ARGV[0] && !ARGV[1] if ARGV[0] && !ARGV[1]
github_site = options[:github_site] ? options[:github_site] : 'github.com' github_site = options[:github_site] ? options[:github_site] : "github.com"
# this match should parse strings such "https://github.com/skywinder/Github-Changelog-Generator" or "skywinder/Github-Changelog-Generator" to user and name # this match should parse strings such "https://github.com/skywinder/Github-Changelog-Generator" or "skywinder/Github-Changelog-Generator" to user and name
match = /(?:.+#{Regexp.escape(github_site)}\/)?(.+)\/(.+)/.match(ARGV[0]) match = /(?:.+#{Regexp.escape(github_site)}\/)?(.+)\/(.+)/.match(ARGV[0])
@@ -134,44 +156,31 @@ module GitHubChangelogGenerator
end end
if !options[:user] && !options[:project] if !options[:user] && !options[:project]
remote = `git config --get remote.#{options[:branch]}.url` if ENV["RUBYLIB"] =~ /ruby-debug-ide/
# try to find repo in format: options[:user] = "skywinder"
# origin git@github.com:skywinder/Github-Changelog-Generator.git (fetch) options[:project] = "changelog_test"
# git@github.com:skywinder/Github-Changelog-Generator.git
match = /.*(?:[:\/])((?:-|\w|\.)*)\/((?:-|\w|\.)*)(?:\.git).*/.match(remote)
if match && match[1] && match[2]
puts "Detected user:#{match[1]}, project:#{match[2]}"
options[:user], options[:project] = match[1], match[2]
else else
remote = `git config --get remote.#{options[:branch]}.url`
# try to find repo in format: # try to find repo in format:
# origin https://github.com/skywinder/ChangelogMerger (fetch) # origin git@github.com:skywinder/Github-Changelog-Generator.git (fetch)
# https://github.com/skywinder/ChangelogMerger # git@github.com:skywinder/Github-Changelog-Generator.git
match = /.*\/((?:-|\w|\.)*)\/((?:-|\w|\.)*).*/.match(remote) match = /.*(?:[:\/])((?:-|\w|\.)*)\/((?:-|\w|\.)*)(?:\.git).*/.match(remote)
if match && match[1] && match[2] if match && match[1] && match[2]
puts "Detected user:#{match[1]}, project:#{match[2]}" puts "Detected user:#{match[1]}, project:#{match[2]}"
options[:user], options[:project] = match[1], match[2] options[:user], options[:project] = match[1], match[2]
else
# try to find repo in format:
# origin https://github.com/skywinder/ChangelogMerger (fetch)
# https://github.com/skywinder/ChangelogMerger
match = /.*\/((?:-|\w|\.)*)\/((?:-|\w|\.)*).*/.match(remote)
if match && match[1] && match[2]
puts "Detected user:#{match[1]}, project:#{match[2]}"
options[:user], options[:project] = match[1], match[2]
end
end end
end end
end end
if !options[:user] || !options[:project]
puts parser.banner
exit
end
if ARGV[1]
options[:tag1] = ARGV[0]
options[:tag2] = ARGV[1]
end
if options[:verbose]
puts 'Performing task with options:'
pp options
puts ''
end
options
end end
end end
end end

View File

@@ -25,7 +25,7 @@ module GitHubChangelogGenerator
class Reader class Reader
def initialize(options = {}) def initialize(options = {})
defaults = { defaults = {
heading_level: '##', heading_level: "##",
heading_structures: [ heading_structures: [
/^## \[(?<version>.+?)\]\((?<url>.+?)\)( \((?<date>.+?)\))?$/, /^## \[(?<version>.+?)\]\((?<url>.+?)\)( \((?<date>.+?)\))?$/,
/^## (?<version>.+?)( \((?<date>.+?)\))?$/ /^## (?<version>.+?)( \((?<date>.+?)\))?$/
@@ -49,7 +49,7 @@ module GitHubChangelogGenerator
# @param [String] heading Heading from the ChangeLog File # @param [String] heading Heading from the ChangeLog File
# @return [Hash] Returns a structured Hash with version, url and date # @return [Hash] Returns a structured Hash with version, url and date
def parse_heading(heading) def parse_heading(heading)
captures = { 'version' => nil, 'url' => nil, 'date' => nil } captures = { "version" => nil, "url" => nil, "date" => nil }
@heading_structures.each do |regexp| @heading_structures.each do |regexp|
matches = Regexp.new(regexp).match(heading) matches = Regexp.new(regexp).match(heading)
@@ -73,7 +73,7 @@ module GitHubChangelogGenerator
headings.each_with_index do |heading, index| headings.each_with_index do |heading, index|
captures = parse_heading(heading) captures = parse_heading(heading)
captures['content'] = sections.at(index + 1) captures["content"] = sections.at(index + 1)
changelog.push captures changelog.push captures
end end

View File

@@ -1,3 +1,3 @@
module GitHubChangelogGenerator module GitHubChangelogGenerator
VERSION = '1.3.11' VERSION = "1.4.0"
end end

View File

@@ -15,15 +15,18 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
require 'coveralls' require "codeclimate-test-reporter"
require 'simplecov' require "simplecov"
require "coveralls"
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
Coveralls::SimpleCov::Formatter,
SimpleCov::Formatter::HTMLFormatter, SimpleCov::Formatter::HTMLFormatter,
Coveralls::SimpleCov::Formatter CodeClimate::TestReporter::Formatter
] ]
SimpleCov.start SimpleCov.start
require 'github_changelog_generator' require "github_changelog_generator"
# This file was generated by the `rspec --init` command. Conventionally, all # This file was generated by the `rspec --init` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
@@ -92,7 +95,7 @@ RSpec.configure do |config|
# Use the documentation formatter for detailed output, # Use the documentation formatter for detailed output,
# unless a formatter has already been configured # unless a formatter has already been configured
# (e.g. via a command-line flag). # (e.g. via a command-line flag).
config.default_formatter = 'doc' config.default_formatter = "doc"
end end
# Print the 10 slowest examples and example groups at the # Print the 10 slowest examples and example groups at the

View File

@@ -21,71 +21,71 @@ describe GitHubChangelogGenerator::Reader do
@reader = GitHubChangelogGenerator::Reader.new @reader = GitHubChangelogGenerator::Reader.new
end end
describe '#parse_heading' do describe "#parse_heading" do
context 'when heading is empty' do context "when heading is empty" do
subject { @reader.parse_heading('## ') } subject { @reader.parse_heading("## ") }
it { is_expected.to be_a(Hash) } it { is_expected.to be_a(Hash) }
it { is_expected.to include('version', 'url', 'date') } it { is_expected.to include("version", "url", "date") }
it { is_expected.to include('version' => nil, 'url' => nil, 'date' => nil) } it { is_expected.to include("version" => nil, "url" => nil, "date" => nil) }
# TODO: Doesn't work? # TODO: Doesn't work?
# it { is_expected.to have_all_string_keys } # it { is_expected.to have_all_string_keys }
end end
context 'when given version, url and date' do context "when given version, url and date" do
subject { @reader.parse_heading('## [1.3.10](https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.10) (2015-03-18)') } subject { @reader.parse_heading("## [1.3.10](https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.10) (2015-03-18)") }
it { is_expected.to include('version' => '1.3.10') } it { is_expected.to include("version" => "1.3.10") }
it { is_expected.to include('url' => 'https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.10') } it { is_expected.to include("url" => "https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.10") }
it { is_expected.to include('date' => '2015-03-18') } it { is_expected.to include("date" => "2015-03-18") }
end end
context 'when no url and date is provided' do context "when no url and date is provided" do
subject { @reader.parse_heading('## foobar') } subject { @reader.parse_heading("## foobar") }
it { is_expected.to include('version' => 'foobar', 'url' => nil, 'date' => nil) } it { is_expected.to include("version" => "foobar", "url" => nil, "date" => nil) }
end end
end end
describe '#parse' do describe "#parse" do
context 'when file is empty' do context "when file is empty" do
subject { @reader.parse('') } subject { @reader.parse("") }
it { is_expected.to be_an(Array) } it { is_expected.to be_an(Array) }
it { is_expected.to be_empty } it { is_expected.to be_empty }
end end
context 'when file has only the header' do context "when file has only the header" do
subject { @reader.parse('# Change Log') } subject { @reader.parse("# Change Log") }
it { is_expected.to be_an(Array) } it { is_expected.to be_an(Array) }
it { is_expected.to be_empty } it { is_expected.to be_empty }
end end
end end
describe 'example CHANGELOG files' do describe "example CHANGELOG files" do
subject { @reader.read(File.expand_path(File.join(File.dirname(__FILE__), '..', 'files', self.class.description))) } subject { @reader.read(File.expand_path(File.join(File.dirname(__FILE__), "..", "files", self.class.description))) }
context 'github-changelog-generator.md' do context "github-changelog-generator.md" do
it { is_expected.to be_an(Array) } it { is_expected.to be_an(Array) }
it { is_expected.not_to be_empty } it { is_expected.not_to be_empty }
it { expect(subject.count).to eq(28) } it { expect(subject.count).to eq(28) }
it { expect(subject.first).to include('version' => '1.3.10') } it { expect(subject.first).to include("version" => "1.3.10") }
it { expect(subject.first).to include('url' => 'https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.10') } it { expect(subject.first).to include("url" => "https://github.com/skywinder/Github-Changelog-Generator/tree/1.3.10") }
it { expect(subject.first).to include('date' => '2015-03-18') } it { expect(subject.first).to include("date" => "2015-03-18") }
it { expect(subject.first).to include('content') } it { expect(subject.first).to include("content") }
it 'content should not be empty' do it "content should not be empty" do
expect(subject.first['content']).not_to be_empty expect(subject.first["content"]).not_to be_empty
end end
end end
context 'bundler.md' do context "bundler.md" do
it { is_expected.to be_an(Array) } it { is_expected.to be_an(Array) }
it { is_expected.not_to be_empty } it { is_expected.not_to be_empty }
it { expect(subject.count).to eq(151) } it { expect(subject.count).to eq(151) }
it { expect(subject.first).to include('version' => '1.9.1') } it { expect(subject.first).to include("version" => "1.9.1") }
it { expect(subject.first).to include('url' => nil) } it { expect(subject.first).to include("url" => nil) }
it { expect(subject.first).to include('date' => '2015-03-21') } it { expect(subject.first).to include("date" => "2015-03-21") }
it { expect(subject.first).to include('content') } it { expect(subject.first).to include("content") }
it 'content should not be empty' do it "content should not be empty" do
expect(subject.first['content']).not_to be_empty expect(subject.first["content"]).not_to be_empty
end end
end end
context 'angular.js.md' do context "angular.js.md" do
it { is_expected.to be_an(Array) } it { is_expected.to be_an(Array) }
it { is_expected.not_to be_empty } it { is_expected.not_to be_empty }
it do it do
pending('Implement heading_level for parser.') pending("Implement heading_level for parser.")
expect(subject.count).to eq(134) expect(subject.count).to eq(134)
end end
# it do # it do