releasinator 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +1 -1
- data/README.md +5 -2
- data/lib/changelog/importer.rb +43 -0
- data/lib/changelog/validator.rb +152 -0
- data/lib/releasinator/version.rb +1 -1
- data/lib/tasks/releasinator.rake +8 -0
- data/lib/validator.rb +2 -2
- data/lib/validator_changelog.rb +0 -115
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c50b2ca2d8e7f05c2cfdcfb7e6277e88dbe9566
|
4
|
+
data.tar.gz: bff4e52e4c64da30a0100041af927320366b2263
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e59589a4510ae9d20c6c484c852b3d43968ff90c9eae075942ed7d11da245fce889f78208382ac649a6304cd76f74bddb9d62eb7eb4021fa312b2773d66dbd95
|
7
|
+
data.tar.gz: c7e3f660cf30e2d6d5db862a87dfe46f8027b40befd2a51869c8f1d1b4dcb8ecd694659b7425e9a1168999bd78c4b06873b0453a881bc3bcfa08542fa1646c28
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
Releasinator release notes
|
2
2
|
==========================
|
3
3
|
|
4
|
+
0.6.2
|
5
|
+
-----
|
6
|
+
* Re-enable bullet punctuation detection, now handling multi-line comments correctly!
|
7
|
+
* Add new utility task, `import:changelog` for creating a changelog from a GitHub repo using the contents of existing GitHub releases.
|
8
|
+
|
4
9
|
0.6.1
|
5
10
|
-----
|
6
11
|
* Improve some error messages.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -74,6 +74,8 @@ release
|
|
74
74
|
--> docs:package
|
75
75
|
--> docs:push
|
76
76
|
|
77
|
+
import:changelog (utility that creates a CHANGELOG.md.tmp from existing GitHub releases)
|
78
|
+
|
77
79
|
```
|
78
80
|
|
79
81
|
### Config
|
@@ -115,11 +117,12 @@ This will 'append' the task `validate:changelog`, running the code block after t
|
|
115
117
|
The releasinator enforces certain conventions. If a filename closely matches the convention, it is renamed and automatically committed. The conventions are documented below:
|
116
118
|
|
117
119
|
1. `README.md`
|
118
|
-
2. `LICENSE`: See [here](http://stackoverflow.com/questions/5678462/should-i-provide-a-license-txt-or-copying-txt-file-in-my-project) for a relevant StackOverflow post on this discussion.
|
119
|
-
3. `CONTRIBUTING.md`: See [a relevant GitHub blog post](https://github.com/blog/1184-contributing-guidelines) for relevant information.
|
120
|
+
2. `LICENSE`: See [here](http://stackoverflow.com/questions/5678462/should-i-provide-a-license-txt-or-copying-txt-file-in-my-project) for a relevant StackOverflow post on this discussion. The authors of this project have chosen to exclude the `.txt` extension to match other popular projects, and GitHub defaults.
|
121
|
+
3. `CONTRIBUTING.md`: See [a relevant GitHub blog post](https://github.com/blog/1184-contributing-guidelines) for relevant information. The authors of this project have have chosen to include the `.md` extension, as these files can get a bit unwieldy without formatting.
|
120
122
|
4. `CHANGELOG.md` - This file is the source of truth for the releasinator. The file should be organized with the most recent release on top, and formatted correctly. The latest release is the one used when the releasinator executes, so it is a precondition that the `CHANGELOG.md` has been edited and committed **prior to releasing**.
|
121
123
|
1. Releases either are contained within an Alt-H2 (`------`) or `##H2` format. Any other format will be rejected.
|
122
124
|
2. Each release MUST start with the release version, and may contain any following text, such as the date, and/or any release summary.
|
125
|
+
5. `.gitignore` and `.DS_store`: While this file is Mac-specific, many repos contain this entry in their `.gitignore` files because it's quite common for developers to not have their global `.gitignore` configured correctly. Therefore, the authors of this project have made the decision to force this entry in all `.gitignores`, as a gesture of goodwill to all these new git users.
|
123
126
|
|
124
127
|
## Behind the Scenes
|
125
128
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative '../git_util'
|
2
|
+
require_relative '../command_processor'
|
3
|
+
|
4
|
+
|
5
|
+
module Releasinator
|
6
|
+
module Changelog
|
7
|
+
class Importer
|
8
|
+
def initialize(releasinator_config)
|
9
|
+
@releasinator_config = releasinator_config
|
10
|
+
end
|
11
|
+
|
12
|
+
def import(repo_url)
|
13
|
+
# create tempfile
|
14
|
+
File.open('CHANGELOG.md.tmp', 'w') do |f|
|
15
|
+
title_string = "#{@releasinator_config[:product_name]} release notes"
|
16
|
+
f.puts title_string
|
17
|
+
|
18
|
+
# print ====== with the length of the previous line for prettiness
|
19
|
+
title_string.length.times { f.print "=" }
|
20
|
+
f.puts
|
21
|
+
|
22
|
+
# read releases
|
23
|
+
github_repo = GitHubRepo.new(repo_url)
|
24
|
+
|
25
|
+
begin
|
26
|
+
github_releases = github_repo.client.releases "#{github_repo.org}/#{github_repo.repo}"
|
27
|
+
github_releases.each do |github_release|
|
28
|
+
puts github_release.inspect if @releasinator_config[:trace]
|
29
|
+
f.puts
|
30
|
+
f.puts github_release.name
|
31
|
+
f.puts "-----"
|
32
|
+
f.puts github_release.body
|
33
|
+
end
|
34
|
+
rescue => error
|
35
|
+
f.puts "<could not read releases from github>"
|
36
|
+
Printer.fail(error.inspect)
|
37
|
+
abort()
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
require 'Vandamme'
|
3
|
+
require 'semantic'
|
4
|
+
require_relative "../current_release"
|
5
|
+
require_relative '../printer'
|
6
|
+
|
7
|
+
module Releasinator
|
8
|
+
module Changelog
|
9
|
+
class Validator
|
10
|
+
RELEASE_REGEX = /\d+\.\d+\.\d+/
|
11
|
+
|
12
|
+
def initialize(releasinator_config)
|
13
|
+
@releasinator_config = releasinator_config
|
14
|
+
end
|
15
|
+
|
16
|
+
# assume changelog_hash is not empty
|
17
|
+
def validate_semver(changelog_hash)
|
18
|
+
latest_release, latest_release_changelog = changelog_hash.first
|
19
|
+
# extract prefix from first release to use on all subsequent releases
|
20
|
+
latest_release_prefix = latest_release.partition(RELEASE_REGEX)[0]
|
21
|
+
|
22
|
+
newer_version = nil
|
23
|
+
changelog_hash.each do |key,value|
|
24
|
+
prefix, version, suffix = key.partition(RELEASE_REGEX)
|
25
|
+
puts "Checking version with prefix:'#{prefix}', version:'#{version}', suffix:'#{suffix}'." if @releasinator_config[:verbose]
|
26
|
+
if prefix != latest_release_prefix
|
27
|
+
Printer.fail("version #{key} does not start with extracted prefix '#{latest_release_prefix}'.")
|
28
|
+
abort()
|
29
|
+
end
|
30
|
+
older_version = Semantic::Version.new version
|
31
|
+
|
32
|
+
if nil != newer_version
|
33
|
+
version_comp = newer_version <=> older_version
|
34
|
+
if version_comp < 0
|
35
|
+
Printer.fail("Semver releases out of order: #{older_version} should be smaller than #{newer_version}")
|
36
|
+
abort()
|
37
|
+
elsif version_comp == 0
|
38
|
+
# this case cannot be found with Vandamme library because 2 versions in a row get overwritten in the underlying hash
|
39
|
+
if suffix.empty?
|
40
|
+
Printer.fail("2 semver releases in a row without a suffix (like -beta, -rc1, etc...) is not allowed.")
|
41
|
+
abort()
|
42
|
+
end
|
43
|
+
else
|
44
|
+
error_suffix = "version increment error - comparing #{newer_version} to #{older_version} does not pass semver validation."
|
45
|
+
# validate the next sequence in semver
|
46
|
+
if newer_version.major == older_version.major
|
47
|
+
if newer_version.minor == older_version.minor
|
48
|
+
check_semver_criteria(newer_version.patch == older_version.patch + 1, "patch #{error_suffix}")
|
49
|
+
else
|
50
|
+
check_semver_criteria(newer_version.minor == older_version.minor + 1 && newer_version.patch == 0, "minor #{error_suffix}")
|
51
|
+
end
|
52
|
+
else
|
53
|
+
check_semver_criteria(newer_version.major == older_version.major + 1 && newer_version.minor == 0 && newer_version.patch == 0, "major #{error_suffix}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
newer_version = older_version
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def check_semver_criteria(condition, message)
|
62
|
+
if !condition
|
63
|
+
Printer.fail(message)
|
64
|
+
abort()
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def validate_changelog_contents(changelog_contents)
|
69
|
+
version_header_regexes = [
|
70
|
+
## h2 using --- separator. Example:
|
71
|
+
# 1.0.0
|
72
|
+
# -----
|
73
|
+
# First release!
|
74
|
+
'(^#{RELEASE_REGEX}).*\n----.*',
|
75
|
+
|
76
|
+
# h1/h2 header retrieved from https://github.com/tech-angels/vandamme/#format and modified to skip headers with dots in the name
|
77
|
+
'^#{0,3} ?([\w\d\.-]+\.[\d\.-]+[a-zA-Z0-9])(?: \W (\w+ \d{1,2}(?:st|nd|rd|th)?,\s\d{4}|\d{4}-\d{2}-\d{2}|\w+))?\n?[=-]*'
|
78
|
+
]
|
79
|
+
|
80
|
+
changelog_hash = nil
|
81
|
+
version_header_regexes.each do |version_header_regex|
|
82
|
+
parser = Vandamme::Parser.new(changelog: changelog_contents, version_header_exp: version_header_regex, format: 'markdown')
|
83
|
+
changelog_hash = parser.parse
|
84
|
+
|
85
|
+
break if !changelog_hash.empty?
|
86
|
+
end
|
87
|
+
|
88
|
+
if changelog_hash.empty?
|
89
|
+
Printer.fail("Unable to find any releases in the CHANGELOG.md. Please check that your formatting is correct.")
|
90
|
+
abort()
|
91
|
+
end
|
92
|
+
|
93
|
+
Printer.success("Found " + changelog_hash.count.to_s.bold + " release(s) in CHANGELOG.md.")
|
94
|
+
|
95
|
+
validate_semver(changelog_hash)
|
96
|
+
|
97
|
+
changelog_hash.each { |release, changelog|
|
98
|
+
validate_single_changelog_entry(changelog)
|
99
|
+
}
|
100
|
+
|
101
|
+
latest_release, latest_release_changelog = changelog_hash.first
|
102
|
+
CurrentRelease.new(latest_release, latest_release_changelog)
|
103
|
+
end
|
104
|
+
|
105
|
+
def validate_single_changelog_entry(entry)
|
106
|
+
previous_line_in_progress = nil
|
107
|
+
|
108
|
+
lines = entry.chomp.split(/\r?\n/)
|
109
|
+
lines.each{ |line|
|
110
|
+
|
111
|
+
if starts_with_bullet? line
|
112
|
+
if previous_line_in_progress
|
113
|
+
Printer.fail("'#{previous_line_in_progress}' is invalid. Bulleted points should end in punctuation.")
|
114
|
+
abort()
|
115
|
+
elsif ends_with_punctuation? line
|
116
|
+
# self-contained line is a-ok, and the usual use-case
|
117
|
+
previous_line_in_progress = nil
|
118
|
+
else
|
119
|
+
# line starts with bullet, but did not end with punctuation
|
120
|
+
previous_line_in_progress = line
|
121
|
+
end
|
122
|
+
elsif previous_line_in_progress
|
123
|
+
# does not start with bullet, and is continuing from previous line
|
124
|
+
if ends_with_punctuation? line
|
125
|
+
# multi-line ending with punctuation is ok!
|
126
|
+
previous_line_in_progress = nil
|
127
|
+
else
|
128
|
+
# middle of multi-line - neither starts with bullet, nor ends with punctuation.
|
129
|
+
previous_line_in_progress = line
|
130
|
+
end
|
131
|
+
else
|
132
|
+
# don't care about empty or code lines interspersed in a changelog entry
|
133
|
+
end
|
134
|
+
}
|
135
|
+
|
136
|
+
# the last line may not be clean. Handle it.
|
137
|
+
if previous_line_in_progress
|
138
|
+
Printer.fail("'#{previous_line_in_progress}' is invalid. Bulleted points should end in punctuation.")
|
139
|
+
abort()
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def starts_with_bullet?(line)
|
144
|
+
line.match /^\s*\*\s+.*$/
|
145
|
+
end
|
146
|
+
|
147
|
+
def ends_with_punctuation?(line)
|
148
|
+
line.match /.*[\!,\?:\.]$/
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
data/lib/releasinator/version.rb
CHANGED
data/lib/tasks/releasinator.rake
CHANGED
@@ -11,6 +11,7 @@ require_relative '../downstream'
|
|
11
11
|
require_relative '../downstream_repo'
|
12
12
|
require_relative '../publisher'
|
13
13
|
require_relative '../validator'
|
14
|
+
require_relative '../changelog/importer.rb'
|
14
15
|
|
15
16
|
include Releasinator
|
16
17
|
|
@@ -154,6 +155,13 @@ task :release => [:"validate:all",:"local:build",:"pm:all",:"downstream:all",:"l
|
|
154
155
|
Printer.success("Done releasing.")
|
155
156
|
end
|
156
157
|
|
158
|
+
namespace :import do
|
159
|
+
desc "import a changelog from release notes contained within GitHub releases"
|
160
|
+
task :changelog => [:config] do
|
161
|
+
Changelog::Importer.new(@releasinator_config).import(GitUtil.repo_url)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
157
165
|
namespace :local do
|
158
166
|
desc "ask user whether to proceed with release"
|
159
167
|
task :confirm => [:config, :"validate:changelog"] do
|
data/lib/validator.rb
CHANGED
@@ -6,7 +6,7 @@ require_relative 'command_processor'
|
|
6
6
|
require_relative 'downstream_repo'
|
7
7
|
require_relative 'github_repo'
|
8
8
|
require_relative 'printer'
|
9
|
-
require_relative '
|
9
|
+
require_relative 'changelog/validator'
|
10
10
|
require_relative 'releasinator/version'
|
11
11
|
|
12
12
|
TEXT_FILE_EXTENSIONS = [
|
@@ -108,7 +108,7 @@ module Releasinator
|
|
108
108
|
validate_exist(@releasinator_config.base_dir, "CHANGELOG.md", search_ignore_path, ["release_notes.md"])
|
109
109
|
|
110
110
|
changelog_contents = get_changelog_contents
|
111
|
-
|
111
|
+
Changelog::Validator.new(@releasinator_config).validate_changelog_contents(changelog_contents)
|
112
112
|
end
|
113
113
|
|
114
114
|
def validate_is_type(obj, type)
|
data/lib/validator_changelog.rb
CHANGED
@@ -1,116 +1 @@
|
|
1
|
-
require 'colorize'
|
2
|
-
require 'Vandamme'
|
3
|
-
require 'semantic'
|
4
|
-
require_relative "current_release"
|
5
|
-
require_relative 'printer'
|
6
1
|
|
7
|
-
module Releasinator
|
8
|
-
class ValidatorChangelog
|
9
|
-
|
10
|
-
RELEASE_REGEX = /\d+\.\d+\.\d+/
|
11
|
-
|
12
|
-
def initialize(releasinator_config)
|
13
|
-
@releasinator_config = releasinator_config
|
14
|
-
end
|
15
|
-
|
16
|
-
# assume changelog_hash is not empty
|
17
|
-
def validate_semver(changelog_hash)
|
18
|
-
latest_release, latest_release_changelog = changelog_hash.first
|
19
|
-
# extract prefix from first release to use on all subsequent releases
|
20
|
-
latest_release_prefix = latest_release.partition(RELEASE_REGEX)[0]
|
21
|
-
|
22
|
-
newer_version = nil
|
23
|
-
changelog_hash.each do |key,value|
|
24
|
-
prefix, version, suffix = key.partition(RELEASE_REGEX)
|
25
|
-
puts "Checking version with prefix:'#{prefix}', version:'#{version}', suffix:'#{suffix}'." if @releasinator_config[:verbose]
|
26
|
-
if prefix != latest_release_prefix
|
27
|
-
Printer.fail("version #{key} does not start with extracted prefix '#{latest_release_prefix}'.")
|
28
|
-
abort()
|
29
|
-
end
|
30
|
-
older_version = Semantic::Version.new version
|
31
|
-
|
32
|
-
if nil != newer_version
|
33
|
-
version_comp = newer_version <=> older_version
|
34
|
-
if version_comp < 0
|
35
|
-
Printer.fail("Semver releases out of order: #{older_version} should be smaller than #{newer_version}")
|
36
|
-
abort()
|
37
|
-
elsif version_comp == 0
|
38
|
-
# this case cannot be found with Vandamme library because 2 versions in a row get overwritten in the underlying hash
|
39
|
-
if suffix.empty?
|
40
|
-
Printer.fail("2 semver releases in a row without a suffix (like -beta, -rc1, etc...) is not allowed.")
|
41
|
-
abort()
|
42
|
-
end
|
43
|
-
else
|
44
|
-
error_suffix = "version increment error - comparing #{newer_version} to #{older_version} does not pass semver validation."
|
45
|
-
# validate the next sequence in semver
|
46
|
-
if newer_version.major == older_version.major
|
47
|
-
if newer_version.minor == older_version.minor
|
48
|
-
check_semver_criteria(newer_version.patch == older_version.patch + 1, "patch #{error_suffix}")
|
49
|
-
else
|
50
|
-
check_semver_criteria(newer_version.minor == older_version.minor + 1 && newer_version.patch == 0, "minor #{error_suffix}")
|
51
|
-
end
|
52
|
-
else
|
53
|
-
check_semver_criteria(newer_version.major == older_version.major + 1 && newer_version.minor == 0 && newer_version.patch == 0, "major #{error_suffix}")
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
newer_version = older_version
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def check_semver_criteria(condition, message)
|
62
|
-
if !condition
|
63
|
-
Printer.fail(message)
|
64
|
-
abort()
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def validate_changelog_contents(changelog_contents)
|
69
|
-
version_header_regexes = [
|
70
|
-
## h2 using --- separator. Example:
|
71
|
-
# 1.0.0
|
72
|
-
# -----
|
73
|
-
# First release!
|
74
|
-
'(^#{RELEASE_REGEX}).*\n----.*',
|
75
|
-
|
76
|
-
# h1/h2 header retrieved from https://github.com/tech-angels/vandamme/#format and modified to skip headers with dots in the name
|
77
|
-
'^#{0,3} ?([\w\d\.-]+\.[\d\.-]+[a-zA-Z0-9])(?: \W (\w+ \d{1,2}(?:st|nd|rd|th)?,\s\d{4}|\d{4}-\d{2}-\d{2}|\w+))?\n?[=-]*'
|
78
|
-
]
|
79
|
-
|
80
|
-
changelog_hash = nil
|
81
|
-
version_header_regexes.each do |version_header_regex|
|
82
|
-
parser = Vandamme::Parser.new(changelog: changelog_contents, version_header_exp: version_header_regex, format: 'markdown')
|
83
|
-
changelog_hash = parser.parse
|
84
|
-
|
85
|
-
break if !changelog_hash.empty?
|
86
|
-
end
|
87
|
-
|
88
|
-
if changelog_hash.empty?
|
89
|
-
Printer.fail("Unable to find any releases in the CHANGELOG.md. Please check that your formatting is correct.")
|
90
|
-
abort()
|
91
|
-
end
|
92
|
-
|
93
|
-
Printer.success("Found " + changelog_hash.count.to_s.bold + " release(s) in CHANGELOG.md.")
|
94
|
-
|
95
|
-
validate_semver(changelog_hash)
|
96
|
-
|
97
|
-
changelog_hash.each { |release, changelog|
|
98
|
-
validate_single_changelog_entry(changelog)
|
99
|
-
}
|
100
|
-
|
101
|
-
latest_release, latest_release_changelog = changelog_hash.first
|
102
|
-
CurrentRelease.new(latest_release, latest_release_changelog)
|
103
|
-
end
|
104
|
-
|
105
|
-
def validate_single_changelog_entry(entry)
|
106
|
-
lines = entry.split(/\r?\n/)
|
107
|
-
lines.each{ |line|
|
108
|
-
if line.match /^\s*\*\s+.*$/ # regex matches bulleted points
|
109
|
-
if !line.match /^\s*\*\s+.*[\!,\?:\.]$/ # regex matches bullet points with punctuation
|
110
|
-
Printer.fail("'#{line}' is invalid. Bulleted points should end in punctuation.")
|
111
|
-
end
|
112
|
-
end
|
113
|
-
}
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: releasinator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- PayPal
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-07-
|
11
|
+
date: 2016-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -153,6 +153,8 @@ files:
|
|
153
153
|
- LICENSE
|
154
154
|
- README.md
|
155
155
|
- Rakefile
|
156
|
+
- lib/changelog/importer.rb
|
157
|
+
- lib/changelog/validator.rb
|
156
158
|
- lib/command_processor.rb
|
157
159
|
- lib/config_hash.rb
|
158
160
|
- lib/copy_file.rb
|